安卓5.1.1及以上 - getRunningAppProcesses()只返回我的应用程序包 [英] Android 5.1.1 and above - getRunningAppProcesses() returns my application package only

查看:6300
本文介绍了安卓5.1.1及以上 - getRunningAppProcesses()只返回我的应用程序包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎谷歌终于关闭了所有的门获取当前前台应用程序包。

It seems Google finally closed all doors for getting the current foreground application package.

在棒棒堂更新,其中死亡<一href="http://developer.android.com/intl/zh-cn/reference/android/app/ActivityManager.html#getRunningTasks(int)"><$c$c>getRunningTasks(int MAXNUM) 并感谢这个答案,我用这个code让前台应用程序包,因为棒棒堂:

After the Lollipop update, which killed getRunningTasks(int maxNum) and thanks to this answer, I used this code to get the foreground application package since Lollipop:

final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
    field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) { 
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
    if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
        app.importanceReasonCode == 0 ) {
        Integer state = null;
        try {
            state = field.getInt( app );
        } catch (Exception ignored) {
        }
        if (state != null && state == PROCESS_STATE_TOP) {
            currentInfo = app;
            break;
        }
    }
}
return currentInfo;

安卓5.1.1及以上(6.0棉花糖),看来,杀<一href="http://developer.android.com/intl/zh-cn/reference/android/app/ActivityManager.html#getRunningAppProcesses()"><$c$c>getRunningAppProcesses()为好。现在它返回自己的应用程序包的列表。

Android 5.1.1 and above (6.0 Marshmallow), it seems, killed getRunningAppProcesses() as well. It now returns a list of your own application package.

UsageStatsManager

我们可以使用新的 UsageStatsManager API作为这里描述但它不适用于所有应用程序的工作。一些系统应用将返回相同的封装

We can use the new UsageStatsManager API as described here but it doesn't work for all applications. Some system applications will return the same package

com.google.android.googlequicksearchbox


AccessibilityService

有些应用程序使用 AccessibilityService (如这里看出),但它有一些缺点。

Some applications use AccessibilityService (as seen here) but it has some disadvantages.

有没有让当前正在运行的应用程序包的另一种方式?

推荐答案

正如其他人所指出的那样,它是目前不可能得到在Android 6.0(棉花糖)前台应用程序。但是,通过分析在shell中运行工具箱PS 的输出,我们可以得到当前运行的应用程序。该 PS 实用程序已被拆开的Andr​​oid从至少Android 2.1系统。这确实的没有的需要root。

As others have pointed out, it is currently not possible to get the foreground app on Android 6.0 (Marshmallow). However, by parsing the output of running toolbox ps in a shell we can get the current running apps. The ps utility has been apart of Android from at least Android 2.1. This does not require root.

修改二○一五年十月二十○日:

我发表了一个项目,GitHub上获取正在运行的应用没有任何权限的列表:请参见:<一href="https://github.com/jaredrummler/AndroidProcesses">https://github.com/jaredrummler/AndroidProcesses

I published a project to GitHub to get a list of running apps without any permissions: See: https://github.com/jaredrummler/AndroidProcesses

我强烈建议你使用该库。我原来的答案是如下:

I highly recommend using the library. My original answer is below:

下面是一类我写来获得当前正在运行的应用程序(将工作在Android 6.0,并且应该至少在的Andr​​oid 4.0 +):

The following is a class I wrote to get the current running apps (will work on Android 6.0 and should work on at least Android 4.0+):

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;

import eu.chainfire.libsuperuser.Shell;

/**
 * @author Jared Rummler
 */
public class ProcessManager {

    private static final String TAG = "ProcessManager";

    private static final String APP_ID_PATTERN;

