接入Appsflyer SDK主要目的是做一些渠道归因统计,也可以做一些事件上报之类的。
1. 仓库依赖
repositories {
mavenCentral()
}
2. 引用SDK
这里为什么引入installreferrer呢,主要是用于Android-GooglePlay安装来源追踪PlayInstallReferrer, 使用商店引荐来源网址可提高归因准确性。
dependencies {
implementation 'com.android.installreferrer:installreferrer:2.2'
implementation 'com.appsflyer:af-android-sdk:6.9.0'
}
3. 声明权限
2022 年初,谷歌宣布改变谷歌播放服务的行为并获取安卓广告 ID。根据公告,针对Android 13(API 33)及更高版本的应用程序必须在其文件中声明Google Play服务正常权限,才能访问设备的广告ID。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
4. receiver声明
<application>
<receiver
android:name="com.appsflyer.SingleInstallBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
</application>
5. 初始化SDK
这里只处理了Google投放和Facebook投放
installChannel可用于af归因的渠道值
<AF_DEV_KEY> af后台返回的Dev Key
<CUSTOMER_ID> 代表CUID 可看业务需要定义,比如手机号或者设备唯一id之类的
class AFApplication : Application() {
override fun onCreate() {
super.onCreate();
val appsFlyerConversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener {
override fun onConversionDataSuccess(conversionData: Map<String, Any>) {
val af_status = if (conversionData["af_status"] == null) "null" else conversionData["af_status"].toString()
// 判断是否是非自然安装
if (af_status == "Non-organic") {
if (conversionData["is_first_launch"] != null && conversionData["is_first_launch"].toString() == "true") {
val media_source = if (conversionData["media_source"] == null) "null" else conversionData["media_source"].toString()
var campaign = if (conversionData["campaign"] == null) "null" else conversionData["campaign"].toString()
if (TextUtils.isEmpty(campaign) || "None" == campaign) {
campaign = "null"
}
if ("googleadwords_int" == media_source) {
val af_channel = if (conversionData["af_channel"] == null) "null" else conversionData["af_channel"].toString()
val network = if (conversionData["network"] == null) "null" else conversionData["network"].toString()
// 正常来说该渠道值 一般会记录到后台使用,方便分析
val installChannel = String.format("%s#%s/%s/%s", media_source, campaign, af_channel, network)
}
else if ("Facebook Ads" == media_source || "restricted" == media_source) {
val adgroup = if (conversionData["adgroup"] == null) "null" else conversionData["adgroup"].toString()
val ad_id = if (conversionData["ad_id"] == null) "null" else conversionData["ad_id"].toString()
// 正常来说该渠道值 一般会记录到后台使用,方便分析
val installChannel = String.format("%s#%s/%s/%s", media_source, campaign, adgroup, ad_id)
} else {
// 正常来说该渠道值 一般会记录到后台使用,方便分析
val installChannel = String.format("%s#%s", media_source, campaign)
}
}
} else {
// 此时该渠道值为默认一个渠道值比如GooglePlay
val installChannel = "GooglePlay"
}
val android_id = if (conversionData["android_id"] == null) "null" else conversionData["android_id"].toString()
val advertising_id = if (conversionData["advertising_id"] == null) "null" else conversionData["advertising_id"].toString()
val install_time = if (conversionData["install_time"] == null) "null" else conversionData["install_time"].toString()
val is_first_launch = if (conversionData["is_first_launch"] == null) false else conversionData["is_first_launch"] as Boolean
}
override fun onConversionDataFail(errorMessage: String) {}
override fun onAppOpenAttribution(conversionData: Map<String, String>) {}
override fun onAttributionFailure(errorMessage: String) {}
}
AppsFlyerLib.getInstance().init("<AF_DEV_KEY>",appsFlyerConversionListener,this.applicationContext)
AppsFlyerLib.getInstance().waitForCustomerUserId(true)
AppsFlyerLib.getInstance().start(this)
AppsFlyerLib.getInstance().setCustomerIdAndLogSession("<CUSTOMER_ID>", this)
AppsFlyerLib.getInstance().setCollectAndroidID(true)
AppsFlyerLib.getInstance().setCollectIMEI(true)
AppsFlyerLib.getInstance().setCollectOaid(true)
AppsFlyerLib.getInstance().setDebugLog(BuildConfig.DEBUG)
}
}
6. 事件上报
EventName 代表事件的名称
eventValues 看业务需要传递相关的数据即可
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.PRICE, 1234.56);
eventValues.put(AFInAppEventParameterName.CONTENT_ID,"1234567");
AppsFlyerLib.getInstance().logEvent(getApplicationContext(), "<EventName>" , eventValues);
AppsFlyerLib.getInstance().logEvent(getApplicationContext(), "<EventName>", eventValue, new AppsFlyerRequestListener()
{
@Override public void onSuccess()
{
Log.d(LOG_TAG, "Event sent successfully");
}
@Override public void onError(int i, @NonNull String s)
{
Log.d(LOG_TAG, "Event failed to be sent:\n" + "Error code: " + i + "\n" + "Error description: " + s);
}
});
7. 混淆
-keep class com.appsflyer.** { *; }
-dontwarn com.appsflyer.**
-dontwarn com.android.installreferrer