如何设置hide的回调接口

android源码中有很多hide的接口,编码时无法直接调用. 怎么办呢? 首先明确一点:hide标记只影响编译时,不影响运行时,只要编译能通过,运行时就能正常访问hide标记的接口,因此,只需要确保调用hide接口能编译通过即可,通常有三种做法:

  1. 基于android源码编译
  2. 修改源码,去除hide标记,并编译成framework.jar导入项目中
  3. 反射
    其中方法1,2操作比较复杂,通常很少使用

调用hide接口或者传入hide类型的参数,都可通过上述方式完成。如果接口接受hide类的回调参数呢?例如:

PackageManager.installPackage(String packageName, android.pm.content.IPackageInstallObjsever observer, int flag)

这个方法中IPackageInstallObserver就是个hide接口,除了上述方法1,2外,没法直接创建子类来实现回调方法. 要解决这个问题,除了还有以下通过如下方式:
copy接口到自己到项目下,且保持包名,类名不变
在自己项目里创建一个与回调接口类相同的包名+类名, 并且创建回调方法,这里不需要创建所有的方法,只需要自己感兴趣的回调方法就行了, 如只需要在自己创建的IPackageInstallObserver类中添加方法packageInstalled(String pkgName, int errorCode)
这样编译的时候就能在编译路径中找到IPcakageInstallObsever类了,编译成功。但是运行时就存在两个相同的类了,不会产生冲突么?答案是不会,因为framework中的IPackageInstallObsever类的ClassLoader是SystemClassLoader,而自己代码是在PathClassLoader中,PathClassLoader的parent是SystemClassLoader, 根据类加在双亲委派机制,查找类时先有parent ClassLoader决定是否能加在,如果parent加在类,child就不再加载,显然,framework中的IPackageInstallObserver会由SystemClassLoader加载,自己创建的IPackageInstallObserver会被当作相同的类,不会再加载,因此,运行时的IPackageInstallObsever一定是来自framework,而不是自己创建的那个,这也是为什么不需要添加所有的回调方法,因为运行时压根就不会理会自己创建的类,它的目的就是为了保证编译通过,只需要包名,类名相同就行了。
使用这种方式需要特别注意一点就是:混淆时一定要keep住回调接口,因为它属于项目私有空间,回调方法默认会被混淆掉,运行时就会出现找不到回调方法掉的异常了。

你可能感兴趣的:(如何设置hide的回调接口)