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

通过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相关的接口找到IActivityManagerIActivityManager是一个系统接口,实现类为ActivityManagerNativeActivityManagerNative基于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状态对应如下图:
在这里插入图片描述
记得调用IActivityManagerunregisterProcessObserver方法反注册。

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来定时获取进程信息进行判断处理。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

言并肃

感谢大哥支持!您的鼓励是我动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值