Android 确定调用哪个process Application.onCreate()的方法

Android 确定调用哪个process Application.onCreate()的方法,android,android-service,Android,Android Service,在我的应用程序中,我有本地服务,它需要在单独的进程中运行。它被指定为 <service android:name=".MyService" android:process=":myservice"></service> 在AndroidManifest.xml中。我还对应用程序对象进行了子类化,并希望在普通启动和myservice启动调用它时在其onCreate方法中进行检测。我发现的唯一可行的解决方案是 但我不想在设备上获取所有正在运行的进程并对它们进行迭代。我

在我的应用程序中,我有本地服务,它需要在单独的进程中运行。它被指定为

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

在AndroidManifest.xml中。我还对应用程序对象进行了子类化,并希望在普通启动和myservice启动调用它时在其onCreate方法中进行检测。我发现的唯一可行的解决方案是


但我不想在设备上获取所有正在运行的进程并对它们进行迭代。我尝试从上下文中使用getApplicationInfo().processName,但不幸的是它总是返回相同的字符串,而上面链接中的解决方案返回:myPackage,myPackage:myservice。我一开始不需要processName,但需要一些好的解决方案来确定普通启动何时调用onCreate方法以及myservice启动何时调用onCreate方法。可能可以通过在某个地方应用某种标记或标签来完成,但我没有找到如何执行该操作。

您可以使用以下代码获取流程名称:

    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
            }
        }
    }
来源。与上述答案相同,但提供了有用的方法

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.
    }
}
private静态最终字符串ACRA\u private\u PROCESS\u NAME=“:ACRA”;
/**
*@如果当前进程是运行SenderService的进程,则返回true。
*注意:这假设您的SenderService配置为使用默认的“:acra”进程。
*/
公共静态布尔值isacranderserviceprocess(){
最后一个字符串processName=getCurrentProcessName();
if(ACRA.DEV_LOGGING)log.d(log_标记,“ACRA processName=”+“processName+”\”);
//processName有时(或总是?)以包名开头,所以我们使用endsWith而不是equals
返回processName!=null&&processName.endsWith(ACRA\u PRIVATE\u PROCESS\u NAME);
}
@可空
私有静态字符串getCurrentProcessName(){
试一试{
返回IOUtils.streamToString(新文件输入流(“/proc/self/cmdline”).trim();
}捕获(IOE异常){
返回null;
}
}
私有静态最终谓词DEFAULT_FILTER=新谓词(){
@凌驾
公共布尔应用(字符串s){
返回true;
}
};
私有静态最终整数无限制=-1;
公共静态final int DEFAULT_BUFFER_SIZE_,单位为字节=8192;
/**
*将InputStream读入字符串
*
*@param输入要读取的InputStream。
*@返回已读取的字符串。
*@如果无法读取InputStream,则引发IOException。
*/
@非空
公共静态字符串streamToString(@NonNull InputStream input)引发IOException{
返回streamToString(输入,默认过滤器,无限制);
}
/**
*将InputStream读入字符串
*
*@param输入要读取的InputStream。
*@param filter谓词,对于应排除的行,该谓词应返回false。
*@param限制要读取的最大行数(保留最后x行)
*@返回已读取的字符串。
*@如果无法读取InputStream,则引发IOException。
*/
@非空
公共静态字符串streamToString(@NonNull InputStream input,谓词筛选器,int limit)引发IOException{
final BufferedReader=新BufferedReader(新的InputStreamReader(输入),ACRAConstants.DEFAULT\u BUFFER\u SIZE\u,以字节为单位);
试一试{
弦线;
最终列表缓冲区=限制==无限制?新建LinkedList():新建BoundedLinkedList(限制);
而((line=reader.readLine())!=null){
如果(过滤器应用(行)){
buffer.add(行);
}
}
返回TextUtils.join(“\n”,缓冲区);
}最后{
安全关闭(读卡器);
}
}
/**
*关闭一个可关闭的窗口。
*
*@param closeable closeable关闭。若closeable为null,那个么方法只返回。
*/
公共静态void safeClose(@Nullable Closeable Closeable){
if(closeable==null)返回;
试一试{
closeable.close();
}捕获(忽略IOException){
//我们尽了最大努力来释放这个资源。我们无能为力。
}
}

您可以使用下一种方法

@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;
}

链接机制是每个人都在使用的。这只在应用程序启动时发生一次。为什么不能使用这种机制呢?链接的解决方案意味着我们迭代设备上所有正在运行的进程,只是为了获得有关当前进程的信息。普通应用程序不会请求所有正在运行的进程-自定义ProcessManager或某些实用程序需要此功能。谢谢,此解决方案适合我。它在某种程度上是低级的,但肯定比迭代系统的所有运行进程要好。表示如果用户运行的是Xposed,则此技术不起作用。你在野外使用这项技术时遇到过任何问题吗?@Sam我们使用这项技术没有任何问题,因为我们确切地知道我们的用户在使用什么设备,他们中没有人使用标准安卓以外的任何设备。