Android 三方集成

Android 阿里Sophix 热更新集成

2022-05-12  本文已影响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.源码地址

上一篇下一篇

猜你喜欢

热点阅读