Android实现app长时间未操作时自动退出app
这里要考虑3个问题,第一个是锁屏问题,第二个是app被切换至后台的问题,第三个是屏幕锁定和解除时app在后台时的问题
一,监听屏幕解锁,锁定
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | publicclassScreenObserver {    privatestaticString TAG = "ScreenObserver";    privateContext mContext;    privateScreenBroadcastReceiver mScreenReceiver;    privateScreenStateListener mScreenStateListener;    privatestaticMethod mReflectScreenState;    publicScreenObserver(Context context) {        mContext = context;        mScreenReceiver = newScreenBroadcastReceiver();        try{            mReflectScreenState = PowerManager.class.getMethod("isScreenOn",                    newClass[] {});        } catch(NoSuchMethodException nsme) {            Log.d(TAG, "API < 7,"+ nsme);        }    }    /**     * screen状态广播接收者     *      * @author xishaomin     *      */    privateclassScreenBroadcastReceiver extendsBroadcastReceiver {        privateString action = null;        @Override        publicvoidonReceive(Context context, Intent intent) {            action = intent.getAction();            if(Intent.ACTION_SCREEN_ON.equals(action)) {                mScreenStateListener.onScreenOn();            } elseif(Intent.ACTION_SCREEN_OFF.equals(action)) {                mScreenStateListener.onScreenOff();            }elseif(Intent.ACTION_USER_PRESENT.equals(action)){                LogUtils.d("---->屏幕解锁完成");            }        }    }    /**     * 请求screen状态更新     *      * @param listener     */    publicvoidrequestScreenStateUpdate(ScreenStateListener listener) {        mScreenStateListener = listener;        startScreenBroadcastReceiver();        firstGetScreenState();    }    /**     * 第一次请求screen状态     */    privatevoidfirstGetScreenState() {        PowerManager manager = (PowerManager) mContext                .getSystemService(Activity.POWER_SERVICE);        if(isScreenOn(manager)) {            if(mScreenStateListener != null) {                mScreenStateListener.onScreenOn();            }        } else{            if(mScreenStateListener != null) {                mScreenStateListener.onScreenOff();            }        }    }    /**     * 停止screen状态更新     */    publicvoidstopScreenStateUpdate() {        mContext.unregisterReceiver(mScreenReceiver);    }    /**     * 启动screen状态广播接收器     */    privatevoidstartScreenBroadcastReceiver() {        IntentFilter filter = newIntentFilter();        filter.addAction(Intent.ACTION_SCREEN_ON);        filter.addAction(Intent.ACTION_SCREEN_OFF);        //当用户解锁屏幕时        filter.addAction(Intent.ACTION_USER_PRESENT);        mContext.registerReceiver(mScreenReceiver, filter);    }    /**     * screen是否打开状态     *      * @param pm     * @return     */    privatestaticbooleanisScreenOn(PowerManager pm) {        booleanscreenState;        try{            screenState = (Boolean) mReflectScreenState.invoke(pm);        } catch(Exception e) {            screenState = false;        }        returnscreenState;    }    publicinterfaceScreenStateListener {        publicvoidonScreenOn();        publicvoidonScreenOff();    }    /**     * 判断屏幕是否已被锁定     * @param c     * @return     */    publicfinalstaticbooleanisScreenLocked(Context c)     {          android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c                  .getSystemService(Context.KEYGUARD_SERVICE);          returnmKeyguardManager.inKeyguardRestrictedInputMode();      }          /**     * 判断当前应用是否是本应用     * @param context     * @return     */    publicstaticbooleanisApplicationBroughtToBackground(finalContext context) {        ActivityManager am = (ActivityManager) context                .getSystemService(Context.ACTIVITY_SERVICE);        List<RunningTaskInfo> tasks = am.getRunningTasks(1);        if(!tasks.isEmpty()) {            ComponentName topActivity = tasks.get(0).topActivity;            if(!topActivity.getPackageName().equals(context.getPackageName())) {                returntrue;            }        }        returnfalse;    }} | 
然后在app的BaseActivity中实现ScreenObserver
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |        privateScreenObservermScreenObserver;              @Override    protectedvoidonCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                mScreenObserver = newScreenObserver(this);        mScreenObserver.requestScreenStateUpdate(newScreenStateListener() {            @Override            publicvoidonScreenOn() {                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))                {                    cancelAlarmManager();                }            }            @Override            publicvoidonScreenOff() {                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))                {                    cancelAlarmManager();                    setAlarmManager();                }            }        });            }        ///此处省略一大坨代码/** * 设置定时器管理器 */privatevoidsetAlarmManager(){            longnumTimeout = 300*1000;//5分钟        LogUtils.d("isTimeOutMode=yes,timeout="+numTimeout);        Intent alarmIntent = newIntent(MainActivity.this, TimeoutService.class);        alarmIntent.putExtra("action", "timeout"); //自定义参数        PendingIntent pi = PendingIntent.getService(MainActivity.this, 1024, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);         longtriggerAtTime =  (System.currentTimeMillis()+numTimeout);         am.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pi); //设定的一次性闹钟,这里决定是否使用绝对时间        LogUtils.d("----->设置定时器");    }    /**     * 取消定时管理器     */    privatevoidcancelAlarmManager()    {        AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);         Intent intent = newIntent(MainActivity.this, TimeoutService.class);         PendingIntent pi = PendingIntent.getService(MainActivity.this, 1024, intent,PendingIntent.FLAG_UPDATE_CURRENT);        // 与上面的intent匹配(filterEquals(intent))的闹钟会被取消         alarmMgr.cancel(pi);        LogUtils.d("----->取消定时器");    }            @Override    protectedvoidonResume() {        LogUtils.e("MainActivity-onResume");        super.onResume();        cancelAlarmManager();        activityIsActive = true;        LogUtils.d("activityIsActive="+activityIsActive);    }        @Override    protectedvoidonStop() {        LogUtils.e("onStop");        super.onStop();        if(ScreenObserver.isApplicationBroughtToBackground(this))        {            cancelAlarmManager();            setAlarmManager();        }    } | 
然后在后台finishActivity
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | publicclassTimeoutService extendsService implementsAppConstants {    @Override    publicIBinder onBind(Intent arg0) {        returnnull;    }    booleanisrun = true;    @Override    publicvoidonCreate() {        LogUtils.e("BindService-->onCreate()");        super.onCreate();    }        @Override    publicintonStartCommand(Intent intent, intflags, intstartId) {        LogUtils.e("BindService-->onStartCommand()");        forceApplicationExit();        returnsuper.onStartCommand(intent, flags, startId);            }        privatevoidforceApplicationExit()    {        newThread(newRunnable() {            @Override            publicvoidrun() {                ActivityListUtil.getInstence().cleanActivityList();                stopSelf();                    }            }).start();    }    @Override    publicvoidonDestroy() {        super.onDestroy();        isrun = false;    }} | 
ActivityListUtil类如下
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | publicclassActivityListUtil {    privatestaticActivityListUtil instence;    publicArrayList<Activity> activityList;    publicActivityListUtil() {        activityList = newArrayList<Activity>();    }    publicstaticActivityListUtil getInstence()     {        if(instence == null) {            instence = newActivityListUtil();        }        returninstence;    }    publicvoidaddActivityToList(Activity activity) {        if(activity!=null)        {            activityList.add(activity);        }    }    publicvoidremoveActivityFromList(Activity activity)    {        if(activityList!=null&& activityList.size()>0)        {            activityList.remove(activity);        }    }    publicvoidcleanActivityList() {        if(activityList!=null&& activityList.size() > 0) {            for(inti = 0; i < activityList.size(); i++) {                Activity activity = activityList.get(i);                if(activity!=null&& !activity.isFinishing())                {                    activity.finish();                }            }        }            }} | 
http://my.oschina.net/ososchina/blog/374050?p=1
Android实现app长时间未操作时自动退出app的更多相关文章
- iOS开发笔记--如何实现程序长时间未操作退出
		我们使用金融软件经常会发现手机锁屏或者长时间未操作就会退出程序或者需要重新输入密码等情况.下面让我们看一下如何实现这种功能.我们知道iOS有一个事件循环机制,也就是大家所说的runloop.我们在对程 ... 
