美文网首页Android 三方集成
Android 阿里Sophix 热更新集成

Android 阿里Sophix 热更新集成

作者: 没有了遇见 | 来源:发表于2022-05-12 17:21 被阅读0次
    dSophix热修复效果.gif

    移动热修复(Mobile Hotfix)是面向Android、iOS平台应用提供的在线热修复服务方案,产品基于阿里巴巴首创的Hotpatch技术,提供细粒度热修复能力,无需等待发版即可实时修复应用线上问题,用户全程无感知。

    Sophix同时使用了热启动的底层替换方案及冷启动的类加载方案,两个方案使用的补丁是相同的。优先热启动。

    热更新防范对比

    方案对比.png

    Sophix 配置使用

    1.添加工程依赖

    1.1 Android Studio集成方式

    gradle远程仓库依赖, 打开项目找到App的build.gradle文件,添加如下配置:

    添加Maven仓库地址:

    repositories {
       maven {
           url "http://maven.aliyun.com/nexus/content/repositories/releases"
       }
    }
    
    

    1.2.添加gradle坐标版本依赖:

    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.3.5'
        ......
    }
    

    2. 添加所需权限

    <!-- 热修复权限 -->
    <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"/>
    
    
    

    3. 配置 appId appSecret appRSA

    3.1 配置AndroidManifest文件

    <!-- 对应aliyun-emas-services.json 中的 hotfix.idSecret-->
    <meta-data
    android:name="com.taobao.android.hotfix.IDSECRET"
    android:value="App ID" />
    <meta-data
    <!-- 对应aliyun-emas-services.json 中的 emas.appSecret-->
    android:name="com.taobao.android.hotfix.APPSECRET"
    android:value="App Secret" />
    <!-- 对应aliyun-emas-services.json 中的 hotfix.rsaSecret->
    <meta-data
    android:name="com.taobao.android.hotfix.RSASECRET"
    android:value="RSA密钥" />
    ...
     <application
            android:name=".application.SophixStubApplication"
            ...
          
    

    3.2 代码中配置

        var instance = SophixManager.getInstance();
            val sharedPreferences = getSharedPreferences(packageName, MODE_PRIVATE)
    
            val packageName = this.packageName
            val appVersion = packageManager.getPackageInfo(packageName, 0).versionName
            val appId = "33***73-1"
            val appSecret = "c2ac57***116"
            val appRSA =
                "MIIEv..."
            instance.setContext(this)
                .setAppVersion(appVersion)
                .setSecretMetaData(appId, appSecret, appRSA)
                    //注意debug relase 版本区分
                .setEnableDebug(true)
                .setEnableFullLog()
                .setPatchLoadStatusStub(object : PatchLoadStatusListener {
                    override fun onLoad(mode: Int, code: Int, info: String?, handlePatchVersion: Int) {
                        val tag = "mode %s code %s info %s version %s"
                        Log.i(TAG, "状态回调 : " + String.format(tag, mode, code, info, handlePatchVersion))
                        if (code == PatchStatus.CODE_LOAD_SUCCESS) {
                            Log.i(TAG, "热修复 加载 成功!")
                        } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
                            Log.i(TAG, "热修复 安装 成功,等待重启.")
                            sharedPreferences?.edit()
                                ?.putBoolean(SOPHIX_AS_RESTART, true)?.apply()
                        } else if (code == PatchStatus.CODE_REQ_CLEARPATCH) {
                            Log.i(TAG, "热修复 回滚 成功,等待重启.")
                        } else if (code == PatchStatus.CODE_REQ_NOUPDATE) {
                            Log.i(TAG, "热修复 没有 可更新补丁!")
                            sharedPreferences?.edit()
                                ?.putBoolean(SOPHIX_AS_RESTART, false)?.apply()
                        }
                    }
    
                }).initialize()
    

    4. 混淆配置

    4.1 Sophix的Application

    #基线包使用,生成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
    

    5.初始化Sophix

    package com.wu.material.application
    
    import android.content.Context
    import android.util.Log
    import androidx.annotation.Keep
    import androidx.multidex.MultiDex
    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
    
    
    /**
     * @author wkq
     *
     * @date 2022年05月12日 13:34
     *
     *@des
     *
     */
    
    class SophixStubApplication : SophixApplication() {
    
        var TAG = "热修复"
    
        var SOPHIX_AS_RESTART = "SOPHIX_AS_RESTART"
        //引用到项目的Application
        @Keep
        @SophixEntry(MaterialApplication::class)
        internal class RealApplicationStub
    
        override fun attachBaseContext(base: Context?) {
            super.attachBaseContext(base)
            // 如果需要使用MultiDex,需要在此处调用。
            MultiDex.install(this)
            try {
                initSophix()
            } catch (e: Exception) {
                Log.i("Strike", "热修复功能初始化失败!", e)
            }
        }
    
        // 热修复
        private fun initSophix() {
            var instance = SophixManager.getInstance();
            val sharedPreferences = getSharedPreferences(packageName, MODE_PRIVATE)
    
            val packageName = this.packageName
            val appVersion = packageManager.getPackageInfo(packageName, 0).versionName
            val appId = "333***3-1"
            val appSecret = "c2ac5***116"
            val appRSA =
                "MIIEv***"
            instance.setContext(this)
                .setAppVersion(appVersion)
                .setSecretMetaData(appId, appSecret, appRSA)
                    //注意debug relase 版本区分
                .setEnableDebug(true)
                .setEnableFullLog()
                .setPatchLoadStatusStub(object : PatchLoadStatusListener {
                    override fun onLoad(mode: Int, code: Int, info: String?, handlePatchVersion: Int) {
                        val tag = "mode %s code %s info %s version %s"
                        Log.i(TAG, "状态回调 : " + String.format(tag, mode, code, info, handlePatchVersion))
                        if (code == PatchStatus.CODE_LOAD_SUCCESS) {
                            Log.i(TAG, "热修复 加载 成功!")
                        } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
                            Log.i(TAG, "热修复 安装 成功,等待重启.")
                            sharedPreferences?.edit()
                                ?.putBoolean(SOPHIX_AS_RESTART, true)?.apply()
                        } else if (code == PatchStatus.CODE_REQ_CLEARPATCH) {
                            Log.i(TAG, "热修复 回滚 成功,等待重启.")
                        } else if (code == PatchStatus.CODE_REQ_NOUPDATE) {
                            Log.i(TAG, "热修复 没有 可更新补丁!")
                            sharedPreferences?.edit()
                                ?.putBoolean(SOPHIX_AS_RESTART, false)?.apply()
                        }
                    }
    
                }).initialize()
        }
    
    }
    
    

    4.2 项目的的Application

    package com.wu.material.application
    
    import androidx.multidex.MultiDexApplication
    import com.baidu.mapapi.CoordType
    import com.baidu.mapapi.SDKInitializer
    import com.taobao.sophix.SophixManager
    import com.wu.material.util.MmkvUtils
    
    
    /**
     * @author wkq
     *
     * @date 2022年03月17日 16:59
     *
     *@des Application 初始化操作
     *
     */
    
    class MaterialApplication : MultiDexApplication()  {
    
    
        companion object{
            var appOnline = false
        }
        override fun onCreate() {
            super.onCreate()
    
    
    
            initBaiduMap()
            initMMKV()
            //应用程序Activity前后端判断
    
            //应用程序Activity前后端判断
            registerActivityLifecycleCallbacks(ActivityLifecycle())
            //热修复 初始化
            SophixStubUtil.init(this@MaterialApplication, packageName)
            SophixManager.getInstance().queryAndLoadNewPatch()
        }
    
        //初始化腾讯MMKV(数据存储)
        private fun initMMKV() {
            MmkvUtils.initMmkv(this)
        }
    
        //初始化百度地图
        private fun initBaiduMap() {
            //在使用SDK各组件之前初始化context信息,传入ApplicationContext
            SDKInitializer.initialize(this);
            //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
            //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
            SDKInitializer.setCoordType(CoordType.BD09LL);
    
        }
    
    
    }
    

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

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

    //  java
    @Keep
    @SophixEntry(MaterialApplication::class)
     internal class RealApplicationStub
    
    //kotlin
     @Keep
        @SophixEntry(MyRealApplication.class)
        static class RealApplicationStub {}
    

    Sophix 补丁处理

    1.注册阿里账户

    官网地址

    2.创建工作空间

    创建工作空间.png image.png

    3.补丁生成

    3.1补丁生成工具 工具地址

    image.png
    补丁生成工具.png

    4.0 生成补丁

    生成补丁文档

    生成补丁.png

    Sophix 发布补丁

    1. 添加版本(对应App的版本)

    添加版本.png

    2. 添加版本(对应App的版本)

    上传补丁.png

    3. 发布补丁

    发布.png 发布补丁png

    注意:

    1.发布区分灰度发布和全量发布 灰度可以现在部分用户更新 (方便测试用).全量发布则是全部用户可以下载

    2. 千万注意需要外部村读取权限!!!!

    总结

    简单梳理了一下Sophix的集成使用过程 ,方便大家集成热更新的这个功能

    欢迎点赞!!!

    资源

    1.Sophix 集成文档

    2.Sophix补丁工具的文档

    3.Sophix 生成补丁的博客

    4.Sophix 异常日志

    5.源码地址

    相关文章

      网友评论

        本文标题:Android 阿里Sophix 热更新集成

        本文链接:https://www.haomeiwen.com/subject/fazsurtx.html