阿里移动热修复

1,261 阅读3分钟

前言:之前用腾讯的bugly,可以实现热修复和全量更新,随着AndroidStudio版本的更新,新版本上就无法集成bugly,于是阿里热修复方案呼之欲出。阿里可以使用最新版的AndroidStudio,缺点是收费。腾讯的bugly免费,但是目前最新版AndroidStudio用不了。

阿里热修复集成方法:(SDK稳健接入)

  1. 添加工程依赖

    Android Studio集成方式

    gradle远程仓库依赖, 项目根目录的build.gradle文件,添加如下配置:

    repositories {
    maven {
        url "http://maven.aliyun.com/nexus/content/repositories/releases"
        }
     }
         dependencies {
           // 添加emas-services插件
         classpath 'com.aliyun.ams:emas-services:1.0.1'
         }
    
    

    添加gradle app目录版本依赖:

    apply plugin: 'com.aliyun.ams.emas-services'
    android {
     ......
     defaultConfig {
         applicationId "com.xxx.xxx" //包名
         ......
         ndk {
             //选择要添加的对应cpu类型的.so库。
             //热修复支持五种
             abiFilters 'arm64-v8a', 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
         }
         ......
     }
     ......
     }
     dependencies {
         ......
             compile 'com.aliyun.ams:alicloud-android-hotfix:3.2.18'
         ......
     }
    
    
    1. 添加应用权限
    <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"/>
    
    1. 配置AndroidManifest文件

      在AndroidManifest.xml中间的application节点下添加如下配置:

      <meta-data
      android:name="com.taobao.android.hotfix.IDSECRET"
      android:value="App ID" />
      <meta-data
      android:name="com.taobao.android.hotfix.APPSECRET"
      android:value="App Secret" />
      <meta-data
      android:name="com.taobao.android.hotfix.RSASECRET"
      android:value="RSA密钥" />
      
    2. 混淆配置

    #基线包使用,生成mapping.txt
    -printmapping mapping.txt
    #生成的mapping.txt在app/build/outputs/mapping/release路径下,移动到/app路径下
    #修复后的项目使用,保证混淆结果一致
    #-applymapping mapping.txt
    #hotfix
    -keep class com.taobao.sophix.**{*;}
    -keep class com.ta.utdid2.device.**{*;}
    #防止inline
    -dontoptimize
    
    1. 初始化
    package com.my.pkg;
    import android.app.Application;
    import android.content.Context;
    import android.support.annotation.Keep;
    import android.util.Log;
    import com.taobao.sophix.PatchStatus;
    import com.taobao.sophix.SophixApplication;
    import com.taobao.sophix.SophixEntry;
    import com.taobao.sophix.SophixManager;
    import com.taobao.sophix.listener.PatchLoadStatusListener;
    import com.my.pkg.MyRealApplication;
    /**
     * Sophix入口类,专门用于初始化Sophix,不应包含任何业务逻辑。
     * 此类必须继承自SophixApplication,onCreate方法不需要实现。
     * 此类不应与项目中的其他类有任何互相调用的逻辑,必须完全做到隔离。
     * AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。
     * 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。
     * 如有其它自定义改造,请咨询官方后妥善处理。
     */
    public class SophixStubApplication extends SophixApplication {
        private final String TAG = "SophixStubApplication";
        // 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
        @Keep
        @SophixEntry(MyRealApplication.class)
        static class RealApplicationStub {}
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
    //         如果需要使用MultiDex,需要在此处调用。
    //         MultiDex.install(this);
            initSophix();
        }
        private void initSophix() {
            String appVersion = "0.0.0";
            try {
                appVersion = this.getPackageManager()
                                 .getPackageInfo(this.getPackageName(), 0)
                                 .versionName;
            } catch (Exception e) {
            }
            final SophixManager instance = SophixManager.getInstance();
            instance.setContext(this)
                    .setAppVersion(appVersion)
                    .setSecretMetaData(null, null, null)
                    .setEnableDebug(true)
                    .setEnableFullLog()
                    .setPatchLoadStatusStub(new PatchLoadStatusListener() {
                        @Override
                        public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
                            if (code == PatchStatus.CODE_LOAD_SUCCESS) {
                                Log.i(TAG, "sophix load patch success!");
                            } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
                                // 如果需要在后台重启,建议此处用SharePreference保存状态。
                                Log.i(TAG, "sophix preload patch success. restart app to make effect.");
                            }
                        }
                    }).initialize();
        }
    }
    

    这其中,关键一点是:

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

    MyRealApplication这个为原来的Application,具体填写自己的Application即可,别忘记了在Androidmanifest.xml中用上述的SophixStubApplication替换原来的Application,否则热更新不能生效。

    然后,在proguard文件里面需要加上下面内容:(替换为自己项目中的路径)

    -keepclassmembers class com.my.pkg.MyRealApplication {
        public <init>();
    }
    -keep class com.my.pkg.SophixStubApplication$RealApplicationStub
    
    1. 创建应用版本
    https://help.aliyun.com/document_detail/93805.htm?spm=a2c4g.11186623.2.8.3b413206sdAdqn
    

    下载json文件添加到app目录下, 然后查看应用信息的内容,把AppKey,AppSecret,RSA更换到上述的AndrodManifest的MetaData中。

    1. 使用

    在移动热修复上传补丁前需创建应用版本,该版本和基线包初始化时所传的版本号对应。这个不像Bugly那样需要在线上持有BaseVersion,需要通过补丁工具SophixPatchTool工具,通过BaseVersion和修复版本进行比较打patch,然后把patch上传,然后进行验证和发布,如果补丁出现了问题,还可以进行回滚。

image.png ```

  1. 加油吧,后续多多使用!发现问题再更新文档!