- web页面长时间未操作自动退出登录
		var lastTime = new Date().getTime(); var currentTime = new Date().getTime(); * * ; //设置超时时间: 10分 $(f ... 
- vue项目前端限制页面长时间未操作超时退出到登录页
		之前项目超时判断是后台根据token判断的,这样判断需要请求接口才能得到返回结果,这样就出现页面没有接口请求时还可以点击,有接口请求时才会退出 现在需要做到的效果是:页面超过30分钟未操作时,无论点击 ... 
- JavaScript长时间未操作自动退出登录
		主要是通过mouseover 来监听有没有进行当前页面操作,通过未操作时间和设定退出的时间做比较,从而退出登录. var oldTime = new Date().getTime(); var new ... 
- WPF窗口长时间无人操作鼠标自动隐藏
		在软件开发中有时会有等待一段时间无人操作后隐藏鼠标,可能原因大致如下: 1.为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作,程序自动跳转到用户登录界面: 2.软件为了 ... 
- iOS实现程序长时间未操作退出
		大部分银行客户端都有这样的需求,在用户一定时间内未操作,即认定为token失效,但未操作是任何判定的呢?我的想法是用户未进行任何touch时间,原理就是监听runloop事件.我们需要进行的操作是创建 ... 
- jsp+js完成用户一定时间未操作就跳到登录页面
		<% String path = request.getContextPath(); String basePath = request.getScheme() + "://" ... 
