Android 反射Method应用

来源:互联网 发布:java base64解码 编辑:程序博客网 时间:2024/06/01 03:59

本人喜欢把复杂的事情简单化,简单的事情复杂化---以前读书的时候,语文老师经常再三强调,写作文的时候不要把题目写”太大”了;只要写一件小事,写的越详细越动人就达到了目的!

---zhibao.liu

 

本来想先介绍反射构造函数,代码写了一部分,发现先介绍反射构造函数不是太”灵活”,所以,就先介绍方法,感觉先介绍了方法,在讲构造函数时,往构造函数中传递参数,然后通过方法在体现出来,效果会更加!

 

大致介下Method.java中需要用到的几个常见的方法:

invoke(Object obj,Object... args)

 

http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html

获取Method对象的几个常见方法,大致如下:

Field[] getDeclaredFields()

 

Method getDeclaredMethod(String name,Class<?>... parameterTypes)

 

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html

上面方法介绍的很少,但是其他方法可以举一反三,主要是上面的方法将来用的时候,见得面也是最多的.当然这也是本人个人一些经验,一些书大谈特谈,讲了很多API之类的,也分析了很多,往往让初学者反而不知道重点,感觉各个都是重点,结果书看起来很费劲,导致很多书越看到后面越没意思了,如果一个人都没办法上手,那教的再多也没什么用,何必搞得那么复杂呢.

废话不过说,同样新建一个java工程:

<1> : 新建以后,工程树如下:

<2> : FlexClass.java代码中增加两个测试用的方法,如下:

/** *  */package com.oneplus.flex;/** * @author zhibao.liu * @date 2015-11-18 * @company : oneplus.Inc */public class FlexClass {public void Show(String information){System.out.println("show information as : "+information);}private int Add(int a,int b){return a+b+1;}}

<3> : 下面看一看主要程序代码中,首先列出反射出来的类中有多少方法:

