Skip to content Skip to sidebar Skip to footer

Find Out The Running Process ID By Package Name

I am working on a script in which I need to supply the PID of my application. I am able to list all the processes with their PIDs by following command and could see the entry of my

Solution 1:

Since Android 7.0 the easiest way to find out the process ID by package name is to use pidof command:

usage: pidof [-s] [-o omitpid[,omitpid...]] [NAME]...

Print the PIDs of all processes with the given names.

-s      single shot, only return one pid.
-o      omit PID(s)

Just run it like this:

adb shell pidof my.app.package

In Android before 7.0 people used ps command and then parsed its output using either built-in filter by comm value (which for android apps is the last 15 characters of the package name) or grep command. The comm filter did not work if the last 15 characters of the name started with a digit and the grep was not included by default until Android 4.2. But even after the proper process line was found the PID value still needed to be extracted.

There were multiple ways to do that. Here is how finding the process and extracting PID could be done with a single sed command:

adb shell "ps | sed -n 's/^[^ ]* *\([0-9]*\).* my\.app\.package$/\1/p'"

Again the problem is that sed was was not included by default until Android 6.0.

But if you must use an older device you can always use the following Android version independent solution. It does not use any external commands - just Android shell built-ins:

adb shell "for p in /proc/[0-9]*; do [[ $(<$p/cmdline) = my.app.package ]] && echo ${p##*/}; done"

The most popular reason for looking for a PID is to use it in some other command like kill. Let's say we have multiple instances of logcat running and we want to finish them all gracefully at once. Just replace the echo with kill -2 in the last command:

adb shell "for p in /proc/[0-9]*; do [[ $(<$p/cmdline) = logcat ]] && kill -2 ${p##*/}; done"

Replace " with ' if running the commands from Linux/OSX shell.


Solution 2:

Instead of using adb shell ps, firstly enter adb shell and then use ps.

Step by step:

  1. Enter adb shell command while a device (or emulator) is connected.
    (Command line prefix will be shell@android:/ $ after executing this command.)

  2. Enter ps | grep <package_name_to_be_filtered> (i.e. ps | grep com.google).


C:> adb shell
shell@android:/ $ ps | grep com.google
u0_a64  3353  2467  903744 52904 ffffffff 00000000 S com.google.process.location
u0_a64  3426  2467  893964 49452 ffffffff 00000000 S com.google.process.gapps

Solution 3:

The processes shown by ps can be limited to those belonging to any given user by piping the output through grep, a filter that is used for searching text. For example, processes belonging to a user with a username adam can be displayed with the following:

ps -ef | grep adam

The -e option generates a list of information about every process currently running. The -f option generates a listing that contains fewer items of information for each process than the -l option.


Solution 4:

Alex P.'s answer is technically answering the question "Find out the running process ID by process name", and not "Find out the running process ID by package name". The difference is subtle, and manifests in process renames via the "android:process" attribute in the <activity> tag.

I fear the correct solution is a bit more involved, and you can read into the workaround Android Studio did to find the true process name here. You'll see the relevant shell script for pre-Android Oreo under resolveLegacyPid, and resolveApplicationId for Android Oreo+:

  /**
   * Asynchronously resolves to the application ID. The application ID is the package name that is
   * ultimately given to the application on the device, which usually comes from the manifest.
   * Note that this may be different from {@link ClientData#getClientDescription()} or
   * {@link ClientData#getPackageName()} due to the manifest containing a process rename XML
   * option via "android:process".
   *
   * <p>When the manifest option is specified, the two aforementioned {@link ClientData }methods
   * will return the process name, not the application ID. Therefore, this method guarantees the
   * application ID if it's possible to resolve. Only if it's not possible will this fall back to
   * using the process name instead.
   */
  private void resolveApplicationId(@NotNull Process process) {
    myResolverExecutor.execute(() -> {
      String command = String.format(Locale.US, "stat -c %%u /proc/%d | xargs -n 1 cmd package list packages --uid", process.getPid());
      CollectingOutputReceiver receiver = new CollectingOutputReceiver();
      try {
        myIDevice.executeShellCommand(command, receiver);
      }
      catch (IOException | TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException e) {
        Logger.getInstance(Device.class).warn("Could not resolve application ID", e);
        return;
      }
      String output = receiver.getOutput();
      if (output.isEmpty()) {
        return;
      }
      Matcher m = PACKAGE_NAME_PATTERN.matcher(output);
      while (m.find()) {
        process.addApplicationId(m.group(1));
      }
    });
  }
  @NotNull
  private Future<Void> resolveLegacyPid(@NotNull String applicationId) {
    return myResolverExecutor.submit(
      () -> {
        // This shell command tries to retrieve the PID associated with a given application ID.
        // To achieve this goal, it does the following:
        //
        // 1) Gets the user name (e.g. u0_a01) using run-as with the application ID and
        //    the whoami command.
        // 2) Runs the ps command under the application ID to get a list of all running
        //    processes running under the user associated with the given application ID.
        //    The output of ps looks something like: "<user> <pid> ..."
        // 3) The output of ps is piped into grep/tr/cut to parse out the second parameter,
        //    of each line, which is the PID of each process.
        // 4) The PID is then used in the readlink command to follow the symbolic links of
        //    the symlinked exe file under the PID's /proc directory.
        // 5) If the symlink resolves to any of the 32 or 64 bit zygote process, the PID is
        //    printed to the console, serving as the output of the script.
        String command =
          String.format(
            "uid=`run-as %s whoami` && " +
            "for pid in `run-as %s ps | grep -o \"$uid[[:space:]]\\{1,\\}[[:digit:]]\\{1,\\}\" | tr -s ' ' ' ' | cut -d ' ' -f2`; do " +
            "  if [[ `run-as %s readlink /proc/$pid/exe` == /system/bin/app_process* ]]; then " +
            "    echo $pid; " +
            "  fi; " +
            "done",
            applicationId, applicationId, applicationId);
        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
        myIDevice.executeShellCommand(command, receiver);
        String output = receiver.getOutput();
        if (output.isEmpty()) {
          return null;
        }
        String[] lines = output.split("\n");
        // We only handle the first return value for now.
        try {
          for (String line : lines) {
            int pid = Integer.parseInt(line.trim());
            myPidToProcess.computeIfPresent(pid, (ignored, process) -> {
              process.addApplicationId(applicationId);
              return process;
            });
          }
        }
        catch (NumberFormatException ignored) {
        }
        return null;
      });
  }

Post a Comment for "Find Out The Running Process ID By Package Name"