全部产品
云市场

Android EMAS统一接入

更新时间:2019-08-30 18:00:26

1.介绍

为了方便EMAS各个产品的接入,我们提供了基于gradle的emas-services插件。

emas-services插件主要目的是为了便于Emas各sdk接入,目前主要涉及到的sdk产品为:httpdns,cps,hotfix,man,feedback。主要工作流程为读取控制台下发的json文件,解析sdk初始化必要的字段(appKey及appSecret等)并保存到工程xml中,各产品sdk默认初始化时自动读取对应字段;解析“services”字段,根据status( 1:表示enable,0表示disable )来动态添加产品的依赖。

2.使用方式

  • 2.1. 控制台下载 aliyun-emas-services.json文件,并将json文件放到应用根目录下(/app/),其内容如下:

    1. {
    2. "config": {
    3. "emas.appKey":"xxxxx",
    4. "emas.appSecret":"xxxxxx",
    5. "emas.packageName":"com.xxx.xxx.demo",
    6. "hotfix.idSecret":"xxxxx",
    7. "hotfix.rsaSecret":"xxxxx",
    8. "httpdns.accountId":"xxxxx",
    9. "httpdns.secretKey":"xxxxxxxxx"
    10. },
    11. "services": {
    12. /* 功能:HTTPDNS*/
    13. "httpdns_service": {
    14. "status": 1,
    15. "version":"1.1.7"
    16. },
    17. /* 功能:移动推送*/
    18. "cps_service": {
    19. "status": 1,
    20. "version":"3.1.3"
    21. },
    22. /* 功能:移动热修复*/
    23. "hotfix_service": {
    24. "status": 1,
    25. "version":"3.2.1"
    26. },
    27. /* 功能:移动数据分析*/
    28. "man_service": {
    29. "status": 1,
    30. "version":"1.2.3"
    31. },
    32. /* 功能:移动用户反馈*/
    33. "feedback_service": {
    34. "status": 1,
    35. "version":"3.1.6"
    36. }
    37. },
    38. "use_maven":true,
    39. "proguard_keeplist":"\n#httpdns\n-keep class com.taobao.** {*;}\n-keep class com.alibaba.** {*;}\n-keep class com.ta.**{*;}\n-keep class com.ut.**{*;}\n-dontwarn com.taobao.**\n-dontwarn com.alibaba.**\n-dontwarn com.ta.**\n-dontwarn com.ut.**\n\n#cps\n-keep class com.taobao.** {*;}\n-keep class com.alibaba.** {*;}\n-keep class com.ta.**{*;}\n-keep class com.ut.**{*;}\n-dontwarn com.taobao.**\n-dontwarn com.alibaba.**\n-dontwarn com.ta.**\n-dontwarn com.ut.**\n-keepclasseswithmembernames class ** {\nnative <methods>;\n}\n-keepattributes Signature\n-keep class sun.misc.Unsafe { *; }\n-keep class com.alipay.** {*;}\n-dontwarn com.alipay.**\n-keep class anet.**{*;}\n-keep class org.android.spdy.**{*;}\n-keep class org.android.agoo.**{*;}\n-dontwarn anet.**\n-dontwarn org.android.spdy.**\n-dontwarn org.android.agoo.**\n\n#hotfix\n#基线包使用,生成mapping.txt\n-printmapping mapping.txt\n#生成的mapping.txt在app/buidl/outputs/mapping/release路径下,移动到/app路径下\n#修复后的项目使用,保证混淆结果一致\n#-applymapping mapping.txt\n#hotfix\n-keep class com.taobao.sophix.**{*;}\n-keep class com.ta.utdid2.device.**{*;}\n#防止inline\n-dontoptimize\n\n#man\n-keep class com.taobao.** {*;}\n-keep class com.alibaba.** {*;}\n-keep class com.ta.**{*;}\n-keep class com.ut.**{*;}\n-dontwarn com.taobao.**\n-dontwarn com.alibaba.**\n-dontwarn com.ta.**\n-dontwarn com.ut.**\n\n#feedback\n-keep class com.taobao.** {*;}\n-keep class com.alibaba.** {*;}\n-keep class com.ta.**{*;}\n-keep class com.ut.**{*;}\n-dontwarn com.taobao.**\n-dontwarn com.alibaba.**\n-dontwarn com.ta.**\n-dontwarn com.ut.**\n"
    40. }
  • 2.2. 项目级目录下build.gradle(<project>/build.gradle):
  1. buildscript {
  2. repositories {
  3. maven {
  4. url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
  5. }
  6. }
  7. dependencies {
  8. // 添加emas-services插件
  9. classpath 'com.aliyun.ams:emas-services:1.0.1'
  10. }
  11. }
  12. allprojects {
  13. repositories {
  14. ...
  15. maven {
  16. url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
  17. }
  18. }
  19. }
  • 2.3. 应用级build.gradle(<project>/<app-module>/build.gradle):
    1. // 在 apply plugin: 'com.android.application' 下添加
    2. apply plugin: 'com.aliyun.ams.emas-services'
  • 2.4. 修改应用目录下json文件(<project>/<app-module>/ aliyun-emas-services.json),将不需要使用的产品service对应的status状态置为0( status=0表示对应不使用对应产品,status=1表示使用对应产品

    “use_maven”字段表示是否采用maven远程依赖的方式添加依赖,true表示使用远程依赖,false表示使用本地libs下aar及jar的方式进行依赖( use_maven=false时,您需要在控制台下载对应使用的产品sdk,并将对应jar&aar放置到应用工程libs目录下,且与json中service对应开关对应 )。

  • 2.5. 点击Android Studio工具栏中的 Sync Project。
  • 2.6. gradle build成功后,会在应用目录build文件夹下生成对应各个产品sdk的proguard-keep文件,如果您的app需要进行混淆,请您将产品生成的proguard-rules文件拷贝到您使用的.pro文件,目录:”/app/build/generated/source/emas-services/${variant.dirName}/ams_values/ams_proguard_rules.pro“。
  • 2.7. 对各sdk进行初始化操作,您可以参考以下代码进行初始化:
  1. public class AppApplication extends Application {
  2. private static final String TAG = "AppApplication";
  3. //hotfix init need attr
  4. public interface MsgDisplayListener {
  5. void handle(String msg);
  6. }
  7. public static MsgDisplayListener msgDisplayListener = null;
  8. public static StringBuilder cacheMsg = new StringBuilder();
  9. @Override
  10. public void onCreate() {
  11. super.onCreate();
  12. initManService();
  13. initFeedbackService();
  14. initHttpDnsService();
  15. initHotfix();
  16. initPushService(this);
  17. }
  18. private void initManService() {
  19. /**
  20. * 初始化Mobile Analytics服务
  21. */
  22. // 获取MAN服务
  23. MANService manService = MANServiceProvider.getService();
  24. // 打开调试日志
  25. manService.getMANAnalytics().turnOnDebug();
  26. manService.getMANAnalytics().setAppVersion("3.0");
  27. // MAN初始化方法之一,通过插件接入后直接在下发json中获取appKey和appSecret初始化
  28. manService.getMANAnalytics().init(this, getApplicationContext());
  29. // MAN另一初始化方法,手动指定appKey和appSecret
  30. // String appKey = "******";
  31. // String appSecret = "******";
  32. // manService.getMANAnalytics().init(this, getApplicationContext(), appKey, appSecret);
  33. // 若需要关闭 SDK 的自动异常捕获功能可进行如下操作,详见文档5.4
  34. //manService.getMANAnalytics().turnOffCrashReporter();
  35. // 通过此接口关闭页面自动打点功能,详见文档4.2
  36. manService.getMANAnalytics().turnOffAutoPageTrack();
  37. // 设置渠道(用以标记该app的分发渠道名称),如果不关心可以不设置即不调用该接口,渠道设置将影响控制台【渠道分析】栏目的报表展现。如果文档3.3章节更能满足您渠道配置的需求,就不要调用此方法,按照3.3进行配置即可
  38. manService.getMANAnalytics().setChannel("某渠道");
  39. // 若AndroidManifest.xml 中的 android:versionName 不能满足需求,可在此指定;
  40. // 若既没有设置AndroidManifest.xml 中的 android:versionName,也没有调用setAppVersion,appVersion则为null
  41. //manService.getMANAnalytics().setAppVersion("2.0");
  42. }
  43. private void initFeedbackService() {
  44. /**
  45. * 添加自定义的error handler
  46. */
  47. FeedbackAPI.addErrorCallback(new FeedbackErrorCallback() {
  48. @Override
  49. public void onError(Context context, String errorMessage, ErrorCode code) {
  50. Toast.makeText(context, "ErrMsg is: " + errorMessage, Toast.LENGTH_SHORT).show();
  51. }
  52. });
  53. FeedbackAPI.addLeaveCallback(new Callable() {
  54. @Override
  55. public Object call() throws Exception {
  56. Log.d("DemoApplication", "custom leave callback");
  57. return null;
  58. }
  59. });
  60. /**
  61. * 建议放在此处做初始化
  62. */
  63. //默认初始化
  64. FeedbackAPI.init(this);
  65. //FeedbackAPI.init(this, "DEFAULT_APPKEY", "DEFAULT_APPSECRET");
  66. /**
  67. * 在Activity的onCreate中执行的代码
  68. * 可以设置状态栏背景颜色和图标颜色,这里使用com.githang:status-bar-compat来实现
  69. */
  70. //FeedbackAPI.setActivityCallback(new IActivityCallback() {
  71. // @Override
  72. // public void onCreate(Activity activity) {
  73. // StatusBarCompat.setStatusBarColor(activity,getResources().getColor(R.color.aliwx_setting_bg_nor),true);
  74. // }
  75. //});
  76. /**
  77. * 自定义参数演示
  78. */
  79. JSONObject jsonObject = new JSONObject();
  80. try {
  81. jsonObject.put("loginTime", "登录时间");
  82. jsonObject.put("visitPath", "登陆,关于,反馈");
  83. } catch (JSONException e) {
  84. e.printStackTrace();
  85. }
  86. FeedbackAPI.setAppExtInfo(jsonObject);
  87. /**
  88. * 以下是设置UI
  89. */
  90. //设置默认联系方式
  91. FeedbackAPI.setDefaultUserContactInfo("13800000000");
  92. //沉浸式任务栏,控制台设置为true之后此方法才能生效
  93. FeedbackAPI.setTranslucent(true);
  94. //设置返回按钮图标
  95. //FeedbackAPI.setBackIcon(R.drawable.ali_feedback_common_back_btn_bg);
  96. //设置标题栏"历史反馈"的字号,需要将控制台中此字号设置为0
  97. FeedbackAPI.setHistoryTextSize(20);
  98. //设置标题栏高度,单位为像素
  99. FeedbackAPI.setTitleBarHeight(100);
  100. }
  101. private void initHttpDnsService() {
  102. // 初始化httpdns
  103. //HttpDnsService httpdns = HttpDns.getService(getApplicationContext(), accountID);
  104. HttpDnsService httpdns = HttpDns.getService(getApplicationContext());
  105. //this.setPreResoveHosts();
  106. // 允许过期IP以实现懒加载策略
  107. //httpdns.setExpiredIPEnabled(true);
  108. }
  109. private void initHotfix() {
  110. String appVersion;
  111. try {
  112. appVersion = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName;
  113. } catch (Exception e) {
  114. appVersion = "1.0.0";
  115. }
  116. SophixManager.getInstance().setContext(this)
  117. .setAppVersion(appVersion)
  118. .setAesKey(null)
  119. //.setAesKey("0123456789123456")
  120. .setEnableDebug(true)
  121. .setPatchLoadStatusStub(new PatchLoadStatusListener() {
  122. @Override
  123. public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
  124. String msg = new StringBuilder("").append("Mode:").append(mode)
  125. .append(" Code:").append(code)
  126. .append(" Info:").append(info)
  127. .append(" HandlePatchVersion:").append(handlePatchVersion).toString();
  128. if (msgDisplayListener != null) {
  129. msgDisplayListener.handle(msg);
  130. } else {
  131. cacheMsg.append("\n").append(msg);
  132. }
  133. }
  134. }).initialize();
  135. }
  136. /**
  137. * 初始化云推送通道
  138. * @param applicationContext
  139. */
  140. private void initPushService(final Context applicationContext) {
  141. PushServiceFactory.init(applicationContext);
  142. final CloudPushService pushService = PushServiceFactory.getCloudPushService();
  143. pushService.register(applicationContext, new CommonCallback() {
  144. @Override
  145. public void onSuccess(String response) {
  146. Log.i(TAG, "init cloudchannel success");
  147. //setConsoleText("init cloudchannel success");
  148. }
  149. @Override
  150. public void onFailed(String errorCode, String errorMessage) {
  151. Log.e(TAG, "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
  152. //setConsoleText("init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
  153. }
  154. });
  155. }
  156. }

上述代码示例为统一接入涉及到的全部sdk初始化代码,您可以按需使用,也可以参考各sdk初始化文档:移动推送移动热修复移动反馈移动数据分析httpdns

  • 注1:每次修改json文件后,都要执行上述步骤中e操作,保证插件读取了新的json配置;use_maven=false时下载sdk(控制台下载oneSdk)后要放到/app/libs中,并注意使用哪个services,一定要将对应sdk加入到libs中;接入emas_services插件后,您在使用各个sdk时,将不需要手动传入APPKey/APPSecret等属性到SDK,也不需要在AndroidManifest.xml配置APPKey/APPSecret,而只需传入Context即可进行初始化。
  • 注2:采用emas统一接入时,请勿开启资源混淆(非代码混淆),若必须采用资源混淆,请按原来传参方式接入。

3. Q&A

Q:运行插件后提示: “File aliyun-emas-services.json is missing. The Emas Services Plugin cannot function without it”.

A:确保您将控制台下载的aliyun-emas-services.json文件已经正确放置到app/目录下。

Q:接入全部产品后,如果遇到以下问题:​ Error:Execution failed for task ‘:app:processDebugManifest’.​ Manifest merger failed with multiple errors, see logs.

A:由于不同sdk设置的allowBackup属性不同,建议在Manifest.xml中添加:

  1. <Application
  2. ....
  3. android:allowBackup="false"
  4. tools:replace="android:allowBackup"/>