本人喜欢把复杂的事情简单化,简单的事情复杂化---以前读书的时候,语文老师经常再三强调,写作文的时候不要把题目写”太大”了;只要写一件小事,写的越详细越动人就达到了目的!
---zhibao.liu
本来想先介绍反射构造函数,代码写了一部分,发现先介绍反射构造函数不是太”灵活”,所以,就先介绍方法,感觉先介绍了方法,在讲构造函数时,往构造函数中传递参数,然后通过方法在体现出来,效果会更加!
大致介绍
一下Method.java
中需要用到的几个常见的方法:
invoke |
|
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
看看,代码很简单,异常处理的代码比实际的代码还要多,运行结果如下:
在上面做进一步扩展,看看如果使用反射出来的方法:
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;
}
}
}
附录 : 在上面工程中已经添加包含下面的两个方法:
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;
}