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
下面是本人的具體代碼事例代碼,需要的到請下載下傳
點選打開連結