patch

来源:互联网 发布:灵山大佛网络取票 编辑:程序博客网 时间:2024/05/22 00:51



public class PatchManager {private Context context;AndFixManager andFixManager;File src;public PatchManager(Context context) {this.context = context;init();}private void init() {andFixManager = new AndFixManager(context);}public void loadPatch(String patch) {src = new File(patch);Patch patch1 = new Patch(src, context);loadPatch(patch1);}public void loadPatch(Patch patch) {// PathClassLoaderClassLoader classLoader = context.getClassLoader();List<String> list;for (String name : patch.getPatchNames()) {list = patch.getClasses(name);andFixManager.fix(src, classLoader, list);}}}



public class Patch {    private static final String PATCH_CLASSES = "Patch-Classes";    private static final String ENTRY_NAME = "META-INF/PATCH.MF";    private File mFile;    private Map<String, List<String>> mClassMap;    private Context context;    public Patch(File mFile, Context context) {        this.mFile = mFile;        this.context = context;        init();    }    public Set<String> getPatchNames() {        return mClassMap.keySet();    }    public List<String> getClasses(String name) {        return mClassMap.get(name);    }    public File getmFile() {        return mFile;    }    private void init() {        JarFile jarFile = null;        InputStream inputStream = null;        mClassMap = new HashMap<String, List<String>>();        List<String> list = new ArrayList<String>();        try {            jarFile = new JarFile(mFile);            JarEntry jarEntry = jarFile.getJarEntry(ENTRY_NAME);            inputStream = jarFile.getInputStream(jarEntry);            Manifest manifest = new Manifest(inputStream);            Attributes main = manifest.getMainAttributes();            Attributes.Name attrName;            for (Iterator<?> ite = main.keySet().iterator(); ite.hasNext(); ) {                attrName = (Attributes.Name) ite.next();                if (attrName != null) {                    String name = attrName.toString();                    if (name.endsWith("Classes")) {                        list = Arrays.asList(main.getValue(name).split(","));                        if (name.equalsIgnoreCase(PATCH_CLASSES)) {                            mClassMap.put(name, list);                        } else {                            mClassMap.put(name.trim().substring(0, name.length() - 8), list);                        }                    }                }            }        } catch (Exception ex) {            Log.i("dongnao", ex.toString());        } finally {            try {                jarFile.close();                inputStream.close();            } catch (Exception e) {                e.printStackTrace();            }        }    }}


public class HandlerNative {    static {        System.loadLibrary("dongnaofix");    }    public static  native  void init(int api);    public  static  native  void replaceMethod(Method src,Method dest);}



public class AndFixManager {private Context context;private File optFile;public AndFixManager(Context context) {this.context = context;HandlerNative.init(Build.VERSION.SDK_INT);}public void fix(File file, final ClassLoader classLoader, List<String> list) {optFile = new File(context.getFilesDir(), file.getName());if (optFile.exists()) {optFile.delete();}try {final DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(),optFile.getAbsolutePath(), Context.MODE_PRIVATE);ClassLoader classLoader1 = new ClassLoader() {@Overrideprotected Class<?> findClass(String className)throws ClassNotFoundException {Class clazz = dexFile.loadClass(className, this);if (clazz == null) {clazz = Class.forName(className);}return clazz;}};Enumeration<String> entry = dexFile.entries();while (entry.hasMoreElements()) {String key = entry.nextElement();if (!list.contains(key)) {continue;}Class realClazz = dexFile.loadClass(key, classLoader1);if (realClazz != null) {fixClass(realClazz, classLoader);}}} catch (IOException e) {e.printStackTrace();}}private void fixClass(Class realClazz, ClassLoader classLoader) {Method[] methods = realClazz.getMethods();for (Method needMethod : methods) {MethodReplace methodReplace = needMethod.getAnnotation(MethodReplace.class);if (methodReplace == null) {continue;}Log.i("dongnao", "找到替换方法   " + methodReplace.toString()+ "  clazz 对象  " + realClazz.toString());String clazz = methodReplace.clazz();String methodName = methodReplace.method();replaceMehod(classLoader, clazz, methodName, realClazz, needMethod);}}private void replaceMehod(ClassLoader classLoader, String clazz,String methodName, Class realClazz, Method method) {try {Class srcClazz = Class.forName(clazz);if (srcClazz != null) {Method src = srcClazz.getDeclaredMethod(methodName,method.getParameterTypes());HandlerNative.replaceMethod(src, method);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}}


@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MethodReplace {    String clazz();    String method();}




0 0