Android 防界面劫持方案,无视Android系统版本限制,无需操作栈

Android 防界面劫持方案

Demo下载地址

http://download.csdn.net/detail/prince_wenzheng/9742068

分析

要想真正做到防劫持,就需要在我们的程序运行时,不允许启动其他应用程序。但是Android为了提高用户的用户体验,对于不同的应用程序之间的切换,基本上是无缝,如果在启动一个Activity时,给它加入一个标志位FLAG_ACTIVITY_NEW_TASK,就能使它置于栈顶并立马呈现给用户。在这种机制下,无法做到真正的防劫持

那么只能使用一种折中的方案,用户使用app的时候,如果被恶意程序劫持跳转到别的界面,这个时候我们就要做出预警提示用户,告诉用户当前界面已经不是我们的app了,有潜在的危险。

这种方案主要有一个问题需要攻克,就是监控是否有程序覆盖了我们的APP,也就是我们需要监控栈顶的变化,在Android5.0之前,可以使用ActivityManager中提供的方法操作栈,但是在Android5.0时,谷歌由于用户隐私的考虑,弱化了这个接口,ActivityManager只能管理自己APP的栈,如果想管理其他APP的栈,需要用户主动授权,而好多手机厂商又对这个权限做了进一步限制,只能为特定的APP授权(如系统捆绑应用)。这样Android5.0之后就无法通过管理栈的方式来进行防劫持。

既然只能对自己的应用进行操作,我们可以从Activity的生命周期做些文章,具体方案往下看

方案

1. 在所有Activity的onPause()方法中,弹出提示用户的警告,延迟1-2秒执行

2. 在所有Activity的onResume()方法中,取消在onPause中的提示

效果

● 当自己的应用切换页面时,触发当前页面的onPause()方法,并立刻触发要跳转页面的onResume()方法,这样就不会发出警告提示用户。

● 当用户主动切换应用程序或者主动退回到桌面时,触发当前界面的onPause()方法,1-2秒后出现警告

● 当应用界面遭到恶意程序劫持时,触发当前界面的onPause()方法,1-2秒后出现警告

注意

1. 不能使用onStop()方法来代替onPause(),因为大部分劫持界面都采用透明主题,而跳转到透明Activity时,是不触发onStop()方法的,可以使用onStart()方法来代替onResume()

2. 当程序中需要加载第三方的Activity时,防劫持机制会判断第三方的Activity是非法的,并弹出警告,项目上在使用时可自行调用onResume(),来取消警告

代码

BaseActivity.java

package com.example.test;

import android.app.Activity;

public class BaseActivity extends Activity {

    @Override
    protected void onResume() {
        Anti_hijackingUtils.getinstance().onResume();
        super.onResume();
    }

    @Override
    protected void onPause() {
        Anti_hijackingUtils.getinstance().onPause(this);
        super.onPause();
    }

}

Anti_hijackingUtils.java

package com.example.test;

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

import android.app.Activity;
import android.widget.Toast;

public class Anti_hijackingUtils {

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

    /**
     * 用于保存当前任务
     */
    private List tasks = null;

    /**
     * 唯一实例
     */
    private static Anti_hijackingUtils anti_hijackingUtils;

    private Anti_hijackingUtils() {
        // 初始化
        tasks = new ArrayList();
        timer = new Timer();
    }

    /**
     * 获取唯一实例
     * 
     * @return 唯一实例
     */
    public static Anti_hijackingUtils getinstance() {
        if (anti_hijackingUtils == null) {
            anti_hijackingUtils = new Anti_hijackingUtils();
        }
        return anti_hijackingUtils;
    }

    /**
     * 在activity的onPause()方法中调用
     * 
     * @param activity
     */
    public void onPause(final Activity activity) {
        MyTimerTask task = new MyTimerTask(activity);
        tasks.add(task);
        timer.schedule(task, 2000);
    }

    /**
     * 在activity的onResume()方法中调用
     */
    public void onResume() {
        if (tasks.size() > 0) {
            tasks.get(tasks.size() - 1).setCanRun(false);
            tasks.remove(tasks.size() - 1);
        }
    }

    /**
     * 自定义TimerTask类
     */
    class MyTimerTask extends TimerTask {
        /**
         * 任务是否有效
         */
        private boolean canRun = true;
        private Activity activity;

        public void setCanRun(boolean canRun) {
            this.canRun = canRun;
        }

        public MyTimerTask(Activity activity) {
            this.activity = activity;
        }

        @Override
        public void run() {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (canRun) {
                        // 程序退到后台,进行风险警告
                        Toast.makeText(activity, "应用Test切换至后台运行",
                                Toast.LENGTH_LONG).show();
                        tasks.remove(MyTimerTask.this);
                    }
                }
            });
        }
    }
}

你可能感兴趣的:(Android)