您的位置:首页 > 移动开发

android 5.1及以上获取正在运行的app(top app)

2016-10-04 17:27 471 查看
1.android 5.0以下:

((ActivityManager.RunningAppProcessInfo)((ActivityManager)paramContext.getSystemService("activity")).getRunningAppProcesses().get(0)).processName;


2.android 5.0:

((ActivityManager.RunningTaskInfo)((ActivityManager)paramContext.getSystemService("activity")).getRunningTasks(1).get(0)).topActivity;


3.android 5.1及以上:

 可以使用stackOverFlow找个一个大神的回答http://stackoverflow.com/a/32366476

使用他写的code:https://github.com/jaredrummler/AndroidProcesses,但是获取的是列表,不能判断哪一个进程是当然显示的应用,用于判断的foreground参数能返回多个true的情况。这个大神又在回答这个问题放出获取当前应用的代码。贴一下代码:

/** first app user */
public static final int AID_APP = 10000;
/** offset for uid ranges for each user */
public static final int AID_USER = 100000;
public static String getForegroundApp() {
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 {
continue;
}
if (!cpuaccctSubsystem.endsWith(Integer.toString(pid))) {
// not an application process
continue;
}
if (cpuSubsystem.endsWith("bg_non_interactive")) {
// background policy
continue;
}
String cmdline = read(String.format("/proc/%d/cmdline", pid));
if (cmdline.contains("com.android.systemui")) {
continue;
}
int uid = Integer.parseInt(
cpuaccctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));
if (uid >= 1000 && uid <= 1038) {
// system process
continue;
}
int appId = uid - AID_APP;
int userId = 0;
// loop until we get the correct user id.
// 100000 is the offset for each user.
while (appId > AID_USER) {
appId -= AID_USER;
userId++;
}
if (appId < 0) {
continue;
}
// u{user_id}_a{app_id} is used on API 17+ for multiple user account support.
// String uidName = String.format("u%d_a%d", userId, appId);
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;
}
} catch (IOException 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(),包名后面会带有乱码
}  依照大神的代码,在实际测试中有的手机能返回当然的包名,有的还是返回null,比照系统文件和代码分析,发现有的手机里cgroup包含两行cpu 和cpuacct,有的则是三行,多了一行memory。所以对代码稍加改动,上面是改动过的。下面对调用的文件和文件内容解释一下:
1.proc下以数字命名的文件夹,文件夹名即是一个进程的pid,该文件夹下的文件包含这个进程的信息;

2.cgroup,控制组群(control groups)的简写,是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。cpu:设置cpu的使用率;cpuacct:记录cpu的统计信息。

3.bg_non_interactive,运行cpu的一个分组,另一分组是apps,当一个应用(进程)即可从apps分组切换到bg_non_interactive,也可以切换回来。apps分组可以利用95%的cpu,而bg_non_interactive只能使用大约5%。

4.cmdline,显示内核启动的命令行。

5.oom_score_adj,这个文件的数值用来标记在内存不足的情况下,启发式的(不知道怎么翻译好==)选择哪个进程被杀掉,值从0(从不被杀掉)到1000(总是被杀掉)。

完整的代码,稍后会上到GitHub.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 进程 5.1