Android 反射Method应用

来源:互联网 发布:索尼网络电视线怎么接 编辑:程序博客网 时间:2024/05/09 17:20

 

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

 

大致介下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代码中增加两个测试用的方法,如下:

[html] view plain copy
  1. /**  
  2.  *   
  3.  */  
  4. package com.oneplus.flex;  
  5.   
  6. /**  
  7.  * @author zhibao.liu  
  8.  * @date 2015-11-18  
  9.  * @company : oneplus.Inc  
  10.  */  
  11. public class FlexClass {  
  12.       
  13.     public void Show(String information){  
  14.         System.out.println("show information as : "+information);  
  15.     }  
  16.       
  17.     private int Add(int a,int b){  
  18.           
  19.         return a+b+1;  
  20.           
  21.     }  
  22.   
  23.       
  24. }  

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

[java] view plain copy
  1. private static void OneplusFlexMethod(String packagename){  
  2.           
  3.         try {  
  4.               
  5.             Class clazz=Class.forName(packagename);  
  6.               
  7.             try {  
  8.                   
  9.                 Object obj = clazz.newInstance();  
  10.                 //获取类所有的方法  
  11.                 Method[] methods=clazz.getDeclaredMethods();  
  12.                   
  13.                 for(int i=0;i<methods.length;i++){  
  14.                       
  15.                     System.out.println("method name : "+methods[i].getName());  
  16.                       
  17.                 }  
  18.                   
  19.             } catch (InstantiationException e) {  
  20.                 // TODO Auto-generated catch block  
  21.                 e.printStackTrace();  
  22.             } catch (IllegalAccessException e) {  
  23.                 // TODO Auto-generated catch block  
  24.                 e.printStackTrace();  
  25.             }  
  26.   
  27.         } catch (ClassNotFoundException e) {  
  28.             // TODO Auto-generated catch block  
  29.             e.printStackTrace();  
  30.         }  
  31.           
  32.     }  

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

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

[java] view plain copy
  1. private static void OneplusFlexShowMethod(String packagename,String methodname){  
  2.           
  3.         try {  
  4.             Class clazz=Class.forName(packagename);  
  5.               
  6.             try {  
  7.                 Object obj=clazz.newInstance();  
  8.                   
  9.                 try {  
  10.                     Method method=clazz.getDeclaredMethod(methodname, new Class[]{String.class});  
  11.                     //make Show method as public , so here can ignore following settings  
  12.                     //method.setAccessible(true);  
  13.                       
  14.                     try {  
  15.                         method.invoke(obj, new Object[]{"I am zhibao.liu from oneplus.Inc!"});  
  16.                     } catch (IllegalArgumentException e) {  
  17.                         // TODO Auto-generated catch block  
  18.                         e.printStackTrace();  
  19.                     } catch (InvocationTargetException e) {  
  20.                         // TODO Auto-generated catch block  
  21.                         e.printStackTrace();  
  22.                     }  
  23.                       
  24.                 } catch (NoSuchMethodException e) {  
  25.                     // TODO Auto-generated catch block  
  26.                     e.printStackTrace();  
  27.                 } catch (SecurityException e) {  
  28.                     // TODO Auto-generated catch block  
  29.                     e.printStackTrace();  
  30.                 }  
  31.                   
  32.             } catch (InstantiationException e) {  
  33.                 // TODO Auto-generated catch block  
  34.                 e.printStackTrace();  
  35.             } catch (IllegalAccessException e) {  
  36.                 // TODO Auto-generated catch block  
  37.                 e.printStackTrace();  
  38.             }  
  39.               
  40.         } catch (ClassNotFoundException e) {  
  41.             // TODO Auto-generated catch block  
  42.             e.printStackTrace();  
  43.         }  
  44.           
  45.     }  

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

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

