利用IActivityManager接口监听android系统中进程状态变化

  • Post author:
  • Post category:其他




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

来定时获取进程信息进行判断处理。



版权声明:本文为CJohn1994原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。