在用户使用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手机也无法获取当前跳入的界面的包名,有了解的还请提示一下,谢谢。