我为我的特定活动设置了一个Android:process =":XX",使其在一个单独的进程中运行.但是当新的活动/进程init时,它将调用我的Application:onCreate(),它包含一些应用程序级初始化.
我正在考虑通过检查当前进程名称来避免重复初始化.
那么有可用的API吗?
谢谢.
Ric*_* Li 27
完整的代码是
String currentProcName = "";
int pid = android.os.Process.myPid();
ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses())
{
if (processInfo.pid == pid)
{
currentProcName = processInfo.processName;
return;
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*röm 25
ActivityManager解决方案包含一个偷偷摸摸的bug,特别是如果您从Application对象中检查自己的进程名称.有时,从getRunningAppProcesses返回的列表根本不包含您自己的进程,从而引发了一个特殊的存在问题.
我解决这个问题的方法是
BufferedReader cmdlineReader = null;
try {
cmdlineReader = new BufferedReader(new InputStreamReader(
new FileInputStream(
"/proc/" + android.os.Process.myPid() + "/cmdline"),
"iso-8859-1"));
int c;
StringBuilder processName = new StringBuilder();
while ((c = cmdlineReader.read()) > 0) {
processName.append((char) c);
}
return processName.toString();
} finally {
if (cmdlineReader != null) {
cmdlineReader.close();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,此解决方案比通过ActivityManager快得多,但如果用户正在运行Xposed或类似操作,则无效.在这种情况下,您可能希望将ActivityManager解决方案作为回退策略.
在API 28+,你可以调用Application.getProcessName(),这仅仅是一个公共的包装周围ActivityThread.currentProcessName()。
在较旧的平台上,只需ActivityThread.currentProcessName()直接致电即可。
请注意,在API 18之前,该方法被错误地调用,ActivityThread.currentPackageName()但实际上仍然返回了进程名。
public static String getNameFromActivityThread() {
if (Build.VERSION.SDK_INT >= 28)
return Application.getProcessName();
else {
// Using the same technique as Application.getProcessName() for older devices
// Using reflection since ActivityThread is an internal API
try {
@SuppressLint("PrivateApi")
Class<?> activityThread = Class.forName("android.app.ActivityThread");
// Before API 18, the method was incorrectly named "currentPackageName", but it still returned the process name
// See https://github.com/aosp-mirror/platform_frameworks_base/commit/b57a50bd16ce25db441da5c1b63d48721bb90687
String methodName = Build.VERSION.SDK_INT >= 18 ? "currentProcessName" : "currentPackageName";
Method getProcessName = activityThread.getDeclaredMethod(methodName);
return (String) getProcessName.invoke(null);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
经过测试并致力于
这是DavidBurström回答的更新.这可以更简洁地写成:
public String get() {
final File cmdline = new File("/proc/" + android.os.Process.myPid() + "/cmdline");
try (BufferedReader reader = new BufferedReader(new FileReader(cmdline))) {
return reader.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Run Code Online (Sandbox Code Playgroud)
总结使用 Kotlin 获取进程名称的不同方法:
基于/sf/answers/1497258171/ ( /proc/pid/cmdline ):
fun getProcessName(): String? =
try {
FileInputStream("/proc/${Process.myPid()}/cmdline")
.buffered()
.readBytes()
.filter { it > 0 }
.toByteArray()
.inputStream()
.reader(Charsets.ISO_8859_1)
.use { it.readText() }
} catch (e: Throwable) {
null
}
Run Code Online (Sandbox Code Playgroud)
基于/sf/answers/3888468951/(来自 SDK v.28 (Android P)):
fun getProcessName(): String? =
if (VERSION.SDK_INT >= VERSION_CODES.P) Application.getProcessName() else null
Run Code Online (Sandbox Code Playgroud)
基于/sf/answers/3217224111/(反射):
fun getProcessName(): String? =
try {
val loadedApkField = application.javaClass.getField("mLoadedApk")
loadedApkField.isAccessible = true
val loadedApk = loadedApkField.get(application)
val activityThreadField = loadedApk.javaClass.getDeclaredField("mActivityThread")
activityThreadField.isAccessible = true
val activityThread = activityThreadField.get(loadedApk)
val getProcessName = activityThread.javaClass.getDeclaredMethod("getProcessName")
getProcessName.invoke(activityThread) as String
} catch (e: Throwable) {
null
}
Run Code Online (Sandbox Code Playgroud)
基于/sf/answers/1374266771/(ActivityManager ):
fun getProcessName(): String? {
val pid = Process.myPid()
val manager = appContext.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager
return manager?.runningAppProcesses?.filterNotNull()?.firstOrNull { it.pid == pid }?.processName
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26365 次 |
| 最近记录: |