利用IActivityManager接口监听系统进程变化
通过ActivityManager获取进程信息
在android开发中,可通过android提供的
ActivityManager
实现应用进程信息的获取,例如通过
ActivityManager
获取栈顶Activity名称的方式如下:
ActivityManager mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
private String getRunningActivity() {
List<ActivityManager.RunningTaskInfo> list = null;
if (mActivityManager != null){
list = mActivityManager.getRunningTasks(1);
}
if (list != null && list.size() > 0){
String runningActivity = list.get(0).topActivity.getClassName();
return runningActivity;
}
return "";
}
IActivityManager介绍
上面方法可得到准确的包名信息来判断对应进程。通过
ActivityManager
也可获取更多的信息,但是不能实时监听系统中进程的变化。在与AMS相关的接口找到
IActivityManager
,
IActivityManager
是一个系统接口,实现类为
ActivityManagerNative
,
ActivityManagerNative
基于binder与AMS通信,时序图如下:
ActivityManagerNative
内部持有AMS的代理,使用
ActivityManagerNative
实际上也是调用AMS的方法。
具体参考链接:
源码分析 — Binder机制(二)之IActivityManager
IActivityManager使用
通过下面方式可获得IActivityManager接口实例:
IActivityManager mIActivityManager = ActivityManagerNative.asInterface(ServiceManager.getService(Context.ACTIVITY_SERVICE));
实时监听进程变化需要通过接口
registerProcessObserver
方法注册观察者,具体方式如下:
private void register() {
try {
if (mIActivityManager != null) {
mProcessObserver = new ProcessObserver();
mIActivityManager.registerProcessObserver(mProcessObserver);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
private class ProcessObserver extends IProcessObserver.Stub {
@Override public void onForegroundActivitiesChanged(final int pid, int uid, final boolean foregroundActivities) {
Log.d(TAG, String.format("onForegroundActivitiesChanged uid %d pid %d fg %b", uid, pid, foregroundActivities));
}
@Override
public void onProcessStateChanged(int pid, int uid, int procState) {
Log.d(TAG,String.format("onProcessStateChanged uid %d pid %d state %d", uid, pid, procState));
//判断进程状态,仅作参考,具体状态见图解
if (procState == ActivityManager.PROCESS_STATE_PERSISTENT || procState == ActivityManager.PROCESS_STATE_PERSISTENT_UI
|| procState == ActivityManager.PROCESS_STATE_TOP || procState == ActivityManager.PROCESS_STATE_SERVICE) {
}
}
@Override public void onProcessDied(int pid, int uid) {
Log.d(TAG, String.format("onProcessDied uid %d pid %d", uid, pid));
}
}
其中procState状态对应如下图:
记得调用
IActivityManager
的
unregisterProcessObserver
方法反注册。
IActivityManager好用的方法
获取系统进程名称和前台Activity,
ActivityManager
获取的方式一样,只不过通过
IActivityManager
就不用再实例化获取
ActivityManager
了。
/**
*也可通过ActivityManager mActivityManager
**/
private String getRunningProcess() {
String processName = "";
try {
if (mIActivityManager != null) {
ActivityManager.RunningAppProcessInfo processInfo
= mIActivityManager.getRunningAppProcesses().get(0);
// 增加process是否在前台的判断
if (processInfo.importance == ActivityManager
.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& processInfo.processState == ActivityManager.START_TASK_TO_FRONT) {
processName = processInfo.processName;
processName = processName.split(":")[0];
Log.d(TAG,"getRunningProcess: " + processName);
}
}
} catch (RemoteException e) {
e.printStackTrace();
}
return processName;
}
获取应用进程栈顶Acitivity方式如下,下面通过为
IActivityManager
来实现:
private String getRunningActivity() {
String runningActivity = "";
try {
if (mIActivityManager != null) {
List<ActivityManager.RunningTaskInfo> runningTaskInfos = mIActivityManager.getTasks(1,0);
if (runningTaskInfos != null && runningTaskInfos.size() > 0) {
runningActivity = runningTaskInfos.get(0).topActivity.getClassName();
Log.d(TAG,"getRunningActivity: " + runningActivity);
}
}
} catch (RemoteException e) {
e.printStackTrace();
}
return runningActivity;
}
ActivityManager
获取的方式有点不同,见前面介绍。
通过进程名称判断是否为系统应用,可通过下面方法判断:
private boolean isSystemApp(String processName) {
if (processName != null) {
try {
PackageManager pm = mContext.getPackageManager();
PackageInfo info = pm.getPackageInfo(processName, 0);
return (info != null) && (info.applicationInfo != null) &&
((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
} else {
return false;
}
}
上面方法主要通过应用信息的flag进行判断,可能存在某个特殊应用需要根据包名判断是否为系统应用。
结语
以上是
IActivityManager
的使用介绍,仅限于系统应用使用,非系统应用无法直接调用
IActivityManager
,可通过
ActivityManager
来定时获取进程信息进行判断处理。