请在 project/build.gradle
文件的 allprojects/repositories
块中添加以下代码:
allprojects {
...
repositories {
...
maven { url "https://sdk-download.airbridge.io/maven" }
...
}
...
}
如果使用 Android Studio Arctic Fox (2020.3.1) 及以上版本创建 Project,或者在 settings.gradle
文件中进行 repository
设置,请在 project/settings.gradle
文件的 dependencyResolutionManagement/repositories
块中添加以下代码:
dependencyResolutionManagement {
...
repositories {
...
maven { url "https://sdk-download.airbridge.io/maven" }
...
}
...
}
请在 app/build.gradle
文件的 dependencies
块中添加以下代码:
dependencies {
...
implementation "io.airbridge:sdk-android:2.+"
...
}
为了确保效率和稳定性,Airbridge Android SDK 同时使用 JetBrains 的 Kotlin 和 Coroutines 库。
如果使用 .aar
直接安装 Airbridge Android SDK,请将以下 Dependency 库添加到 Project 中:
提示
Airbridge Android SDK 需要 1.4 及以上版本的 Kotlin stdlib 和 Kotlinx coroutines 库。
Airbridge Android SDK 2.24.2 及以上版本中需要添加 Play Services Appset 库 Dependency 以收集 App Set ID。
请在 AndroidManifest.xml
文件添加权限,如下所示:
<manifest ...>
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
...
</manifest>
请在 AndroidManifest.xml
文件中注册的 Application
类文件的 onCreate
方法下添加以下代码:
@Override
public void onCreate() {
super.onCreate();
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.build();
Airbridge.init(this, config);
}
override fun onCreate() {
super.onCreate()
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.build()
Airbridge.init(this, config)
}
注意
为确保正常运行,请确保在
Application
类的onCreate
时调用init
函数。
YOUR_APP_NAME
和 YOUR_APP_SDK_TOKEN
可在 Airbridge 面板的 [设置] >[Token] 获取。
完成 Airbridge Android SDK 安装和设置后,您可以通过以下方法检查设置是否正确:
您可以通过以下方法在 LogCat 检查 App 的 Log:
注意
由于此方法可能暴露用户信息,请确保此方法仅在
Build.DEBUG
下运行。
// Default log level = Log.INFO
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLogLevel(Log.DEBUG)
.build();
Airbridge.init(this, config);
// Default log level = Log.INFO
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLogLevel(Log.DEBUG)
.build()
Airbridge.init(this, config)
请在测试设备安装并启用 App。
导航至 Airbridge 面板的 [原始数据]>[App 实时记录]。
在搜索栏中输入测试设备的 Google 广告 ID(Google Advertising ID,简称 GAID)。
Attention
如果搜索不到具有您在搜索栏中输入的 GAID 的 Install 事件,请检查是否已按照上述指南正确完成安装。
Attention
GAID 可在 Android 设备的 [设置]>[Google]>[广告] 获取。
请在 Airbridge 面板的 [追踪链接]>[深度链接] 注册 3 项信息:
Android URI Scheme
Android 包名称
sha256_cert_fingerprints
请在 Android URI Scheme 输入栏输入您的 Android URI Scheme,包括 ://
。Airbridge 的 Android URI Scheme 仅支持英文小写字母、数字、连字符(-)、加号(+)。
注意
请为已发布或即将发布的 App 和开发用的 App 注册不同的 URI Scheme。
如果已发布或即将发布的 App 与开发用的 App 具有相同的 URI Scheme,深度链接可能会打开意外的 App。
您在 Airbridge 面板注册 App 时输入的应用商店 URL 会自动填充已发布 App 的包名称。
要为即将发布或开发用的 App 设置深度链接,需要手动输入包名称。
获取 sha256_cert_fingerprints 的方法如下:
请准备在 Google Play Store 注册 App 时使用的 keystore
文件。
请在 Terminal
运行以下命令:
keytool -list -v -keystore my-release-key.keystore
请从 Certificate fingerprints
复制 SHA256
值并将其输入到 Airbridge 面板的 sha256_cert_fingerprints 输入栏。
Certificate fingerprints:
MD5: 4C:65:04:52:F0:3F:F8:65:08:D3:71:86:FC:EF:C3:49
SHA1: C8:BF:B7:B8:94:EA:5D:9D:38:59:FE:99:63:ED:47:B2:D9:5A:4E:CC
SHA256: B5:EF:4D:F9:DC:95:E6:9B:F3:9A:5E:E9:D6:E0:D8:F6:7B:AB:79:C8:78:67:34:D9:A7:01:AB:6A:86:01:0E:99
多个 sha256_cert_fingerprints 值可以用逗号(,)分隔输入。
如果使用 Airbridge Android SDK 2.21.1 及以上版本,请按照以下步骤设置 Intent Filter
。如果使用 Airbridge Android SDK 2.21.0 及以下版本,请按照 本指南 设置 Intent Filter
。
请打开 AndroidManifest.xml
文件。
请在将处理深度链接的 Activity
中添加 Intent Filter
,如下所示:
<activity ...>
...
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="YOUR_APP_NAME.abr.ge" />
<data android:scheme="https" android:host="YOUR_APP_NAME.abr.ge" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="YOUR_APP_NAME.airbridge.io" />
<data android:scheme="https" android:host="YOUR_APP_NAME.airbridge.io" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="YOUR_APP_URI_SCHEME" />
</intent-filter>
...
</activity>
为了使在 Activity
中设置的 Intent Filter
处理深度链接,需要进行以下设置:
@Override
protected void onResume() {
super.onResume();
Airbridge.getDeeplink(getIntent(), new AirbridgeCallback<Uri>() {
@Override
public void onSuccess(Uri uri) {
// Process deeplink data
}
@Override
public void onFailure(Throwable throwable) {
// Error
}
@Override
public void onComplete() {
// After process deeplink data
}
});
}
// The code below is required for proper deeplink processing
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
override fun onResume() {
super.onResume()
Airbridge.getDeeplink(intent, object : AirbridgeCallback<Uri> {
override fun onSuccess(uri: Uri) {
// Process deeplink data
}
override fun onFailure(throwable: Throwable) {
// Error
}
override fun onComplete() {
// After process deeplink data
}
})
}
// The code below is required for proper deeplink processing
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
}
在 Airbridge Android SDK 中发生延迟深度链接的典型情况下,相应的 Activity
会根据 AndroidManifest.xml
文件中设置的 Intent Filter
自动调用,通过深度链接回调相同的方式处理。
如果希望使用延迟深度链接中的信息来进行特殊操作,或者希望防止延迟深度链接自动调用 Activity
,可以进行以下设置:
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnDeferredDeeplinkReceiveListener(new OnDeferredDeeplinkReceiveListener() {
@Override
public boolean shouldLaunchReceivedDeferredDeeplink(Uri uri) {
// If you want to open the target activity, please return true otherwise false
// Default returning value = true
return true;
}
})
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnDeferredDeeplinkReceiveListener(object : OnDeferredDeeplinkReceiveListener {
override fun shouldLaunchReceivedDeferredDeeplink(uri: Uri): Boolean {
// If you want to open the target activity, please return true otherwise false
// Default returning value = true
return true
}
})
.build()
Airbridge.init(this, config)
完成 Airbridge Android SDK 深度链接设置后,可以通过点击 URI Scheme 检查是否能正确跳转到相应的 App 页面。
YOUR_APP_URI_SCHEME://
深度链接设置正确无误时,您可在 Airbridge 面板的 [原始数据]>[App 实时记录] 查看深度链接打开(Deeplink Open)记录。
Airbridge 收集以下用户标识符信息,以监测跨 Web 和 App 的用户贡献:
User Email : 用户邮箱
User Phone : 用户电话号码
User ID : 用户唯一 ID (可识别用户并且在 Web 端和 App 端一致的 ID)
User Alias : 可以代表用户的其他 ID (例:忠诚计划专用 ID、集团子公司统一 ID)
用户邮箱和电话号码将自动进行 SHA256 哈希处理后发送到服务器。
您可通过以下方法在 Airbridge Android SDK 设置用户标识符信息:
// Automatically hashed on client side using SHA256
// Can turn off hashing feature with special flag
Airbridge.getCurrentUser().setEmail("testID@ab180.co");
Airbridge.getCurrentUser().setPhone("821012341234");
// Does not hash
Airbridge.getCurrentUser().setId("testID");
Airbridge.getCurrentUser().setAlias("key", "value");
// Clear user data
Airbridge.expireUser()
// Automatically hashed on client side using SHA256
// Can turn off hashing feature with special flag
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
// Does not hash
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("key", "value")
// Clear user data
Airbridge.expireUser()
User Alias 最多可设置 10 个。
User Alias 的 key 是 string 类型,最多为 128 个字符。
User Alias 的 key 必须符合正则表达式 ^[a-zA-Z_][a-zA-Z0-9_]*$
User Alias 的 value 是 string 类型,最多为 128 个字符。
设置用户标识符信息后,所有事件将包含标识符信息进行发送。
您可以为提高 MTA(Multi-touch attribution, 多触点归因)分析的准确性、内部数据分析以及与第三方解决方案的集成等目的设置附加用户属性。
Airbridge.getCurrentUser().setAttribute("key", "value");
Airbridge.getCurrentUser().setAttribute("key", "value")
User Attribute 最多可设置 100 个。
User Attribute 的 key 是 string 类型,最多为 128 个字符。
User Attribute 的 key 必须符合正则表达式 ^[a-zA-Z_][a-zA-Z0-9_]*$
User Attribute 的 value 类型可以为 integer、float、long、boolean 或 string,且如果是 string,则最多为 1024 个字符。
Airbridge Android SDK 中设置的用户信息可在 Airbridge 面板的 [原始数据]>[App 实时记录] 查看。
您可在 Airbridge Android SDK 中设置设备标识符,使以后收集的所有事件包含设备标识符。设置后,无论 App 是否关闭,设备标识符将保留,除非手动删除。
Airbridge.setDeviceAlias("ADD_YOUR_KEY", "AND_YOUR_VALUE")
Airbridge.removeDeviceAlias("DELETE_THIS_KEY")
Airbridge.clearDeviceAlias()
Airbridge.setDeviceAlias("ADD_YOUR_KEY", "AND_YOUR_VALUE");
Airbridge.removeDeviceAlias("DELETE_THIS_KEY");
Airbridge.clearDeviceAlias();
方法 | 说明 |
---|---|
setDeviceAlias(key: String, value: String) | 将键值对添加到设备标识符中。 |
removeDeviceAlias(key: String) | 删除相应于 key 的设备标识符。如果没有相应的设备标识符,则不执行任何操作。 |
clearDeviceAlias() | 删除所有设备标识符。 |
Airbridge Android SDK 调用的所有事件都可以包含以下 6 个属性进行发送:
Event Category:事件名称 (string) 必填
Event Action:事件属性 1 (string)
Event Label:事件属性 2 (string)
Event Value:事件属性 3 (number)
Event Semantic Attributes:标准事件属性 (map<string, object>)
Event Custom Attributes:自定义事件属性 (map<string, object>)
您可使用 Airbridge Android SDK 发送标准事件(Standard Event),如下所示:
Number eventValue = 10;
Map<String, Object> eventAttributes = new HashMap<String, Object>();
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.put(SemanticAttributes.KEY_CURRENCY, "USD");
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW, "event_action", "event_label", eventValue, eventAttributes, semanticAttributes);
val eventValue = 10
val eventAttributes = mutableMapOf<String, String>()
val semanticAttributes = mutableMapOf<String, String>()
semanticAttributes[SemanticAttributes.KEY_CURRENCY] = "USD"
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW, "event_action", "event_label", eventValue, eventAttributes, semanticAttributes)
如果存在标准事件未涵盖的特定需求,您可发送自定义事件(Custom Event),如下所示:
Number eventValue = 10;
Map<String, String> eventAttributes = new HashMap<String, String>();
Map<String, String> semanticAttributes = new HashMap<String, String>();
semanticAttributes.put(SemanticAttributes.KEY_CURRENCY, "USD");
Airbridge.trackEvent("event_category", "event_action", "event_label", eventValue, eventAttributes, semanticAttributes);
val eventValue = 10
val eventAttributes = mutableMapOf<String, String>()
val semanticAttributes = mutableMapOf<String, String>()
semanticAttributes[SemanticAttributes.KEY_CURRENCY] = "USD"
Airbridge.trackEvent("event_category", "event_action", "event_label", eventValue, eventAttributes, semanticAttributes)
有关 Semantic Attributes 的更多信息,请参阅 本指南。
您还可以按照以下方法预定义类,并根据 App 的需求继承它们:
class MyAppEvent extends Event {
public MyAppEvent() {
super("my_custom_category");
}
}
...
Airbridge.trackEvent(new MyAppEvent());
...
class MyAppEvent : Event("my_custom_category")
...
Airbridge.trackEvent(MyAppEvent())
...
Airbridge.getCurrentUser().setEmail("me@sample.com");
Airbridge.getCurrentUser().setPhone("821012341234");
Airbridge.getCurrentUser().setId("12345");
Airbridge.getCurrentUser().setAlias("alias1", "value");
Airbridge.getCurrentUser().setAttributes("attr1", 1234);
Airbridge.trackEvent(StandardEventCategory.SIGN_UP);
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("alias1", "value")
Airbridge.getCurrentUser().setAttribute("attr1", 1234)
Airbridge.trackEvent(StandardEventCategory.SIGN_UP)
Airbridge.getCurrentUser().setEmail("me@sample.com");
Airbridge.getCurrentUser().setPhone("821012341234");
Airbridge.getCurrentUser().setId("12345");
Airbridge.getCurrentUser().setAlias("alias1", "value");
Airbridge.getCurrentUser().setAttributes("attr1", 1234);
Airbridge.trackEvent(StandardEventCategory.SIGN_IN);
Airbridge.getCurrentUser().email = "testID@ab180.co"
Airbridge.getCurrentUser().phone = "821012341234"
Airbridge.getCurrentUser().id = "testID"
Airbridge.getCurrentUser().setAlias("alias1", "value")
Airbridge.getCurrentUser().setAttribute("attr1", 1234)
Airbridge.trackEvent(StandardEventCategory.SIGN_IN)
Airbridge.trackEvent(StandardEventCategory.SIGN_OUT);
Airbridge.expireUser();
Airbridge.trackEvent(StandardEventCategory.SIGN_OUT)
Airbridge.expireUser()
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW);
Airbridge.trackEvent(StandardEventCategory.HOME_VIEW)
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setQuery("Coca Cola");
Airbridge.trackEvent(StandardEventCategory.SEARCH_RESULT_VIEW, null, null, null, null, semanticAttributes);
val semanticAttributes = SemanticAttributes()
semanticAttributes.query = "Coca Cola"
Airbridge.trackEvent(StandardEventCategory.SEARCH_RESULT_VIEW, null, null, null, null, semanticAttributes)
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProductListId("beverage_1");
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
Airbridge.trackEvent(StandardEventCategory.PRODUCT_LIST_VIEW, null, null, null, null, semanticAttributes);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val semanticAttributes = SemanticAttributes()
semanticAttributes.productListId = "beverage_1"
semanticAttributes.products = listOf(fanta, cocacola)
Airbridge.trackEvent(StandardEventCategory.PRODUCT_LIST_VIEW, null, null, null, null, semanticAttributes)
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
Airbridge.trackEvent(StandardEventCategory.PRODUCT_DETAILS_VIEW, null, null, null, null, semanticAttributes);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val semanticAttributes = SemanticAttributes()
semanticAttributes.products = listOf(fanta, cocacola)
Airbridge.trackEvent(StandardEventCategory.PRODUCT_DETAILS_VIEW, null, null, null, null, semanticAttributes)
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setCartId("cart_123");
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
semanticAttributes.setCurrency("usd");
Event event = new Event(StandardEventCategory.ADD_TO_CART);
event.setValue(4.98);
event.setSemanticAttributes(semanticAttributes);
Airbridge.trackEvent(event);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val event = Event(StandardEventCategory.ADD_TO_CART).apply {
value = 4.98
semanticAttributes = SemanticAttributes().apply {
cartId = "cart_123"
products = listOf(fanta, cocacola)
currency = "usd"
}
}
Airbridge.trackEvent(event)
Product fanta = new Product();
fanta.setId("fanta_orange");
fanta.setName("FANTA Orange");
fanta.setQuantity(1);
fanta.setCurrency("usd");
fanta.setPrice(1.99);
fanta.setPosition(0);
Product cocacola = new Product();
cocacola.setId("cocacola_low_sugar");
cocacola.setName("Cocacola Low Sugar");
cocacola.setQuantity(1);
cocacola.setCurrency("usd");
cocacola.setPrice(2.99);
cocacola.setPosition(1);
SemanticAttributes semanticAttributes = new SemanticAttributes();
semanticAttributes.setProducts(Arrays.asList(fanta, cocacola));
semanticAttributes.setCurrency("usd");
semanticAttributes.setInAppPurchased(true);
Event event = new Event(StandardEventCategory.ORDER_COMPLETED);
event.setValue(4.98);
event.setSemanticAttributes(semanticAttributes);
Airbridge.trackEvent(event);
val fanta = Product()
fanta.id = "fanta_orange"
fanta.name = "FANTA Orange"
fanta.quantity = 1
fanta.currency = "usd"
fanta.price = 1.99
fanta.position = 0
val cocacola = Product()
cocacola.id = "cocacola_low_sugar"
cocacola.name = "Cocacola Low Sugar"
cocacola.quantity = 1
cocacola.currency = "usd"
cocacola.price = 2.99
cocacola.position = 1
val event = Event(StandardEventCategory.ORDER_COMPLETED).apply {
value = 4.98
semanticAttributes = SemanticAttributes().apply {
products = listOf(fanta, cocacola)
currency = "usd"
inAppPurchased = true
}
}
Airbridge.trackEvent(event)
Airbridge Android SDK 发送的事件可在 Airbridge 面板的 [原始数据]>[App 实时记录] 查看。
如果由于隐私法等原因无法收集广告 ID(Advertising ID),您可以使用移除了广告 ID 收集功能的 Restricted SDK。Restricted SDK 从 2.22.2 版本开始支持。
请在 app/build.gradle
文件的 dependencies
块中添加以下代码:
dependencies {
...
implementation "io.airbridge:sdk-android-restricted:2.+"
...
}
库 | 链接 |
---|---|
Airbridge SDK restricted |
您可以通过设置 SDK 签名防止 SDK 伪造(SDK Spoofing)。请在 SDK 初始化代码之前调用 setSDKSignatureSecret
函数来更改设置。
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSDKSignatureSecret("YOUR_SDK_SIGNATURE_SECRET_ID", "YOUR_SDK_SIGNATURE_SECRET")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSDKSignatureSecret("YOUR_SDK_SIGNATURE_SECRET_ID", "YOUR_SDK_SIGNATURE_SECRET")
.build()
Airbridge.init(this, config)
为了设置 SDK 签名,需要 SDK 签名凭证。请参阅 本指南 获取 SDK 签名凭证。
如果出于内部数据分析等目的需要发送未经哈希处理的用户标识符信息,可以通过以下设置停止对 User Email 和 User Phone 信息的哈希处理:
注意
由于此选项将敏感个人信息提供给第三方,因此必须事先采取额外的内部安全措施。
// Default User Info Hash Enabled = true
val option = AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setHashUserInformationEnabled(false)
.build()
Airbridge.initializeSDK(this, option)
// Default User Info Hash Enabled = true
AirbridgeOption option = new AirbridgeOptionBuilder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setHashUserInformationEnabled(false)
.build();
Airbridge.initializeSDK(this, option);
您可以通过以下设置,以在设定的会话期间内,即使用户重新启用 App,也可判断为同一个会话,而不重新发送 App 启用事件:
// Default Session Timeout = 5 minutes
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSessionTimeoutSeconds(300)
.build();
Airbridge.init(this, config);
// Default Session Timeout = 5 minutes
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSessionTimeoutSeconds(15)
.build()
Airbridge.init(this, config)
此功能在根据隐私法(例:GDPR、CCPA)收集和传输数据时需要征得用户同意的情况下非常有用。
您可通过以下设置明确地开始收集和传输数据:
// Default Auto Start Tracking Enabled = true
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(false)
.build();
Airbridge.init(this, config);
...
// Set a variable like below
if (properties.isGDPRAccepted) {
Airbridge.startTracking();
}
// Default Auto Start Tracking Enabled = true
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAutoStartTrackingEnabled(false)
.build()
Airbridge.init(this, config)
...
// Set a variable like below
if (properties.isGDPRAccepted) {
Airbridge.startTracking()
}
如果由于 App 内的多个深度链接操作,导致难以通过 Airbridge 一目了然地查看再互动(Re-engagement)绩效,您可以通过以下设置过滤并仅查看由 Airbridge 深度链接产生的绩效。
开启此功能后,仅当通过符合以下条件的深度链接打开 App 时,才会监测深度链接绩效。
通过 Airbridge 面板中注册的深度链接打开 App 时
通过 airbridge.io
深度链接打开 App 时
通过 deeplink.page
深度链接打开 App 时
通过 abr.ge
深度链接打开 App 时
当 airbridge_referrer
query 信息存在时
// Default Airbridge Link Only = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackAirbridgeLinkOnly(true)
.build();
Airbridge.init(this, config);
// Default Airbridge Link Only = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackAirbridgeLinkOnly(true)
.build()
Airbridge.init(this, config)
您可以通过 Airbridge Android SDK 收取 Facebook 的 Deferred App Link。
另请参阅:应用事件入门指南(Android 版)
另请参阅:为应用广告添加深度链接
请在 project/build.gradle
文件中添加 repository
:
allprojects {
...
repositories {
...
mavenCentral()
...
}
...
}
请在 app/build.gradle
文件的 dependencies
块中添加以下代码:
dependencies {
...
implementation 'com.facebook.android:facebook-android-sdk:latest.release'
...
}
请在 app/res/values/string.xml
文件中添加以下 string:
...
<string name="facebook_app_id">FACEBOOK_APP_ID</string>
<string name="facebook_client_token">FACEBOOK_CLIENT_TOKEN</string>
...
请在 AndroidManifest.xml
文件的 <application>
元素中添加以下 <meta-data>
:
...
<application android:label="@string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
...
</application>
...
请将此选项设置为 true
:
// Default Facebook Deferred App Link Enabled = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setFacebookDeferredAppLinkEnabled(true)
.build();
Airbridge.init(this, config);
// Default Facebook Deferred App Link Enabled = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setFacebookDeferredAppLinkEnabled(true)
.build()
Airbridge.init(this, config)
使用 Firebase Messaging 的 App 卸载追踪设置在 Airbridge Android SDK 2.6.0 及以上版本可用。
有关 App 卸载追踪设置的更多信息,请参阅 本指南。
您可以通过以下设置收集用户的位置信息:
注意
位置信息必须以合法目的和方式收集,使用此功能请谨慎。
// Choose one
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
// Default Location Collection Enabled = false
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLocationCollectionEnabled(true)
.build();
Airbridge.init(this, config);
// Default Location Collection Enabled = false
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLocationCollectionEnabled(true)
.build()
Airbridge.init(this, config)
注意
Airbridge Android SDK 收集
LastKnownLocation
信息。如果未获取 GPS 信息,即使有适当的权限和设置也可能不存在任何值。
如果希望监测各应用商店(例:Google Play Store、One Store、Huawei Store)的 App 安装数量,可以通过以下方法为发布在各应用商店的 App 设置标识符,以便在 Airbridge 面板中查看各应用商店的 App 安装数量:
请在 android:value
输入应用商店的名称(例:playStore
、oneStore
、huaweiStore
)。
...
<application android:label="@string/app_name" ...>
...
<meta-data android:name="co.ab180.airbridge.app_market_identifier" android:value="playStore"/>
...
</application>
...
请在 setAppMarketIdentifier
输入应用商店的名称 (例:playStore
、oneStore
、huaweiStore
)。
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAppMarketIdentifier("playStore")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setAppMarketIdentifier("playStore") // oneStore, huaweiStore ...
.build()
Airbridge.init(this, config)
您可以在基础报告选择 App Market Identifier 分组,或在导出 App 原始数据时选择 App Market Identifier 属性,以查看各应用商店的 App 安装数量。
为了提高质量,当 SDK 内部运行发生意外错误时,Airbridge Android SDK 将向 Airbridge 服务器发送相关信息。如果您不希望发送此信息,可以通过以下设置阻止发送。
// Default Error Log Collection Enabled = true
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setErrorLogCollectionEnabled(false)
.build();
Airbridge.init(this, config);
// Default Error Log Collection Enabled = true
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setErrorLogCollectionEnabled(false)
.build()
Airbridge.init(this, config)
当事件传输失败时,Airbridge Android SDK 将存储该事件并稍后重试发送。您可以通过以下设置限制此类事件的存储空间。
int count = 10;
long bytes = 1000000L;
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventMaximumBufferCount(count)
.setEventMaximumBufferSize(bytes)
.build();
Airbridge.init(this, config);
val count = 1_000
val bytes = 1_000_000L
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventMaximumBufferCount(count)
.setEventMaximumBufferSize(bytes)
.build()
Airbridge.init(this, config)
由于元数据管理,事件缓冲区的大小略小于数据的实际大小。
您可以通过添加以下代码设置事件发送周期:
// Default Event Transmit Interval = 0 millisecond
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventTransmitInterval(3000)
.build();
Airbridge.init(this, config);
// Default Event Transmit Interval = 0 millisecond
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setEventTransmitInterval(3000)
.build()
Airbridge.init(this, config)
注意
在
setEventTransmitInterval
输入负值会导致IllegalArgumentException
运行时错误。
您可以通过以下设置收集在会话中发生的 ORGANIC_REOPEN
和 FOREGROUND
事件:
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackInSessionLifeCycleEventEnabled(true)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setTrackInSessionLifeCycleEventEnabled(true)
.build()
Airbridge.init(this, config)
您可以通过以下设置清空设备内部未发送至 Airbridge 服务器的未处理事件数据库。
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setResetEventBufferEnabled(true)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setResetEventBufferEnabled(true)
.build()
Airbridge.init(this, config)
注意
如果在 Airbridge Android SDK 2.18.0 及以上版本的 App 中使用追踪链接,将记录 “深度链接页面浏览(Deeplink Pageview)” 目标事件(Target Event)。如果深度链接页面浏览频繁随后深度链接打开(Deeplink Open)发生,可能会影响深度链接打开的绩效。
深度链接页面浏览的的默认归因窗口为 3 天。如果希望更改此归因窗口,请联系您的 CSM。
您可以通过以下设置使用户在 App 中跳转到同一 App 的另一个页面,无需通过外部浏览器。请注意,使用您自定义的链接短 ID 的追踪链接无法在 App 中使用。
Airbridge.click("https://abr.ge/~~~")
Airbridge.impression("https://abr.ge/~~~")
追踪链接被点击时调用,然后将点击计入点击统计,并将用户跳转到预先设置的 App 或 Web 目的地,或后备目的地。
追踪链接被展示在用户界面(UI)时调用,然后将展示计入展示统计。
MIR 收集设置在 Airbridge Android SDK 2.22.3 及以上版本可用。请添加以下代码设置 MIR 收集。
完成设置后,需要在 Airbridge 面板输入 Install Referrer Decryption Key,以查看解密后的 MIR。有关输入 Install Referrer Decryption Key 的方法,请参阅 本指南。
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setMetaInstallReferrer("YOUR_FACEBOOK_APP_ID")
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setMetaInstallReferrer("YOUR_FACEBOOK_APP_ID")
.build()
Airbridge.init(this, config)
为遵守《数字市场法案》(Digital Markets Act, 简称 DMA),用户的同意信息(User Consent)必须共享给 Airbridge。请注意,所有欧洲经济区(European Economic Area,简称 EEA)用户的同意信息应始终共享给 Airbridge。有关 DMA 的更多信息,请参阅 本指南。
1. 请检查启用 App 的用户所在地。如果用户在 EEA(eea=1
)启用了 App,则检查是否已取得该用户的同意。如果已取得,请继续步骤 3。
提示
Airbridge 无法提供有关存储用户同意信息或实现同意弹窗的指导。请咨询法律顾问。
2. 如果尚未取得用户的同意,请通过同意弹窗等方法取得用户的同意。必须收集 adPersonalization
和 adUserData
。
注意
从 2024-03-06 起,必须对 EEA 的现有用户和新用户至少取得一次同意。
必须共享给 Airbridge 的用户同意信息如下。eea
值不是用户的直接响应,也不是 Airbridge 自动收集的信息。请根据用户所在地确定 eea
值并将其共享给 Airbridge。
Airbridge 字段 |
Google 字段 |
说明 |
---|---|---|
<string> |
| 表示用户是否在 EEA,或 DMA 适用地区。该值不是用户的直接响应,也不是 Airbridge 自动收集的信息。请根据用户所在地确定 不处理除 - - |
<string> |
| 对于收集信息以提供个性化广告(Personalized Ads) 的用户同意情况。不处理除 - - |
<string> |
| 对于向 Google 发送用于广告目的用户数据的同意情况。不处理除 - - |
3. 请初始化 Airbridge Android SDK,并在收集用户信息之前将用户同意信息共享给 Airbridge。
注意
必须为
eea
、adPersonalization
和adUserData
使用相同的名称。请根据同意情况正确输入
0
或1
。
// MainApplication.kt
override fun onCreate() {
super.onCreate()
// Initialize Airbridge SDK
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
// Make Airbridge SDK explicitly start tracking
.setAutoStartTrackingEnabled(false)
.build()
Airbridge.init(this, config)
// Set device alias into Airbridge SDK
// Based on actual region
Airbridge.setDeviceAlias("eea", "0" or "1")
// Based on actual user consent
Airbridge.setDeviceAlias("adPersonalization", "0" or "1")
Airbridge.setDeviceAlias("adUserData", "0" or "1")
// Explicitly start tracking
Airbridge.startTracking()
// MainApplication.java
@Override
public void onCreate() {
super.onCreate();
// Initialize Airbridge SDK
AirbridgeConfig config = new AirbridgeConfig.Builder("APP_NAME", "APP_TOKEN")
// Make Airbridge SDK explicitly start tracking
.setAutoStartTrackingEnabled(false)
.build();
Airbridge.init(this, config);
// Set device alias into Airbridge SDK
// Based on actual region
Airbridge.setDeviceAlias("eea", "0" or "1");
// Based on actual user consent
Airbridge.setDeviceAlias("adPersonalization", "0" or "1");
Airbridge.setDeviceAlias("adUserData", "0" or "1");
// Explicitly start tracking
Airbridge.startTracking();
}
您可以通过以下设置收取归因结果数据:
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnAttributionResultReceiveListener(new OnAttributionResultReceiveListener() {
@Override
public void onAttributionResultReceived(@NonNull Map<String, String> result) {
// Process attribution data
}
})
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setOnAttributionResultReceiveListener(object : OnAttributionResultReceiveListener {
override fun onAttributionResultReceived(result: Map<String, String>) {
// Process attribution data
}
})
.build()
Airbridge.init(this, config)
可以收取的数据如下:
字段 | 说明 |
---|---|
attributedChannel | 渠道 (string) |
attributedCampaign | 广告系列 (string) |
attributedAdGroup | 广告组 (string) |
attributedAdCreative | 广告素材 (string) |
attributedContent | 内容 (string) |
attributedTerm | 关键词 (string) |
attributedSubPublisher | 子渠道 (string) |
attributedSubSubPublisher1 | 二级子渠道 1 (string) |
attributedSubSubPublisher2 | 二级子渠道 2 (string) |
attributedSubSubPublisher3 | 二级子渠道 3 (string) |
如果归因结果为无归因(Unattributed),您将收取:
{
"attributedChannel": "unattributed"
}
归因结果数据使用指南
有归因时:
在 SDK 初始化后的 40 秒内传递数据。
如果由于 App 关闭而未传递数据,则在下次 App 启用时,将在 SDK 初始化后的 40 秒内传递数据。
在极少数情况下,传递数据可能需要最多 5 分钟。
无归因(Unattributed)时:
在 SDK 初始化至少 3 小时后 App 重新启用时,传递数据。
不建议在需要实时处理的情况下使用归因结果回调传递的数据。
您可以通过以下设置停用 Airbridge 的所有功能:
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSdkEnabled(false)
.build();
Airbridge.init(this, config);
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setSdkEnabled(false)
.build()
Airbridge.init(this, config)
注意
如果同时设置了“未处理事件删除设置” 和 “Airbridge 停用设置”,后者将优先,导致前者不运行。
App 生命周期事件(例:安装、打开、深度链接打开)只需在您的 Hybrid App 安装 Airbridge Android SDK 即可自动追踪,但应用内事件(例:注册、订单完成)由于实际上是在 WebView 环境的网站内发生的浏览器事件,而无法自动追踪。Airbridge 通过让 Android SDK 从 WebView 环境的网站上安装的 Web SDK 获取事件,从而支持应用内事件追踪。借助此功能,您无需单独创建原生和 WebView 环境之间的桥接功能。
注意
为了使用此功能,必须完成 2 个 SDK 安装:移动原生环境中的 Airbridge Android SDK 和 WebView 环境网站上的 Airbridge Web SDK。
请在目标 WebView 上调用 Airbridge::setJavascriptInterface
函数,如下所示:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWebView();
}
void initWebView() {
webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
Airbridge.setJavascriptInterface(webView, "YOUR_WEB_SDK_TOKEN");
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://dev.blog.airbridge.io/websdk-web-app/");
}
}
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initWebView()
}
fun initWebView() {
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
Airbridge.setJavascriptInterface(webView, "YOUR_WEB_TOKEN")
webView.webChromeClient = WebChromeClient()
webView.webViewClient = WebViewClient()
webView.loadUrl("http://my_company.com/main")
}
}
YOUR_WEB_SDK_TOKEN
可在 Airbridge 面板的 [设置]>[Token] 获取。
完成设置后,请按照 本指南 在您的网站上初始化 Airbridge Web SDK。
请打开 AndroidManifest.xml
文件。
请添加 com.google.android.gms.permission.AD_ID
权限,如下所示:
<manifest ...>
...
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
...
</manifest>
有关更多信息,请参阅 Google 指南。
通过 Braze SDK 发送的推送通知打开深度链接时,可能发生无法收集 “Deeplink open(深度链接打开)”,然而收集 “Open(打开)” 的问题。原因如下:
Airbridge SDK 通过 Activity
的 action
和 intent
的 dataString
值判断深度链接打开和打开。然而,通过 Braze SDK 发送的推送通知打开深度链接时,App 会通过 Braze SDK 中定义的 NotificationTrampolineActivity
打开,但 Airbridge SDK 在该 Activity
的 action
和 intent
无法获取 dataString
值,导致无法判断事件。
该问题可以通过 Airbridge Android SDK 版本 2.21.5 中新增的以下 interface
解决:
AirbridgeConfig config = new AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLifecycleIntegration(new AirbridgeLifecycleIntegration() {
@Nullable
@Override
public String getDataString(@NotNull Activity activity) {
if (activity.getClass().getName().equals("com.braze.push.NotificationTrampolineActivity")
&& activity.getIntent() != null
&& activity.getIntent().getExtras() != null) {
return activity.getIntent().getExtras().getString("uri");
}
return null;
}
})
.build();
Airbridge.init(this, config)
val config = AirbridgeConfig.Builder("YOUR_APP_NAME", "YOUR_APP_SDK_TOKEN")
.setLifecycleIntegration {
it.takeIf { it.javaClass.name == "com.braze.push.NotificationTrampolineActivity" }
?.run { intent?.extras?.getString("uri") }
}
.build()
Airbridge.init(this, config)
deeplink.page
已在 Airbridge Android SDK 版本 2.21.1 中被弃用,但为了保持向后兼容性仍受支持并可正常运行。
如果使用 Airbridge Android SDK 版本 2.21.0 及以下版本,请按照以下步骤设置 Intent Filter
:
请打开 AndroidManifest.xml
文件。
请在处理深度链接的 Activity
中添加 Intent Filter
,如下所示:
<activity ...>
...
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="YOUR_APP_NAME.deeplink.page" />
<data android:scheme="https" android:host="YOUR_APP_NAME.deeplink.page" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="YOUR_APP_NAME.airbridge.io" />
<data android:scheme="https" android:host="YOUR_APP_NAME.airbridge.io" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="YOUR_APP_URI_SCHEME" />
</intent-filter>
</activity>
java.lang.NoClassDefFoundError: kotlin/coroutines/AbstractCoroutineContextKey
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
...
根据 @qwwdfsad,kotlinx-coroutines-core
库 1.3.5 及以上版本强制使用 kotlin-stdlib
库 1.3.70 及以上版本。
如果通过 gradlew dependencies
命令使用 kotlinx-coroutines-core
库 1.3.5 及以上版本,请确保使用 kotlin-stdlib
库 1.3.70 及以上版本。
如果 Android App 需要 Auto Backup,可能需要定义 Auto Backup 规则。如此情况下,由于 Airbridge Android SDK 为了防止自动复制内部数据在 AndroidManifest.xml
文件中定义单独的 airbridge_auto_backup_rules.xml
,可能会导致如 Manifest merger failed : Attribute application@fullBackupContent value=(true)
的冲突。
冲突发生时需要设置 tools:replace="android:fullBackupContent"
并对相应的自定义 Auto Backup 规则文件进行额外的合并操作。
Airbridge Android SDK 定义的 Auto Backup 规则如下:
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="airbridge-internal" />
<exclude domain="sharedpref" path="airbridge-install" />
<exclude domain="sharedpref" path="airbridge-user-info" />
<exclude domain="sharedpref" path="airbridge-user-alias" />
<exclude domain="sharedpref" path="airbridge-user-attributes" />
<exclude domain="database" path="airbridge.db" />
</full-backup-content>
HashMap<String, Object> semanticAttributes = new HashMap();
semanticAttributes.put("products", Arrays.asList(
// double brace initialization issue
new HashMap<String, Object>() {{
put("name", "MacBook Pro");
put("price", 1548200);
put("position", 1);
put("brandID", 23);
put("brandName", "apple");
}},
new HashMap<String, Object>() {{
put("name", "MacBook Air");
put("price", 1500000);
put("position", 2);
put("brandID", 23);
put("brandName", "apple");
}}
)
);
HashMap<String, Object> customAttributes = new HashMap();
customAttributes.put("customKey", "customValue");
Airbridge.trackEvent(
"purchase",
"action",
"label",
3048200,
customAttributes,
semanticAttributes
);
由于 Google 的 GSON 库中存在 双括号初始化的已知问题,如果使用双括号初始化创建 Product Object(如上所示),可能会导致 Product 数据丢失。建议您自行创建并使用自己的 Product Object,如 订单完成(Order Complete)的示例代码。
更新 SDK 时,请考虑以下内容:
对于 2023-09-04 或以后创建的 Airbridge App,2.22.0~2.23.0 版本中存在的深度链接回调提供的深度链接 URL 被解码 2 次的问题得到解决。
添加了在 App 转入后台时停止事件发送的初始化选项。
您可以通过设置 AirbridgeConfig#setTransmitEventOnBackgroundEnabled
函数,在 App 转入后台时停止事件发送。
默认值为 true
,意味即使 App 在后台运行时,也会发送未发送的事件。
deeplink.page
已被弃用。从 2.21.1 版本开始,请使用 abr.ge
作为深度链接域名进行代码编写。
为了保持向后兼容性,deeplink.page
仍然受支持并可正常运行。
更改为默认不收集在会话中发生的 ORGANIC_REOPEN
和 FOREGROUND
事件。
如果在低于 2.19.1 的版本收集 ORGANIC_REOPEN
和 FOREGROUND
事件,可以通过设置 AirbridgeConfig#setTrackInSessionLifeCycleEventEnabled
继续收集这些事件。
默认值为 false
,意味不收集 ORGANIC_REOPEN
和 FOREGROUND
事件。
删除了 BACKGROUND
事件。
更改为只有在调用 Airbridge.click
时收集深度链接事件。
Was this page helpful?