A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

原文地址:
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 ~~

1 个回复

倒序浏览
真棒,顶一个
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马