[java] view plain copy
  1. private static void OneplusFlexMethod(String packagenmae,String methodname){  
  2.           
  3.         try {  
  4.             Class clazz=Class.forName(packagenmae);  
  5.             try {  
  6.                 Object obj=clazz.newInstance();  
  7.                   
  8.                 try {  
  9.   
  10.                     Method method=clazz.getDeclaredMethod(methodname, new Class[]{int.class,int.class});  
  11.                     method.setAccessible(true);  
  12.                     try {  
  13.                         Object ret=method.invoke(obj, new Object[]{10,12});  
  14.                         if(ret!=null){  
  15.                             System.out.println("return : "+ret.toString());  
  16.                         }  
  17.                     } catch (IllegalArgumentException e) {  
  18.                         // TODO Auto-generated catch block  
  19.                         e.printStackTrace();  
  20.                     } catch (InvocationTargetException e) {  
  21.                         // TODO Auto-generated catch block  
  22.                         e.printStackTrace();  
  23.                     }  
  24.                       
  25.                 } catch (NoSuchMethodException e) {  
  26.                     // TODO Auto-generated catch block  
  27.                     e.printStackTrace();  
  28.                 } catch (SecurityException e) {  
  29.                     // TODO Auto-generated catch block  
  30.                     e.printStackTrace();  
  31.                 }  
  32.                   
  33.             } catch (InstantiationException e) {  
  34.                 // TODO Auto-generated catch block  
  35.                 e.printStackTrace();  
  36.             } catch (IllegalAccessException e) {  
  37.                 // TODO Auto-generated catch block  
  38.                 e.printStackTrace();  
  39.             }  
  40.   
  41.         } catch (ClassNotFoundException e) {  
  42.             // TODO Auto-generated catch block  
  43.             e.printStackTrace();  
  44.         }  
  45.           
  46.     }  

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


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


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

下面正式切入正题:

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


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