- Web页面长时间无操作后再获取焦点时转到登录界面
		今天开始讲新浪博客搬到博客园. 在工作中遇到的小问题,感觉有点意思,就记录下来吧! 该问题分为两种情况,一.Web页面长时间无操作后,在对其进行操作,比如点击“首页”.“设 ... 
- SSH连接服务器时,长时间不操作就会断开的解决方案
		最近在配置服务器相关内容时候,不同的事情导致长时间不操作,页面就断开了连接,不能操作,只能关闭窗口,最后通过以下命令解决. SSH连接linux时,长时间不操作就断开的解决方案: 1.修改/etc/s ... 
随机推荐
- 将正确的 HTTP 头转发给后端服务器的一些问题
			Apache Software Foundation 的 HTTP 服务器项目(通常称为 Apache)是当今互联网上占据优势的 Web 服务器,它占据了 60% 以上的市场份额.Apache 服务器 ... 
- 注意自己的dns设置 - 阿权的书房
			一般而言,随便找个合适的dns服务器作为自己的dns解析服务器即可,但如果选择不当,可能就会导致网络选择并不是最优的.这个情况一般发生在电信网通优化的域名上. 检查方法(域名有所替换): [root@ ... 
- 关于Message目录的设定
			Yii2 默认了两个message 目录,一个是 yii 和app ,所以如果想自定义message目录,要在自己配置文件中覆盖 i18n的设定,请注意,不能使用 *,要使用 app,才能生效 
- thrift
			环境准备: 1.下载window版本的thrift编译器 2.下载idea的thirft插件 3.设置thrift编译工具为:步骤1下载的编译器 4.编写thrift文件 namespace java ... 
- [学习笔记]RAID及实验
			RAID: RAID 0 好比只用左手拿了一摞大饼放在那里,相比于只拿一张饼吃,吃的速度会加快.但是万一掉了,就没有了. RAID 1 好比左右手两手一边一个大饼,怎么样都有的吃.但是一只手掉了,还有 ... 
- NV OIT algorithm : Depth  peeling is a fragment-level depth sorting technique
			https://developer.nvidia.com/content/interactive-order-independent-transparency Correctly rendering ... 
- 【Spec for GS5】不要嘲笑程序员不懂烂漫
			// // main.cpp // 生日快乐 // // Created by wasdns on 16/11/21. // Copyright © 2016年 wasdns. All rights ... 
- P4factory <Integration with Mininet>
			在终端A进入simple_router目录,make bm之后,执行 ./run_demo.bash 成功和Mininet进行协作: *** Creating network *** Adding h ... 
- thanksgiving day (eat)
			1.try a nibble of your food 2.dig in (开动) 3.ingest in (吞咽) 4.devoured(狼吞虎咽) 5.wolf down your food 6 ... 
- Overengineering
			https://en.wikipedia.org/wiki/Overengineering Overengineering (or over-engineering) is the designing ... 
