Подключаем MyTracker и AppMetrica к игре на Godot
В прошлой статье мы написали простую игру на Godot и опубликовали ее в рустор. Теперь попробуем заработать на ней. Для этого нам нужно реализовать все необходимые плагины - аналитика, реклама, подписки и тд.
Godot замечательный движок для игр, но под него оч мало готовых плагинов. Особенно, плагинов для российских сервисов яндекса или vk. Поэтому нам нужно будет реализовать плагины для аппметрки, майтрекера, майтаргета, рся и рустора.
Начать нужно с аналитики. Она нужна любому приложению, без аналитики не получится закупить трафик, непонятно сколько времени пользователь проводит в приложении. Есть два сервиса аналитик, которые меня интересуют - AppMetrica и MyTracker. В этой статье реализуем работу с обоими сервисами. Это позволит закупать рекламу и в рекламной сети яндекса, и в рекламной сети vk.
Вторым шагом нужно будет подключить рекламу и подписки. Связать их с аналитикой и считать заработанные деньги.
Плагин MyTracker
Добавляем приложение в MyTracker. Начинаем с указания ссылки на приложение в русторе.
Создаем проект и указываем валюту RUB. По умолчанию валюта будет USD, но мы будем закупаться в RU и реклама у нас будет только из русских сервисов.
Сохраняем настройки и попадаем на страничку с инструкцией по подключению SDK.
Все готово, идем создавать плагин и подключать его в нашу игру.
Первым делом нужно создать обычный Android проект. Никаких хитростей тут нет, все делаем как с обычным Android приложением.
После создания проекта добавляем новый модуль с названием my-tracker
. Тут будет реализована вся логика плагина, которая станет доступна в нашей игре. Но чтобы все заработала нужно добавить специальную библиотеку для разработки плагинов под Android. Эту библиотеку можно найти на страничке с загрузками, выбираем пункт “AAR library for Android” и скачиваем .aar библиотеку в папку godot-lib
Чтобы библиотека из godot-lib
стала доступна в проекте, нужно создать правильный gradle скрипт.
1configurations.maybeCreate("default")
2artifacts.add("default", file('godot-lib.4.0.2.stable.template_release.aar'))
Все модули нужно перечислить в settings.gradle
1rootProject.name = "rustore-my-tracker"
2include ':app'
3include ':godot-lib'
4include ':my-tracker'
Зависимости
Теперь нужно подключить саму библиотеку MyTracker. Посмотреть актуальную версию можно в документации. На момент написания статьи актуальная версия была 'com.my.tracker:mytracker-sdk:3.0.+'
. Но подключать ее будем по-хитрому.
Чтобы Godot смог подтянуть наш файл, нужно создать специальный файл MyTracker.gdap
. В этом файле должна быть все необходимая информация о плагине.
1[config]
2
3name="MyTracker"
4binary_type="local"
5binary="my-tracker-release.aar"
6
7[dependencies]
8
9remote=["com.my.tracker:mytracker-sdk:3.0.+"]
Информация в файле достаточно очевидна. Указываем имя плагина в параметре name
, в параметре binary_type
указываем local
, а в binary
указываем название собранной .aar
библиотеки. Можно указать binary_type=remote
и тогда в параметре binary
нужно будет указать ссылку на .aar
Самое интересное начинается в секции dependencies
. Зависимости можно указать как local
или remote
. В нашем случае указывается только одна remote
зависимость. При необходимости есть возможность указать список сторонних репозиториев через параметр custom_maven_repos=[]
, но для нашего плагина это не нужно. Все эти зависимости будут использоваться при сборке нашей игры Godot. Узнать больше подробностей про параметры плагина можно в официальной документации
А теперь нужно применить магии gradle. Напишем немного кода, чтобы не копировать руками зависимость из my-tracker/MyTracker.gdap
в my-tracker/build.gradle
.
1dependencies {
2 File gdap = new File("my-tracker/MyTracker.gdap")
3 def match = gdap.text =~ /(?<=remote=)[^;]+/
4
5 def remote = Eval.me(match[0])
6
7 for(item in remote){
8 println "implementing $item"
9 implementation item
10 }
11
12 compileOnly project(':godot-lib')
13}
Этот код честно подсмотрен в плагине для admob - неплохой пример для изучения. Но у нас будет лучше, конечно же.
В коде выше мы открываем файл MyTracker.gdap
, парсим его, находим все пакеты указанные в параметре remote
и подключаем их как implementation
. Теперь, если нужно поднять версию Android библиотеки, то достаточно внести изменения только в один файл. Конечно, отдельно нужно будет указать кастомные репозитории, но даже так жизнь становится проще.
Все зависимости подключены и можно приступать к написанию скриптом. Давайте создадим файл для нашего плагина, назовем его MyTracker.kt
. Итоговая структура проекта получается такой:
- app/
- godot-lib/
- build.gradle
- godot-lib.4.0.2.stable.template_release.aar
- my-tracker/
- src/
- build.gradle
- MyTracker.gdap
- build.gradle
- settings.gradle
Реализация
Начнем с создания класса нашего плагина в файле MyTracker.kt
:
1package ru.rustore.mytracker
2
3import org.godotengine.godot.Godot
4import org.godotengine.godot.plugin.GodotPlugin
5
6class MyTracker(godot: Godot?) : GodotPlugin(godot) {
7 override fun getPluginName(): String {
8 return "MyTracker"
9 }
10}
Пока все просто. Наследуемся от базового класса GodotPlugin
и реализуем один метод getPluginName()
который, ожидаемо, возвращает название плагина.
Чтобы наша игра смогла найти этот класс и загрузить плагин, необходимо добавить нужную информацию в файл AndroidManifest.xml
нашего модуля my-tracker
:
1<?xml version="1.0" encoding="utf-8"?>
2<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3 <application>
4 <meta-data
5 android:name="org.godotengine.plugin.v1.MyTracker"
6 android:value="ru.rustore.mytracker.MyTracker" />
7 </application>
8</manifest>
MyTracker
- название нашего плагинаru.rustore.mytracker.MyTracker
- полный пуль к файлу плагина
Теперь нам нужно реализовать инициализацию трекера. По-хорошему, инициализировать трекер нужно непосредственно при создании приложения в методе Application.onCreate()
. Но в MyTracker есть возможность ручной инициализации с использованием метода trackLaunchManually()
:
1package ru.rustore.mytracker
2
3import com.my.tracker.MyTracker as Tracker
4import org.godotengine.godot.Godot
5import org.godotengine.godot.plugin.GodotPlugin
6import org.godotengine.godot.plugin.UsedByGodot
7
8class MyTracker(godot: Godot?) : GodotPlugin(godot) {
9 override fun getPluginName(): String {
10 return "MyTracker"
11 }
12
13 @UsedByGodot
14 fun init(key: String) {
15 if (godot == null) {
16 return
17 }
18
19 Tracker.initTracker(key, godot.requireActivity().application)
20 Tracker.trackLaunchManually(godot.requireActivity())
21 }
22}
Сначала добавляем метод init()
и помечаем его @UsedByGodot
. Как несложно догадаться, этот метод будет доступен из Godot.
Теперь нужно добавить возможность конфигурировать трекер из Godot. Для этого добавляем пачку методов, которые проксируют вызовы методов класса MyTrackerConfig
1@UsedByGodot
2fun setTrackingLaunchEnabled(trackingLaunchEnabled: Boolean) {
3 Tracker.getTrackerConfig().setTrackingLaunchEnabled(trackingLaunchEnabled)
4}
5
6@UsedByGodot
7fun setLaunchTimeout(seconds: Int) {
8 Tracker.getTrackerConfig().setLaunchTimeout(seconds)
9}
10
11@UsedByGodot
12fun setBufferingPeriod(seconds: Int) {
13 Tracker.getTrackerConfig().setBufferingPeriod(seconds)
14}
15
16@UsedByGodot
17fun setForcingPeriod(seconds: Int) {
18 Tracker.getTrackerConfig().setForcingPeriod(seconds)
19}
20
21@UsedByGodot
22fun setAutotrackingPurchaseEnabled(autotrackingPurchaseEnabled: Boolean) {
23 Tracker.getTrackerConfig().setAutotrackingPurchaseEnabled(autotrackingPurchaseEnabled)
24}
25
26@UsedByGodot
27fun setTrackingPreinstallEnabled(trackingPreinstallEnabled: Boolean) {
28 Tracker.getTrackerConfig().setTrackingPreinstallEnabled(trackingPreinstallEnabled)
29}
30
31@UsedByGodot
32fun setApkPreinstallParams(apkPreinstallParams: String) {
33 Tracker.getTrackerConfig().setApkPreinstallParams(apkPreinstallParams)
34}
Отлично, теперь из Godot можно будет настраивать трекер. Но нужно добавить возможность указывать параметры.
1@UsedByGodot
2fun setCustomParam(key: String, value: String) {
3 Tracker.getTrackerParams().setCustomParam(key, value)
4}
5
6@UsedByGodot
7fun setEmail(email: String) {
8 Tracker.getTrackerParams().setEmail(email)
9}
10
11@UsedByGodot
12fun setCustomUserId(id: String) {
13 Tracker.getTrackerParams().setCustomUserId(id)
14}
15
16@UsedByGodot
17fun setAge(age: Int) {
18 Tracker.getTrackerParams().setAge(age)
19}
20
21@UsedByGodot
22fun setPhone(phone: String) {
23 Tracker.getTrackerParams().setPhone(phone)
24}
25
26@UsedByGodot
27fun setLang(lang: String) {
28 Tracker.getTrackerParams().setLang(lang)
29}
На самом деле сеттеров еще больше, но я использовал только самые популярные. Не уверен, что в 2023 году в игре на Godot может понадобиться сеттер setIcqId()
.
Осталось добавить последний и самый важный набор методов для трекания событий.
1@UsedByGodot
2fun trackInviteEvent(params: Dictionary) {
3 Tracker.trackInviteEvent(params.map { e -> e.key to e.value.toString() }.toMap())
4}
5
6@UsedByGodot
7fun trackLevelEvent(level: Int, params: Dictionary) {
8 Tracker.trackLevelEvent(level, params.map { e -> e.key to e.value.toString() }.toMap())
9}
10
11@UsedByGodot
12fun trackEvent(name: String, params: Dictionary) {
13 Tracker.trackEvent(name, params.map { e -> e.key to e.value.toString() }.toMap())
14}
Обратите внимание на тип переменной params
. Мы не можем из Godot просто передать тип Map<String, String>
. Поддерживаются только типы: void
, boolean
, int
, float
, java.lang.String
, org.godotengine.godot.Dictionary
, int[]
, byte[]
, float[]
, java.lang.String[]
. Поэтому нам нужно конвертировать org.godotengine.godot.Dictionary
в тип Map<String, String>
.
С помощью метода params.map { e -> e.key to e.value.toString() }.toMap()
мы пробегаемся по всем значениям мапы и конвертим их в строку String
, а потом результат отдается в виде Map<String, String>
. Надеюсь, это сработает.
Важно добавить еще один метод - трекание эффективности рекламы в приложении. Этот метод нам очень понадобится, когда будем отслеживать сколько рекламы заработали по какому источнику.
1@UsedByGodot
2fun trackAdEvent(name: String, network: Int, params: org.godotengine.godot.Dictionary) {
3 var event: AdEventBuilder? = null
4
5 if (name == EVENT_IMPRESSION) {
6 event = AdEventBuilder.newImpressionBuilder(network)
7 }
8
9 if (name == EVENT_CLICK) {
10 event = AdEventBuilder.newClickBuilder(network)
11 }
12
13 if (name == EVENT_REVENUE) {
14 event = AdEventBuilder.newRevenueBuilder(
15 network,
16 params.get(AD_REVENUE) as? Double ?: 0.0,
17 params.get(AD_CURRENCY) as? String ?: "")
18 }
19
20 if (params.containsKey(AD_SOURCE)) {
21 event?.withSource(params[AD_SOURCE] as? String)
22 }
23
24 if (params.containsKey(AD_ID)) {
25 event?.withAdId(params[AD_ID] as? String)
26 }
27
28 if (params.containsKey(AD_PLACEMENT_ID)) {
29 event?.withAdId(params[AD_PLACEMENT_ID] as? String)
30 }
31
32 if (params.containsKey(AD_FORMAT)) {
33 event?.withAdFormat(params[AD_FORMAT] as? String)
34 }
35
36 Tracker.trackAdEvent(event?.build())
37}
38
39companion object {
40 const val EVENT_IMPRESSION = "impression"
41 const val EVENT_CLICK = "click"
42 const val EVENT_REVENUE = "revenue"
43
44 const val AD_REVENUE = "revenue"
45 const val AD_CURRENCY = "currency"
46 const val AD_SOURCE = "source"
47 const val AD_ID = "ad_id"
48 const val AD_PLACEMENT_ID = "placement_id"
49 const val AD_FORMAT = "format"
50}
В этом методе используется AdEventBuilder
, который создает правильное событие в зависимости от переданного параметра name
. Параметр network
используется для передачи идентификатора рекламной сетки, но в SDK я нашел только такой класс с двумя сетками:
1public @interface AdNetwork {
2 int ADMOB = 1;
3 int MOPUB = 2;
4}
Попробуем передавать разные id и посмотрим, заработает ли это. В параметре params
передаются значения, которые нужны для правильного учета рекламных событий.
Еще один не маловажный метод - учет покупок. Он реализуется довольно просто:
1fun trackPurchaseEvent(
2 sku: String,
3 purchase: String,
4 signature: String,
5 params: Dictionary
6) {
7 Tracker.trackPurchaseEvent(
8 JSONObject(sku),
9 JSONObject(purchase),
10 signature,
11 params.map { e -> e.key to e.value.toString() }.toMap()
12 )
13}
Чтобы учитывать покупки через него, нужно отключить автоматический теркинг покупок используя метод setAutotrackingPurchaseEnabled(false)
.
По умолчанию, SDK MyTracker отправляет данные на сервер раз в 15 минут. Но некоторые события важно отправить как можно раньше и для этого есть метод flush()
1@UsedByGodot
2fun flush() {
3 Tracker.flush()
4}
Все нужные методы добавлены, собираем наш плагин и будем его тестировать в реальной игре.
Сейчас добавлены только базовые методы, которые позволят интегрировать и использовать SDK MyTracker в нашей игре. Но методов там побольше и я не описывал все возможные примеры их использования. Если вам нужно больше информации, то обратитесь к официальной доке.
Сборка и подключение
Собираем все как обычный Android модуль командой ./gradlew build
. Остается только скопировать файлы my-tracker-release.aar
и MyTracker.gdap
в папку res://android/plugins
В вашей игре должен быть установлен Android Build Template для корректной работы плагина. Как его скачать и установить рассказывалось в прошлой статье. Если у вас все корректно установлено, то после добавления плагина он будет виден в списке на экране настройки экспорта:
А это значит что плагин доступен в коде самой игры.
Использование
Все начинается с метода _ready() в скрипте Game.gd
. Нужно проверить доступность плагина методом Engine.has_singleton()
1func _ready():
2 if Engine.has_singleton("MyTracker"):
3 var tracker = Engine.get_singleton("MyTracker")
tracker
- это экземпляр нашего плагина. Мы можем вызывать методы, которые мы определили в класса плагина.
1func _ready():
2 if Engine.has_singleton("MyTracker"):
3 var tracker = Engine.get_singleton("MyTracker")
4
5 tracker.setDebugMode(true)
6 tracker.init("xxxxxxxxxxx")
xxxxxxxxxxx
- это SDK ключ, который мы получили при создании приложения в настройках MyTracker. Метод setDebugMode(true)
позволяет увидеть в logcat приложения как работает MyTracker.
Залогируем событие завершения игры и событие рестарта. Для этого немного подправим код нашей игры
1func _on_collided():
2 tracker.trackEvent("finish", {
3 "points": "%d" % score,
4 })
5 restart.show()
6 hero.active = false
7 hero.boom()
8 play = false
9 for ch in get_children():
10 if ch.is_in_group("Enemy"):
11 remove_child(ch)
12
13
14func _on_restart_pressed():
15 tracker.trackEvent("restart", {
16 "points": "%d" % score,
17 })
18 get_tree().reload_current_scene()
Эти события можно будет смотреть в отчетах MyTracker
Убираем вызов tracker.setDebugMode(true)
, собираем игру и публикуем новую версию в RuStore.
Исходники
Исходники плагина доступны по ссылке
Плагин AppMetrica
Интеграция MyTracker оказалась несложной. Но им одним сыт не будешь. Нам нужна интеграция с AppMetrica, чтобы закупать рекламу в сетке яндекса.
Для начала регистрируем приложение в AppMetrica. Все делается максимально просто - добавляем ссылку на приложение и сохраняем полученный API ключ для использования в SDK
API ключ понадобится для инициализации SDK
Зависимости
Начинаем интеграцию уже привычным способом. Создаем новый Android проект, добавляем новый модуль app-metrica
, добавляем еще модуль godot-lib
. Не забываем добавить модули в проект:
1rootProject.name = "rustore-app-metrica"
2include ':app'
3include ':godot-lib'
4include ':app-metrica'
Создаем файл .gdap
и описываем все нужные параметры для нашего плагина:
1[config]
2
3name="AppMetrica"
4binary_type="local"
5binary="app-metrica-release.aar"
6
7[dependencies]
8
9remote=["com.yandex.android:mobmetricalib:5.3.+"]
Настраиваем gradle скрипты:
1dependencies {
2 File gdap = new File("app-metrica/AppMetrica.gdap")
3 def match = gdap.text =~ /(?<=remote=)[^;]+/
4
5 def remote = Eval.me(match[0])
6
7 for(item in remote){
8 println "implementing $item"
9 implementation item
10 }
11
12 compileOnly project(':godot-lib')
13}
Создаем класс нашего плагина AppMetrica.kt
:
1package ru.rustore.appmetrica
2
3import org.godotengine.godot.Godot
4import org.godotengine.godot.plugin.GodotPlugin
5
6class AppMetrica(godot: Godot?) : GodotPlugin(godot) {
7 override fun getPluginName(): String {
8 return "AppMetrica"
9 }
10}
Не забываем внести нужную информацию в AndroidManifest.xml
:
1<?xml version="1.0" encoding="utf-8"?>
2<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3 <application>
4 <meta-data
5 android:name="org.godotengine.plugin.v1.AppMetrica"
6 android:value="ru.rustore.appmetrica.AppMetrica" />
7 </application>
8</manifest>
Болванка для сервиса готова, можно начинать реализацию.
Реализация
Как и для MyTracker, тут все начинается с инициализации. Она будет отличаться от инициализации MyTracker, но принцип похож. Тут тоже нужно будет сконфигурировать трекер и инициализировать его. Но тут сначала нужно создать конфиг с правильным SDK ключом, сохранить в переменную, вызвать нужные методы для настройки конфига и уже потом инициализировать сам трекер с заранее подготовленным конфигом.
Начнем с создания конфига
1class AppMetrica(godot: Godot?) : GodotPlugin(godot) {
2 lateinit var config: YandexMetricaConfig.Builder
3
4 override fun getPluginName(): String {
5 return "AppMetrica"
6 }
7
8 @UsedByGodot
9 fun config(key: String) {
10 config = YandexMetricaConfig.newConfigBuilder(key)
11 }
12}
Добавляем метод для инициализации
1@UsedByGodot
2fun init() {
3 if (godot == null) {
4 return
5 }
6
7 YandexMetrica.activate(godot.requireContext(), config.build())
8 YandexMetrica.reportAppOpen(godot.requireActivity())
9}
Метод reportAppOpen
нужен для отстукивания события открытия приложения. Обычно, аналитика инициализируется в методе onCreate()
самого Android приложения. Но в Godot мы инициализируем AppMetrica значительно позже, поэтому необходимо руками вызвать этот метод.
Но перед тем как инициализировать плагин, нужно правильно настроить конфиг, который будет использоваться для инициализации трекера. Я не буду перечислять все методы, их довольно много. Покажу только несколько для примера:
1@UsedByGodot
2fun withAppVersion(version: String) {
3 config.withAppVersion(version)
4}
5
6@UsedByGodot
7fun setSessionTimeout(timeout: Int) {
8 config.withSessionTimeout(timeout)
9}
10
11@UsedByGodot
12fun withCrashReporting(enabled: Boolean) {
13 config.withCrashReporting(enabled)
14}
15
16// ...
В этих методах все манипуляции происходят с объектом config
, который мы инициализировали в методе config()
Методы учета событий походи на аналогичные в MyTracker. Начнем с простых - учет ошибок и учет событий:
1@UsedByGodot
2fun reportAppOpen(name: String) {
3 YandexMetrica.reportAppOpen(name)
4}
5
6@UsedByGodot
7fun reportError(group: String, message: String) {
8 YandexMetrica.reportError(group, message)
9}
10
11@UsedByGodot
12fun reportEvent(name: String, params: org.godotengine.godot.Dictionary) {
13 YandexMetrica.reportEvent(name, params.toMutableMap())
14}
С методом reportError()
все просто, указываем группу ошибок и текстовое сообщение ошибки. В методе reportEvent()
все тоже просто - указываем название события и передаем параметры в params: org.godotengine.godot.Dictionary
Теперь добавляем методы, которые нужны для трекания самого важного - денег. В MyTracker можно учитывать события рекламы и покупки. В AppMetrica тоже будет два события для учета покупок и показа рекламы.
Начнем с показа рекламы:
1@UsedByGodot
2fun reportAdRevenue(revenue: Double, currency: String, params: org.godotengine.godot.Dictionary) {
3 val event = AdRevenue.newBuilder(revenue, Currency.getInstance(currency))
4
5 if (params.containsKey(AD_TYPE)) {
6 val ad = when (params.get(AD_TYPE) as String) {
7 "native" -> AdType.NATIVE
8 "banner" -> AdType.BANNER
9 "rewarded" -> AdType.REWARDED
10 "interstitial" -> AdType.INTERSTITIAL
11 "mrec" -> AdType.MREC
12 else -> AdType.OTHER
13 }
14 event.withAdType(ad)
15 }
16
17 if (params.containsKey(AD_NETWORK)) {
18 event.withAdNetwork(params[AD_NETWORK].toString())
19 }
20
21 if (params.containsKey(AD_UNIT_ID)) {
22 event.withAdUnitId(params[AD_UNIT_ID].toString())
23 }
24
25 if (params.containsKey(AD_UNIT_NAME)) {
26 event.withAdUnitName(params[AD_UNIT_NAME].toString())
27 }
28
29 if (params.containsKey(AD_PLACEMENT_ID)) {
30 event.withAdPlacementId(params[AD_PLACEMENT_ID].toString())
31 }
32
33 if (params.containsKey(AD_PLACEMENT_NAME)) {
34 event.withAdPlacementName(params[AD_PLACEMENT_NAME].toString())
35 }
36
37 if (params.containsKey(AD_PRECISION)) {
38 event.withPrecision(params[AD_PRECISION].toString())
39 }
40
41 if (params.containsKey(AD_PAYLOAD)) {
42 val json = JSONObject(params[AD_PAYLOAD].toString())
43 val payload = json.toMap().map { e -> e.key to e.value.toString() }.toMap()
44
45 event.withPayload(payload)
46 }
47
48 YandexMetrica.reportAdRevenue(event.build())
49}
50
51companion object {
52 const val AD_NETWORK = "network"
53 const val AD_TYPE = "type"
54 const val AD_PRECISION = "precision"
55 const val AD_PLACEMENT_ID = "placement_id"
56 const val AD_PLACEMENT_NAME = "placement_name"
57 const val AD_UNIT_ID = "unit_id"
58 const val AD_UNIT_NAME = "unit_name"
59 const val PAYLOAD = "payload"
60}
Метод получается довольно жирненьким, нужно учесть много параметров, которые передаются через params: org.godotengine.godot.Dictionary
. Это и ид баннера(unit), и ид плейсмента (placement_id), и ряд других важных параметров. Все эти параметры указываются для события, которое инициализируется AdRevenue.newBuilder(revenue, Currency.getInstance(currency))
с указанием revenue
и валюты.
Добавим метод для учета покупок внутри приложения:
1@UsedByGodot
2fun reportRevenue(revenue: Long, currency: String, params: org.godotengine.godot.Dictionary) {
3 val revenue = Revenue.newBuilderWithMicros(revenue, Currency.getInstance(currency))
4
5 if (params.containsKey(REVENUE_QUANTITY)) {
6 revenue.withQuantity(params[REVENUE_QUANTITY] as? Int)
7 }
8
9 if (params.containsKey(REVENUE_PRODUCT_ID)) {
10 revenue.withProductID(params[REVENUE_PRODUCT_ID].toString())
11 }
12
13 if (params.containsKey(PAYLOAD)) {
14 revenue.withPayload(params[PAYLOAD].toString())
15 }
16
17 if (params.containsKey(REVENUE_RECEIPT)) {
18 val receipt: Receipt.Builder = Receipt.newBuilder()
19 .withData(params[REVENUE_RECEIPT].toString())
20 if (params.containsKey(REVENUE_SIGNATURE)) {
21 receipt.withSignature(params[REVENUE_RECEIPT].toString())
22 }
23
24 revenue.withReceipt(receipt.build())
25 }
26
27 YandexMetrica.reportRevenue(revenue.build())
28}
29
30companion object {
31 const val AD_NETWORK = "network"
32 const val AD_TYPE = "type"
33 const val AD_PRECISION = "precision"
34 const val AD_PLACEMENT_ID = "placement_id"
35 const val AD_PLACEMENT_NAME = "placement_name"
36 const val AD_UNIT_ID = "unit_id"
37 const val AD_UNIT_NAME = "unit_name"
38
39 const val REVENUE_QUANTITY = "quantity"
40 const val REVENUE_PRODUCT_ID = "product_id"
41 const val REVENUE_RECEIPT = "receipt"
42 const val REVENUE_SIGNATURE = "signature"
43
44 const val PAYLOAD = "payload"
45}
Принцип прям такой же как и в методе reportAdRevenue()
с небольшими изменениями. Немного подправил список констант, чтоб их можно было использовать в обоих методах
Сборка и подключение
Собираем наш новый модуль командой ./gradlew build
, копируем файлы app-metrica-release.aar
и AppMetrica.gdap
в папку res://android/plugins
Стал доступен новый плагин с “App Metrica”. Всего в списке уже два плагина, а будет еще больше :)
Использование
Настало время добавить AppMetrica в нашу игру и выложить новую версию в рустор. Код будем добавлять рядом с кодом MyTracker в метод _ready()
в скрипте Game.gd
1var tracker: Object
2var metrica: Object
3
4func _ready():
5 if Engine.has_singleton("MyTracker"):
6 tracker = Engine.get_singleton("MyTracker")
7
8 tracker.setDebugMode(true)
9 tracker.init("xxxxxxxxxx")
10
11 if Engine.has_singleton("AppMetrica"):
12 metrica = Engine.get_singleton("AppMetrica")
13
14 metrica.config("zzzzzzzz")
15 metrica.withLogs()
16 metrica.init()
Обратите внимание, что порядок вызова методов для плагина AppMetrica важен. Сначала вызываем метод config(key)
с указанием ключа SDK. Потом вызываем методы, необходимые для настройки конфигурации и только потом вызываем init()
.
Осталось экспортировать игру как apk, загрузить новую версию в RuStore и ждать когда появятся первые события.
Исходники
Исходники плагина доступны по ссылке. Исходники игры тоже доступны на gitflic.
Что дальше
В следующих статье напишем еще одну обертку для Godot над RuStore SDK платежей, интегрируем ее и добавим магазин в нашу игру. Потом перейдем к рекламным SDK.