[html] view plain copy
  1. package com.oneplus.oneplusandroidflexmethod;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6.   
  7. import android.net.ConnectivityManager;  
  8. import android.os.Bundle;  
  9. import android.app.Activity;  
  10. import android.content.Context;  
  11. import android.util.Log;  
  12. import android.view.Menu;  
  13. import android.view.View;  
  14. import android.view.View.OnClickListener;  
  15. import android.widget.CheckBox;  
  16.   
  17. /**  
  18.  * @author zhibao.liu  
  19.  * @date 2015-11-18  
  20.  * @company : oneplus.Inc  
  21.  */  
  22.   
  23. public class OneplusFlexMethodActivity extends Activity implements  
  24.         OnClickListener {  
  25.   
  26.     private static final String TAG = "oneplus";  
  27.     private static final String PACKAGENAME = "android.net.ConnectivityManager";  
  28.   
  29.     private ConnectivityManager mConnectivityManager;  
  30.   
  31.     private CheckBox mCheckBox;  
  32.   
  33.     // android.net.ConnectivityManager  
  34.   
  35.     @Override  
  36.     protected void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.oneplus_flex_method);  
  39.   
  40.         mCheckBox = (CheckBox) findViewById(R.id.oneplus_enable);  
  41.         mCheckBox.setOnClickListener(this);  
  42.           
  43.         OneplusFlexMethodAudioManagerX(OneplusFlexMethodActivity.this);  
  44.   
  45.     }  
  46.     //setStreamOnePlusMute  
  47.     //下面这个方法只能够在oneplus 手机才能够使用  
  48.     private void OneplusFlexMethodStreamX(Context context){  
  49.           
  50.         Object obj=this.getSystemService(Context.AUDIO_SERVICE);  
  51.           
  52.         try {  
  53.             Class clazz=Class.forName("android.media.AudioManager");  
  54.               
  55.             try {  
  56.                 //only can excute in oneplus phone  
  57.                 Method method=clazz.getDeclaredMethod("setStreamOnePlusMute", new Class[]{int.class,boolean.class});  
  58.                 method.setAccessible(true);  
  59.   
  60.                 try {  
  61.                     method.invoke(obj, new Object[]{3,true});  
  62.                 } catch (IllegalArgumentException e) {  
  63.                     // TODO Auto-generated catch block  
  64.                     e.printStackTrace();  
  65.                 } catch (IllegalAccessException e) {  
  66.                     // TODO Auto-generated catch block  
  67.                     e.printStackTrace();  
  68.                 } catch (InvocationTargetException e) {  
  69.                     // TODO Auto-generated catch block  
  70.                     e.printStackTrace();  
  71.                 }  
  72.                   
  73.                   
  74.             } catch (NoSuchMethodException e) {  
  75.                 // TODO Auto-generated catch block  
  76.                 e.printStackTrace();  
  77.             }  
  78.               
  79.               
  80.         } catch (ClassNotFoundException e) {  
  81.             // TODO Auto-generated catch block  
  82.             e.printStackTrace();  
  83.         }  
  84.           
  85.           
  86.     }  
  87.       
  88.     private void OneplusFlexMethodAudioManagerX(Context context){  
  89.           
  90.         Object object=this.getSystemService(Context.AUDIO_SERVICE);  
  91.           
  92.         try {  
  93.             Class clazz=Class.forName("android.media.AudioManager");  
  94.               
  95.             try {  
  96.                 Method method=clazz.getDeclaredMethod("isValidRingerMode", new Class[]{int.class});  
  97.                   
  98.                 method.setAccessible(true);  
  99.                   
  100.                 try {  
  101.                     Object ret=method.invoke(object, new Object[]{1});  
  102.                       
  103.                     Log.i(TAG,"result : "+ret.toString());  
  104.                       
  105.                     method=clazz.getDeclaredMethod("getLastAudibleStreamVolume", new Class[]{int.class});  
  106.                       
  107.                     method.setAccessible(true);  
  108.                       
  109.                     ret=method.invoke(object, new Object[]{7});  
  110.                       
  111.                     Log.i(TAG,"result : "+ret.toString());  
  112.                                           
  113.                 } catch (IllegalArgumentException e) {  
  114.                     // TODO Auto-generated catch block  
  115.                     e.printStackTrace();  
  116.                 } catch (IllegalAccessException e) {  
  117.                     // TODO Auto-generated catch block  
  118.                     e.printStackTrace();  
  119.                 } catch (InvocationTargetException e) {  
  120.                     // TODO Auto-generated catch block  
  121.                     e.printStackTrace();  
  122.                 }  
  123.                   
  124.             } catch (NoSuchMethodException e) {  
  125.                 // TODO Auto-generated catch block  
  126.                 e.printStackTrace();  
  127.             }  
  128.               
  129.         } catch (ClassNotFoundException e) {  
  130.             // TODO Auto-generated catch block  
  131.             e.printStackTrace();  
  132.         }  
  133.           
  134.     }  
  135.   
  136.     private void OneplusFlexMethodStatusBarX(Context context) {  
  137.   
  138.         Object object = OneplusFlexMethodActivity.this  
  139.                 .getSystemService("statusbar");  
  140.         Class clazz;  
  141.         try {  
  142.             clazz = Class.forName("android.app.StatusBarManager");  
  143.             Method method;  
  144.             try {  
  145.                 if (mCheckBox.isChecked()) {  
  146.                     method = clazz.getMethod("expandNotificationsPanel",  
  147.                             null);  
  148.                 }else{  
  149.                     method = clazz.getMethod("collapsePanels",  
  150.                             null);  
  151.                 }  
  152.                   
  153.                 method.setAccessible(true);  
  154.                 try {  
  155.                     method.invoke(object, null);  
  156.                 } catch (IllegalArgumentException e) {  
  157.                     // TODO Auto-generated catch block  
  158.                     e.printStackTrace();  
  159.                 } catch (IllegalAccessException e) {  
  160.                     // TODO Auto-generated catch block  
  161.                     e.printStackTrace();  
  162.                 } catch (InvocationTargetException e) {  
  163.                     // TODO Auto-generated catch block  
  164.                     e.printStackTrace();  
  165.                 }  
  166.             } catch (NoSuchMethodException e) {  
  167.                 // TODO Auto-generated catch block  
  168.                 e.printStackTrace();  
  169.             }  
  170.         } catch (ClassNotFoundException e) {  
  171.             // TODO Auto-generated catch block  
  172.             e.printStackTrace();  
  173.         }  
  174.   
  175.     }  
  176.   
  177.     private void OneplusFlexMethodX(Context context) {  
  178.   
  179.         Log.i(TAG, "OneplusFlexMethodX");  
  180.   
  181.         mConnectivityManager = (ConnectivityManager) context  
  182.                 .getSystemService(Context.CONNECTIVITY_SERVICE);  
  183.   
  184.         try {  
  185.   
  186.             Class clazz = Class.forName(PACKAGENAME);  
  187.   
  188.             try {  
  189.                 Field field = clazz.getDeclaredField("mService");  
  190.                 field.setAccessible(true);  
  191.   
  192.                 try {  
  193.                     Object obj = field.get(mConnectivityManager);  
  194.                     Class clavv = Class.forName(obj.getClass().getName());  
  195.   
  196.                     Log.i(TAG, "clavv name : " + clavv.getName());  
  197.                     try {  
  198.   
  199.                         Method method = clavv.getDeclaredMethod(  
  200.                                 "isTetheringSupported", null);  
  201.                         Log.i(TAG, "method name : " + method.getName());  
  202.                         method.setAccessible(true);  
  203.   
  204.                         try {  
  205.                             Object objret = method.invoke(obj, null);  
  206.   
  207.                             Log.i(TAG, "can support ? " + objret);  
  208.   
  209.                         } catch (InvocationTargetException e) {  
  210.                             // TODO Auto-generated catch block  
  211.                             e.printStackTrace();  
  212.                         }  
  213.   
  214.                     } catch (NoSuchMethodException e) {  
  215.                         // TODO Auto-generated catch block  
  216.                         e.printStackTrace();  
  217.                     }  
  218.   
  219.                 } catch (IllegalArgumentException e) {  
  220.                     // TODO Auto-generated catch block  
  221.                     e.printStackTrace();  
  222.                 } catch (IllegalAccessException e) {  
  223.                     // TODO Auto-generated catch block  
  224.                     e.printStackTrace();  
  225.                 }  
  226.   
  227.             } catch (NoSuchFieldException e) {  
  228.                 // TODO Auto-generated catch block  
  229.                 e.printStackTrace();  
  230.             }  
  231.   
  232.         } catch (ClassNotFoundException e) {  
  233.             // TODO Auto-generated catch block  
  234.             e.printStackTrace();  
  235.         }  
  236.   
  237.     }  
  238.   
  239.     @Override  
  240.     public void onClick(View view) {  
  241.         // TODO Auto-generated method stub  
  242.   
  243.         int resId = view.getId();  
  244.   
  245.         switch (resId) {  
  246.         case R.id.oneplus_enable:  
  247.             OneplusFlexMethodX(OneplusFlexMethodActivity.this);  
  248.             // OneplusFlexMethodStatusBarX(OneplusFlexMethodActivity.this);  
  249.             break;  
  250.         default:  
  251.             break;  
  252.         }  
  253.   
  254.     }  
  255.   
  256. }  

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



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

