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<RunningTaskInfo> 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<String> names = new ArrayList<String>();
		PackageManager packageManager = context.getPackageManager();
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		List<ResolveInfo> 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<String> names = new ArrayList<String>();
		PackageManager packageManager = context.getPackageManager();
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		List<ResolveInfo> 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<String, Integer>();
		}
		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
下面是本人的具体代码事例代码,需要的到请下载
点击打开链接







  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值