如何生成内部hide接口实例并通过反射作为参数进行传递

一、前言

android系统源码中,有很多的api是隐藏的,在eclipse中通过sdk是无法访问到的。这些api有的是整个类/接口、有的是某个具体的方法、或者变量,在源码中通过文档注释内的“@hide”字符进行标识。如果我们需要去访问这些被hide的方法、类,可以采用如下两种方式:

1、在源码环境下进行访问,即将我们的工程放到源码下进行编译,这样是可以访问的;

2、通过java的反射机制

 

二、场景描述

这里讲述的是在eclipse下直接通过反射机制来访问系统隐藏api。举例如下:

android.app.ActivityManagerNative类定义了一个setActivityController(IActivityController watcher)方法,该方法通过参数IAcitivityController设置一个监听器,用来监听系统启动某个Activity。当系统启动某个Activity时,会调用IAcitivityController的回调方法。

在工程中可以通过获取ActivityManagerNative对象并生成一个IActivityController实例作为setActivityController()的参数传递过去,从而达到在工程中监听到系统Activity的启动。

 

ActivityManagerNative.java和IAcitivityController.aidl均为hide api,如下:

package android.app;
/** {@hide} */
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
  }
   
  public void setActivityController(IActivityController watcher) throws RemoteException{}
}
  
package android.app;
import android.content.Intent;
/**
 * Testing interface to monitor what is happening in the activity manager
 * while tests are running.  Not for normal application development.
 * {@hide}
 */
interface IActivityController

以上类都有“@hide”标识,所以需要通过反射的机制来进行访问。ActivityManagerNative对象可通过反射和该类的静态方法getDefault()获取到,再通过setActivityController方法设置监听器。但IActivityController也是内部hide aidl文件,如何继承该接口并实例化呢?

解决方案:把系统内的IActivityController.aidl文件在我们自己的工程里按照同样的包结构创建一份,在程序中继承该接口,在调用setActivityController时传入该实例即可。



三、实现过程

1、拷贝系统内IActivityController.aidl到工程中,与系统内该文件包结构保持一致:

2、程序中实现该接口:

	private class ActivityController extends IActivityController.Stub {

		public boolean activityStarting(Intent intent, String pkg) {
			return true;
		}

		public boolean activityResuming(String pkg) {
			return true;
		}

		public int appEarlyNotResponding(String processName, int pid,
				String annotation) {
			return 0;
		}

		public boolean appCrashed(String processName, int pid, String shortMsg,
				String longMsg, long timeMillis, String stackTrace) {
			return false;
		}

		public int appNotResponding(String processName, int pid,
				String processStats) {
			return 0;
		}
	}

3、通过反射获取ActivityManagerNative对象并调用方法setActivityController进行监听器设置:

	private void setActivityController() {
		try {
			Class<?> cActivityManagerNative = Class
					.forName("android.app.ActivityManagerNative");
			Method mGetDefault = cActivityManagerNative.getMethod("getDefault",
					null);
			Object oActivityManagerNative = mGetDefault.invoke(null, null);
			Class<?> i = Class.forName("android.app.IActivityController$Stub");

			Method mSetActivityController = cActivityManagerNative.getMethod(
					"setActivityController",
					Class.forName("android.app.IActivityController"));
			mSetActivityController.invoke(oActivityManagerNative,
					new ActivityController());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}



没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试