全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 钉钉智能硬件

稳健接入

更新时间:2018-01-03 09:27:04

稳健接入

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. * AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。
  16. * 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。
  17. * 如有其它自定义改造,请咨询官方后妥善处理。
  18. */
  19. public class SophixStubApplication extends SophixApplication {
  20. private final String TAG = "SophixStubApplication";
  21. // 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
  22. @Keep
  23. @SophixEntry(MyRealApplication.class)
  24. static class RealApplicationStub {}
  25. @Override
  26. protected void attachBaseContext(Context base) {
  27. super.attachBaseContext(base);
  28. // 如果需要使用MultiDex,需要在此处调用。
  29. // MultiDex.install(this);
  30. initSophix();
  31. }
  32. private void initSophix() {
  33. String appVersion = "0.0.0";
  34. try {
  35. appVersion = this.getPackageManager()
  36. .getPackageInfo(this.getPackageName(), 0)
  37. .versionName;
  38. } catch (Exception e) {
  39. }
  40. final SophixManager instance = SophixManager.getInstance();
  41. instance.setContext(this)
  42. .setAppVersion(appVersion)
  43. .setSecretMetaData(null, null, null)
  44. .setEnableDebug(true)
  45. .setEnableFullLog()
  46. .setPatchLoadStatusStub(new PatchLoadStatusListener() {
  47. @Override
  48. public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
  49. if (code == PatchStatus.CODE_LOAD_SUCCESS) {
  50. Log.i(TAG, "sophix load patch success!");
  51. } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
  52. // 如果需要在后台重启,建议此处用SharePreference保存状态。
  53. Log.i(TAG, "sophix preload patch success. restart app to make effect.");
  54. }
  55. }
  56. }).initialize();
  57. }
  58. }

这里的初始化和快速接入中的是一样的,务必放在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,也应在initSophix之前添加。
  2. 把RealApplicationStub的SophixEntry注解的内容改为自己原先真正的MyRealApplication类。
  3. 混淆文件中确保某些内容不被混淆。
  4. AndroidManifest里面的application改为新增的SophixStubApplication入口类。

如果开发者之前已经完成了快速接入,想修改为这种新方式接入时,有以下注意事项:

  1. 需要在原Application中把相关初始化逻辑去除,避免重复初始化导致异常。
  2. queryAndLoadNewPatch的调用处和原先一致,不需要改变。
本文导读目录