Android热修复之阿里Sophix的使用详解

阿里Spohix简介

阿里巴巴对Android热修复技术已经进行了长达多年的探索。

最开始,是手淘基于Xposed进行了改进,产生了针对Android Dalvik虚拟机运行时的Java Method Hook技术,Dexposed。但这个方案由于对底层Dalvik结构过于依赖,最终无法继续兼容Android5.0以后ART虚拟机,因此作罢。

后来支付宝提出了新的热修复方案Andfix。Andfix同样是一种底层结构替换的方案,也达到了运行时生效即时修复的效果,并且重要的是,做到了Dalvik和ART环境的全版本兼容。阿里百川结合手淘在实际工程中使用Andfix的经验,对相关业务逻辑解耦后,推出了阿里百川Hotfix方案,并得到了良好的反响。

此时的百川Hotfix已经是一个很不错的产品了,对于基本的代码修复需求都可以解决,安全性和易用性都做的比较好。然而,它所依赖的基石,Andfix本身,是有局限性的。且不说其底层固定结构的替换方案稳定性不好,其使用范围也存在着诸多限制,虽然可以通过改造代码绕过限制来达到相同的修复目的,但这种方式既不优雅也不方便。而更大的问题是,Andfix只提供了代码层面的修复,对于资源和so的修复都还未能实现。

再看一下同期的其他热修复方案,此时的热修复技术可谓是百花齐放,微信的Tinker、QQ空间的Nuwa、饿了么的Amigo、美团的Robust等等,各个热修复方案争相发布,都声称自己可以做到全方位全功能的热修复。不过他们各自有自身的局限性,或者不够稳定,或者补丁过大,或者效率低下,或者使用起来过于繁琐,大部分技术上看起来似乎可行,但实际体验并不好。而在我们看来,有很多技术细节能够做得更加完美。

终于在2017年6月11日,手淘技术团队联合阿里云正式发布了新一代Android移动热修复方案——Sophix。

Sophix的横空出世,将会打破各家热修复技术纷争的局面。我们可以满怀信心地说,在Android热修复的三大领域:代码修复、资源修复、so修复方面,以及方案的安全性和易用性方面,Sophix都做到了业界领先.

阿里Spohix使用

Android热修复之阿里Sophix的使用详解_第1张图片
Android热修复之阿里Sophix的使用详解_第2张图片
Android热修复之阿里Sophix的使用详解_第3张图片

首先我们在阿里云创建Demo后,然后创建Android Sophix demo

第一步

我们在project下build.gradle中添加依赖
// 添加emas-services插件
classpath ‘com.aliyun.ams:emas-services:1.0.1’
//
maven { url ‘http://maven.aliyun.com/nexus/content/repositories/releases/’ }
Android热修复之阿里Sophix的使用详解_第4张图片
在app的build.gradle中添加依赖

apply plugin: ‘com.aliyun.ams.emas-services’

api ‘com.aliyun.ams:alicloud-android-hotfix:3.2.3’

repositories {
        maven {
            url "http://maven.aliyun.com/nexus/content/repositories/releases"
        }
    }

Android热修复之阿里Sophix的使用详解_第5张图片
Android热修复之阿里Sophix的使用详解_第6张图片

在清单文件中添加权限,6.0需要动态申请,还需要添加你在阿里云创建demo的App ID,App Secret,RSA密钥










如果需要混淆添加混淆代码

#基线包使用,生成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.**{*;}
-dontwarn com.alibaba.sdk.android.utils.**
#防止inline
-dontoptimize

创建SophixApllication

package com.sophix.demo;

import android.app.Application;
import android.content.Context;
import android.support.annotation.Keep;
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;
/**
 * Sophix入口类,专门用于初始化Sophix,不应包含任何业务逻辑。
 * 此类必须继承自SophixApplication,onCreate方法不需要实现。
 * 此类不应与项目中的其他类有任何互相调用的逻辑,必须完全做到隔离。
 * AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。
 * 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。
 * 如有其它自定义改造,请咨询官方后妥善处理。
 */
public class SophixStubApplication extends SophixApplication {
    private final String TAG = "SophixStubApplication";
    // 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
    @Keep
    @SophixEntry(MyRealApplication.class)
    static class RealApplicationStub {}
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
//         如果需要使用MultiDex,需要在此处调用。
//         MultiDex.install(this);
        initSophix();
    }
    private void initSophix() {
        String appVersion = "1.0.0";
        try {
            appVersion = this.getPackageManager()
                    .getPackageInfo(this.getPackageName(), 0)
                    .versionName;
        } catch (Exception e) {
        }
        final SophixManager instance = SophixManager.getInstance();
        instance.setContext(this)
                .setAppVersion(appVersion)
                .setSecretMetaData(null, null, null)
                .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, "sophix load patch success!");
                        } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
                            // 如果需要在后台重启,建议此处用SharePreference保存状态。
                            Log.i(TAG, "sophix preload patch success. restart app to make effect.");
                        }
                    }
                }).initialize();
    }
}

其中MyRealApplication是我们的真正的application,我们在其中做我们项目的初始化等操作

package com.sophix.demo;

import android.app.Application;
import com.taobao.sophix.SophixManager;

public class MyRealApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // queryAndLoadNewPatch不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻,如onCreate中
        SophixManager.getInstance().queryAndLoadNewPatch();
    }
}

然后我们在清单文件中将application添加

  android:name=".SophixStubApplication"

第二生成补丁

我们需要通过阿里云的一个工具生成补丁包

patch补丁包生成需要使用到打补丁工具SophixPatchTool, 如还未下载打包工具,请前往下载Android打包工具。
Mac版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_macos.zip
Windows版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_windows.zip
Linux版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_linux.zip
调试工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/hotfix_debug_tool-release.apk

Android热修复之阿里Sophix的使用详解_第7张图片
通过旧包和新包生成补丁,在阿里云平台上传补丁,这的应用版本需要和SophixStubApplication中 String appVersion = “1.0.0” 一致
Android热修复之阿里Sophix的使用详解_第8张图片
上传完成后,等一会就把BUG修复了
其实阿里云的Sophix文档写的很清楚傻瓜式接入,毕竟是收费的,下一篇介绍Sophix原理

你可能感兴趣的:(热修复)