原文地址:
http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820284&idx=1&sn=43cbc5cbbf7d67ca3c5d8dc05f6fd4d0&scene=0#wechat_redirect
1
概述
我在学习Andorid的时候,经历过这样的事,有一次我听说:Android应用有个入口类,叫做ActivityThread,里面有个入口方法叫做:main。当我第一次听main方法的时候,我激动的眼泪都下来了,好亲切,我迫不及待的在IDE中查找该类:`ActivityThread`,IDE却无情的给我返回了一个:
No matches found
这感受就像下载了一晚上葫芦娃似的。如果你遇到过和我一样的问题,没解决那么可以看下本文,解决了你也可以看下本文。
这些默认在IDE中无法查找到的类或者方法呢,一般都是因为其被标识了@hide或者是属于com.android.internal中的类。
我们在开发Android的时候,一般会选择指定的编译版本,这个版本会对应使用我们下载的SDK目录中对应版本的android.jar(sdk/platforms/android-version/android.jar),在这个jar中呢,默认移除了所有的被`@hide`标识的方法或者类,以及internal包下的类。
所以会造成,我们默认情况下,在IDE中无法查看到该类。
ok,那么本文主要解决上述问题了,其实类似的解决方案网络上挺多的,但是本文的解决方式突出一个字:快。如何你现在存在上述问题,阅读完本文,瞬间就能解决。
本文也能同时做到,不需要反射轻松调用被`@hide`标识的类或者方法,以及在internal下的类。
2
解决方案
解决方案其实说白了很简单,既然android.jar默认去掉了被标识了@hide或者是属于com.android.internal中的class文件或者方法,我们再加上不就好了。
那么问题来了:我们去哪找这些类呢?
从android设备中提取(`/system/framework/framework.jar`)
从一些提供源码下载的网站下载(http://grepcode.com/)
从设备中提取过程可以看下这篇文章:
http://blog.csdn.net/linghu_java/article/details/8283042
从grepcode下载并成功导入可以参考,下面这篇:
http://blog.csdn.net/liu470368500/article/details/40189397
该方法还是相当好用的,不过目前grepcode上最新版本为22。
那么本文的方案呢?
既然存在这样一个问题,都需要去整这个完整的android.jar,所以已经有人帮助我们在做这样的事情了,并且在github上搭建了一个项目,项目地址:
https://github.com/anggrayudi/android-hidden-api
A library that provides access to Android hidden API and internal resources.
该项目提供了各个版本android.jar的下载,看个图:
我们所要做的就是两步:
1. 下载指定的版本的android.jar
2. copy 覆盖我们sdk目录对应版本的android.jar
例如,我这里下载android-23下的android.jar,然后找到我SDK中对应的jar:
`sdk/platforms/android-23/android.jar`,直接使用下载的jar进行替换即可(当然,为了安全,你可以先备份下原本的jar)。
好了,这样就搞定了,如果你是Android Studio,它会自动检测到变化,稍等1分钟估计就可以查看了。
如果是eclipse,估计需要重启。
3
效果
(1)首先是查看各种类
被@hide标识的类:
2.internal包下的类
这样就可以开心的学习了~~
除此之外还有另一份惊喜 ~
(2) 调用hide、internal API
关于调用hide API,是ddup群的小二提问才引起我的关注,没有她这个提问估计也没有这篇文章。
1. 调用hide API
先看一段常见的代码,例如外部资源换肤,插件化,都需要解决读取插件apk中的资源问题。
涉及到的代码如下:
可以看到AssetManager对象的构造,以及addAssetPath方法的调用都是通过反射调用的。原因就是因为默认的情况下,这两个方法在默认的android.jar中是不存在的。
默认情况下直接调用会这样:
而经过我们上述的解决方案之后,代码直接访问就不会出错了,如下:
是不是觉得很神奇~~Andrid Studio ,Eclipse中都可以直接访问hide API了。
ps:今天的代码为了体现没有错误,部分代码直接在Android Studio中直接截图。
2. 访问internal包下API
恩,internal包下的例子一时没想到,我好像没怎么用到过里面的API,所以就不纠结了,主要是为了查看源码学习~~
你可以随便找个类去声明一下,我在Android Studio中测试是没有问题的。
不过在eclipse中internal包下的类是无法使用的,据说ADT做了限制~~
4
总结
这么做做相比反射的方式有什么好处呢?
首先性能上相比反射的代码肯定会有一定的提升,其次这么写方便、不容易写错API,反射太容易写错方法名字符串了。
这么做相比反射的方式有什么不好的地方呢?
不好的地方就是如果大家是团队合作的方式,只有你替换了android.jar别人都没替换,那么可能会打起来吧。
最后要说明的是,不管是@hide还是internal包下的API,只要使用了,都有不确定的因素,说不定哪天该方法该类就不存在了。
当然有些黑科技目前可能必须这么做,所以一般都需要去try,catch,做一些兼容方案。
当然对于学习源码角度来说,学会导入这些隐藏的API是百利无一害的~~
希望本文可以节省到你的时间 , ~~ have a nice day ~~ |
|