Activity生命周期监听接口:ActivityLifecycleCallbacks

1. 需求场景

项目遇到新需求:给App设置指纹解锁或者手势密码解锁,例如,App切换至后台或者进程关闭,时间如果超过20sec,App再次切换至前台或者重新打开,要让用户验证指纹或者手势密码,验证通过的话才能进入home页,当然,具体的时间长短,后端可配。

2. 方案分析

记录App切换至后台或进程被杀死的时间点是解决问题的关键点一,假设这个时间点是T1;记录App再次切换至前台或者重新打开的时间点是解决问题的关键点二,假设这个时间点是T2。只要能准确的记录T1和T2,上述需求就迎刃而解(假设后端配置的时间间隔为timeSpan)。
if (T1-T2>timeSpan){
    // 超时,验证指纹或者手势密码
}

3. 监听T1和T2的基本思路

(1).写一个基类BaseActivity,所有新创建的Activity全都继承基类;

(2).在基类中定义一个int变量activeNum,记录当前存活的Activity个数;

(3).回调基类的onResume()方法,activeNum就加1,回调基类的onStop()方法, activeNum就减1;

(4).当activeNum的值减到0,说明App进入后台或者被Kill,记录时间点T1并保存.因为App不同页面间切换都会走onResume(),所以在记录时间点T1的同时,保存一个标记checkTimeFlag, 置为true,这个标记用来判断下次调用onResume()时是否为T2时间点

(5).在基类的onResume()方法里获取并判断标记checkTimeFlag,true的话,获取App切换到前台或者重新打开的时间点T2,检查是否超时,超时的话,将标记checkTimeFlag置为false并验证用户指纹或者手势密码;

(6).配置的时间间隔timeSpan可以在启动页从后端获取,每次走启动页的时候刷新一次,当然个别场景会有些延迟,例如,用户从页面A进入后台,timeSpan修改了,但是用户切回前台,判断时使用的timeSpan还是上次的,不是修改后的,这种场景不走启动页刷新timeSpan,如果非要实时的话,其实可以把接口请求写在onResume()里,获取T2之后,请求接口获取timeSpan。

通过控制BaseActivity的onResume()和onStop()方法实现需求是可以的,但是,这个方法要求所有Activity都必须继承基类,而且在BaseActivity中实现这样的逻辑显然不太好,代码会显得臃肿。其实,Android为我们提供了一个非常好的接口:ActivityLifecycleCallbacks来监听Activity的生命周期方法,把上述思路放到接口的回调方法里是再好不过的。

4.ActivityLifecycleCallbacks使用方法

Activity生命周期监听接口:ActivityLifecycleCallbacks_第1张图片

1)定义类  AppLifecycleCallbacks implements ActivityLifecycleCallbacks

public class AppLifecycleCallbacks implements ActivityLifecycleCallbacks {
    private int activeNum;
    private int timeSpan = 15;
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }
    public void onActivityStarted(Activity activity) {
    }
    public void onActivityResumed(Activity activity) {
        if ((boolean) SPUtils.get(activity, "checkTimeoutFlag", false)) {
            SPUtils.put(activity, "checkTimeoutFlag", false);
            checkTimeout(activity);
        }
        activeNum += 1;
    }
    public void checkTimeout(Context context) {
        long enterTime = System.currentTimeMillis();
        long stopTime = (long) SPUtils.get(context, "stopTime", 0l);
        // Todo
        // 需要实时的话,请求接口获取timeSpan放在这里做
        LogUtil.Log("jacob", "enterTime:" + enterTime + "----stopTime:" + stopTime +
                "----" + (enterTime - stopTime));
        if (enterTime - stopTime > timeSpan * 1000) {
            ComponentsManager.toVerifyFingerprint(context);
        }
    }
    @Override
    public void onActivityPaused(Activity activity) {
    }
    public void onActivityStopped(Activity activity) {
        activeNum -= 1;
        if (activeNum == 0) {
            long stopTime = System.currentTimeMillis();
            LogUtil.Log("jacob", "stopTime" + stopTime);
            SPUtils.put(activity, "stopTime", stopTime);
            SPUtils.put(activity, "checkTimeoutFlag", true);
        }
    }
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }
    public void onActivityDestroyed(Activity activity) {
    }
}

(2)自定义类  CustomApplication extends Application 

在onCreate()中注册监听实现类

registerActivityLifecycleCallbacks(new AppLifecycleCallbacks());

(3)修改AndroidManifest.xml中Application

   <application android:name=".CustomApplication"  

5. 感言

第一次写Blog,没什么经验。脑子里一堆想法,真要写下来,蛮难的,先从简单的写起,再接再厉,希望一次比一次好。





你可能感兴趣的:(Android)