您的位置:首页 > 移动开发 > Android开发

Android 反射Method应用

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

大致介
下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

/**

*

*/

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


[java] view
plain copy

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();

}

}

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

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

[java] view
plain copy

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方法,基本上将上面的方法重写一遍:

[java] view
plain copy

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应用基本上是一样的:

[html] view
plain copy

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其实大胆的去使用,实践几个案例,就会发现原来这么容易,以后做项目,完全可以忽略系统里面的接口是隐藏还是没有隐藏,公开的就直接使用,隐藏的就反射.

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

[html] view
plain copy

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: