android获取当前设备运行app的进程
1.当前设备进程分类
进程优先级从高到低可分为四种:前台进程、可视进程、服务进程、缓存进程。
前台进程(foreground process):用户当前正在进行可操作的,一般满足以下条件:
(1).屏幕顶层运行Activity(处于onResume()状态),用户正与之交互。
(2).有BroadcastReceiver正在执行代码。
(3).有Service在其回调方法(onCreate()、onStart()、onDestroy())中正在执行代码。
可视进程(visible process):做用户当前意识到的工作。一般满足以下条件:
(1).屏幕上显示Activity,但不可操作(处于onPause()状态)。
(2).有service通过调用Service.startForeground(),作为一个前台服务运行。
(3).含有用户意识到的特定的服务,如动态壁纸、输入法等
服务进程(service process):含有以startService()方法启动的service。虽然该进程用户不直接可见,
但是它们一般做一些用户关注的事情(如数据的上传与下载)。这些进程一般不会杀死,除非系统内存不足以
保持前台进程和可视进程的运行。 对于长时间运行的service(如30分钟以上),系统会考虑将之降级为缓存进程,
避免长时间运行导致内存泄漏或其他问题,占用过多RAM以至于系统无法分配充足资源给缓存进程。
缓存/后台进程(cached/background process):一般来说包含以下条件:
(1). 包含多个Activity实例,但是都不可见(处于onStop()且已返回)。
系统如有内存需要,可随意杀死。
2.android SDK版本20以下获取当前进程
在android5.0即sdk20以下,获取当前进程需要在注册权限,权限为:
android.Manifest.permission.GET_TASKS
获取之前先判断权限是否已注册:
/** * 检查当前应用是否有指定的权限 * * @param context * @param permName * --权限 * @return true--有, false--没有 */public static boolean checkPermission(Context context, String permName) {PackageManager pm = context.getPackageManager();if (PackageManager.PERMISSION_GRANTED == pm.checkPermission(permName, context.getPackageName())) {return true;}return false;}
最后获取当前进程包名:
/** * 获取当用户在试用的应用包名,适用于5.0以下 * * @param context * @return */public static String getRunningTask(Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List taskInfos = am.getRunningTasks(1);if (taskInfos != null && taskInfos.size() > 0) {ComponentName cn = taskInfos.get(0).topActivity;return cn.getPackageName();}return "";}
在android5.0即sdk20以上(包含20),要获取当前设备进程,用常规方式只能获取自身应用,若自身应用不是前台进程,者获取不到其他进程包名。以下方式是通过读取系统进程底层文件来获取当前进程包名。
/** * 获取当用户在试用的应用包名,适用于5.0以上 * * @return */public static String getForegroundApp(Context context) {File[] files = new File("/proc").listFiles();int lowestOomScore = Integer.MAX_VALUE;String foregroundProcess = null;for (File file : files) {if (!file.isDirectory()) {continue;}int pid;try {pid = Integer.parseInt(file.getName());} catch (NumberFormatException e) {continue;}try {String cgroup = read(String.format("/proc/%d/cgroup", pid));String[] lines = cgroup.split("\n");String cpuSubsystem;String cpuaccctSubsystem;if (lines.length == 2) {// 有的手机里cgroup包含2行或者3行,我们取cpu和cpuacct两行数据cpuSubsystem = lines[0];cpuaccctSubsystem = lines[1];} else if (lines.length == 3) {cpuSubsystem = lines[0];cpuaccctSubsystem = lines[2];} else if (lines.length == 5) {cpuSubsystem = lines[2];cpuaccctSubsystem = lines[4];} else {continue;}if (!cpuaccctSubsystem.endsWith(Integer.toString(pid))) {continue;}if (cpuSubsystem.endsWith("bg_non_interactive")) {continue;}String cmdline = read(String.format("/proc/%d/cmdline", pid));if (isContainsFilter(cmdline)) {continue;}int uid = Integer.parseInt(cpuaccctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));if (uid >= 1000 && uid <= 1038) {continue;}int appId = uid - AID_APP;while (appId > AID_USER) {appId -= AID_USER;}if (appId < 0) {continue;}File oomScoreAdj = new File(String.format("/proc/%d/oom_score_adj", pid));if (oomScoreAdj.canRead()) {int oomAdj = Integer.parseInt(read(oomScoreAdj.getAbsolutePath()));if (oomAdj != 0) {continue;}}int oomscore = Integer.parseInt(read(String.format("/proc/%d/oom_score", pid)));if (oomscore < lowestOomScore) {lowestOomScore = oomscore;foregroundProcess = cmdline;}if (foregroundProcess == null) {return null;}int indexOf = foregroundProcess.indexOf(":");if (indexOf != -1) {foregroundProcess = foregroundProcess.substring(0, indexOf);}} catch (NumberFormatException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}return foregroundProcess;}private static String read(String path) throws IOException {StringBuilder output = new StringBuilder();BufferedReader reader = new BufferedReader(new FileReader(path));output.append(reader.readLine());for (String line = reader.readLine(); line != null; line = reader.readLine()) {output.append('\n').append(line);}reader.close();return output.toString().trim();// 不调用trim(),包名后会带有乱码}
有一些应用是常驻应用包名,添加过滤方法:
/** * filter包名过滤 * * @param cmdline * @return */public static boolean isContainsFilter(String cmdline) {boolean flag = false;if (filterMap == null || filterMap.isEmpty() || filterMap.size() == 0) {initFliter();}if (filterMap != null) {for (String key : filterMap.keySet()) {if (cmdline.contains(key)) {flag = true;break;}}}return flag;}
下面方法是判断是否为第三方应用,并且有界面的应用:
/** * 判断是否为第三方应用,并且有界面的应用 * * @param context * @param packageName * @return true:第三方应用,并且有界面 */public static boolean isUserApp(Context context, String packageName) {List names = new ArrayList();PackageManager packageManager = context.getPackageManager();Intent intent = new Intent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_HOME);List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);//for (ResolveInfo resolveInfo : list) {names.add(resolveInfo.activityInfo.packageName);}if (!names.contains(packageName)) {if (packageManager.getLaunchIntentForPackage(packageName) != null) {return true;}}return false;}
下面方法是判断是否为桌面应用:
/** * 是否为桌面应用 * * @param context * @param packageName * @return */public static boolean isLauncherApp(Context context, String packageName) {List names = new ArrayList();PackageManager packageManager = context.getPackageManager();Intent intent = new Intent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_HOME);List list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);//for (ResolveInfo resolveInfo : list) {names.add(resolveInfo.activityInfo.packageName);}if (names.contains(packageName)) {return true;}return false;}
有一些第三方常驻顶层应用,可以在初始化的时候添加进去,比如: /** * 初始化filter */public static void initFliter() {if (filterMap == null) {filterMap = new HashMap();}if (filterMap.isEmpty() || filterMap.size() == 0) {filterMap.put("com.android.systemui", 0);filterMap.put("com.aliyun.ams.assistantservice", 0);filterMap.put("com.meizu.cloud", 0);filterMap.put("com.android.incallui", 0);filterMap.put("com.amap.android.location", 0);filterMap.put("com.android.providers.contacts", 0);filterMap.put("com.samsung.android.providers.context", 0);filterMap.put("com.android.dialer", 0);filterMap.put("com.waves.maxxservice", 0);filterMap.put("com.lge.camera", 0);filterMap.put("se.dirac.acs", 0);filterMap.put("/", 0);}}
转载请说明出处: http://blog.csdn.net/u012438830/article/details/78526152 下面是本人的具体代码事例代码,需要的到请下载
点击打开链接
更多相关文章
- Android(三):远程Service基本操作
- Android(安卓)8.0 系统启动流程之init进程--第二阶段(五)
- android多进程深入分析
- Android学习系列(7)--App消息通知机制
- Activity的启动流程分析
- 《Android开发艺术探索》读书笔记 (2) 第2章 IPC机制
- Android(安卓)9.0及以上版本中,关于多进程问题对于WebView的影响
- android学习和广告平台赚钱
- Android(安卓)8.1 开机流程分析(1)