在网上看到很多热修复的文章,由于本人水平有限,在这里只讲解流程以及怎么实现,原理自己在网上找吧。
热修复方案有很多,比较有名的就是阿里巴巴的dexposed,AndFix以及QQ的Dex分包方案HotFix,Nuwa,DroidFix,在这里讲下AndFix和Nuwa的使用。
在使用这两个热修复框架之前先简单介绍下:
AndFix:全称是Android hot-fix。是阿里开源的一个Android热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug。支持Android 2.3 到 6.0。
Nuwa:Nuwa,采用纯Java实现,能够热修复你的Android应用.
1.Nuwa的实现(注意:nuwa打出来的patch.jar在手机本地不能删除,如果删除则app又会回到之前有bug的状态):
第一步:在AndroidManifest中添加权限uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” 。
第二步:在工程的根目录的build.gradle文件中的dependencies中添加 classpath ‘cn.jiajixin.nuwa:gradle:1.2.2’,如下图
第三步:在app的build.gradle中添加依赖SDK:compile ‘cn.jiajixin.nuwa:nuwa:1.0.0’和apply plugin: “cn.jiajixin.nuwa”如下图:
好了我们的配置就完了,但是可能你会报Error:Cannot get property ‘taskDependencies’ on null object这样的错误,其解决方法是将Gradle Plugin的版本降低至1.2.3就可以了,当然Gradle Version也要相应的降低至2.8。如下图:
下面就是使用nuwa了:
第四步:使用nuwa开始热更新代码的编写
MainActivity:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView textView;
BugClass bugClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.hello);
bugClass = new BugClass();
textView.setText(bugClass.bug());
}
}
BugClass:
public class BugClass {
String bug(){
return "f";
}
}
BaseApplication:
public class BaseApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
Nuwa.init(this);
Nuwa.loadPatch(this, Environment.getExternalStorageDirectory().getAbsolutePath().concat("/patch.jar"));
Log.e("nuwa",Environment.getExternalStorageDirectory().getAbsolutePath().concat("/patch.jar"));
}
}
一定要记得在清单文件中写上android:name=”.BaseApplication”,不然不会加载差分包。如下图:
在这里我们要注意下:
这里有个需要注意的地方是自定义Application必须是直接继承自Application的类,如若自定义类AClazz继承自Application,又自定义类BClazz继承自AClazz并在注册表声明为BClazz,那么就会出现以下异常。也就是我们的初始化操作必须放在直属继承Application的AClazz当中。如下图:
第五步:运行app
注意:运行过程中可能会中途报错Execution failed for task ‘app:nuwaClassBeforeDexDebug’并在控制台将会输出以下信息
为解决以上遇到的问题,我们需要在app底下的build.gradle中加入multiDexEnabled true,如下图:
运行完app,在app\build\output目录下复制nuwa文件夹到任意位置,例如C:\nuwa,可以再项目工作空间复制也可以在studio中复制:
现在我们手机运行的是有bug的app,现在我们需要打patch.jar包放在手机根目录去修复这个bug,也就是和我们说的热修复(注:我这里是为了方便在sd卡中放patch.jar,在项目中你就要从你们的服务器中下载patch.jar)。
第六步:首先赶紧把你的有bug的地方改了(在这里我是把BugClass中返回的数值改了),看到别的文章建议是在执行命令前都应该先Clean以下项目(app\bulid\outputs\ 内容将重置),那我们就clear下,然后执行命令:
运行cmd–>切换到项目根目录(根目录下存在gradlew与gradlew.bat两个文件)–>执行命令(因为没有mac,所以…,但是windows亲测可以):
Mac:gradlew clean nuwaDebugPatch -P NuwaDir=C:\nuwa
Windows:gradlew.bat clean nuwaDebugPatch -P NuwaDir=C:\nuwa
然后就ok啦,去app\build\outputs\nuwa\debug目录下找到patch.jar文件,将这个文件放到手机sd卡根目录中,重新启动app就可以看到你刚才改的效果了。但是注意:在执行 Mac:gradlew clean nuwaDebugPatch -P NuwaDir=C:\nuwa
Windows:gradlew.bat clean nuwaDebugPatch -P NuwaDir=C:\nuwa命令时可能会出现这样的错误:
不要着急,我们在cdm命令中输入set ANDROID_HOME=D:/android/sdk ,等号后面的是你的sdk路径,执行完此命令然后再执行一遍 Mac:gradlew clean nuwaDebugPatch -P NuwaDir=C:\nuwa
Windows:gradlew.bat clean nuwaDebugPatch -P NuwaDir=C:\nuwa
,看看是否还会出现刚才的问题,不会出现啦(注意:你在执行命令之前一定要把你的bug改了,不然不会出现patch.jar),现在去app\build\outputs\nuwa\debug文件夹下找到patch.jar,将patch.jar放到sd卡根目录下,赶紧重启app见证奇迹吧。
2.AndFix的实现
第一步:在清单文件中加
uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE”
uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”
在清单文件Application中加 android:name=”.AppContext”
第二步:
在app的build.gradle文件的dependencies中加:
compile 'com.alipay.euler:andfix:0.3.1@aar'
第三步:写代码:
AppContext.java:
public class AppContext extends Application {
String apatch_path = "/out.apatch";
String path_all = "";
private PatchManager patchManager;
@Override
public void onCreate() {
super.onCreate();
patchManager = new PatchManager(this);//初始化 PatchManager
patchManager.init(BuildConfig.VERSION_CODE + "");
patchManager.loadPatch();//Load patch 加载补丁
try {
path_all = "/sdcard" + apatch_path;
File file = new File(path_all);
if (file.exists()) {
Log.e("path exists" , file.getPath());
patchManager.addPatch(path_all);//Add patch 添加补丁
} else {
Log.e("path unexists", path_all + "========");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
setTextFixAfter();
}
private void setTextFixAfter() {
textView.setText("andfix热修复之前");
}
}
第四步:下载工具:AndFix 提供了一个补丁创建工具 apkpatch
如何使用这个工具:
1.将下载的apkpatch.zip工具解压在某一个文件夹。
2.准备两个apk,一个是线上的apk,另一个是修复了bug的apk(测都这两个apk都是使用带签名的,不知道不带签名的会不会成功),将这两个apk放在apkpatch工具解压的文件夹下.
3.这个工程的签名文件*.jks也放在apkpatch工具解压的文件夹下.
4.执行命令apkpatch.bat -f -t -o -k -p <> -a -e <>注意: 1.执行上述命令时,记得一定要cd到apkpatch-1.0.3目录下,然后再输入命令
这里是我的apkpatch解压目录(包含两个apk以及签名文件):
这里是我的命令:
第五步:在apkpatch工具解压的文件夹下有一个output文件夹,在这个文件夹中有一个.apath结尾的文件,修改这个文件的名字为out,即:out.apath.
第六步:手机上卸载你修改bug后的app,将修改bug前的apk放到sd卡上并且安装运行看效果,然后再把out.apatch文件放在手机sd卡根目录上,重启apk查看效果,看看和之前的效果是否一样,如果上述步骤正确,重启app后肯定是修改后的app的效果.
好了,Nuwa和Andfix热修复框架就讲解完了,有什么不对的请大家指出来,我们一起学习一起进步。