Android Mobile Hotfix(阿里云——移动热修复接入)

版权声明:转载请标明出处 https://blog.csdn.net/Android_man_me/article/details/82142230

首先你需要注册并登陆 阿里云移动研发平台,查看官方文档,下载SDK等,集成过程并不复杂。本文主要记录接入流程跟遇到的问题

什么是热修复

热修复,是一种使用补丁来更新修复的手段。不需要通过重新发布App,下载安装等一系列繁琐的过程。

热修复原理

总结参考文档,修复框架很多,但热修复框架的核心技术主要有三类

  • 代码修复
  • 资源修复
  • 动态链接库修复

代码修复主要有三个方案,分别是底层替换方案、类加载方案和Instant Run方案,具体请参考以下链接

参考文档:

https://www.jianshu.com/p/a4bf979cce3b(Android热更新之初探)

https://blog.csdn.net/itachi85/article/details/79522200(Android热修复原理)

插件化开发

将整个app拆分成多个模块,每个模块都是一个app,这些模块包括一个宿主和多个插件。(解决 65535 问题)

插件化Small方案:http://code.wequick.net/Small/cn/quickstart

组件化开发

将整个app拆分成多个模块,每个模块都是一个组件(Module),也就是lib。项目功能需求比较复杂的时候,或者多人开发的时候,非常不错的一种方案。便于开发,调试。代码逻辑结构清晰,便于代码的维护,重用,降低耦合度。

参考文档:

https://www.jianshu.com/p/704cac3eb13d(Android 插件化和热修复知识梳理)

https://blog.csdn.net/guiying712/article/details/55213884(Android组件化方案)

https://blog.csdn.net/u012513972/article/details/78269288(Android热更新技术的研究与实现)

记录部分学习内容,下面主要介绍 Sophix接入以及简单使用:

 官方文档:https://help.aliyun.com/product/51340.html?spm=5176.131995.673114.doc1.13e969fd9JwVdh

Android Studio 集成(快速接入)

第一步,添加依赖配置

这里注意是都在 app的build.gradle文件下,添加配置

repositories {
        mavenLocal()
        //阿里云仓库
        maven {
            url "http://maven.aliyun.com/nexus/content/repositories/releases"
        }
        mavenCentral()
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }

添加依赖:

implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.4'

第二步,AndroidManifest.xml文件 添加权限

    <!-- 网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!-- 外部存储读权限,调试工具加载本地补丁需要 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在Android 6.0及以上,需要对READ_EXTERNAL_STORAGE权限做处理

还有data数据配置,我是在代码中进行设置的,推荐使用。避免别人解析破解

第三步,初始化处理

/**
 * Sophix入口类,专门用于初始化Sophix,稳健接入方式
 * <p>
 * Sophix入口类,专门用于初始化Sophix,不应包含任何业务逻辑。
 * 此类必须继承自SophixApplication,onCreate方法不需要实现。
 * 此类不应与项目中的其他类有任何互相调用的逻辑,必须完全做到隔离。
 * AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。
 * 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。
 */
public class SophixStubApplication extends SophixApplication {

    private static final String TAG = "SophixStubApplication";

    // 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
    @Keep
    @SophixEntry(MyApplication.class)
    static class RealApplicationStub {

    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        //如果需要使用MultiDex,需要在此处调用。
//         MultiDex.install(this);
        initSophix();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // queryAndLoadNewPatch不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻
        SophixManager.getInstance().queryAndLoadNewPatch();
    }

    /**
     * 初始化 Sophix
     */
    private void initSophix() {

        String appVersion = "0.0.0";
        try {
            appVersion = this.getPackageManager()
                    .getPackageInfo(this.getPackageName(), 0)
                    .versionName;
        } catch (Exception e) {
            e.printStackTrace();
        }

        Log.e(TAG, "initSophix: " + appVersion);

        final SophixManager instance = SophixManager.getInstance();
        instance.setContext(this)
                .setAppVersion(appVersion)
                .setSecretMetaData(getResourceById(R.string.ali_sophix_IDSECRET), getResourceById(R.string.ali_sophix_APPSECRET), getResourceById(R.string.ali_sophix_RSASECRET))
                .setEnableDebug(true)//日志
                .setAesKey(null)
                .setPatchLoadStatusStub(new PatchLoadStatusListener() {
                    @Override
                    public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {

                        Log.e(TAG, "onLoad: " + code);
                        if (code == PatchStatus.CODE_LOAD_SUCCESS) {
                            // 表明补丁加载成功

                        } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {

                            // 如果需要在后台重启,建议此处用SharePreference保存状态。
                            // 表明新补丁生效需要重启. 开发者可提示用户或者强制重启;
                            // 建议: 用户可以监听进入后台事件, 然后调用killProcessSafely自杀,以此加快应用补丁,详见1.3.2.3
                            //SophixManager.getInstance().killProcessSafely();

                        } else {

                            // 其他错误信息
                            Log.e(TAG, "onLoad: " + code);

                        }
                    }
                }).initialize();
    }


    /**
     * 获取 string 资源
     *
     * @param rid
     * @return
     */
    private String getResourceById(int rid) {
        return this.getResources().getString(rid);
    }


}

我使用 稳健接入方式

注意在@SophixEntry() 此处指定项目原有的Application,但是在AndroidManifest中引用的是SophixStubApplication

    @Keep
    @SophixEntry(MyApplication.class)
    static class RealApplicationStub {

    }

通过setSecretMetaData() 设置 阿里参数(创建项目后会看到)

 @Override
    public void onCreate() {
        super.onCreate();
        // queryAndLoadNewPatch不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻
        SophixManager.getInstance().queryAndLoadNewPatch();
    }

官方文档比较详细,仅记录一些比较容易错过的细节

补丁版本问题

  • 初始化通过setAppVersion()设置版本号,这个版本号将用于,客户端(当前集成app)来比对上传到阿里后台的补丁版本,发布的补丁版本号,跟代码中设置的要一致,否则无法加载到
  • 每一个版本,只能允许有一个补丁,若有变动,需要停止旧版本补丁的发布,替换新补丁(所以,紧急的一些小BUG,可以用此方式,当改动比较大,需求变动多,必备的版本更新下载,重新安装的方式,也是不可少的)

补丁相关问题

  • 打新旧包的时候,必须关闭Android Studio 的 Install Run 
  • 补丁替换,必须保证bug的叠加修复。(比如第一个补丁修复A-bug,发现 B-bug需要第二个补丁。那么在第二个补丁中,必须修改了A+B 两个bug)
  • 使用该热修复,不能有增加或删减 Android组件的变动,否则无法成功修复(还没测试)

主要以学习记录为目的,记录一些不错的文档链接。

猜你喜欢

转载自blog.csdn.net/Android_man_me/article/details/82142230