APP界面防劫持,处于后台时弹窗提示

当程序处于后台时弹窗提醒,防止其他APP界面劫持

1. 实现对APP所有Activity生命周期的监控

顶层activity中onStope方法被执行,则认为程序处于后台。由于Activity被销毁或者activity不再处于栈顶时也会调用onStop方法所以要加判断排除这两种情况。

  private static int started;
  private static int stopped;
   @Override
    public void onActivityStarted(Activity activity) {
        ++started;
    }
      @Override
    public void onActivityStopped(final Activity activity) {
        ++stopped;
         if (isApplicationInBackground()) {
        //..........弹窗前要做些判断排除activity被销毁时执行这种情况.....
        }
    }
   public static boolean isApplicationInBackground() {
        return started == stopped;
    }
2. 使用防界面劫持工具类

在Application中注册ActivityLifecycleCallbacks

public class MyApplication extends Application {

 @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(
                new NewsLifecycleHandler("安监应用切换至后台")//被劫持时的提示语
                        .setUnnoticeActivity("StartActivity")// 该activity处于栈顶 时程序处于后台,但是不提示
                        .setDestroyedActivity("LoginActivity", "MainActivity")//栈内唯一activity被销毁,时不提示。例如在登录界面退出程序此时栈内只有LoginActivity退出会执行onStop方法触发弹出框所以要加判断防止误报
        );
    }
}
3. 防劫持工具类源码
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;

/**
 * 程序中任何一个activity处于后台时(onStope)都将触发提醒
 */
public class NewsLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    // I use four separate variables here. You can, of course, just use two and
    // increment/decrement them instead of using four and incrementing them all.
    private static int resumed;
    private static int paused;
    private static int started;
    private static int stopped;
    private static int destroyed;
    private String msg;
    private List destroyActivities = new ArrayList<>();
    private List unnoticeActivities = new ArrayList<>();
    private boolean flag = true;


    /**
     * 用于执行定时任务
     */
    private Timer timer = null;

    /**
     * @param msg 程序进入后台提示用于
     */
    public NewsLifecycleHandler(String msg) {
        resetVariables();
        this.msg = msg;
    }

    /**
     * 由于销毁activity时会触发onStop方法,所以在这里设置,避免误报
     *
     * @return
     */
    public NewsLifecycleHandler setDestroyedActivity(String... activityName) {
        Collections.addAll(this.destroyActivities, activityName);
        return this;
    }

    /**
     * 该Activities处于后台时不提示
     *
     * @param activityName
     * @return
     */
    public NewsLifecycleHandler setUnnoticeActivity(String... activityName) {
        Collections.addAll(this.unnoticeActivities, activityName);
        return this;
    }

    public void resetVariables() {
        resumed = 0;
        paused = 0;
        started = 0;
        stopped = 0;
        flag = true;
    }


    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        Log.i("test", "onActivityCreated-----" + activity.getClass().getSimpleName());
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        destroyed++;
        if (destroyActivities.contains(activity.getClass().getSimpleName())) {
            Log.i("test", "进入标志位判定" + activity.getClass().getSimpleName());
            flag = false;
        }
        Log.i("test", "onActivityDestroyed-----" + activity.getClass().getSimpleName());
    }

    @Override
    public void onActivityResumed(Activity activity) {
        ++resumed;
    }

    @Override
    public void onActivityPaused(Activity activity) {
        ++paused;
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {
        ++started;
    }


    @Override
    public void onActivityStopped(final Activity activity) {
        ++stopped;
        if (isApplicationInBackground()) {
            flag = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(500);//暂停500毫秒 让以下代码后于onDestroy方法执行,用来判断是否是栈内唯一Activity被销毁才触发onStop方法。
                        Log.i("test", "stopped-----" + activity.getClass().getSimpleName());
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Log.i("test", "执行前flag " + flag + " " + activity.getClass().getSimpleName());
                                if (flag && !unnoticeActivities.contains(activity.getClass().getSimpleName())) {
                                    Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
                                }
                            }
                        });
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

    // If you want a static function you can use to check if your application is
    // foreground/background, you can use the following:


    public static boolean isApplicationVisible() {
        return started > stopped;
    }

    public static boolean isApplicationInForeground() {
        return resumed > paused;
    }

    public static boolean isApplicationInBackground() {
        return started == stopped;
    }

}

你可能感兴趣的:(android)