阿里熱修復之Sophix——公有云釋出版整合步驟
阿新 • • 發佈:2018-11-23
Sophix 公有云接入
去年的時候寫的一篇阿里雲熱修復的文章,那時它還是在公測階段,一直沒能投產,而今,公司專案需要整合已經投產的阿里Sophix功能,所以再次集成了一遍,記錄下了步驟和遇到的一些問題。
一、在app/build.gradle中新增依賴包
dependencies {
implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.4'
implementation 'com.android.support:multidex:1.0.3'
}
附上我的Demo中的app下的build檔案
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.dotawang.sophixdemo"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
abiFilters 'armeabi', 'x86'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['jniLibs']
}
}
//處理混淆上的問題
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/ASL2.0'
exclude 'META-INF/notice.txt'
}
signingConfigs {
releaseConfig {
storeFile file("release.keystore")
storePassword "hschyf"
keyAlias "hswinner"
keyPassword "hschyf"
}
debugConfig {
storeFile file("release.keystore")
storePassword "hschyf"
keyAlias "hswinner"
keyPassword "hschyf"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.releaseConfig
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debugConfig
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.4'
implementation 'com.android.support:multidex:1.0.3'
//出現Error:Execution failed for task ':app:preDebugAndroidTestBuild'的解決方法
androidTestCompile('com.android.support:support-annotations:26.1.0') {
force = true
}
}
二、在專案下的build.gradle中新增依賴包
repositories {
... ...
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
}
附上我的Demo中的專案下的build檔案
buildscript {
repositories {
google()
jcenter()
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
allprojects {
repositories {
google()
jcenter()
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
三、介面程式碼
1) MainActivity的程式碼(佈局中就一個TextView控制元件,自行建立)
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tv);
initData();
}
private void initData() {
textView.setText("這是修復前的效果!!!");
//textView.setText("這是修復後的效果!!!");
//textView.setText("這是第二次修復後的效果!!!");
}
}
2) WinnerApplication的程式碼
import android.app.Application;
import com.taobao.sophix.SophixManager;
public class WinnerApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//獲取阿里熱修復的補丁包 獲取控制檯狀態
SophixManager.getInstance().queryAndLoadNewPatch();
}
}
3) SophixStubApplication的程式碼(阿里雲熱修復整合時要求加入的類,並且注意要在AndroidManifest中加入name去引入)
import android.content.Context;
import android.support.annotation.Keep;
import android.support.multidex.MultiDex;
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;
/**
*阿里公有云的穩健接入整合
*/
public class SophixStubApplication extends SophixApplication {
private final String TAG = "SophixStubApplication";
// 此處SophixEntry應指定真正的Application,並且保證RealApplicationStub類名不被混淆。
@Keep
@SophixEntry(WinnerApplication.class)
static class RealApplicationStub {}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// 如果需要使用MultiDex,需要在此處呼叫,並去除原Applicaton中的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)
.setAesKey(null)
.setAppVersion(appVersion)
//設定null預設取AndroidManifest中設定的值
.setSecretMetaData(null, null, null)
//除錯狀態下true,上線模式下false
.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, "表明補丁載入成功");
} else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
// 如果需要在後臺重啟,建議此處用SharePreference儲存狀態。
Log.i(TAG, "使用者可以監聽進入後臺事件, 然後應用自殺");
}else if (code == PatchStatus.CODE_REQ_CLEARPATCH){
//一鍵清除補丁狀態 回退版本
} else {
// 其它錯誤資訊, 檢視PatchStatus類說明
Log.i(TAG," 其它錯誤資訊, 檢視PatchStatus類說明");
}
}
}).initialize();
}
// 在WinnerApplicationn中呼叫了這裡就不需要了
// @Override
// public void onCreate() {
// super.onCreate();
// // queryAndLoadNewPatch不可放在attachBaseContext 中,否則無網路許可權
// SophixManager.getInstance().queryAndLoadNewPatch();//再原有的Application中加入獲取補丁包的方法onCreate()
//
// }
}
四、 AndroidManifest中引入程式碼:
android:name=".SophixStubApplication"
附上AndroidManifest的程式碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dotawang.sophixdemo">
<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"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<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">
<meta-data
android:name="com.taobao.android.hotfix.IDSECRET"
android:value="25060525" />
<meta-data
android:name="com.taobao.android.hotfix.APPSECRET"
android:value="94e9460d950eef1b3d39f179bee007f0" />
<meta-data
android:name="com.taobao.android.hotfix.RSASECRET"
android:value="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD6xfkkCKr2zCI7C3HeAecXVtSzh91QIx+wt5f0h46vTPCAlQglvQwhLOXMTrNV3iCx4VLQcp8YDgfNh85ftuZa2X89z2nVjpZzoXOZzxaIXANBmsVgt68v/tQ8uN2nUFK2uZmsPDsYmpjBjzo9XYhbWBr0b+tylmsj3T5c5avTiVUD55FLq/SiLTvfVtqxDvAIpCjZj6azg6ncs6nZ3LmotCt1jhmXZHL94qmZyRVo1nAhrurUSxKgqkQnsowjWyxOpOa0r22umWi7st9aA+PG3h2G1STN7IFoxUAAdNZM+WhAtT98uZA8s1BH8RuBQZbXPVQ/KPAC5shWrXgetIg7AgMBAAECggEAfcR0IuJF++h88mfW/6SspUPjAPcOw3YaGqK5DuY9ZSWNKK+Vmnepcan2xfRidJomg4+h3PDfYU0IFMgbdF1iQgX6jqFLTtNoGS3LsEPv5QtghrJ8cvksX0HKZ3m/kH30PbfvnjXG3ZwLKGgQqV4TWNxjCFxpFNrjeOUotaZp+nhThketIgGkOWiUVULmcKhPUEZIQh0P4SVQmO8KoVSKwMT1kuwSLQOyZ1jZsU+1dtj/5OJ8Fz/XKLljxPvqPaQidhAyY2VAVKm31w/z7zSIE+lmJ5aj1+mcL5hGbc1wXHS1KVkvNPJc0NsSL1Izt+roTDRlzeuhGYKz0jkuS4djYQKBgQD/2M2+NJPdGIsCrW0ZsK7deOvQAtoODcHj93z0LOvMKGyUHnH6wOLBbjwnUhJ+VdPddH4Zm4imRaH6WOO8FahkMvB1BIM1AsMFPa3kP+JDsHq+QT5Bqlg3kebkhliz3a7dLEKNKizeZo5thgihBzCAssQ2w0F96SPjvCHohZqszwKBgQD67GRp/dZGftkK4mll4HODbl81aZgzoEOs7Dn0A372Xrpg+dG2xaMgms9IWKaODPJh15LymzWlhT42sP68Kh/StwXJPJc9nCaL3OtBNQuqrTqTAzErvcDuw5x65WiSZAky5TrkzthzILLdwQhjd82abuWUuhv7BIPjKdGf0wFA1QKBgH11Sgawb6WmqFwKwQos+sK9zhz1mQn1MxPfw5VVBdfaJsxHVasZtNgXf0Xk2A69daQNwNw7ybmHQdOqjRopIKbp18H6EYEINqu2QDRCI2j//GCZS7cVmia91BRR0ON6nIn2bzgb616vub35UPftt5oUj2UvQElG7wN4uMP16BA/AoGBAPIuswQyAVxtFeMRgBTaO+OA5dfRoRtC9c6y+YRw01vLNixfMnAr9TSE9sem+KpmCJMy1BvgfjjRj6iN0G+gYLKp/6WpG3hVfEbF5TI8lpQXOk+mZxEGxm4s0p0zSmjwsIg1A1DP683Co6CwrP4EJaeGnYOc1WDDjN/1/uM5bx45AoGBAIAZf1IY0ODHkAjasdUTk1Kuggu2JWp+nrVcZewVEf0U1iOp4zl2+SmiUMkYIsu514nxoVTbjF4cNI6puFSIGFUCjqylIAx4vqDUNiTbHm5cs7JNYm3ktNrF8CumtK/XlQC2R19CY5pEJ8goeqaArgVTvwhscLM1CVSTZPnsuLZb" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
五、proguard-rules.pro混淆程式碼的匯入
#基線包使用,生成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
#匯入阿里熱修復Utils時混淆出錯新增
-dontwarn com.alibaba.sdk.android.utils.**
-keep class android.support.multidex.**{*;}
-keep class com.hundsun.winner.application.base.WinnerApplication {
public <init>();
}
-keep class com.hundsun.winner.application.base.SophixStubApplication$RealApplicationStub
六、.gitignore忽略程式碼的新增
.DS_Store
*.swp
# Gradle
/build
.gradle/
target/
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
# sonar
.sonar/
# Android
local.properties
nohup.out
到這裡基本就結束了,下面的就剩下完成你要的簽名包了,這些你直接應用我專案裡面的也行,自己換也可以
注意的地方就是匯入依賴這裡:
1、報錯Error:Execution failed for task ‘:app:preDebugAndroidTestBuild’
解決方法就是加入程式碼:
androidTestCompile('com.android.support:support-annotations:26.1.0') {
force = true
}
2、報錯can’t find superclass or interface com.ut.mini.IUTApplication或者can’t find superclass or interface com.alibaba.sdk.android.beacon.Beacon$OnUpdateListener這些類似的情況
解決方法是:
在混淆規則中新增-dontwarn com.alibaba.sdk.android.utils.**即可解決
3、如果出現簽名打的包無法安裝的問題,而不整合熱修復時專案是可以安裝的問題的話,那就只有一種可能(前提是用的同一種機型安裝的apk),看下圖:
記得將V1和V2都勾選上,否則就會出現上面的情況,具體原因不知道,反正個人感覺有點反人類。
4、報錯Error:Error: Expected resource of type color [ResourceType]
出現原因是:個人開始以為是專案中某些東西寫的不規範導致的,但是不整合阿里熱修復時是可以正常執行的,後來整合過後就出這問題了,開始懷疑阿里的熱修復對規則有要求,最終反編譯才知道是自己新增的混淆規則中有東西寫錯了
解決方法:
看下圖
這裡的包名一定要是你專案中的對應的類的路徑,否則按照阿里雲熱修復整合文件上的複製來會出問題的(吐槽下:文件這裡都不標註下這裡要改為自己的包名的,還命名的跟三方的某個名字似的,不知道的真的容易被坑到)