    static {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // Android 4.2 (JB-MR1) changed the UID name of apps for multiple user account support.
            APP_ID_PATTERN = "u\\d+_a\\d+";
        } else {
            APP_ID_PATTERN = "app_\\d+";
        }
    }

    public static List<Process> getRunningProcesses() {
        List<Process> processes = new ArrayList<>();
        List<String> stdout = Shell.SH.run("toolbox ps -p -P -x -c");
        for (String line : stdout) {
            try {
                processes.add(new Process(line));
            } catch (Exception e) {
                android.util.Log.d(TAG, "Failed parsing line " + line);
            }
        }
        return processes;
    }

    public static List<Process> getRunningApps() {
        List<Process> processes = new ArrayList<>();
        List<String> stdout = Shell.SH.run("toolbox ps -p -P -x -c");
        int myPid = android.os.Process.myPid();
        for (String line : stdout) {
            try {
                Process process = new Process(line);
                if (process.user.matches(APP_ID_PATTERN)) {
                    if (process.ppid == myPid || process.name.equals("toolbox")) {
                        // skip the processes we created to get the running apps.
                        continue;
                    }
                    processes.add(process);
                }
            } catch (Exception e) {
                android.util.Log.d(TAG, "Failed parsing line " + line);
            }
        }
        return processes;
    }

    public static class Process implements Parcelable {

        /** User name */
        public final String user;

        /** User ID */
        public final int uid;

        /** Processes ID */
        public final int pid;

        /** Parent processes ID */
        public final int ppid;

        /** virtual memory size of the process in KiB (1024-byte units). */
        public final long vsize;

        /** resident set size, the non-swapped physical memory that a task has used (in kiloBytes). */
        public final long rss;

        public final int cpu;

        /** The priority */
        public final int priority;

        /** The priority, <a href="https://en.wikipedia.org/wiki/Nice_(Unix)">niceness</a> level */
        public final int niceness;

        /** Real time priority */
        public final int realTimePriority;

        /** 0 (sched_other), 1 (sched_fifo), and 2 (sched_rr). */
        public final int schedulingPolicy;

        /** The scheduling policy. Either "bg", "fg", "un", "er", or "" */
        public final String policy;

        /** address of the kernel function where the process is sleeping */
        public final String wchan;

        public final String pc;

        /**
         * Possible states:
         * <p/>
         * "D" uninterruptible sleep (usually IO)
         * <p/>
         * "R" running or runnable (on run queue)
         * <p/>
         * "S" interruptible sleep (waiting for an event to complete)
         * <p/>
         * "T" stopped, either by a job control signal or because it is being traced
         * <p/>
         * "W" paging (not valid since the 2.6.xx kernel)
         * <p/>
         * "X" dead (should never be seen)
         * </p>
         * "Z" defunct ("zombie") process, terminated but not reaped by its parent
         */
        public final String state;

        /** The process name */
        public final String name;

        /** user time in milliseconds */
        public final long userTime;

        /** system time in milliseconds */
        public final long systemTime;

        // Much dirty. Much ugly.
        private Process(String line) throws Exception {
            String[] fields = line.split("\\s+");
            user = fields[0];
            uid = android.os.Process.getUidForName(user);
            pid = Integer.parseInt(fields[1]);
            ppid = Integer.parseInt(fields[2]);
            vsize = Integer.parseInt(fields[3]) * 1024;
            rss = Integer.parseInt(fields[4]) * 1024;
            cpu = Integer.parseInt(fields[5]);
            priority = Integer.parseInt(fields[6]);
            niceness = Integer.parseInt(fields[7]);
            realTimePriority = Integer.parseInt(fields[8]);
            schedulingPolicy = Integer.parseInt(fields[9]);
            if (fields.length == 16) {
                policy = "";
                wchan = fields[10];
                pc = fields[11];
                state = fields[12];
                name = fields[13];
                userTime = Integer.parseInt(fields[14].split(":")[1].replace(",", "")) * 1000;
                systemTime = Integer.parseInt(fields[15].split(":")[1].replace(")", "")) * 1000;
            } else {
                policy = fields[10];
                wchan = fields[11];
                pc = fields[12];
                state = fields[13];
                name = fields[14];
                userTime = Integer.parseInt(fields[15].split(":")[1].replace(",", "")) * 1000;
                systemTime = Integer.parseInt(fields[16].split(":")[1].replace(")", "")) * 1000;
            }
        }

        private Process(Parcel in) {
            user = in.readString();
            uid = in.readInt();
            pid = in.readInt();
            ppid = in.readInt();
            vsize = in.readLong();
            rss = in.readLong();
            cpu = in.readInt();
            priority = in.readInt();
            niceness = in.readInt();
            realTimePriority = in.readInt();
            schedulingPolicy = in.readInt();
            policy = in.readString();
            wchan = in.readString();
            pc = in.readString();
            state = in.readString();
            name = in.readString();
            userTime = in.readLong();
            systemTime = in.readLong();
        }

        public String getPackageName() {
            if (!user.matches(APP_ID_PATTERN)) {
                // this process is not an application
                return null;
            } else if (name.contains(":")) {
                // background service running in another process than the main app process
                return name.split(":")[0];
            }
            return name;
        }

        public PackageInfo getPackageInfo(Context context, int flags)
                throws PackageManager.NameNotFoundException
        {
            String packageName = getPackageName();
            if (packageName == null) {
                throw new PackageManager.NameNotFoundException(name + " is not an application process");
            }
            return context.getPackageManager().getPackageInfo(packageName, flags);
        }

        public ApplicationInfo getApplicationInfo(Context context, int flags)
                throws PackageManager.NameNotFoundException
        {
            String packageName = getPackageName();
            if (packageName == null) {
                throw new PackageManager.NameNotFoundException(name + " is not an application process");
            }
            return context.getPackageManager().getApplicationInfo(packageName, flags);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(user);
            dest.writeInt(uid);
            dest.writeInt(pid);
            dest.writeInt(ppid);
            dest.writeLong(vsize);
            dest.writeLong(rss);
            dest.writeInt(cpu);
            dest.writeInt(priority);
            dest.writeInt(niceness);
            dest.writeInt(realTimePriority);
            dest.writeInt(schedulingPolicy);
            dest.writeString(policy);
            dest.writeString(wchan);
            dest.writeString(pc);
            dest.writeString(state);
            dest.writeString(name);
            dest.writeLong(userTime);
            dest.writeLong(systemTime);
        }

        public static final Creator<Process> CREATOR = new Creator<Process>() {

            public Process createFromParcel(Parcel source) {
                return new Process(source);
            }

            public Process[] newArray(int size) {
                return new Process[size];
            }
        };
    }

}