[html] view plain copy
  1. public static Class[] getMethodTypeClass(String[] types) {  
  2.         Class[] cs = new Class[types.length];  
  3.         for (int i = 0; i < cs.length; i++) {  
  4.             if (!TextUtils.isEmpty(types[i])) {  
  5.                 if (TextUtils.equals(types[i], "int")  
  6.                         || TextUtils.equals(types[i], "Integer")) {  
  7.                     cs[i] = Integer.TYPE;  
  8.                 } else if (TextUtils.equals(types[i], "float")  
  9.                         || TextUtils.equals(types[i], "Float")) {  
  10.                     cs[i] = Float.TYPE;  
  11.                 } else if (TextUtils.equals(types[i], "double")  
  12.                         || TextUtils.equals(types[i], "Double")) {  
  13.                     cs[i] = Double.TYPE;  
  14.                 } else if (TextUtils.equals(types[i], "long")  
  15.                         || TextUtils.equals(types[i], "Long")) {  
  16.                     cs[i] = Long.TYPE;  
  17.                 } else if (TextUtils.equals(types[i], "boolean")  
  18.                         || TextUtils.equals(types[i], "Boolean")) {  
  19.                     cs[i] = Boolean.TYPE;  
  20.                 } else if (TextUtils.equals(types[i], "String")) {  
  21.                     cs[i] = String.class;  
  22.                 } else {  
  23.                     try {  
  24.                         cs[i] = Class.forName(types[i]);  
  25.                     } catch (ClassNotFoundException e) {  
  26.                         e.printStackTrace();  
  27.                     }  
  28.                 }  
  29.             }  
  30.         }  
  31.         return cs;  
  32.     }  
  33.   
  34. public static Object[] getParaValueObject(String[] types, String[] paras) {  
  35.         Object[] objects = new Object[paras.length];  
  36.         for (int i = 0; i < objects.length; i++) {  
  37.             if (!TextUtils.isEmpty(paras[i])) {  
  38.                 if (TextUtils.equals(types[i], "int")  
  39.                         || TextUtils.equals(types[i], "Integer")) {  
  40.                     objects[i] = new Integer(paras[i]);  
  41.                 } else if (TextUtils.equals(types[i], "float")  
  42.                         || TextUtils.equals(types[i], "Float")) {  
  43.                     objects[i] = new Float(paras[i]);  
  44.                 } else if (TextUtils.equals(types[i], "double")  
  45.                         || TextUtils.equals(types[i], "Double")) {  
  46.                     objects[i] = new Double(paras[i]);  
  47.                 } else if (TextUtils.equals(types[i], "long")  
  48.                         || TextUtils.equals(types[i], "Long")) {  
  49.                     objects[i] = new Long(paras[i]);  
  50.                 } else if (TextUtils.equals(types[i], "boolean")  
  51.                         || TextUtils.equals(types[i], "Boolean")) {  
  52.                     objects[i] = new Boolean(paras[i]);  
  53.                 } else if (TextUtils.equals(types[i], "String")) {  
  54.                     objects[i] = paras[i];  
  55.                 } else {  
  56.                     // try {  
  57.                     // objects[i] = Class.forName(types[i]);  
  58.                     // } catch (ClassNotFoundException e) {  
  59.                     // e.printStackTrace();  
  60.                     // }  
  61.                 }  
  62.             }  
  63.         }  
  64.         return objects;  
  65.     }  
0 0
原创粉丝点击