最近在抽取Android原生Browser及MediaPlayer的时候,直接把代码copy出来,然后在Eclipse里编译发现很多错误,根本原因是这些Apps调用了很多系统隐藏(带@hide标记)public对象或public对象的隐藏API。使用Android隐藏的API主要有两种办法:1.利用Java反射机制,使用反射的方法得到隐藏API;2.使用源码编译时生成的全编译过的classes.jar包。
1,使用Java反射机制
(一)访问隐藏public类
- try {
- Class policyClass =Class.forName("com.android.internal.policy.PolicyManager");
- } catch (Exception e) {
- e.printStackTrace();
- }
(二)访问隐藏类的static方法
- try {
- Method makenewwindow =policyClass.getMethod("makeNewWindow", newClass[] {Context.class});
- Window win = (Window)makenewwindows.invoke(null, context);
- } catch (Exception e) {
- e.printStackTrace();
- }
(三)访问public类的私有成员变量
- try {
- Fieldf =WebSettings.class.getDeclaredField("mBuiltInZoomControls");
- f.setAccessible(true); //关闭访问检查
- f.setBoolean(wSettings,false); //wSettings是WebSettings对象
- }catch(Exception e) {
- Log.i(LOGTAG,e.toString());
- }
(四)访问public类的私有成员方法
- try {
- Method m= WebSettings.class.getDeclaredMethod("getCurrentUserAgent");
- m.setAccessible(true); //关闭访问检查
- m.invoke(wSettings); //wSettings是WebSettings对象
- } catch(Exception e) {
- Log.i(LOGTAG, e.toString());
- }
- try {
- Object[] args = {Integer.valueOf(5)};
- Method m = WebSettings.class.getMethod("setPageCacheCapacity", newClass[]{int.class});
- m.invoke(wSettings,args); //wSettings是WebSettings对象
- } catch(Exception e) {
- Log.i(LOGTAG, e.toString());
- }
- try {
- Methodm = WebView.class.getMethod("getWebChromeClient");
- Objectob = m.invoke(mSubView);
- WebChromeClient client = (WebChromeClient) ob;
- }catch(Throwable ignored) {
- }
2,如果不想修改代码,就需要使用第二种方法:导入全编译的classes.jar包。编译Android框架源码后,将生成全编译的classes.jar导入到工程中。使用Eclipse,Android工程添加library(BuildPath -> Add Libraries->User Library->New User Library),将.jar文件加入添加到library,同时勾选“SystemLibrary”选项,以避免产生“java.lang.OutOfMemoryError:Java Heap Space”错误。如果已经正确导入了jar库,却仍然找不到隐藏的API。原因可能是Buildclass path order不正确,即android.jar和classes.jar的导入顺序不对,具体调节Buildclass path order,选择Build Path-> Config Build Path->Order and Export,调整自定义的library与android.jar的顺序。