全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 智能硬件
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 更多

稳健接入

更新时间:2018-03-14 11:30:06

Sophix最新版本引入了新的初始化方式。

原来的初始化方式仍然可以使用。只是新方式可以提供更全面的功能修复支持,将会带来以下优点:初始化与应用原先业务代码完全隔离,使得原先真正的Application可以修复,并且减少了补丁预加载时间等等。另外,新方式能够更完美地兼容Android 8.0以后版本。

具体而言,是需要用户自行加入以下这个类:

  1. package com.my.pkg;
  2. import android.app.Application;
  3. import android.content.Context;
  4. import android.support.annotation.Keep;
  5. import android.util.Log;
  6. import com.taobao.sophix.PatchStatus;
  7. import com.taobao.sophix.SophixApplication;
  8. import com.taobao.sophix.SophixEntry;
  9. import com.taobao.sophix.SophixManager;
  10. import com.taobao.sophix.listener.PatchLoadStatusListener;
  11. import com.my.pkg.MyRealApplication;
  12. /**
  13. * Sophix入口类,专门用于初始化Sophix,不应包含任何业务逻辑。
  14. * 此类必须继承自SophixApplication,onCreate方法不需要实现。
  15. * 此类不应与项目中的其他类有任何互相调用的逻辑,必须完全做到隔离。
  16. * AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。
  17. * 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。
  18. * 如有其它自定义改造,请咨询官方后妥善处理。
  19. */
  20. public class SophixStubApplication extends SophixApplication {
  21. private final String TAG = "SophixStubApplication";
  22. // 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
  23. @Keep
  24. @SophixEntry(MyRealApplication.class)
  25. static class RealApplicationStub {}
  26. @Override
  27. protected void attachBaseContext(Context base) {
  28. super.attachBaseContext(base);
  29. // 如果需要使用MultiDex,需要在此处调用。
  30. // MultiDex.install(this);
  31. initSophix();
  32. }
  33. private void initSophix() {
  34. String appVersion = "0.0.0";
  35. try {
  36. appVersion = this.getPackageManager()
  37. .getPackageInfo(this.getPackageName(), 0)
  38. .versionName;
  39. } catch (Exception e) {
  40. }
  41. final SophixManager instance = SophixManager.getInstance();
  42. instance.setContext(this)
  43. .setAppVersion(appVersion)
  44. .setSecretMetaData(null, null, null)
  45. .setEnableDebug(true)
  46. .setEnableFullLog()
  47. .setPatchLoadStatusStub(new PatchLoadStatusListener() {
  48. @Override
  49. public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
  50. if (code == PatchStatus.CODE_LOAD_SUCCESS) {
  51. Log.i(TAG, "sophix load patch success!");
  52. } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
  53. // 如果需要在后台重启,建议此处用SharePreference保存状态。
  54. Log.i(TAG, "sophix preload patch success. restart app to make effect.");
  55. }
  56. }
  57. }).initialize();
  58. }
  59. }

这里的初始化和快速接入中的是一样的,务必放在attachBaseContext中,onCreate不需要自行实现。同时自定义的SophixStubApplication需要继承com.taobao.sophix.SophixApplication。初始化设置选项如有疑问,请参考快速接入中的接口说明

这其中,关键一点是:

  1. @Keep
  2. @SophixEntry(MyRealApplication.class)
  3. static class RealApplicationStub {}

SophixEntry应指定项目中原先真正的Application(原项目里application的android::name指定的),这里用MyRealApplication指代。并且保证RealApplicationStub类名不被混淆。而SophixStubApplication的类名和包名可以自行取名。

这里的Keep是android.support包中的类,目的是为了防止这个内部静态类的类名被混淆,因为sophix内部会反射获取这个类的SophixEntry。如果项目中没有依赖android.support的话,就需要在progurad里面手动指定RealApplicationStub不被混淆,详见下文。

然后,在proguard文件里面需要加上下面内容:

  1. -keepclassmembers class com.my.pkg.MyRealApplication {
  2. public <init>();
  3. }
  4. # 如果不使用android.support.annotation.Keep则需加上此行
  5. # -keep class com.my.pkg.SophixStubApplication$RealApplicationStub

目的是防止真正Application的构造方法被proguard混淆。

最后,需要把AndroidManifest里面的application改为这个新增的SophixStubApplication类:

  1. <application
  2. android:name="com.my.pkg.SophixStubApplication"
  3. ... ...>
  4. ... ...

这样便完成了新方式的初始化接入改造。

总结一下,改造过程一共有四个步骤:

  1. 把此SophixStubApplication入口类添加进项目中,所有Sophix相关初始化放在此类中。并且不应包含开发者的任何业务逻辑代码。 若使用了MultiDex,也应在SophixStubApplication的initSophix之前添加,并且需要记得在原来的Application里面去除MultiDex,避免重复调用导致问题。
  2. 把RealApplicationStub的SophixEntry注解的内容改为自己原先真正的MyRealApplication类。
  3. 混淆文件中确保某些内容不被混淆。
  4. AndroidManifest里面的application改为新增的SophixStubApplication入口类。

最后,还需要注意以下几点:

  1. 其他接口的使用方法请参考接口说明
  2. 补丁版本的作用以及规则请参考版本管理说明
  3. 如果开发者之前已经完成了快速接入,想修改为这种新方式接入时,需要在原Application中把相关初始化以及MultiDex逻辑去除,避免重复初始化导致异常。queryAndLoadNewPatch的调用处和原先一致,不需要改变。
本文导读目录