确定由哪个进程调用 Application.onCreate()
Determine by which process Application.onCreate() is called
在我的应用程序中,我有本地服务,需要在单独的进程中 运行。它被指定为
<service android:name=".MyService" android:process=":myservice"></service>
在 AndroidManifest.xml 中。我还将 Application 对象子类化,并希望在它的 onCreate 方法中检测它何时被普通启动调用以及何时被 myservice 启动调用。
描述了我找到的唯一可行的解决方案
但我不想获取设备上的所有 运行ning 进程并迭代它们。我尝试使用 Context 中的 getApplicationInfo().processName,但不幸的是它总是 return 相同的字符串,而 link 上面的解决方案 return: myPackage, myPackage:myservice。我一开始不需要 processName,但是一些好的解决方案可以确定普通启动何时调用 onCreate 方法以及 myservice 启动何时调用。也许可以通过在某处应用某种标签或标签来完成,但我没有找到如何做。
您可以使用此代码获取进程名称:
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
}
}
}
来自 Acra 个来源。与上述答案相同,但提供了有用的方法
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.
}
}
可以使用下一个方法
@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;
}
在我的应用程序中,我有本地服务,需要在单独的进程中 运行。它被指定为
<service android:name=".MyService" android:process=":myservice"></service>
在 AndroidManifest.xml 中。我还将 Application 对象子类化,并希望在它的 onCreate 方法中检测它何时被普通启动调用以及何时被 myservice 启动调用。
描述了我找到的唯一可行的解决方案但我不想获取设备上的所有 运行ning 进程并迭代它们。我尝试使用 Context 中的 getApplicationInfo().processName,但不幸的是它总是 return 相同的字符串,而 link 上面的解决方案 return: myPackage, myPackage:myservice。我一开始不需要 processName,但是一些好的解决方案可以确定普通启动何时调用 onCreate 方法以及 myservice 启动何时调用。也许可以通过在某处应用某种标签或标签来完成,但我没有找到如何做。
您可以使用此代码获取进程名称:
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
}
}
}
来自 Acra 个来源。与上述答案相同,但提供了有用的方法
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.
}
}
可以使用下一个方法
@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;
}