Android 无法获取正在运行的程序

时间:2022-06-23 04:57:27

Android源码系统层之前可以顺利的获取正在运行的程序和kill正在运行的程序,在第三方应用上加入android.permission.REAL_GET_TASKS权限也可以获取。加入权限<uses-permission android:name="android.permission.GET_TASKS" />

方法如下:

    /**
     * @return The lists of the RunningApps
     */
    public List<HashMap<String, Object>> getRunningApp() {
        appInfos.clear();
        final PackageManager pm = mContext.getPackageManager();
        am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        runningProcess = am.getRunningAppProcesses();// use it if the getRunningTasks API is deprecated
        runningTasks = am.getRunningTasks(MAX_RUNNING_TASKS);//The maximum number of running list
        Log.i(TAG, "runningProcess = " + runningProcess.size());
        Log.i(TAG, "runningTasks = " + runningTasks.size());
        for (int i = 0; i< runningTasks.size(); i++){
            ActivityManager.RunningTaskInfo rt = runningTasks.get(i);
            if (i == 0){
                //skip the front task, also see the top of tasks stack
                continue;
            }
            HashMap<String, Object> runningAppInfo = new HashMap<String, Object>();
            ComponentName component = rt.baseActivity;
            String pkgName = component.getPackageName();
            String className = component.getClassName();
            String shortclassName = component.getShortClassName();
            ApplicationInfo applicationInfo = null;
            Log.i(TAG, "runningTasks pkgName = " + pkgName);
            if (pkgName.equals("com.android.launcher3") || pkgName.equals("com.android.systemui")) {
                // skip the launcher and systemui, the special tasks.
                continue;
            }
            try {
                applicationInfo = pm.getApplicationInfo(pkgName, 0);
                // skip the system app
//				if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
//					continue;
//				}
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            } finally {
            }

            String applicationName = (String) pm.getApplicationLabel(applicationInfo);
            Drawable icon = pm.getApplicationIcon(applicationInfo);
            int id = rt.id;
            ActivityManager.TaskThumbnail taskThumbnail = am.getTaskThumbnail(id);
            Bitmap thumbnail = taskThumbnail.mainThumbnail;
            runningAppInfo.put("pkgname", pkgName);
            runningAppInfo.put("appname", applicationName);
            runningAppInfo.put("thumbnail", thumbnail);
            runningAppInfo.put("taskid", id);
            runningAppInfo.put("icon", icon);
            appInfos.add(runningAppInfo);
        }
        return appInfos;
    }



但是今儿在第三方应用研究Process和Task的关系时发现getRunningTasks()方法只能获取到当前应用和Launcher。确认代码无误后查看该方法源码:


     * @deprecated As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method
     * is no longer available to third party
     * applications: the introduction of document-centric recents means
     * it can leak person information to the caller.  For backwards compatibility,
     * it will still retu rn a small subset of its data: at least the caller's
     * own tasks, and possibly some other tasks
     * such as home that are known to not be sensitive.


该方法实际上是不建议使用的了,并且在Android L以后不支持第三方应用调用该方法,就算在Manifest里面声明了权限也是不被认可的。而且根据Google的安全性考虑这个接口可能会在后面一本版本被彻底弃用

因为Android L以后Google为了提升系统的安全性,进行了权限收敛,限制了很多以前可以使用的接口, 这些被限制的接口大多都容易向第三方泄露用户的隐私信息。但是为了保证向后兼容性,仍然可以获取到一些RunningTasks数据的子集(至少包括当前调用者的Task和Launcher这种不含敏感信息的数据)。

而且文档指出,针对于普通第三方应用(不包含预置APK)这个接口目前只可用于Debug(然而这个本人测试发现Debug也不可以)和展示系统的任务管理器。不清楚360这些在5.0以后是如何实现的,待研究。


对于替代方法可参考:

http://*.com/questions/26714285/is-there-an-alternative-for-getrunningtask-api/27304318#27304318

http://*.com/questions/24625936/getrunningtasks-doesnt-work-in-android-l/27140347#27140347