1.MainActivity

import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.xinrui.hotfix.utils.FixBug;import com.xinrui.hotfix.utils.HotFix;public class MainActivity extends Activity implements View.OnClickListener{    private TextView fix_txt,show_txt;    private FixBug mFixMe;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        init();    }    public void init(){        fix_txt=(TextView)findViewById(R.id.fixtxt);        show_txt=(TextView)findViewById(R.id.show);        fix_txt.setOnClickListener(this);        show_txt.setOnClickListener(this);        mFixMe = new FixBug(MainActivity.this);    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.fixtxt:                checkFix();                break;            case R.id.show:                mFixMe.showWhat();                break;        }    }    private void checkFix(){        try {            String dexPath = Environment.getExternalStorageDirectory() + "/classes2.dex";            HotFix.fixDexFile(MainActivity.this, dexPath);            Toast.makeText(MainActivity.this, "修复成功", Toast.LENGTH_SHORT).show();        } catch (Exception e) {            Toast.makeText(MainActivity.this, "修复失败" + e.getMessage(), Toast.LENGTH_SHORT).show();            e.printStackTrace();        }    }}

2.activity_main.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">    <TextView        android:id="@+id/fixtxt"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="25sp"        android:text="修复"        android:layout_marginTop="100px"        android:layout_centerHorizontal="true"        android:layout_alignParentTop="true"/>    <TextView        android:id="@+id/notgril"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Not Gril!"        android:layout_centerInParent="true"        android:visibility="gone"/>    <ImageView        android:id="@+id/gril"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:visibility="gone"/>    <TextView        android:id="@+id/show"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="显示"        android:textSize="25sp"        android:layout_marginBottom="100px"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"/></RelativeLayout>

3.HotFix类

import java.io.File;import java.lang.reflect.Array;import java.lang.reflect.Field;import android.content.Context;import dalvik.system.DexClassLoader;import dalvik.system.PathClassLoader;/** * 作者:created by yufenfen on 2019/3/21:12:13 * 邮箱: ybyj1314@126.com */public class HotFix {    /**     * 修复指定的类     *     * @param context        上下文对象     * @param fixDexFilePath   修复的dex文件路径     */    public static void fixDexFile(Context context, String fixDexFilePath) {        if (fixDexFilePath != null && new File(fixDexFilePath).exists()) {            try {                injectDexToClassLoader(context, fixDexFilePath);            } catch (Exception e) {                e.printStackTrace();            }        }    }    /**     * @param context     * @param fixDexFilePath 修复文件的路径     * @throws ClassNotFoundException     * @throws NoSuchFieldException     * @throws IllegalAccessException     */    private static void injectDexToClassLoader(Context context, String fixDexFilePath)            throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {        //读取 baseElements        PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();        Object basePathList = getPathList(pathClassLoader);        Object baseElements = getDexElements(basePathList);        //读取 fixElements        String baseDexAbsolutePath = context.getDir("dex", 0).getAbsolutePath();        DexClassLoader fixDexClassLoader = new DexClassLoader(                fixDexFilePath, baseDexAbsolutePath, fixDexFilePath, context.getClassLoader());        Object fixPathList = getPathList(fixDexClassLoader);        Object fixElements = getDexElements(fixPathList);        //合并两份Elements        Object newElements = combineArray(baseElements, fixElements);        //一定要重新获取,不要用basePathList,会报错        Object basePathList2 = getPathList(pathClassLoader);        //新的dexElements对象重新设置回去        setField(basePathList2, basePathList2.getClass(), "dexElements", newElements);    }    /**     * 通过反射先获取到pathList对象     *     * @param obj     * @return     * @throws ClassNotFoundException     * @throws NoSuchFieldException     * @throws IllegalAccessException     */    private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException,            IllegalAccessException {        return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");    }    /**     * 从上面获取到的PathList对象中,进一步反射获得dexElements对象     *     * @param obj     * @return     * @throws NoSuchFieldException     * @throws IllegalAccessException     */    private static Object getDexElements(Object obj) throws NoSuchFieldException, IllegalAccessException {        return getField(obj, obj.getClass(), "dexElements");    }    private static Object getField(Object obj, Class cls, String str)            throws NoSuchFieldException, IllegalAccessException {        Field declaredField = cls.getDeclaredField(str);        declaredField.setAccessible(true);//设置为可访问        return declaredField.get(obj);    }    private static void setField(Object obj, Class cls, String str, Object obj2)            throws NoSuchFieldException, IllegalAccessException {        Field declaredField = cls.getDeclaredField(str);        declaredField.setAccessible(true);//设置为可访问        declaredField.set(obj, obj2);    }    /**     * 合拼dexElements ,并确保 fixElements 在 baseElements 之前     *     * @param baseElements     * @param fixElements     * @return     */    private static Object combineArray(Object baseElements, Object fixElements) {        Class componentType = fixElements.getClass().getComponentType();        int length = Array.getLength(fixElements);        int length2 = Array.getLength(baseElements) + length;        Object newInstance = Array.newInstance(componentType, length2);        for (int i = 0; i < length2; i++) {            if (i < length) {                Array.set(newInstance, i, Array.get(fixElements, i));            } else {                Array.set(newInstance, i, Array.get(baseElements, i - length));            }        }        return newInstance;    }}

4.FixBug 类

import android.app.Activity;import android.content.Context;import android.util.Log;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.xinrui.hotfix.R;public class FixBug {    private final String TAG = "FixBug";    private ImageView mBelle;    private TextView mNotShow;    private Context mContext;    //false: bug, true: fix    private boolean fix = false;    public FixBug(Activity context) {        mContext = context;        mBelle = (ImageView) context.findViewById(R.id.gril);        mNotShow = (TextView) context.findViewById(R.id.notgril);    }    public void showWhat() {        if (fix) {            fixBug();            Log.d(TAG, "fix bug!");        } else {            mBelle.setVisibility(View.GONE);            mNotShow.setVisibility(View.VISIBLE);            Log.d(TAG, "this is a bug!");        }    }    private void fixBug() {        try {            mBelle.setVisibility(View.VISIBLE);            mNotShow.setVisibility(View.GONE);            mBelle.setBackgroundResource(R.drawable.timg);        } catch (Exception e) {            e.printStackTrace();        }    }}

更多相关文章

  1. Android(安卓)获取手机信号
  2. Android获取SDK的版本信息
  3. 获取android联系人信息
  4. android版本更新代码
  5. android java获取当前时间的总结
  6. Android(安卓)获取网络图片
  7. Android(安卓)圆角矩形ImageView
  8. android 版本号比较大小
  9. Android(安卓)图片加载缓存

随机推荐

  1. 群统计v0.9: 特殊权重票,现场活动投票利器
  2. 如何尽快掌握Python?
  3. Redission 实现分布式锁
  4. 一文教你了解redis哨兵模式
  5. 不用***,如何查看国外技术文章
  6. Redis数据迁移的4种方法
  7. Python到底怎么读?
  8. 多线程学习(二) 多线程创建4种方式
  9. 多线程学习(一) 线程与进程的理解
  10. Error reading device /dev/bakupvg/baku