android5.1+获取当前运行的app

这段时间做的一个项目,需要获取当前正在运行的app,android5.0之前可以使用getRunningTask获取,5.0这个方法不可用了,但是提供了getRunningAppProcess也可以获得。但是自从android5.1以后,Google从安全和隐私方面考虑,也废弃了这个方法,现在只能返回自己的应用。这段时间一直在研究,在网上也搜寻了很久,诸如,通过反射ActivityManager.RunningAppProcessInfo下的“processState”,或者反射android.app.ActivityThread,或者获取正在运行的top activity也都是失败。还有使用UsageState,AccessableService,这些需要用户手动开启,不符合项目需要。也找过源代码研究比如ActivityManagerNative的,系统设置里的应用管理代码,也都无功而返。

     终于在stackOverFlow找个一个大神的回答http://stackoverflow.com/a/32366476。读取android下proc的文件夹获取进程的相关信息。虽然之前看到过这个大神的获取正在运行的进程列表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(总是被杀掉)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值