1. 程式人生 > >阿里熱修復之Sophix——公有云釋出版整合步驟

阿里熱修復之Sophix——公有云釋出版整合步驟

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]
出現原因是:個人開始以為是專案中某些東西寫的不規範導致的,但是不整合阿里熱修復時是可以正常執行的,後來整合過後就出這問題了,開始懷疑阿里的熱修復對規則有要求,最終反編譯才知道是自己新增的混淆規則中有東西寫錯了
解決方法:
看下圖
這裡寫圖片描述
這裡的包名一定要是你專案中的對應的類的路徑,否則按照阿里雲熱修復整合文件上的複製來會出問題的(吐槽下:文件這裡都不標註下這裡要改為自己的包名的,還命名的跟三方的某個名字似的,不知道的真的容易被坑到)

我的demo的github地址,有需要的可以自取:https://github.com/gitwangyang/SophixDemo.git

有問題歡迎諮詢:QQ824553938