android学习日记:利用反射调用隐藏API

来源:互联网 发布:ui用什么软件 编辑:程序博客网 时间:2024/05/16 14:14

最近用到了反射,最后虽然做到了,不过感觉网上相关的介绍都不是很清楚,就自己总结了下。

反射调用一个@hide的方法:

例如android.widget.AutoCompleteTextView包下面的setDropDownAlwaysVisible函数,这个函数在源码中是被hide掉的,调用的时候肯定要先获得一个AutoCompleteTextView的具体对象,所以这个对象也要在反射的时候被指定。

主要的反射函数:

public Object setDropDownAlwaysVisible(AutoCompleteTextView data,boolean b) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{Object[] params = new Object[1];params[0] = b;Class ownerClass = Class.forName("android.widget.AutoCompleteTextView");Log.i(TAG,"ownerclass is "+ownerClass);Class[] args= new Class[1];args[0] = boolean.class;Method method = ownerClass.getDeclaredMethod("setDropDownAlwaysVisible", args);Log.i(TAG,"method is "+method);method.setAccessible(true);Log.i(TAG,"data is "+data+"\nb is "+b);return method.invoke(data, b);}


反射的机制大概就是,先根据类的名字找到具体的类,然后再进入这个类中,依据特定的方法名和特定的参数类型信息来定位这个类中的具体方法(很多时候一个类里同名不同参的方法有好几个)。最后通过method.invoke来将这个方法加载到具体的类里。

这个反射函数的返回值类型是Object,可以转化成各种想要的类型(String,int等,转换方法度娘上有很多)。

首先要找到我们需要反射方法的类中,代码就是Class ownerClass = Class.forName("android.widget.AutoCompleteTextView"); 方法不止forName这一种。

然后通过得到的ownerClass来找具体的方法:Method method = ownerClass.getDeclaredMethod("setDropDownAlwaysVisible", args); 第一个参数是方法的名字(不含参数,只是名字)。第二个参数args是一个类型数组,包含了这个函数所有的参数类型,例子中的类型是boolean(我当时写成了Boolean,运行出现问题。。。),注意的是这个boolean.class一定要和原方法中的数据类型一模一样,顺序也要一样,不然会定位不到这个方法。如果函数没有参数,可以直接class[] args=null。

得到method的之后将之设为可以Access,然后就可以装载了。

装载函数:method.invoke(data, b); 这行代码会返回一个Object类型。参数data是你想装载到的类名字(类型是object)。参数b是你需要在data中传入这个method的参数。

最后,具体在代码中的调用:

AutoCompleteTextView view = (AutoCompleteTextView)findViewById(R.id.ac);try {setDropDownAlwaysVisible(view, false);} catch (Exception e){e.printStackTrace();}


当代码中不需要实例化类,或者要调用隐藏类中的方法的时候,只需要在反射函数中new一个class即可。

例如:Class ownerClass = Class.forName("android.content.res.AssetManager");
  Object newclass = ownerClass.newInstance();

然后最后将方法invoke到这个newclass上即可实现调用。

未完待续

原创粉丝点击