• Android 系统中适配OAID获取


    一、OAID概念

    OAID(Open Anonymous Identification)是一种匿名身份识别标识符,
    用于在移动设备上进行广告追踪和个性化广告投放。它是由中国移动通信集
    团、中国电信集团和中国联通集团共同推出的一项行业标准
    OAID值为一个64位的数字

    二、OAID产生的背景

    在Android10以上,安卓是禁止我们获取IMEI的,那如果想要唯一标识一部手机,那我们可以使用OAID。
    因传统的移动终端设备标识如国际移动设备识别码(IMEI)等已被部分国家认定为用户隐私的一部分,并存在被篡改和冒用的风险,所以在Android 10及后续版本中非厂商系统应用将无法获取IMEI、MAC等设备信息。无法获取IMEI会在用户行为统计过程中对设备识别产生一定影响。
    近日移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案,选择OAID字段作为IMEI等的替代字段。OAID字段是由中国信通院联合华为、小米、OPPO、VIVO等厂商共同推出的设备识别字段,具有一定的权威性,可满足用户行为统计的使用场景。

    三、由于OAID 引发的问题

    环境:高通865 Android10 虚拟化

    1、问题现象

    第三方游戏应用集成了移动联盟sdk获取oaid,但是系统并没有适配oaid,导致第三方应用集成移动联盟sdk获取oaid时获取为空导致应用闪退。

    2、解决思路

    (1)、编写一个apk,集成到系统,开机自启,应用中定义了一个服务和重写了相对应的获取oaid的接口
    (2)、定义一个oaid属性值,persist.oaid用来设置和获取oaid值
    (3)、第三方应用调用移动联盟sdk获取oaid时,调用步骤1中重写的获取oaid接口,该接口通过属性值persist.oaid读取oaid的值,返回给第三方应用,这样就可以避免获取到oaid值为空情况。

    3、处理步骤

    3.1 编写apk,这里以适配OPPO厂商为例,每种厂商有可能重写的接口和方式不一样,这里需要注意。oppo厂商的代码如下,具体的可以下载源码查看。

    BootCompletedReceiver.java代码如下:
    1. package com.heytap.openid;
    2. import android.app.ActivityManager;
    3. import android.content.BroadcastReceiver;
    4. import android.content.Context;
    5. import android.content.Intent;
    6. import android.text.TextUtils;
    7. import android.util.Log;
    8. import java.util.List;
    9. public class BootCompletedReceiver extends BroadcastReceiver {
    10. // private final String ACTION_BOOT_COMPLETED = "com.matrixlauncher.oncreate"; //开机Launcher广播
    11. private final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; //系统开机广播
    12. @Override
    13. public void onReceive(Context context, Intent intent) {
    14. if (intent != null) {
    15. Log.d("CCCCC", "Oppo BootCompletedReceiveronReceive");
    16. if (!TextUtils.isEmpty(intent.getAction()) && intent.getAction().equals(ACTION_BOOT_COMPLETED)) {
    17. if (!isRun(context)) {
    18. Log.d("CCCCC", "Oppo BootCompletedReceiveronReceive start IdentifyService");
    19. context.startService(new Intent(context, IdentifyService.class));
    20. }
    21. }
    22. }
    23. }
    24. /**
    25. * 判断应用是否在运行
    26. *
    27. * @param context
    28. * @return
    29. */
    30. public boolean isRun(Context context) {
    31. ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    32. List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(100);
    33. boolean isAppRunning = false;
    34. String MY_PKG_NAME = "com.heytap.openid";
    35. //100表示取的最大的任务数,info.topActivity表示当前正在运行的Activity,info.baseActivity表系统后台有此进程在运行
    36. for (ActivityManager.RunningTaskInfo info : list) {
    37. if (info.topActivity.getPackageName().equals(MY_PKG_NAME) || info.baseActivity.getPackageName().equals(MY_PKG_NAME)) {
    38. isAppRunning = true;
    39. break;
    40. }
    41. }
    42. return isAppRunning;
    43. }
    44. }
    IdentifyService.java代码如下:
    1. package com.heytap.openid;
    2. import android.app.Service;
    3. import android.content.Intent;
    4. import android.os.IBinder;
    5. import android.os.RemoteException;
    6. import android.util.Log;
    7. import androidx.annotation.Nullable;
    8. public class IdentifyService extends Service {
    9. @Override
    10. public void onCreate() {
    11. super.onCreate();
    12. Log.d("CCCCC", "Oppo IdentifyService onCreate()");
    13. }
    14. @Nullable
    15. @Override
    16. public IBinder onBind(Intent intent) {
    17. return binder;
    18. }
    19. private final IOpenID.Stub binder = new IOpenID.Stub() {
    20. @Override
    21. public String getSerID(String pkgName, String sign, String type) throws RemoteException {
    22. Log.d("CCCCC", "Oppo OpenDeviceIdentifierService.Stub getOaid=" + SysProp.get("persist.oaid", ""));
    23. return SysProp.get("persist.oaid", "");
    24. }
    25. };
    26. }

    IOpenID.aidl代码如下:

    1. // IOpenID.aidl
    2. package com.heytap.openid;
    3. // Declare any non-default types here with import statements
    4. interface IOpenID {
    5. String getSerID(String pkgName, String sign, String type);
    6. }

    AndroidManifest.xml代码如下:

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3. package="com.heytap.openid"
    4. android:sharedUserId="android.uid.system">
    5. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    6. <application
    7. android:allowBackup="true"
    8. android:icon="@mipmap/ic_launcher"
    9. android:label="@string/app_name"
    10. android:roundIcon="@mipmap/ic_launcher_round"
    11. android:supportsRtl="true"
    12. android:theme="@style/AppTheme">
    13. <!-- 开机广播 -->
    14. <receiver
    15. android:name=".BootCompletedReceiver"
    16. android:enabled="true"
    17. android:exported="true">
    18. <intent-filter>
    19. <action android:name="com.matrixlauncher.oncreate" />
    20. <action android:name="android.intent.action.BOOT_COMPLETED" />
    21. </intent-filter>
    22. </receiver>
    23. <service android:name=".IdentifyService"
    24. android:enabled="true"
    25. android:exported="true">
    26. <intent-filter>
    27. <action android:name="action.com.heytap.openid.OPEN_ID_SERVICE" />
    28. <category android:name="android.intent.category.DEFAULT" />
    29. </intent-filter>
    30. </service>
    31. </application>
    32. </manifest>

    代码结构如下,注意:包名那些都是固定的:


    文章末尾会附上相关资料和适配华为、OPPO、三星、Vivo的应用服务源码

    3.2 将编译好的apk集成到系统(集成apk的文件和位置仅供参考,有可能不一样,示例集成 OppoAnonymousId.apk)

    3.2.1 Qualcomm865_vir/vendor/qcom/proprietary/prebuilt_HY11/target/product/qssi/prebuilt.mk中添加

    PRODUCT_PACKAGES += OppoAnonymousId

    3.2.2  Qualcomm865_vir/device/qcom/qssi/system.prop中新增属性

    1. #oaid
    2. persist.oaid=0

    3.2.3  Qualcomm865_vir/frameworks/base/core/java/android/app/ActivityThread.java中修改manufacturer值

    3.2.4 /home/wenyang/workplace/code/Qualcomm865_vir/vendor/qcom/proprietary/prebuilt_HY11/target/product/qssi/Android.mk中新增需要集成的apk

    1. include $(CLEAR_VARS)
    2. LOCAL_MODULE := OppoAnonymousId
    3. LOCAL_MODULE_OWNER := qcom
    4. LOCAL_MODULE_TAGS := optional
    5. LOCAL_MODULE_CLASS := APPS
    6. LOCAL_CERTIFICATE := platform
    7. LOCAL_MODULE_SUFFIX := .apk
    8. LOCAL_SRC_FILES := ../../.././target/product/qssi/system/app/OppoAnonymousId/OppoAnonymousId.apk
    9. LOCAL_MULTILIB := 64
    10. LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/app
    11. include $(BUILD_PREBUILT)

    3.2.5 device/qcom/qssi/apps_white_list.txt和 device/qcom/kona/apps_white_list.txt中添加OppoAnonymousId,如下图所示:

    3.3 修改设备厂商为OPPO(和3.2.3步骤重复,建议采用3.2.3改机的形式修改,如果采用改机形式修改 ro.product.manufacturer属性值,此步骤可忽略)
     ro.product.manufacturer=OPPO
    3.4 修改设备厂商后,安装测试oaid test_get_oaid.apk,看看是否支持获取oaid

    4、验证

    4.1查看应用是否存在
     pm list packages | grep com.heytap.openid

    如果服务正常启动,通过上面的命令,可以查到如下结果:

    或者通过如下命令查看进程是否存在:

    ps  -A |  grep  com.heytap.openid
    4.2查看是否有调用重写的接口

    第三方应用获取oaid时,是否有调用我们写的apk aidl中的接口,这里以oppo为例,查看日志会调用下面的接口:

    oaid适配应用源码和相关资料下载链接: https://download.csdn.net/download/banzhuantuqiang/88331871

  • 相关阅读:
    e2e测试框架之Cypress
    Android 插件化
    yolov8 strongSORT多目标跟踪工具箱BOXMOT
    全国各地演讲口才培训机构信息那么多需要如何选择?
    面向对象设计模式02.抽象工厂模式&责任链模式&观察者模式
    【Unity Build-In管线的SurfaceShader剖析_PBS光照函数】
    E. Matrix and Shifts(思维+遍历正对角线)
    SpringMVC:拦截器+文件上传下载, 拦截器
    一文解析-通过实例讲解 Linux 内存泄漏检测方法
    物联网实战--入门篇之(七)嵌入式-MQTT
  • 原文地址:https://blog.csdn.net/banzhuantuqiang/article/details/132832661