Просмотр исходного кода

Activity反劫持等 allowBackup设为false

fancy 5 лет назад
Родитель
Сommit
932ff2fba6

+ 1 - 1
o2android/app/src/main/AndroidManifest.xml

@@ -36,7 +36,7 @@
 
     <application
         android:name=".O2App"
-        android:allowBackup="true"
+        android:allowBackup="false"
         android:hardwareAccelerated="true"
         android:icon="@mipmap/logo"
         android:label="@string/app_name"

+ 27 - 1
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/app/o2/login/LoginActivity.kt

@@ -5,13 +5,15 @@ import android.graphics.BitmapFactory
 import android.media.AudioManager
 import android.media.MediaPlayer
 import android.os.Bundle
-import androidx.core.content.ContextCompat
+import android.os.Looper
 import android.text.InputType
 import android.text.TextUtils
 import android.view.KeyEvent
 import android.view.View
 import android.view.WindowManager
 import android.view.inputmethod.InputMethodManager
+import android.widget.Toast
+import androidx.core.content.ContextCompat
 import kotlinx.android.synthetic.main.activity_login.*
 import net.muliba.changeskin.FancySkinManager
 import net.zoneland.x.bpm.mobile.v1.zoneXBPM.*
@@ -185,6 +187,10 @@ class LoginActivity: BaseMVPActivity<LoginContract.View, LoginContract.Presenter
 
     override fun onResume() {
         super.onResume()
+        //清除用户名密码
+        login_edit_username_id.setText("")
+        login_edit_password_id.setText("")
+        edit_login_captcha_input.setText("")
 
         playBeep = true
         val audioService = getSystemService(Context.AUDIO_SERVICE) as AudioManager
@@ -194,6 +200,26 @@ class LoginActivity: BaseMVPActivity<LoginContract.View, LoginContract.Presenter
         initBeepSound()
     }
 
+    override fun onStop() {
+        super.onStop()
+
+        //Activity反劫持检测工具
+        Thread(Runnable { // 白名单
+            val safe = AntiHijackingUtil.checkActivity(applicationContext)
+            // 系统桌面
+            val isHome = AntiHijackingUtil.isHome(applicationContext)
+            // 锁屏操作
+            val isReflectScreen = AntiHijackingUtil.isReflectScreen(applicationContext)
+            // 判断程序是否当前显示
+            if (!safe && !isHome && !isReflectScreen) {
+                Looper.prepare()
+                Toast.makeText(applicationContext, R.string.activity_safe_warning,
+                        Toast.LENGTH_LONG).show()
+                Looper.loop()
+            }
+        }).start()
+    }
+
     override fun onDestroy() {
         super.onDestroy()
         countDownHelper.destroy()

+ 151 - 0
o2android/app/src/main/java/net/zoneland/x/bpm/mobile/v1/zoneXBPM/utils/AntiHijackingUtil.java

@@ -0,0 +1,151 @@
+package net.zoneland.x.bpm.mobile.v1.zoneXBPM.utils;
+
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Description: Activity反劫持检测工具
+ * author: zs
+ * Date: 2018/7/8 16:31
+ */
+public class AntiHijackingUtil {
+    public static final String TAG = "AntiHijackingUtil";
+
+    /**
+     * 检测当前Activity是否安全
+     */
+    public static boolean checkActivity(Context context) {
+        PackageManager pm = context.getPackageManager();
+        // 查询所有已经安装的应用程序
+        List<ApplicationInfo> listAppcations =
+                pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
+        Collections.sort(listAppcations, new ApplicationInfo.DisplayNameComparator(pm));// 排序
+
+        List<String> safePackages = new ArrayList<>();
+        for (ApplicationInfo app : listAppcations) {// 这个排序必须有.
+            if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                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())) {
+                return true;
+            }
+            // 白名单比对
+            for (String safePack : safePackages) {
+                if (safePack.equals(runningActivityPackageName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private 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 = (ActivityManager.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;
+    }
+
+    /**
+     * 判断当前是否在桌面
+     *
+     * @param context 上下文
+     */
+    public static boolean isHome(Context context) {
+        ActivityManager mActivityManager =
+                (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
+        return getHomes(context).contains(rti.get(0).topActivity.getPackageName());
+    }
+
+    /**
+     * 获得属于桌面的应用的应用包名称
+     *
+     * @return 返回包含所有包名的字符串列表
+     */
+    private static List<String> getHomes(Context context) {
+        List<String> names = new ArrayList<String>();
+        PackageManager packageManager = context.getPackageManager();
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_HOME);
+        List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
+                PackageManager.MATCH_DEFAULT_ONLY);
+        for (ResolveInfo ri : resolveInfo) {
+            names.add(ri.activityInfo.packageName);
+        }
+        return names;
+    }
+
+    /**
+     * 判断当前是否在锁屏再解锁状态
+     *
+     * @param context 上下文
+     */
+    public static boolean isReflectScreen(Context context) {
+        KeyguardManager mKeyguardManager =
+                (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+        return mKeyguardManager.inKeyguardRestrictedInputMode();
+    }
+}

+ 3 - 0
o2android/app/src/main/res/values/strings.xml

@@ -2,6 +2,7 @@
     <string name="app_name">O2OA</string>
     <string name="app_about">关于O2OA</string>
     <string name="app_name_about">O2OA</string>
+    <string name="activity_safe_warning">已切换至后台运行!</string>
     <string name="copy_right">&#169;</string>
     <string name="reserved">All right reserved.</string>
     <string name="version">版本:</string>
@@ -13,6 +14,8 @@
     <string name="bind_phone_choose_company">选择单位</string>
     <string name="app_error">应用异常</string>
 
+
+
     <string name="launch_start">准备中&#8230;</string>
     <string name="launch_network_is_not_connected">网络未连接,请检查网络连接情况!</string>
     <string name="launch_check_bind">正在连接O2云&#8230;</string>