patch



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) {
		// PathClassLoader
		ClassLoader 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() {
				@Override
				protected 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值