引言
这个deltaDNA SDK允许你的Android游戏记录游戏中的事件并上传其玩家的行为。其包括事件缓存、众多辅助方法和一些自动化的行为来帮助你简化你的整合。
事件被以JSON对象发送到deltaDNA 平台,这些事件被使用在线的显示面板来管理和跟踪。
当你的游戏触发事件以后,这个SDK将在本地存储它们并在网络连接可用时定期上传或者在你选择的时间上传。这允许SDK收集数据而不考虑网络连通性,并让你可以控制上传的时间和频率。
事件的复杂度有所不同,但是都来自同一个事件格式。这个文档和附加的案例应用将提供不断增加复杂性的事件案例。
DeltaDNA Android SDK第4版:
deltaDNA SDK可以用于基于第9版和更新版本(Android 2.3+)内核SDK的Android项目。
随着我们SDK第4版的发布,我们在分配这个SDK和如何使用这个SDK方面有一些重要的更新。对于在整合中已经改变了什么的更多详细介绍请查看:https://github.com/deltaDNA/android-sdk/tree/master/docs/migrations
Gradle
为了导入这个SDK,你将必须添加如下几行到你Android项目的Gradle文件。
在你的顶层构建脚本
1 2 3 4 5 6 |
allprojects { repositories { maven { url 'http://deltadna.bintray.com/android' } // repositories为你其他的dependencies... } } |
在你APP的构建脚本
1 |
compile 'com.deltadna.android:deltadna-sdk:4.0.3' |
初始化SDK
这个SDK需要在一个Application子类中通过如下参数进行初始化:
- Application实例
- environmentKey,这是一个分配给你的应用的唯一的32位字符型字符串。你将被为你的游戏开发和产品分配相互独立的应用键值。当你从开发测试转换到产品应用时,你需要改变这个初始化SDK时的环境键值。
- collectUrl,这是收集你的事件的服务器地址。
- engageUrl,这是提供实时A/B测试(real-time A/B Testing)和命中目标(Targetting)的服务器地址。这只在你的游戏使用这些功能时被要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); DDNA.initialise(new DDNA.Configuration( this, "environmentKey", "collectUrl", "engageUrl")); } } |
这些参数可以从你的游戏详情页面找到。
请注意,你的开发(DEV)和实际(LIVE)环境有不同的environmentKey参数。当你从开发和测试环境迁移到产品时,你将需要改变这个初始化SDK时的环境键值。在游戏详情页面还有一个自动生成的代码片段,可以简单的复制和粘贴来使用其整合这个SDK。
启用和停止
在你的Activity类中,你需要使用onCreate(Bundle)方法中的DDNA.instance().startSdk()函数启用这个SDK。同样地,使用onDestroy()方法中的DDNA.instance().stopSdk()函数停止这个SDK。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class MyActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DDNA.instance().startSdk(); } @Override public void onDestroy() { DDNA.instance().stopSdk(); super.onDestroy(); } } |
这是初始化这个Unity SDK和开始发送事件所需的最少代码。SDK第一次运行时其将自动发送newPlayer事件,并且游戏每次运行时自动发送gameStarted和clientDevice事件。
事件剖析
所有的事件都以一个共同基础架构的JSON文件记录下来。这个文件对每个事件类型各不相同,但是所有的这些事件文件都遵循如下的最小架构:
1 2 3 4 5 6 7 8 9 10 11 |
{ "eventName": "gameEnded", "userID": "a2e92bdd-f59d-498f-9385-2ae6ada432e3", "sessionID": "0bc56224-8939-4639-b5ba-197f84dad4f4", "eventUUID": "faaa4ca7-c5d4-4ea6-a373-2abc11cdff54", "eventTimestamp": "2016-04-01 10:51:05.400", "eventParams": { "sdkVersion": "Android SDK v4.0.3" "platform": "ANDROID" } } |
Android SDK将为你发送的每一个事件自动生成userID、sessionID、eventTimestamp、eventUUID、platform和sdkVersion参数。当你添加额外参数到每一个事件时,其将被放置于eventParams对象中。
在你的JSON事件中参数的顺序并不重要。
你可以在事件管理器(Event Manager)检查每个事件要求的参数,还有类型以及任何格式或者枚举规则。(设置/SETUP->管理事件/MANAGE EVENTS)。
参数可以是可选的(Optional)或者必需的(Required)。任何可选参数都不是必须包含在你的事件中。如果你没有为其设置一个有效值,最好是将其完全排除,而不是将其的值设置为零或空。
基本的事件结构为记录不同层次复杂性的事件提供了非常强的灵活性,从像上面那个例子一样的非常简单的事件到包含嵌套数组的复杂事件。下面的代码案例将展示从简单到复杂的各种事件。
请注意所有的事件都需要确认,如果他们与事件管理器(Event Manager)中的架构不同,其将被拒绝。
事件浏览器QA工具对调试你的事件可以非常有用。你可以查看最近几分钟内从设备发送过来的事件,检查发送的参数和确认发送的事件。(设置/SETUP->事件浏览器/EVENT BROWSER)
设置
从你的游戏详情页面复制上面展示的简单初始化代码是开始从你的玩家收集分析数据要求的最少代码。你将很快开始添加更多的事件和调整你的实现。确保进一步查看这个页面的下面部分,关于完整的设置、方法和帮助列表。同时,这里还有两个添加的有用设置的相同初始化代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DDNA.initialise(new DDNA.Configuration(this, "22079697190426055695055037414340", "https://collect4792jmprb.deltadna.net/collect/api", "https://engage4792jmprb.deltadna.net" ).clientVersion("1.0") .withSettings(new DDNA.SettingsModifier() { @Override public void modify(Settings settings) { settings.setBackgroundEventUpload(false); settings.setDebugMode(true); } } ) ); |
- 通过在配置(Configuration)对象指定客户端版本(clientVersion),我们设置在事件中发送到deltaDNA平台的客户端版本(clientVersion)。这是明智的,并且对确认在你的游戏不同版本之间玩家行为的不同非常有用。特别是当一个客户端版本更新是可选时,许多移动用户不考虑更新。
- 我们告诉SDK不要自动上传事件,而是人工控制何时其被发送。
- 告诉SDK输出关于你收集的事件和与deltaDNA通信的详细调试信息。这在与QA协同使用时是特别有用的——在开发过程中交互验证,其将帮助你解决那些导致各种你的事件验证失败的问题。
还有许多更多的配置选项和设置可以被用来调整SDK和你的需求。
案例1——一个简单事件。
我们已经看到的初始化代码将自动发送newPlayer、clientDevice和gameStarted事件到deltaDNA。下面的代码中我们将添加一个我们自己的事件到代码。
当我们添加我们的游戏到deltaDNA时,一些默认事件将自动添加。这些事件对于所有的游戏往往是标准事件,被用于驱动显示界面的很多内容。现在我们将只使用其中的一个标准事件。
1 2 3 4 5 6 |
Log.d(TAG, "record an options event"); DDNA.instance().recordEvent( new Event("options") .putParam("option", "Music") .putParam("action", "Disabled") ); |
如下的JSON事件将被上传
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "eventName": "options", "eventTimestamp": "2016-04-01 11:37:32.826", "eventUUID": "f3eb2a0e-26c8-4541-9e21-3cd93a22d2d8", "sessionID": "66bd78b8-85dc-4a4f-96c1-2d018e5f0263", "userID": "4bf1aaaa-c7d5-4f70-82eb-a4db9d7b446f", "eventParams": { "option": "Music", "action": "Disabled", "platform": "ANDROID", "sdkVersion": "Android SDK v4.0.3" } } |
案例2——添加一个新的模板事件
前一个案例使用了我们7个标准事件中的一个。这次我们将做一些更进一步的工作。我们将从预定义的模板事件列表添加一个事件到我们的框架,然后从我们的代码中触发这个事件。这个例子将只展示以初始化创建事件,上传已经在前一个案例展示了。
从事件模板列表添加一个missionStarted事件到你的事件框架,然后添加一个新的字符串类型的missionDifficulty参数。
记录missonStarted事件的代码。
1 2 3 4 5 6 7 |
DDNA.instance().recordEvent( new Event("missionStarted") .putParam("missionName", "Mission01") .putParam("missionID", "M001") .putParam("isTutorial", false) .putParam("missionDifficulty", "EASY") ); |
如下的JSON事件将被上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "eventName": "missionStarted", "eventTimestamp": "2016-04-01 12:44:08.250", "eventUUID": "43e2134d-00c7-474f-8be4-a5679e2cb6e2", "sessionID": "00262054-4009-4ac1-aae0-636f69ff8446", "userID": "4bf1aaaa-c7d5-4f70-82eb-a4db9d7b446f", "eventParams": { "missionName": "Mission01", "missionID": "M001", "isTutorial": false, "missionDifficulty": "EASY", "platform": "ANDROID", "sdkVersion": "Android SDK v4.0.3" } } |
案例3——一个复杂事件
前面的案例非常简单,并没有太多需要解释的。但是,下面的案例更复杂一些,因为其介绍嵌套、矩阵和一些玩家购买、交易、赢得、与游戏或其他玩家交换货币和装备时可能会遇到的特别对象。好消息是其结构非常的标准,下面的事件可以足够的复杂。
我们将触发一个记录玩家使用一些真实货币购买一个包括一些虚拟货币和装备的宝箱的交易(transaction)事件。我们还将利用deltaDNA与Google Play商店的收入确认功能来检查交易是否有效。
正如你看到的交易(transaction)事件的结构有一些复杂。其包括一些用来记录productsSpent和productsReceived的产品(Product)对象。
我们的JSON事件将看起来像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
{ "eventName": "transaction", "eventTimestamp": "2016-04-04 15:19:11.784", "eventUUID": "6f296298-b9bf-4249-ad46-ea00f64ac1f2", "sessionID": "9d31872c-4b37-4315-a34f-f42cc13b14bc", "userID": "42b02d9a-f4b9-4dfb-99e5-cbbf21efd222", "eventParams": { "transactionName": "IAP an in app purchase", "transactionType": "PURCHASE", "productsReceived": { "virtualCurrencies": [{ "virtualCurrency": { "virtualCurrencyName": "Golden ring", "virtualCurrencyType": "PREMIUM", "virtualCurrencyAmount": 1 } }], "items": [{ "item": { "itemName": "Aragorns sword", "itemType": "sword", "itemAmount": 1 } }, { "item": { "itemName": "Legolas bow", "itemType": "bow", "itemAmount": 1 } }, { "item": { "itemName": "Gimilis axe", "itemType": "axe", "itemAmount": 1 } }] }, "productsSpent": { "realCurrency": { "realCurrencyType": "USD", "realCurrencyAmount": 100 } }, "platform": "ANDROID", "sdkVersion": "Android SDK v4.0.3" } } |
1 2 3 4 5 6 7 8 9 |
DDNA.instance().recordEvent(new Transaction( "IAP an in app purchase", "PURCHASE", new Product().addItem("Aragorns sword", "sword", 1) .addItem("Legolas bow", "bow", 1) .addItem("Gimilis axe", "axe", 1) .addVirtualCurrency("Golden ring", "PREMIUM", 1), new Product().setRealCurrency("USD", 100)) ); |
1 2 3 4 |
"realCurrency": { "realCurrencyType": "USD", "realCurrencyAmount": 499 } |
这个事件可以被设计的更复杂,但结构是合乎逻辑的、灵活的,并为玩家消费或者接收任何货币和装备的组合提供一种机制。
交易确认
这个平台可以承担在各个商店的交易收据确认功能,以确保所有显示在你的显示界面的收入都是真实的收入而没有被屏蔽或者丢失的游戏数据。
如果你想要使用交易确认你将需要添加一些细节到“编辑游戏详情(Edit Game Details)”页面。这个页面可以从欢迎页面左侧的“管理游戏(Manage Games)”链接进入。
在你的“管理游戏详情页面”设置你的RSA公钥
公钥是必须的,以便我们可以确认由Google提供的签名。Google返回的消息摘要已经被使用私钥加密——签名验证过程需要公钥在其可以与一个由我们这边来自收据数据的摘要对比之前将这个摘要进行解译。
然后发送transactionServer,购买数据是transactionReceipt,“APP内数据签名”是transactionReceiptSignature
1 2 3 4 5 6 7 8 9 10 |
"transactionServer":"GOOGLE", "transactionReceipt":"{ \"orderId\":\"GPA.1234-5678-9012-34567\", \"packageName\":\"com.example.app\", \"productId\":\"exampleSku\", \"purchaseTime\":1345678900000, \"purchaseState\":0, \"developerPayload\":\"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ\", \"purchaseToken\":\"opaque-token-up-to-1000-characters\" }", "transactionReceiptSignature ":"rNvoHwiBdLSW+........VncbYVJ61fmfsQ==" |
AMAZON(亚马逊)
要验证一个亚马逊商店IAP,发送transactionServer参数为AMAZON,purchaseToken参数为amazonPurchaseToken,在amazonUserID参数中从Amazon检索userID。从这个页面查看更多关于Amazon APP购买的信息。
“transactionServer”: “AMAZON”,
“amazonPurchaseToken”: “2:Cgegdpydx7a6……cvcGSrRw==”,
“amazonUserID”: “rqHhP8Rqdzi…MRE0Ls-IlfuHKp6xhW4”
这时deltaDNA将确认你的收入,并添加一个额外的revenueValidated参数到你的交易事件,其包括如下潜在的值。
- 0 – 不进行确认
- 1 – 收入通过确认检查
- 2 – 收入未通过确认检查
- 3 – 收入尝试确认,但结果未知(确认服务可能不可用)
带有状态码2或3的交易确认失败,将被排除在你的收入计算图表和用户指标之外。
在在线视频页面有一个关于收入确认的更多细节的在线视频和附属的演讲幻灯片。
案例4——吸引(Engage)
游戏可以从吸引(Engage)取回时间敏感信息来决定基于一个设定的吸引(Engage)活动是否应当在一个特定的时间对用户产生一个特别的行为。即你的游戏应当在一个游戏中预定的决策点发送吸引(Engage)请求,响应将允许你立刻个性化的制定对玩家的游戏行为。
下面的案例展示了你可以如何使用吸引(Engage)来实现改变一个IAP对玩家做出的行动:
- 在deltaDNA平台创建一个针对性的活动
- 发出一个吸引(Engage)请求
- 对回调中接收的回应做出反应。
1 2 3 4 5 6 7 |
{ "transactionID": 1898710706656641000, "parameters": { "creditPackPrice": 99, "creditPackSize": 1 } } |
吸引(Engage)响应包括一个transactionID和一个包含一些关于玩家在这个时间点参数的参数对象。
你可能收到一个响应包括transactionID但是没有包含个性化值的参数。这表明玩家未能成功达到任何资质标准或者被分配到一个控制组。
如果服务器有一个错误的处理你的吸引(Engage)请求,你的响应将包括一个statusCode参数含有相关的状态码。
- 400 – 输入格式畸形或者其他形式的不正确,或者你发送的实时参数没有被添加到你的游戏参数列表。
- 403 – 保密的哈希键值不正确或者吸引(Engage)在你的账号没有被启用。
请检查你已经启用了“按需定制版(On-Demand)”包在你的游戏(Game)->包(Packages)页面,要做这个操作你可能需要在你的deltaDNA账号获得账号所有者权限。 - 404 – 不正确的链接或者未知的环境键值
图片消息
吸引(Engage)命中目标(Targeting)也可以实时传送基于图片的弹出消息到你的游戏并展示弹出的消息。每条消息被设计为一个命中目标(Targeting)的一部分,并被发送给一个选定的用户。Unity SDK有一个弹出类在你的游戏上一层绘制图片消息。弹出是一个事件驱动,因此你可以控制何时这个图片从我们的服务器下载和何时呈现给玩家。
每个消息由两部分组成,一个智能画面(sprite map)包括背景图片和一些按钮,以及描述如何显示这些部分的布局规划图。这个布局图用来强制约束如何按比例放置弹出的位置。这意味着我们不需要担心屏幕的尺寸,但是我们也可以保护屏幕的一部分不要被覆盖。图片可以在符合这些约束的前提下画的尽可能大,同时仍保持原始的长宽比。
这将展示给你你已经在平台配置的图片消息。
图片消息的吸引(Engage)请求和其他的吸引(Engage)活动请求是相同的。这个响应JSON被用来创建这个图片消息,包括弹出的图片和布局信息,以及分配给图片的任何行为信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
{ "transactionID": 1898738848054116400, "image": { "width": 512, "height": 256, "format": "png", "spritemap": { "background": { "x": 2, "y": 74, "width": 320, "height": 180 }, "buttons": [ { "x": 2, "y": 38, "width": 160, "height": 34 }, { "x": 2, "y": 2, "width": 160, "height": 34 } ] }, "layout": { "landscape": { "background": { "contain": { "halign": "center", "valign": "center", "left": "10%", "right": "10%", "top": "0px", "bottom": "0%" }, "action": { "type": "dismiss" } }, "buttons": [ { "x": 160, "y": 145, "action": { "type": "action", "value": "POWERUP" } }, { "x": 0, "y": 145, "action": { "type": "dismiss" } } ] } }, "shim": { "mask": "dimmed", "action": { "type": "dismiss" } }, "url": "https://download.deltadna.net/engagements/f20f3c4fc19d4d49bc365b472770c065.png" }, "parameters": { "powerUpName": "MoHawk" } } |
- url是这个智能画面(sprite map)图片文件的位置。width和height是图片的尺寸,format是这个图片的格式。
- spritemap对象描述了图片资源在智能画面(sprite map)的位置。buttons是可选的,基于在消息中按钮的数量。
- layout对象描述了背景如何在屏幕上显示。其包括landscape和/或portrait键值取决于倾向的布局。如果只有一个键值被设置那么这个规则被应用而无关于屏幕方向。布局方向包括背景和按钮位置的规则。对于背景有两个模式可选:
cover是成比例的背景图片所以其可以尽可能的大,
contain是使图片尽可能的大但满足所有的约束条件。 - 每个背景和按钮对象都可以有一个行为。这个行为的type(类型)可以是none、dismiss、link或者action。
如果类型是link或者action,一个value(值) 字段将提供一个字符串值来传回到和这个按钮连接的回调。如果是一个link,这时SDK将自动打开浏览器。
1234"action": {"type": "action","value": "POWERUP"}
1234"action": {"type": "link","value": "http: //www.deltadna.com"} - shim字段描述了在这个消息后面屏幕的其他部分如何被操作。mask可以是
none,这种情况下没有东西被添加,因此在弹出后面的任何按钮都仍然可以被点击;
clear,将是背景按钮被禁止点击的效果;
dimmed,使屏幕变灰。这个shim还支持这样的行为,点击它也可以dismiss(关闭)这个弹出窗口。
Google云消息——推送通知
SDK可以存储设备的Android注册ID并将其发送到deltaDNA,因此你可以发送有针对性的推送通知消息给玩家。
如果你的应用已经处理了ID检索,这时你可以通过调用下面的语句在SDK设置它。
1 |
DDNA.instance().setRegistrationId("your_id"); |
然而你还可以使用deltadna-sdk-notifications插件,其只要求你这边更少的工作来刷新GCM ID或Token。
如果你想要从接收推送消息注销客户端,这时你应当调用
1 |
DDNA.instance().clearRegistrationId(); |