android 热补丁 增量更新 区别,andfix 增量升级更新 热补丁修复
本文转自:http://blog.csdn.net/ityangjun/article/details/49097621最近想着Android有没有什么热补丁更新技术的实现,于是上网搜索。接着实现了这一功能后,记录一下,免得自己忘了,可能文章会有出错的地方,望指出,呵呵搜索发现有这3种方式可以实现(至于其他的方式,暂不清楚)1.dexposedgithubhttps://github....
本文转自:http://blog.csdn.net/ityangjun/article/details/49097621
最近想着Android有没有什么热补丁更新技术的实现,于是上网搜索。接着实现了这一功能后,记录一下,免得自己忘了,可能文章会有出错的地方,望指出,呵呵
搜索发现有这3种方式可以实现(至于其他的方式,暂不清楚)
1.dexposed github https://github.com/alibaba/dexposed
2.andfix github https://github.com/alibaba/AndFix
3.bsdiff http://blog.csdn.net/lazyer_dog/article/details/47173013
dexposed和andfix是alibaba的开源项目,都是apk增量更新的实现框架,目前dexposed的兼容性较差,只有2.3,4.0~4.4兼容,其他Android版本不兼容或未测试,详细可以去dexposed的github项目主页查看,而andfix则兼容2.3~6.0,所以就拿这个项目来实现增量更新吧。至于bsdiff,只是阅览了一下,还没研究过。
首先 git clone github https://github.com/alibaba/AndFix,将andfix项目下载下来,Android studio可以在build.gradle里导入andfix,
compile 'com.alipay.euler:andfix:0.3.1@aar'
但是我是使用module的方式添加andfix,这样可以直接查看编辑源码,而且直接gradle导入的话还有个问题,后面再说。
andfix项目里有sample,导入也行,自己新建也行,我是自己新建项目,接着导入andfix作为module,demo里就两个类,mainactivity和myapplication
andfix里有些文件夹不用导入的,例如tools,doc等,记得新建jniLibs文件夹,libs里的so文件移到jniLibs里。
public classMainApplication extendsApplication {
private static finalString TAG= "euler";private static finalString APATCH_PATH= "/out.apatch";private static finalString DIR= "apatch";//补丁文件夹/*** patch manager*/privatePatchManager mPatchManager;@Overridepublic voidonCreate() {
super.onCreate();// initializemPatchManager= newPatchManager(this);mPatchManager.init("1.0");Log.d(TAG,"inited.");// load patchmPatchManager.loadPatch();// Log.d(TAG, "apatch loaded.");// add patch at runtimetry{
// .apatch file pathString patchFileString = Environment.getExternalStorageDirectory()
.getAbsolutePath() + APATCH_PATH;mPatchManager.addPatch(patchFileString);Log.d(TAG,"apatch:"+ patchFileString + " added.");//这里我加了个方法,复制加载补丁成功后,删除sdcard的补丁,避免每次进入程序都重新加载一次File f = newFile(this.getFilesDir(),DIR+ APATCH_PATH);if(f.exists()) {
booleanresult = newFile(patchFileString).delete();if(!result)
Log.e(TAG,patchFileString + " delete fail");}
} catch(IOException e) {
Log.e(TAG,"",e);}
}
public classMainActivity extendsActivity {
private static finalString TAG= "euler";@Overridepublic voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);toast();}
@Overrideprotected voidonDestroy() {
super.onDestroy();android.os.Process.killProcess(android.os.Process.myPid());}
//旧方法,1.apk private voidtoast() { Toast.makeText(this,"old",Toast.LENGTH_SHORT).show();}}
刚刚说的直接在gradle里导入andfix会有个问题,是在原来的项目中,加载一次补丁后,out.apatch文件会copy到getFilesDir目录下的/apatch文件夹中,在下次补丁更新时,会检测补丁是否已经添加在apatch文件夹下,已存在就不会复制加载sdcard的out.apatch。
原来的addpath方法
public voidaddPatch(String path) throwsIOException {
File src = newFile(path);File dest = newFile(mPatchDir,src.getName());if(!src.exists()){
throw newFileNotFoundException(path);}
if(dest.exists()) {
Log.d(TAG,"patch ["+ path + "] has be loaded.");return;}
FileUtil.copyFile(src,dest);// copy to patch's directoryPatch patch = addPatch(dest);if(patch != null) {
loadPatch(patch);}
}
修改后,判断apatch下的out.apatch存在即删除掉,重新复制加载sdcard下的out.apatch
public voidaddPatch(String path) throwsIOException {
File src = newFile(path);File dest = newFile(mPatchDir,src.getName());if(!src.exists()) {
throw newFileNotFoundException(path);}
if(dest.exists()) {
Log.d(TAG,"patch ["+ src.getName() + "] has be loaded.");booleandeleteResult = dest.delete();if(deleteResult)
Log.e(TAG,"patch ["+ dest.getPath() + "] has be delete.");else{
Log.e(TAG,"patch ["+ dest.getPath() + "] delete error");return;}
}
FileUtil.copyFile(src,dest);// copy to patch's directoryPatch patch = addPatch(dest);if(patch != null) {
loadPatch(patch);}
}
还有源码混淆
-optimizationpasses5 #指定代码的压缩级别-dontusemixedcaseclassnames#是否使用大小写混合-dontskipnonpubliclibraryclasses#是否混淆第三方jar-dontpreverify#混淆时是否做预校验-verbose#混淆时是否记录日志-optimizations!code/simplification/arithmetic,!field/*,!class/merging/* #混淆时所采用的算法#重要,別忘了這些,不混淆andfix包,不混淆native方法-dontwarnandroid.annotation
-dontwarncom.alipay.euler.**
-keepclass com.alipay.euler.** {*;}
-keepclass * extends java.lang.annotation.Annotation
-keepclasseswithmembernamesclass * {
native ;}
接着打包1.apk,
然后修改mainactivity的toast(),打包2.apk
//修改Toast內容,2.apkprivate voidtoast() {
Toast.makeText(this,"new",Toast.LENGTH_SHORT).show();}
cmd输入命令,具体参数看usage
如无错误,编译后会生成一个apatch文件,改名成out.apatch
安装打开1.apk
关闭app,将out.apatch放sdcard根目录后,重新打开app,toast方法改变了
ps:
1. 这里只是简单的测试了一下,没有复杂的功能,而且andfix不支持布局资源等的修改。
2. github主页的issues反应说Android4.0.4,以及5.0以上版本会crash,不过我使用了两个虚拟机,genymotion的4.2和5.0虚拟机,没有错误,其他请自测
3. 使用了apk加固时(360加固,百度加固等等),发现在加固前要先apkpatch制作补丁,不能使用加固后的apk制作,否则补丁无法使用,但是在加固前制作的补丁可以很容易的被反编译出源码
demo下载 http://download.csdn.net/detail/ityangjun/9177377
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)