在用户使用app的时候,如果被恶意程序劫持跳转到别的界面,这个时候我们就要做出预警提示用户,告诉用户当前界面已经不是我们的app有潜在的危险.代码的工作原理很简单就是在我们所写的activity对象的Onstop生命周期判断,将要跳转的界面是否是安全的。

       具体代码如下



[java]  view plain  copy

 



    1. public class AntiHijackingUtil {  
    2.       
    3. public static final String TAG = "AntiHijackingUtil";  
    4.       
    5. // 白名单列表  
    6. private static List<String> safePackages;  
    7.       
    8. static {  
    9. new ArrayList<String>();  
    10.     }  
    11.       
    12. public static void configSafePackages(List<String> packages) {  
    13. return;  
    14.     }  
    15. private static PackageManager pm;  
    16. private List<ApplicationInfo> mlistAppInfo;    
    17. /**
    18.      * 检测当前Activity是否安全
    19.      */  
    20. public static boolean checkActivity(Context context) {  
    21. boolean safe = false;  
    22.          pm = context.getPackageManager();    
    23. // 查询所有已经安装的应用程序    
    24.             List<ApplicationInfo> listAppcations = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);    
    25. new ApplicationInfo.DisplayNameComparator(pm));// 排序    
    26. new ArrayList<ApplicationInfo>(); // 保存过滤查到的AppInfo    
    27. //appInfos.clear();    
    28. for (ApplicationInfo app : listAppcations) {//这个排序必须有.    
    29. if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {    
    30. //appInfos.add(getAppInfo(app));    
    31.                 safePackages.add(app.packageName);  
    32.              }    
    33.          }   
    34. //得到所有的系统程序包名放进白名单里面.  
    35.           
    36.         ActivityManager activityManager =(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
    37.         String runningActivityPackageName;  
    38. int sdkVersion;   
    39.           
    40. try {    
    41.             sdkVersion = Integer.valueOf(android.os.Build.VERSION.SDK);    
    42. catch (NumberFormatException e) {    
    43. 0;    
    44.         }   
    45.           
    46. if(sdkVersion>=21){//获取系统api版本号,如果是5x系统就用这个方法获取当前运行的包名  
    47.             runningActivityPackageName= getCurrentPkgName(context);  
    48.         }  
    49. else runningActivityPackageName=activityManager.getRunningTasks(1).get(0).topActivity.getPackageName();  
    50. //如果是4x及以下,用这个方法.  
    51.                
    52.            
    53. if(runningActivityPackageName!=null){//有些情况下在5x的手机中可能获取不到当前运行的包名,所以要非空判断。  
    54. if (runningActivityPackageName.equals(context.getPackageName())) {     
    55. true;  
    56.            }  
    57.           
    58. // 白名单比对  
    59. for (String safePack : safePackages) {  
    60. if (safePack.equals(runningActivityPackageName)) {  
    61. true;  
    62.                }  
    63.            }  
    64.         }  
    65.           
    66. return safe;          
    67.     }  
    68.       
    69.       
    70.       
    71. public static String getCurrentPkgName(Context context) {//5x系统以后利用反射获取当前栈顶activity的包名.  
    72. null;  
    73. null;  
    74. int START_TASK_TO_FRONT = 2;  
    75. null;  
    76.           
    77. try {  
    78. class.getDeclaredField("processState");//通过反射获取进程状态字段.  
    79. catch (Exception e) {  
    80.             e.printStackTrace();  
    81.         }  
    82.         ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
    83.         List appList = am.getRunningAppProcesses();  
    84.         ActivityManager.RunningAppProcessInfo app;  
    85.           
    86. for (int i=0;i<appList.size();i++){  
    87. //ActivityManager.RunningAppProcessInfo app : appList  
    88.             app=(RunningAppProcessInfo) appList.get(i);  
    89. if (app.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {//表示前台运行进程.  
    90. null;  
    91. try {  
    92. //反射调用字段值的方法,获取该进程的状态.  
    93. catch (Exception e) {  
    94.                     e.printStackTrace();  
    95.                 }  
    96. if (state != null && state == START_TASK_TO_FRONT) {//根据这个判断条件从前台中获取当前切换的进程对象.  
    97.                     currentInfo = app;  
    98. break;  
    99.                 }  
    100.             }  
    101.         }  
    102.           
    103. if (currentInfo != null) {  
    104.             pkgName = currentInfo.processName;  
    105.         }  
    106. return pkgName;  
    107.     }  
    108. }



              代码的 使用方法也很简单,只需要在你自己写的Activity的Onstop中调用boolean safe = AntiHijackingUtil.checkActivity(this);即可得到跳转的界面是否需要提示.

     

              这里要说明一下 getCurrentPkgName()在有些5x手机也无法获取当前跳入的界面的包名,有了解的还请提示一下,谢谢。