本来想先介绍反射构造函数,代码写了一部分,发现先介绍反射构造函数不是太”灵活”,所以,就先介绍方法,感觉先介绍了方法,在讲构造函数时,往构造函数中传递参数,然后通过方法在体现出来,效果会更加!
大致介绍
一下Method.java
中需要用到的几个常见的方法:
| |
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html |
获取Method对象的几个常见方法,大致如下:
Field[] getDeclaredFields |
|
Method getDeclaredMethod |
|
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 block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (SecurityException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 implements
- OnClickListener {
- private static final String TAG = "oneplus";
- private static final String PACKAGENAME = "android.net.ConnectivityManager";
- private ConnectivityManager mConnectivityManager;
- private CheckBox mCheckBox;
- // android.net.ConnectivityManager
- @Override
- protected 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 phone
- Method 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 block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.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 block
- e.printStackTrace();
- }
- } catch (NoSuchMethodException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (IllegalArgumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (NoSuchFieldException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- @Override
- public void onClick(View view) {
- // TODO Auto-generated method stub
- int 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;
- }