Android 反射Method应用

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

---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

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

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

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;
	}

























你可能感兴趣的:(Android,反射技术应用手稿)