天天看點

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

下面是本人的具體代碼事例代碼,需要的到請下載下傳

點選打開連結