【问题标题】:Android M: How to get all processes UID's?Android M:如何获取所有进程的 UID?
【发布时间】:2015-08-25 01:22:21
【问题描述】:

我有一个应用程序使用traffic stats API 来查看哪些正在运行的进程正在使用网络。

我以前是通过getRunningAppProcesses()方法获取uid来实现的。显然,这已在 Android M 中更改为仅返回您的应用程序包名称,如 here 所示。

我的问题是:还有其他方法可以获取 Android M 中每个正在运行的进程的名称 UID吗?

这是我之前如何执行此操作的示例,我想在 Android M 上重新创建此功能。

List<RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();

PackageManager pm = context.getPackageManager();
for (int i = 0; i < procInfos.size(); i++) {
    try {
        String packageName = procInfos.get(i).processName;
        String appName = "";
        try {
            appName = pm.getApplicationLabel(
                    pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA))
                        .toString();
        } catch (NameNotFoundException e) {
            appName = "";
        }

        int uid = procInfos.get(i).uid;
        long ulBytes = TrafficStats.getUidTxBytes(uid);
        long dlBytes = TrafficStats.getUidRxBytes(uid);
        // Do other stuff.

非常感谢任何帮助。谢谢!

【问题讨论】:

标签: android process uid android-6.0-marshmallow


【解决方案1】:

你可以使用ActivityManager.getRunningServices(int maxNum):

PackageManager pm = context.getPackageManager();
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> runningServices = am.getRunningServices(Integer.MAX_VALUE);
for (ActivityManager.RunningServiceInfo service : runningServices) {
    String appName;
    try {
        appName = pm.getApplicationInfo(service.process, 0).loadLabel(pm).toString();
    } catch (PackageManager.NameNotFoundException e) {
        appName = null;
    }

    int uid = service.uid;

    long ulBytes = TrafficStats.getUidTxBytes(uid);
    long dlBytes = TrafficStats.getUidRxBytes(uid);
}

文档指出这不适用于生产。我也没有对它进行太多测试。如果不符合您的要求,请发表评论。我能想到的唯一另一件事是解析在 shell 中运行 ps 的输出。

更新

在 shell 中解析ps 的输出,我们可以得到当前正在运行的应用程序。示例:

PackageManager pm = context.getPackageManager();
// Get the output of running "ps" in a shell.
// This uses libsuperuser: https://github.com/Chainfire/libsuperuser
// To add this to your project: compile 'eu.chainfire:libsuperuser:1.0.0.+'
List<String> stdout = Shell.SH.run("ps");
List<String> packages = new ArrayList<>();
for (String line : stdout) {
    // Get the process-name. It is the last column.
    String[] arr = line.split("\\s+");
    String processName = arr[arr.length - 1].split(":")[0];
    packages.add(processName);
}

// Get a list of all installed apps on the device.
List<ApplicationInfo> apps = pm.getInstalledApplications(0);

// Remove apps which are not running.
for (Iterator<ApplicationInfo> it = apps.iterator(); it.hasNext(); ) {
    if (!packages.contains(it.next().packageName)) {
        it.remove();
    }
}

for (ApplicationInfo app : apps) {
    String appName = app.loadLabel(pm).toString();
    int uid = app.uid;
    long ulBytes = TrafficStats.getUidTxBytes(uid);
    long dlBytes = TrafficStats.getUidRxBytes(uid);
    /* do your stuff */
}

【讨论】:

  • 嗨,贾里德,感谢您的回复!我已经对其进行了测试,它适用于正在运行的服务。但是,它会跳过所有其他进程。例如,由于我的应用程序不在服务中,我看不到自己的应用程序网络使用情况。我还尝试在 adb shell 中运行 ps 命令,它返回一个 PID,但不是我需要的 uid,所以它看起来也不起作用。
  • 查看我的更新。在运行最新 Android 6.0 版本的 Nexus 7 上测试。
  • 嗨 Jared,抱歉,我花了一点时间才回复。这看起来是一个非常好的答案。我还有一个问题要问你。您从哪里获得 Shell.SH.run("ps"); 的 Shell 库?命令?我无法在本地找到那个图书馆。我已经看到了 Runtime.getRuntime().exec("ps"); 的替代方案。但我想看看我能不能让你的工作方式。谢谢!
  • @Dave 我在 cmets 中添加了它。该库在这里:github.com/Chainfire/libsuperuser 您可以将其添加为 gradle 中的依赖项。 compile 'eu.chainfire:libsuperuser:1.0.0.+'
  • 太棒了,谢谢贾里德!这对我来说看起来很完美。干杯!
猜你喜欢
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 2012-10-02
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
相关资源
最近更新 更多