前言
??在IT行業(yè)蓬勃發(fā)展的今天迹缀,作為程序猿的我們要時刻緊跟IT技術(shù)的步伐。移動互聯(lián)網(wǎng)發(fā)展可謂日新月異慰安,各種黑科技橫空出世盆耽,目不暇接蹋砚!今天我們就來學(xué)習(xí)下如何正確集成阿里云的移動熱修復(fù)黑科技——Sophix。按照阿里云官方集成文檔摄杂,我們含辛茹苦地把Demo搭建好了坝咐,Demo運行起來也能正常加載修復(fù)包Pathch
。但是析恢,當(dāng)你按照文檔真正把Sophix集成到你的項目中的時候墨坚,各種 can not find class...
,一萬匹曹泥馬在你心中狂奔而過S彻摇泽篮!
步驟簡介
-
創(chuàng)建項目
1、新建項目:SophixDemo
2袖肥、在項目的build.gradle
文件中添加maven
路徑:
allprojects {
repositories {
google()
jcenter()
//aliyun hot fix
maven { url "http://maven.aliyun.com/nexus/content/repositories/releases" }
}
}
?3咪辱、在app
的build.gradle
文件中添加SDK引用:
dependencies {
//其他SDK引用
//Sophix hot fix SDK
implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.0'
}
?4振劳、創(chuàng)建SophixStubApplication.java
和MyApplication.java
MyApplication.java
import android.app.Application;
import com.taobao.sophix.SophixManager;
/**
* Created on 2018/2/2.
*
* @author jsc
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//hot fix. Load patch from aliyun service.
SophixManager.getInstance().queryAndLoadNewPatch();
}
}
SophixStubApplication.java
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.Keep;
import android.support.multidex.MultiDex;
import android.support.v7.app.AlertDialog;
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;
/**
* Sophix入口類椎组,專門用于初始化Sophix,不應(yīng)包含任何業(yè)務(wù)邏輯历恐。
* 此類必須繼承自SophixApplication寸癌,onCreate方法不需要實現(xiàn)专筷。
* 此類不應(yīng)與項目中的其他類有任何互相調(diào)用的邏輯,必須完全做到隔離蒸苇。
* AndroidManifest中設(shè)置application為此類磷蛹,而SophixEntry中設(shè)為原先Application類。
* 注意原先Application里不需要再重復(fù)初始化Sophix溪烤,并且需要避免混淆原先Application類味咳。
* 如有其它自定義改造,請咨詢官方后妥善處理檬嘀。
*/
public class SophixStubApplication extends SophixApplication {
private final String TAG = "SophixStubApplication";
//aesKey必須是16位數(shù)字或字母的組合槽驶,是和補丁工具設(shè)置里面AES Key保持完全一致, 補丁才能正確被解密進而加載
final String aesKey = "";
final String appId = "";
final String appSecret = "";
final String rsa = "";
// 此處SophixEntry應(yīng)指定真正的Application,并且保證RealApplicationStub類名不被混淆鸳兽。
@Keep
@SophixEntry(MyApplication.class)
static class RealApplicationStub {
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// 如果需要使用MultiDex掂铐,需要在此處調(diào)用。
MultiDex.install(this);
initSophix();
}
private void initSophix() {
String appVersion;
try {
appVersion = this.getPackageManager()
.getPackageInfo(this.getPackageName(), 0)
.versionName;
} catch (Exception e) {
appVersion = "0.0.0";
}
SophixManager.getInstance().setContext(this)
.setAesKey(aesKey)
.setAppVersion(appVersion)
.setSecretMetaData(appId, appSecret, rsa)
.setEnableDebug(false)
.setEnableFullLog()
.setPatchLoadStatusStub(new PatchLoadStatusListener() {
@Override
public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
switch (code){
case PatchStatus.CODE_LOAD_SUCCESS:
// Toast.makeText(getBaseContext(), "Patch更新成功", Toast.LENGTH_SHORT).show();
break;
case PatchStatus.CODE_LOAD_RELAUNCH:
// 如果需要在后臺重啟揍异,建議此處用SharePreference保存狀態(tài)全陨。
showForceRestartAppDialog();
break;
}
}
}).initialize();
}
private void showForceRestartAppDialog(){
new AlertDialog.Builder(getBaseContext())
.setMessage("Patch更新成功,請重啟應(yīng)用衷掷!")
.setCancelable(false)
.setPositiveButton("退出應(yīng)用", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SophixManager.getInstance().killProcessSafely();
}
}).show();
}
}
aesKey
——必須是16位數(shù)字或字母的組合辱姨,是和補丁工具設(shè)置里面AES Key保持完全一致, 補丁才能正確被解密加載
appId
——從 APP管理 中獲取
appSecret
——從 APP管理 中獲取
rsa
——從 APP管理 中獲取
?5、添加SophixStubApplication
到你的AndroidManifest.xml
中戚嗅。
我們只添加SophixStubApplication就可以了炮叶,MyApplication不用添加進去。因為SophixStubApplication內(nèi)部會通過反射找到我們的MyApplication渡处。關(guān)鍵代碼@SophixEntry(MyApplication.class)
镜悉。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jsc.exam.sophix">
<application
android:name=".SophixStubApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AboutActivity"></activity>
</application>
</manifest>
6、編寫混淆文件医瘫。在app
下的proguard-rules.pro
文件中添加:
#基線包使用侣肄,生成mapping.txt
-printmapping mapping.txt
#生成的mapping.txt在app/buidl/outputs/mapping/release路徑下,移動到/app路徑下
#修復(fù)后的項目使用醇份,保證混淆結(jié)果一致
#-applymapping /build/outputs/mapping/release/mapping.txt
#hotfix
-keep class com.taobao.sophix.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#防止inline
-dontoptimize
-keepclassmembers class jsc.exam.sophix.MyApplication {
public <init>();
}
# 如果不使用android.support.annotation.Keep則需加上此行
# -keep class com.my.pkg.SophixStubApplication$RealApplicationStub
{提別提示}:
??a稼锅、當(dāng)我們在打包發(fā)布包的時候我們開啟printmapping
,關(guān)閉applymapping
僚纷。這時候在項目文件夾app\build\outputs\mapping\release
下生成mappint.txt
文件矩距。這時候apk
和這個mapping.txt
文件我們都要做一份保存(按照規(guī)范的開發(fā)流程,這時候在代碼倉庫中需要建立一個新的的分支branch怖竭,不管是用svn還是git代碼倉庫)锥债。apk
用來發(fā)布,mappting.txt
文件是用來生成補丁patch
打包用。
??b哮肚、當(dāng)我們在打包補丁包的時候我們關(guān)閉printmapping
登夫,開啟applymapping
。這時候applymapping
指向我們mappting.txt
文件所在的路徑允趟。在demo中直接指向了app\build\outputs\mapping\release\mappint.txt
恼策。
如前言所說的各種 can not find class
的罪魁禍首多半就是混淆。
如果找不類潮剪,我們可以從以下幾方面去找到問題:
A涣楷、檢查發(fā)布包、補丁包抗碰、APP管理的版本號是否一致总棵。
B、檢查發(fā)布包改含、補丁包是否用同一份mapping.txt來混淆打包的情龄。
只要注意以上兩點,集成Sophix
基本上不會出現(xiàn)什么問題的捍壤。
- 生成補丁包——請參照官方文檔
- 測試補丁包——請參照官方文檔
- 發(fā)布補丁包——請參照官方文檔[APP管理]
源碼
示例:https://github.com/JustinRoom/SophixDemo
結(jié)尾
??希望這篇小文章能幫使用Sophix的小伙伴們跳過這些坑骤视,不奢求打賞,加個關(guān)注啰鹃觉!我是JustinEoy专酗,QQ:1006368252
。