項目中的路由框架中,須要獲取到當前的進程名,一開始經過經常使用的ActivityManager.getRunningAppProcesses()
寫法,上線後發現有必定隨機機率的異常發生,致使業務邏輯出現問題。經查,不一樣的Android版本和機型上,此方法調用確實有可能機率性拋出異常。android
爲兼容各個不一樣的版本和機型,獲取進程名能夠從多個不一樣維度分別進行,最後封裝成工具庫供上層調用。且考慮到進程名的變量屬性,經過定義靜態變量將其進一步做緩存化處理,減小沒必要要的調取過程。緩存
最終封裝後的工具類以下:markdown
public class ProcessUtil {
private static final String TAG = "ProcessUtil";
private static String sProcessName = "";
private ProcessUtil() {
}
public static String getCurrentProcessName(Context context) {
if(!TextUtils.isEmpty(sProcessName)) {
return sProcessName;
}
try {
sProcessName = getCurrentProcessNameByActivityManager(context);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
if(!TextUtils.isEmpty(sProcessName)) {
return sProcessName;
}
try {
sProcessName = getCurrentProcessNameByApplication();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
if(!TextUtils.isEmpty(sProcessName)) {
return sProcessName;
}
try {
sProcessName = getProcessNameByCmd();
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
if(!TextUtils.isEmpty(sProcessName)) {
return sProcessName;
}
try {
sProcessName = getCurrentProcessNameByActivityThread();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return sProcessName;
}
public static String getCurrentProcessNameByActivityManager(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
public static String getCurrentProcessNameByApplication() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return Application.getProcessName();
}
return null;
}
public static String getProcessNameByCmd() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("/proc/" + android.os.Process.myPid() + "/cmdline"));
String processName = reader.readLine();
if (!TextUtils.isEmpty(processName)) {
processName = processName.trim();
}
return processName;
} catch (Exception e) {
Log.e(TAG, "getProcessName read is fail. exception=" + e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
Log.e(TAG, "getProcessName close is fail. exception=" + e);
}
}
return null;
}
public static String getCurrentProcessNameByActivityThread() {
String processName = null;
try {
final Method declaredMethod = Class.forName("android.app.ActivityThread", false, Application.class.getClassLoader())
.getDeclaredMethod("currentProcessName", (Class<?>[]) new Class[0]);
declaredMethod.setAccessible(true);
final Object invoke = declaredMethod.invoke(null, new Object[0]);
if (invoke instanceof String) {
processName = (String) invoke;
}
} catch (Throwable e) {
Log.e(TAG, e.toString());
}
return processName;
}
}
複製代碼