from : http://blog.csdn.net/liubaill/article/details/51322808
总结一下热修复框架nuwa的使用和,使用过程中遇到的问题https://github.com/jasonross/Nuwa
文中demo位置https://github.com/nononopro/nuwaExample
配置
1.在project的biuld.gradle中加入
<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">classpath <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'cn.jiajixin.nuwa:gradle:1.2.2'</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
之后我们的文件类似于这样
<code class="hljs lua has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> repositories {
jcenter()
}
dependencies {
classpath <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.tools.build:gradle:1.2.1'</span>
// NOTE: Do <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> place your application dependencies here; they belong
// <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> the individual <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">module</span> build.gradle files
classpath <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'cn.jiajixin.nuwa:gradle:1.2.2'</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>
2.在app的build.gradle添加
<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'cn.jiajixin.nuwa:nuwa:1.0.0'</span>
apply plugin: <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"cn.jiajixin.nuwa"</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
然后构建,注意如果构建过程中出现错误
Error:Cannot get property 'taskDependencies' on null object
是因为gradle版本是1.5将其回退到1.2.1
3.在项目的BaseApplication中添加
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">attachBaseContext</span>(Context <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">base</span>) {
super.attachBaseContext(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">base</span>);
Nuwa.init(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
到此基本配置完成,这个过程可能会遇到一些问题我们后边再说。
使用
使用很简单Nuwa.loadPatch(this,patchFile)
需要加载的地方加载你的补丁包patch.jar,通常在app启动的时候。这里我放在BaseApplication里
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">BaseApplication</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Application</span> {</span>
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">attachBaseContext</span>(Context base) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.attachBaseContext(base);
Nuwa.init(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
Nuwa.loadPatch(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, Environment.getExternalStorageDirectory().getAbsolutePath().concat(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/patch.jar"</span>));
Log.e(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"nuwa"</span>,Environment.getExternalStorageDirectory().getAbsolutePath().concat(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/patch.jar"</span>));
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
补丁包的制作
以我的demo为例,MyApplication编译运行然后进入C:\MyProject\MyApplication\app\build\outputs`将文件夹下的nuwa文件夹拷贝到一个目录下,我们这里拷贝到C:\nuwa,现在将项目拷贝一份放入其它目录修改其中的类,相当于改bug的过程,修改完成后进入项目根目录如图
![这里写图片描述](https://img-blog.csdn.net/20160505142842998)
在这里打开命令窗口输入
<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">gradlew clean nuwaDebugPatch -<span class="hljs-constant" style="box-sizing: border-box;">P</span> <span class="hljs-constant" style="box-sizing: border-box;">NuwaDir</span>=<span class="hljs-constant" style="box-sizing: border-box;">C</span><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:/nuwa</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
会在当前工程的app\build\outputs\nuwa\debug目录下生成补丁包patch.jar
将补丁包copy进手机adb push patch.jar /sdcard/,这个补丁包正常应该放在服务器,下载得到。
重启app,可以看到补丁包被正确加载
使用过程中遇到的一些问题汇总
1.刚才说过的Error:Cannot get property 'taskDependencies' on null object
gradle版本1.5会报这个错,回退至1.2.1解决
2.运行报错
<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-constant" style="box-sizing: border-box;">Error</span><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:Execution</span> failed <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> task <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">':app:nuwaClassBeforeDexDebug'</span>.
> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
解决方法将debug模式也添加混淆
`buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
3.打包时作者给的命令是./gradlew clean nuwaQihooDebugPatch -P NuwaDir=/Users/jason/Documents/nuwa
后边的NuwaDir我们知道了就是我们拷贝出来的nuwa文件夹的路径,nuwaQihooDebugPatch 注意这个参数其中的qihoo是根据渠道生成的,我们自己如果不指定渠道没这个文件夹自然会找不到路径,我这里没有设置所以是这样gradlew clean nuwaDebugPatch -P NuwaDir=C:/nuwa
4.Could not find class ‘cn.jiajixin.nuwa.Hack’, referenced from method a.a.a.a.b.解决:proguard-rules.pro中加入-keep class cn.jiajixin.nuwa.** { *; }
防止被混淆
5.E/nuwa: /storage/emulated/0/patch.jar is null如果你的读取路径都没问题看一下权限是否打开
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">uses-permission</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"android.permission.READ_EXTERNAL_STORAGE"</span> /></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
6.java.lang.NoClassDefFoundError: cn.jiajixin.nuwa.Hack 如果报这个错那么将你的报错的BaseApliication在app的gradle中如下配置,nuwa{ }与android{}平级
nuwa {
excludeClass = ['BaseApplication.class']
}
其他框架
除了nuwa之外还有其他开源框架,之前看的是https://github.com/dodola/HotFix
打包什么的不是自动化,必须手动的将改动文件提取打包,可用性太低。
参考链接
https://github.com/jasonross/Nuwa/issues
https://github.com/jasonross/Nuwa
https://zhuanlan.zhihu.com/p/20308548
想看源码讲解的话看看这个博主的文章Android 热修复Nuwa的原理及Gradle插件源码解析