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