移动热修复(Mobile Hotfix)是面向Android、iOS平台应用提供的在线热修复服务方案,产品基于阿里巴巴首创的Hotpatch技术,提供细粒度热修复能力,无需等待发版即可实时修复应用线上问题,用户全程无感知。
Sophix同时使用了热启动的底层替换方案及冷启动的类加载方案,两个方案使用的补丁是相同的。优先热启动。
热更新防范对比
方案对比.pngSophix 配置使用
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.png3.补丁生成
3.1补丁生成工具 工具地址
image.png补丁生成工具.png
4.0 生成补丁
生成补丁.pngSophix 发布补丁
1. 添加版本(对应App的版本)
添加版本.png2. 添加版本(对应App的版本)
上传补丁.png3. 发布补丁
发布.png 发布补丁png注意:
1.发布区分灰度发布和全量发布 灰度可以现在部分用户更新 (方便测试用).全量发布则是全部用户可以下载
2. 千万注意需要外部村读取权限!!!!
总结
简单梳理了一下Sophix的集成使用过程 ,方便大家集成热更新的这个功能
网友评论