Android应用开发中如何访问隐藏API(4.0以前版本)

来源:互联网 发布:mac格式工厂中文版 编辑:程序博客网 时间:2024/05/08 19:51

最近在抽取Android原生Browser及MediaPlayer的时候,直接把代码copy出来,然后在Eclipse里编译发现很多错误,根本原因是这些Apps调用了很多系统隐藏(带@hide标记)public对象或public对象的隐藏API。使用Android隐藏的API主要有两种办法:1.利用Java反射机制,使用反射的方法得到隐藏API;2.使用源码编译时生成的全编译过的classes.jar包。

1,使用Java反射机制

(一)访问隐藏public类

      例如PolicyManager就是个隐藏类,如果非要在App层访问它,那么就可以使用reflect技术:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. try {    
  2.     Class policyClass =Class.forName("com.android.internal.policy.PolicyManager");    
  3. } catch (Exception e) {    
  4.      e.printStackTrace();  
  5. }  

(二)访问隐藏类的static方法

      因为没有隐藏类的对象实例,所以只能用null去访问它的static方法或成员:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. try {   
  2.      Method makenewwindow =policyClass.getMethod("makeNewWindow", newClass[]   {Context.class});  
  3.      Window win = (Window)makenewwindows.invoke(null, context);   
  4. } catch (Exception e) {  
  5.      e.printStackTrace();  
  6. }  

(三)访问public类的私有成员变量

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. try {  
  2.   
  3.          
  4.        Fieldf =WebSettings.class.getDeclaredField("mBuiltInZoomControls");  
  5.        f.setAccessible(true);           //关闭访问检查  
  6.   
  7.        f.setBoolean(wSettings,false); //wSettings是WebSettings对象  
  8.  }catch(Exception e) {  
  9.        Log.i(LOGTAG,e.toString());  
  10. }  

(四)访问public类的私有成员方法    

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. try {  
  2.   
  3.      
  4.     Method mWebSettings.class.getDeclaredMethod("getCurrentUserAgent");  
  5.    m.setAccessible(true); //关闭访问检查         
  6.   
  7.    m.invoke(wSettings); //wSettings是WebSettings对象  
  8. } catch(Exception e) {  
  9.    Log.i(LOGTAG, e.toString());  
  10. }  

 (五)访问public类的@hide的public成员

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. try {  
  2.   
  3.   Object[] args = {Integer.valueOf(5)};  
  4.   
  5.   Method m = WebSettings.class.getMethod("setPageCacheCapacity", newClass[]{int.class});  
  6.    m.invoke(wSettings,args); //wSettings是WebSettings对象  
  7. } catch(Exception e) {  
  8.   Log.i(LOGTAG, e.toString());  
  9. }  
  10.   
  11.   
  12.   
  13. try {  
  14.      Methodm = WebView.class.getMethod("getWebChromeClient");  
  15.      Objectob = m.invoke(mSubView);  
  16.   
  17.     WebChromeClient client = (WebChromeClient) ob;  
  18.  }catch(Throwable ignored) {  
  19.  }  

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的顺序。

 

   利用反射技术的优点是灵活,能解决一些访问限制的问题,能够在不兼容的系统捕获异常,而使程序不至于崩溃;缺点是步骤比较多,需要熟悉要调用的类、方法名称访问属性,大量使用反射会大大增加代码,对代码的健壮性不利。一般被hide的类或成员可能还不太成熟稳定,所以不便公开。

   另外一种解决以上访问问题的方法是导入全编译的classes.jar包,这种方法比较简单。一旦导入,就像隐藏的API在SDK中变得可见了一样,其缺点是系统版本兼容问题,而且很多hide的类或方法也被同时导入。

0 0
原创粉丝点击