就在类复制到项目,如果你想使用它。您还需要添加 libsuperuser 作为依赖于你的build.gradle文件:

Just copy the class into your project if you wish to use it. You will also need to add libsuperuser as a dependency to your build.gradle file:

compile 'eu.chainfire:libsuperuser:1.0.0.+'


示例/测试:

(上一台Nexus 9当前运行的中号开发商preVIEW测试):


Example/Test:

(tested on a Nexus 9 running the current M developer preview):

new AsyncTask<Void, Void, List<ProcessManager.Process>>() {

    long startTime;

    @Override
    protected List<ProcessManager.Process> doInBackground(Void... params) {
        startTime = System.currentTimeMillis();
        return ProcessManager.getRunningApps();
    }

    @Override
    protected void onPostExecute(List<ProcessManager.Process> processes) {
        StringBuilder sb = new StringBuilder();
        sb.append("Execution time: ").append(System.currentTimeMillis() - startTime).append("ms\n");
        sb.append("Running apps:\n");
        for (ProcessManager.Process process : processes) {
            sb.append('\n').append(process.name);
        }
        new AlertDialog.Builder(MainActivity.this).setMessage(sb.toString()).show();
    }
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

我写了下面code获得阅读Android源$ C ​​$ C后的And​​r​​oid 6.0前台应用程序。我只测试它在我的Nexus 9,它似乎工作。在code是混乱的(现在),但我真的需要有人来测试它。

I wrote the following code to get the foreground app on Android 6.0 after reading Android source code. I have only tested it on my Nexus 9 and it seems to work. The code is messy (right now) but I really need someone to test it out.

复制并粘贴到下面的code到任何类,并调用 getForegroundApp()

Copy and paste the following code into any class and call getForegroundApp():

/** 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");

      if (lines.length != 2) {
        continue;
      }

      String cpuSubsystem = lines[0];
      String cpuaccctSubsystem = lines[1];

      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();
}


修改二零一五年十月一十一日:

在Android 5.0以上,工具箱PS 不会返回所有进程是SELinux执行。

On Android 5.0+, toolbox ps will not return all processes if SELinux is enforcing.

这篇关于安卓5.1.1及以上 - getRunningAppProcesses()只返回我的应用程序包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