package xuanli.hbdx.xj.tvjoy.cn.study_hotfix.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Comparator;
import dalvik.system.BaseDexClassLoader;
import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* author 岳明明
* description
* Created by yzm on 2017/9/5.
*/
public class PatchFixUtil {
private static PatchFixUtil mPatchUtil ;
private static final String TAG = PatchFixUtil.class.getSimpleName() ;
private static final String PATCH_CODE = "patch_code" ;
private static final String PATCH_CONFIG = "patch_config" ;
private OkHttpClient mClient ;
//检测补丁链接
private static final String CHECK_URL = "http://192.168.2.121:8080/examples/hotfix/config/config.json" ;
//补丁保存地址(文件夹)
private String patchPath ;
//hack.dex存放地址
private String hackPath ;
//补丁优化释放地址
private String optPath ;
private Context context ;
private String patchCode ;
private String patchUrl ;
private PatchFixUtil(Context context){
this.context = context.getApplicationContext() ;
mClient = new OkHttpClient() ;
initPatchPaths();
loadHackDex() ;
}
/**
*初始化补丁路径
*/
private void initPatchPaths(){
// /data/data/com.yam.tet/app_hack
File fHackPath = context.getDir("hack", Context.MODE_PRIVATE) ;
createDirs(fHackPath);
hackPath = fHackPath.getAbsolutePath() ;
File fPatchPath = context.getDir("patch", Context.MODE_PRIVATE) ;
createDirs(fPatchPath);
patchPath = fPatchPath.getAbsolutePath() ;
File fOptPath = context.getDir("opt", Context.MODE_PRIVATE) ;
createDirs(fOptPath);
optPath = fOptPath.getAbsolutePath() ;
}
/**
* 创建文件夹
* @param file
*/
private void createDirs(File file){
if(!file.exists()){
file.mkdirs() ;
}
}
public static PatchFixUtil getInstance(Context context){
synchronized (PatchFixUtil.class){
if(mPatchUtil == null){
mPatchUtil = new PatchFixUtil(context) ;
}
}
return mPatchUtil ;
}
private void loadHackDex(){
//判断hack.dex是否存在
File hack = new File(hackPath+File.separator+"hack.dex") ;
if(!hack.exists()){
//从Assets文件夹中拷贝到“hackPath”
copyHackDex(hack);
//加载hack.dex
load(hack);
}else{
//加载hack.dex
load(hack);
}
Log.d(TAG, "hack.dex加载完成...") ;
}
/**
* 复制hack.dex到安全文件夹
* @param hack
* @return
*/
private boolean copyHackDex(File hack){
Log.d(TAG,"copy hack.dex...") ;
try {
OutputStream os = new FileOutputStream(hack) ;
InputStream is = context.getAssets().open("hack.dex") ;
int len ;
byte[] buffer = new byte[1024] ;
while((len=is.read(buffer,0,buffer.length))!=-1){
os.write(buffer, 0, len);
}
os.close();
is.close();
Log.d(TAG,"copy hack.dex finish...") ;
return true ;
} catch (Exception e) {
e.printStackTrace();
}
return false ;
}
/**
* 加载hack.dex和所有补丁包
*/
private void load(File hack) {
loadPatch(hack);
fixPatch() ;
}
/**
* 操作补丁相关
*/
public void doPatchFix(){
//检测是否存在补丁包
Request request = new Request.Builder()
.get()
.url(CHECK_URL)
.build() ;
Call call = mClient.newCall(request) ;
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "check patch failed....") ;
}
@Override
public void onResponse(Call call, Response response) throws IOException {
JSONObject jsonObject = JSON.parseObject(response.body().string());
patchCode = jsonObject.getString("patchCode") ;
Log.d(TAG, "pathCode:"+patchCode) ;
//判断是否存在补丁
if(!"-1".equals(patchCode)){
//判断当前补丁是否已经下载过
if(isFixed()){
Log.d(TAG, "this version pathCode is fixed...") ;
fixPatch();
}else{
//获取补丁链接
patchUrl = jsonObject.getString("patchUrl") ;
//开启补丁下载
downLoadPatch() ;
}
}
}
});
}
/**
* 下载补丁
*/
private void downLoadPatch() {
Request request = new Request.Builder()
.get()
.url(patchUrl)
.build() ;
Call call = mClient.newCall(request) ;
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "the patch download failed...") ;
Log.d(TAG, e.getMessage()) ;
}
@Override
public void onResponse(Call call, Response response) throws IOException {
byte[] buffer = new byte[2048] ;
int len = 0 ;
OutputStream os = new FileOutputStream(patchPath+File.separator+patchCode+".dex") ;
InputStream is = response.body().byteStream() ;
Log.d(TAG, "start download patch...") ;
while((len=is.read(buffer,0,buffer.length))!=-1){
os.write(buffer,0, len);
}
os.close();
is.close();
Log.d(TAG, "download patch finish...") ;
Log.d(TAG, "start fixed patch...") ;
}
});
}
/**
* 修复补丁(热修复的核心代码)
* 几个知识点:
*
* 1. Android类加载机制中2个重要类加载器:”PathClassLoader“和”DexClassLoader“均继承自BaseDexClassLoader
* PathClassLoader:用于加载系统类(类均在dex文件中),PS:app运行时,会一并将本app所有类加载
* DexClassLoader:用于加载应用类,我们自己的动态加载的类
*
* 2. 系统运行APP的时候,会用“PathClassLoader”装载运行该app所有需的dex,从java层面,这个过程我们是无法干预的
*
* 3. 当app运行中,用到某个类A的时候,PathClassLoader会去查找自己的PathList中的Element[]数组中查找类A,
* 一旦找到,立马返回,不去管Element[]数组中是否还有一个类A
*
* 4. 通过源码,可知道Element类,是PathList的一个内部类,其中存储的是dex文件、dex路径等等,找类A的真正实现,
* 是通过本地方法从dex文件中查找的。结论:用到某个类时,PathClassLoad
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
通过类加载机制动手实现Android热修复 (188个子文件)
gradlew.bat 2KB
fileSnapshots.bin 17.7MB
fileHashes.bin 487KB
taskArtifacts.bin 409KB
fileSnapshots.bin 72KB
taskArtifacts.bin 43KB
localClassSetAnalysis.bin 41KB
localClassSetAnalysis.bin 28KB
localClassSetAnalysis.bin 26KB
localJarClasspathSnapshot.bin 22KB
fileHashes.bin 22KB
localClassSetAnalysis.bin 21KB
localClassSetAnalysis.bin 21KB
localJarClasspathSnapshot.bin 20KB
localJarClasspathSnapshot.bin 20KB
localJarClasspathSnapshot.bin 19KB
localJarClasspathSnapshot.bin 19KB
built.bin 0B
hack.dex 472B
.gitignore 127B
.gitignore 8B
.gitignore 8B
build.gradle 2KB
build.gradle 851B
build.gradle 521B
build.gradle 205B
settings.gradle 47B
gradlew 5KB
Inject.groovy 4KB
PreDexTransform.groovy 3KB
JarZipUtil.groovy 3KB
Register.groovy 449B
Study-Hotfix.iml 10KB
hack.iml 10KB
BuildSrc.iml 7KB
MyHotfix.iml 885B
mockable-android-26.jar 24.38MB
gradle-wrapper.jar 52KB
PatchFixUtil.java 14KB
CheckHotfix.java 10KB
PatchFix.java 4KB
Activity2.java 1KB
MainActivity.java 1KB
HotfixConfig.java 844B
ExampleInstrumentedTest.java 802B
People.java 799B
ExampleInstrumentedTest.java 767B
HotfixCallBack.java 606B
Student.java 476B
MyApplication.java 443B
ExampleUnitTest.java 430B
ExampleUnitTest.java 410B
AntilazyLoad.java 142B
localClassSetAnalysis.lock 17B
localClassSetAnalysis.lock 17B
localJarClasspathSnapshot.lock 17B
localJarClasspathSnapshot.lock 17B
localJarClasspathSnapshot.lock 17B
localJarClasspathSnapshot.lock 17B
localClassSetAnalysis.lock 17B
taskArtifacts.lock 17B
localClassSetAnalysis.lock 17B
taskArtifacts.lock 17B
localJarClasspathSnapshot.lock 17B
localClassSetAnalysis.lock 17B
cache.properties.lock 2B
ic_launcher_round.png 14KB
ic_launcher.png 10KB
ic_launcher_round.png 10KB
ic_launcher.png 8KB
ic_launcher_round.png 6KB
ic_launcher.png 5KB
ic_launcher_round.png 4KB
ic_launcher.png 3KB
ic_launcher_round.png 2KB
ic_launcher.png 2KB
proguard-rules.pro 965B
proguard-rules.pro 965B
gradle.properties 747B
local.properties 554B
gradle-wrapper.properties 236B
cache.properties 51B
profile-2017-09-11-12-35-42-472.rawproto 13KB
workspace.xml 289KB
misc.xml 2KB
activity_main.xml 1KB
AndroidManifest.xml 1KB
gradle.xml 739B
compiler.xml 686B
activity_2.xml 684B
exposed_instrumentation_api_publish_0_5.xml 653B
animated_vector_drawable_26_0_0_alpha1.xml 645B
support_vector_drawable_26_0_0_alpha1.xml 642B
espresso_idling_resource_2_2_2.xml 635B
support_media_compat_26_0_0_alpha1.xml 633B
support_core_utils_26_0_0_alpha1.xml 627B
support_fragment_26_0_0_alpha1.xml 621B
support_core_ui_26_0_0_alpha1.xml 618B
support_compat_26_0_0_alpha1.xml 615B
appcompat_v7_26_0_0_alpha1.xml 609B
共 188 条
- 1
- 2
资源评论
一个有梦想的屌丝程序员
- 粉丝: 31
- 资源: 7
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 毕业设计-仿生六足机器人的制作全教程源码+电子元器件+程序代码+线路组件图+安装教程+搭建视频教程
- 基于ROS和webots的xrobot机械臂仿真初探C++源码
- 基于ROS的点焊机器人仿真与控制python源码+文档说明+使用说明+详细注释
- 基于vue实现的细粒度交通时空大数据分析系统+源代码+文档说明
- 安卓大作业-基于Electron的交通时空大数据分析挖掘系统客户端(Android)+源代码+文档说明+界面截图
- 基于Java的朱氏集团客户关系管理系统设计源码
- 基于C++的作业提交与批改系统设计源码
- 基于Vue2的移动端电影资讯网站设计源码
- 高分课程设计作业-基于QT的模仿宝石迷阵游戏C++源码+文档说明+界面截图
- 基于Apache Spark的Spark DistCP重实现设计源码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功