private static void OneplusFlexMethod(String packagename){try {Class clazz=Class.forName(packagename);try {Object obj = clazz.newInstance();//获取类所有的方法Method[] methods=clazz.getDeclaredMethods();for(int i=0;i<methods.length;i++){System.out.println("method name : "+methods[i].getName());}} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

看看,代码很简单,异常处理的代码比实际的代码还要多,运行结果如下:

在上面做进一步扩展,看看如果使用反射出来的方法:

private static void OneplusFlexShowMethod(String packagename,String methodname){try {Class clazz=Class.forName(packagename);try {Object obj=clazz.newInstance();try {Method method=clazz.getDeclaredMethod(methodname, new Class[]{String.class});//make Show method as public , so here can ignore following settings//method.setAccessible(true);try {method.invoke(obj, new Object[]{"I am zhibao.liu from oneplus.Inc!"});} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

注意:由于method.setAccessible(true);public类型,所以这一句不是必须的.其实里面主要是getDeclaredMethod方法的第二个参数,有点别扭,我这里为了保持原生态”,没有通过转变的方式传入参数,可以让读者直观感受传值方式, invoke方法也是一样的,执行结果如下 :

同理,使用Add方法,基本上将上面的方法重写一遍:

private static void OneplusFlexMethod(String packagenmae,String methodname){try {Class clazz=Class.forName(packagenmae);try {Object obj=clazz.newInstance();try {Method method=clazz.getDeclaredMethod(methodname, new Class[]{int.class,int.class});method.setAccessible(true);try {Object ret=method.invoke(obj, new Object[]{10,12});if(ret!=null){System.out.println("return : "+ret.toString());}} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

只要注意传入参数的方式正确就基本上OK了,运行结果如下:


下面看一看在Android中如何使用方法反射达到自己的目的,在反射Android系统里面那些未公开的,标记有@hide的方法或者参数,使用者必须要知道反射的对象是什么,它能够完成什么,即需要使用者首先要熟悉Android系统源代码,熟悉framework层的框架,希望使用者提前熟读framework层的代码,当然很多还是需要很多工作经验,对于很多普通应用开发者的确有点难度,因为一般很多应用开发者会认为”那些都是Android本身的,是Android的原因(Android系统没有公开提供给应用开发者),所以,我们这个不能够做,那个不能够实现”,所以在这里希望建议读者即使是普通的Android应用开发者,熟读Android源码,绝对可以提高自己开发的一个档次,而不会是android”听话的傀儡”,比如说我们下面使用的一个方法,它已经被标记上了@hide,代表这个方法不能够被普通的开发者使用,只能够提供给系统本身使用:


上面的代码是从Android系统源代码中截取出来的,上面已经标出@hide字样,标示应用层是不能够使用的(不能够直接被调用).

下面正式切入正题:

<1> : 新建工程,工程树如下:


<2> : 有Android本身反射的也是java类,所以其实和普通的java应用基本上是一样的:

package com.oneplus.oneplusandroidflexmethod;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import android.net.ConnectivityManager;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.util.Log;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.CheckBox;/** * @author zhibao.liu * @date 2015-11-18 * @company : oneplus.Inc */public class OneplusFlexMethodActivity extends Activity implementsOnClickListener {private static final String TAG = "oneplus";private static final String PACKAGENAME = "android.net.ConnectivityManager";private ConnectivityManager mConnectivityManager;private CheckBox mCheckBox;// android.net.ConnectivityManager@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.oneplus_flex_method);mCheckBox = (CheckBox) findViewById(R.id.oneplus_enable);mCheckBox.setOnClickListener(this);OneplusFlexMethodAudioManagerX(OneplusFlexMethodActivity.this);}//setStreamOnePlusMute//下面这个方法只能够在oneplus 手机才能够使用private void OneplusFlexMethodStreamX(Context context){Object obj=this.getSystemService(Context.AUDIO_SERVICE);try {Class clazz=Class.forName("android.media.AudioManager");try {//only can excute in oneplus phoneMethod method=clazz.getDeclaredMethod("setStreamOnePlusMute", new Class[]{int.class,boolean.class});method.setAccessible(true);try {method.invoke(obj, new Object[]{3,true});} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private void OneplusFlexMethodAudioManagerX(Context context){Object object=this.getSystemService(Context.AUDIO_SERVICE);try {Class clazz=Class.forName("android.media.AudioManager");try {Method method=clazz.getDeclaredMethod("isValidRingerMode", new Class[]{int.class});method.setAccessible(true);try {Object ret=method.invoke(object, new Object[]{1});Log.i(TAG,"result : "+ret.toString());method=clazz.getDeclaredMethod("getLastAudibleStreamVolume", new Class[]{int.class});method.setAccessible(true);ret=method.invoke(object, new Object[]{7});Log.i(TAG,"result : "+ret.toString());} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private void OneplusFlexMethodStatusBarX(Context context) {Object object = OneplusFlexMethodActivity.this.getSystemService("statusbar");Class clazz;try {clazz = Class.forName("android.app.StatusBarManager");Method method;try {if (mCheckBox.isChecked()) {method = clazz.getMethod("expandNotificationsPanel",null);}else{method = clazz.getMethod("collapsePanels",null);}method.setAccessible(true);try {method.invoke(object, null);} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private void OneplusFlexMethodX(Context context) {Log.i(TAG, "OneplusFlexMethodX");mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);try {Class clazz = Class.forName(PACKAGENAME);try {Field field = clazz.getDeclaredField("mService");field.setAccessible(true);try {Object obj = field.get(mConnectivityManager);Class clavv = Class.forName(obj.getClass().getName());Log.i(TAG, "clavv name : " + clavv.getName());try {Method method = clavv.getDeclaredMethod("isTetheringSupported", null);Log.i(TAG, "method name : " + method.getName());method.setAccessible(true);try {Object objret = method.invoke(obj, null);Log.i(TAG, "can support ? " + objret);} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchFieldException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic void onClick(View view) {// TODO Auto-generated method stubint resId = view.getId();switch (resId) {case R.id.oneplus_enable:OneplusFlexMethodX(OneplusFlexMethodActivity.this);// OneplusFlexMethodStatusBarX(OneplusFlexMethodActivity.this);break;default:break;}}}

上面的代码就不过去讲解,和java使用完全是一样的,可能很多人刚开始一看,感觉心里面隐隐有点点障碍,觉得很难下手,只要了解了java的反射,Android其实大胆的去使用,实践几个案例,就会发现原来这么容易,以后做项目,完全可以忽略系统里面的接口是隐藏还是没有隐藏,公开的就直接使用,隐藏的就反射.



附录 : 在上面工程中已经添加包含下面的两个方法:

public static Class[] getMethodTypeClass(String[] types) {Class[] cs = new Class[types.length];for (int i = 0; i < cs.length; i++) {if (!TextUtils.isEmpty(types[i])) {if (TextUtils.equals(types[i], "int")|| TextUtils.equals(types[i], "Integer")) {cs[i] = Integer.TYPE;} else if (TextUtils.equals(types[i], "float")|| TextUtils.equals(types[i], "Float")) {cs[i] = Float.TYPE;} else if (TextUtils.equals(types[i], "double")|| TextUtils.equals(types[i], "Double")) {cs[i] = Double.TYPE;} else if (TextUtils.equals(types[i], "long")|| TextUtils.equals(types[i], "Long")) {cs[i] = Long.TYPE;} else if (TextUtils.equals(types[i], "boolean")|| TextUtils.equals(types[i], "Boolean")) {cs[i] = Boolean.TYPE;} else if (TextUtils.equals(types[i], "String")) {cs[i] = String.class;} else {try {cs[i] = Class.forName(types[i]);} catch (ClassNotFoundException e) {e.printStackTrace();}}}}return cs;}public static Object[] getParaValueObject(String[] types, String[] paras) {Object[] objects = new Object[paras.length];for (int i = 0; i < objects.length; i++) {if (!TextUtils.isEmpty(paras[i])) {if (TextUtils.equals(types[i], "int")|| TextUtils.equals(types[i], "Integer")) {objects[i] = new Integer(paras[i]);} else if (TextUtils.equals(types[i], "float")|| TextUtils.equals(types[i], "Float")) {objects[i] = new Float(paras[i]);} else if (TextUtils.equals(types[i], "double")|| TextUtils.equals(types[i], "Double")) {objects[i] = new Double(paras[i]);} else if (TextUtils.equals(types[i], "long")|| TextUtils.equals(types[i], "Long")) {objects[i] = new Long(paras[i]);} else if (TextUtils.equals(types[i], "boolean")|| TextUtils.equals(types[i], "Boolean")) {objects[i] = new Boolean(paras[i]);} else if (TextUtils.equals(types[i], "String")) {objects[i] = paras[i];} else {// try {// objects[i] = Class.forName(types[i]);// } catch (ClassNotFoundException e) {// e.printStackTrace();// }}}}return objects;}

























0 0
原创粉丝点击