Determine by which process Application.onCreate() is called

1.4k Views Asked by At

In my application I have local service, which needs to be run in separate process. It is specified as

<service android:name=".MyService" android:process=":myservice"></service>

in AndroidManifest.xml. I also subclass Application object and want to detect in it's onCreate method when it is called by ordinary launch and when by myservice launch. The only working solution that I have found is described by

https://stackoverflow.com/a/28907058/2289482

But I don't want to get all running processes on device and iterate over them. I try to use getApplicationInfo().processName from Context, but unfortunately it always return the same String, while the solution in the link above return: myPackage, myPackage:myservice. I don't need processName at the first place, but some good solution to determine when onCreate method is called by ordinary launch and when by myservice launch. May be it can be done by applying some kind of tag or label somewhere, but i didn't find how to do it.

3

There are 3 best solutions below

3
On BEST ANSWER

You can use this code to get your process name:

    int myPid = android.os.Process.myPid(); // Get my Process ID
    InputStreamReader reader = null;
    try {
        reader = new InputStreamReader(
                new FileInputStream("/proc/" + myPid + "/cmdline"));
        StringBuilder processName = new StringBuilder();
        int c;
        while ((c = reader.read()) > 0) {
            processName.append((char) c);
        }
        // processName.toString() is my process name!
        Log.v("XXX", "My process name is: " + processName.toString());
    } catch (Exception e) {
        // ignore
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (Exception e) {
                // Ignore
            }
        }
    }
0
On

From Acra sources. The same way as above answer but presents useful methods

private static final String ACRA_PRIVATE_PROCESS_NAME= ":acra";

/**
 * @return true if the current process is the process running the SenderService.
 *          NB this assumes that your SenderService is configured to used the default ':acra' process.
 */
public static boolean isACRASenderServiceProcess() {
    final String processName = getCurrentProcessName();
    if (ACRA.DEV_LOGGING) log.d(LOG_TAG, "ACRA processName='" + processName + '\'');
    //processName sometimes (or always?) starts with the package name, so we use endsWith instead of equals
    return processName != null && processName.endsWith(ACRA_PRIVATE_PROCESS_NAME);
}

@Nullable
private static String getCurrentProcessName() {
    try {
        return IOUtils.streamToString(new FileInputStream("/proc/self/cmdline")).trim();
    } catch (IOException e) {
        return null;
    }
}

private static final Predicate<String> DEFAULT_FILTER = new Predicate<String>() {
    @Override
    public boolean apply(String s) {
        return true;
    }
};
private static final int NO_LIMIT = -1;

public static final int DEFAULT_BUFFER_SIZE_IN_BYTES = 8192;

/**
 * Reads an InputStream into a string
 *
 * @param input  InputStream to read.
 * @return the String that was read.
 * @throws IOException if the InputStream could not be read.
 */
@NonNull
public static String streamToString(@NonNull InputStream input) throws IOException {
    return streamToString(input, DEFAULT_FILTER, NO_LIMIT);
}

/**
 * Reads an InputStream into a string
 *
 * @param input  InputStream to read.
 * @param filter Predicate that should return false for lines which should be excluded.
 * @param limit the maximum number of lines to read (the last x lines are kept)
 * @return the String that was read.
 * @throws IOException if the InputStream could not be read.
 */
@NonNull
public static String streamToString(@NonNull InputStream input, Predicate<String> filter, int limit) throws IOException {
    final BufferedReader reader = new BufferedReader(new InputStreamReader(input), ACRAConstants.DEFAULT_BUFFER_SIZE_IN_BYTES);
    try {
        String line;
        final List<String> buffer = limit == NO_LIMIT ? new LinkedList<String>() : new BoundedLinkedList<String>(limit);
        while ((line = reader.readLine()) != null) {
            if (filter.apply(line)) {
                buffer.add(line);
            }
        }
        return TextUtils.join("\n", buffer);
    } finally {
        safeClose(reader);
    }
}

/**
 * Closes a Closeable.
 *
 * @param closeable Closeable to close. If closeable is null then method just returns.
 */
public static void safeClose(@Nullable Closeable closeable) {
    if (closeable == null) return;

    try {
        closeable.close();
    } catch (IOException ignored) {
        // We made out best effort to release this resource. Nothing more we can do.
    }
}
0
On

You can use the next method

@Nullable
public static String getProcessName(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningAppProcessInfo processInfo : activityManager.getRunningAppProcesses()) {
        if (processInfo.pid == android.os.Process.myPid()) {
            return processInfo.processName;
        }
    }
    return null;
}