android 介面防劫持提示
阿新 • • 發佈:2019-02-17
在使用者使用app的時候,如果被惡意程式劫持跳轉到別的介面,這個時候我們就要做出預警提示使用者,告訴使用者當前介面已經不是我們的app有潛在的危險.程式碼的工作原理很簡單就是在我們所寫的activity物件的Onstop生命週期判斷,將要跳轉的介面是否是安全的。
具體程式碼如下
程式碼的 使用方法也很簡單,只需要在你自己寫的Activity的Onstop中呼叫boolean safe = AntiHijackingUtil.checkActivity(this);即可得到跳轉的介面是否需要提示.public class AntiHijackingUtil { public static final String TAG = "AntiHijackingUtil"; // 白名單列表 private static List<String> safePackages; static { safePackages = new ArrayList<String>(); } public static void configSafePackages(List<String> packages) { return; } private static PackageManager pm; private List<ApplicationInfo> mlistAppInfo; /** * 檢測當前Activity是否安全 */ public static boolean checkActivity(Context context) { boolean safe = false; pm = context.getPackageManager(); // 查詢所有已經安裝的應用程式 List<ApplicationInfo> listAppcations = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES); Collections.sort(listAppcations,new ApplicationInfo.DisplayNameComparator(pm));// 排序 List<ApplicationInfo> appInfos = new ArrayList<ApplicationInfo>(); // 儲存過濾查到的AppInfo //appInfos.clear(); for (ApplicationInfo app : listAppcations) {//這個排序必須有. if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { //appInfos.add(getAppInfo(app)); safePackages.add(app.packageName); } } //得到所有的系統程式包名放進白名單裡面. ActivityManager activityManager =(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); String runningActivityPackageName; int sdkVersion; try { sdkVersion = Integer.valueOf(android.os.Build.VERSION.SDK); } catch (NumberFormatException e) { sdkVersion = 0; } if(sdkVersion>=21){//獲取系統api版本號,如果是5x系統就用這個方法獲取當前執行的包名 runningActivityPackageName= getCurrentPkgName(context); } else runningActivityPackageName=activityManager.getRunningTasks(1).get(0).topActivity.getPackageName(); //如果是4x及以下,用這個方法. if(runningActivityPackageName!=null){//有些情況下在5x的手機中可能獲取不到當前執行的包名,所以要非空判斷。 if (runningActivityPackageName.equals(context.getPackageName())) { safe = true; } // 白名單比對 for (String safePack : safePackages) { if (safePack.equals(runningActivityPackageName)) { safe = true; } } } return safe; } public static String getCurrentPkgName(Context context) {//5x系統以後利用反射獲取當前棧頂activity的包名. ActivityManager.RunningAppProcessInfo currentInfo = null; Field field = null; int START_TASK_TO_FRONT = 2; String pkgName = null; try { field = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState");//通過反射獲取程序狀態欄位. } catch (Exception e) { e.printStackTrace(); } ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List appList = am.getRunningAppProcesses(); ActivityManager.RunningAppProcessInfo app; for (int i=0;i<appList.size();i++){ //ActivityManager.RunningAppProcessInfo app : appList app=(RunningAppProcessInfo) appList.get(i); if (app.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {//表示前臺執行程序. Integer state = null; try { state = field.getInt(app);//反射呼叫欄位值的方法,獲取該程序的狀態. } catch (Exception e) { e.printStackTrace(); } if (state != null && state == START_TASK_TO_FRONT) {//根據這個判斷條件從前臺中獲取當前切換的程序物件. currentInfo = app; break; } } } if (currentInfo != null) { pkgName = currentInfo.processName; } return pkgName; } }
這裡要說明一下 getCurrentPkgName()在有些5x手機也無法獲取當前跳入的介面的包名,有了解的還請提示一下,謝謝。