在用戶使用app的時候,如果被惡意程序劫持跳轉到別的界面,這個時候我們就要做出預警提示用戶,告訴用戶當前界面已經不是我們的app有潛在的危險.代碼的工作原理很簡單就是在我們所寫的activity對象的Onstop生命週期判斷,將要跳轉的界面是否是安全的
- 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;
- }
- }
代碼的 使用方法也很簡單,只需要在你自己寫的Activity的Onstop中調用boolean safe = AntiHijackingUtil.checkActivity(this);即可得到跳轉的界面是否需要提示.