这里要考虑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
public class ScreenObserver {
 
    private static String TAG = "ScreenObserver";
    private Context mContext;
    private ScreenBroadcastReceiver mScreenReceiver;
    private ScreenStateListener mScreenStateListener;
    private static Method mReflectScreenState;
 
    public ScreenObserver(Context context) {
        mContext = context;
        mScreenReceiver = new ScreenBroadcastReceiver();
        try {
            mReflectScreenState = PowerManager.class.getMethod("isScreenOn",
                    new Class[] {});
        catch (NoSuchMethodException nsme) {
            Log.d(TAG, "API < 7," + nsme);
        }
    }
 
    /**
     * screen状态广播接收者
     
     * @author xishaomin
     
     */
    private class ScreenBroadcastReceiver extends BroadcastReceiver {
        private String action = null;
 
        @Override
        public void onReceive(Context context, Intent intent) {
            action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mScreenStateListener.onScreenOn();
            else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                mScreenStateListener.onScreenOff();
            }else if(Intent.ACTION_USER_PRESENT.equals(action)){
                LogUtils.d("---->屏幕解锁完成");
            }
        }
    }
 
    /**
     * 请求screen状态更新
     
     * @param listener
     */
    public void requestScreenStateUpdate(ScreenStateListener listener) {
        mScreenStateListener = listener;
        startScreenBroadcastReceiver();
 
        firstGetScreenState();
    }
 
    /**
     * 第一次请求screen状态
     */
    private void firstGetScreenState() {
        PowerManager manager = (PowerManager) mContext
                .getSystemService(Activity.POWER_SERVICE);
        if (isScreenOn(manager)) {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOn();
            }
        else {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOff();
            }
        }
    }
 
    /**
     * 停止screen状态更新
     */
    public void stopScreenStateUpdate() {
        mContext.unregisterReceiver(mScreenReceiver);
    }
 
    /**
     * 启动screen状态广播接收器
     */
    private void startScreenBroadcastReceiver() {
        IntentFilter filter = new IntentFilter();
        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
     */
    private static boolean isScreenOn(PowerManager pm) {
        boolean screenState;
        try {
            screenState = (Boolean) mReflectScreenState.invoke(pm);
        catch (Exception e) {
            screenState = false;
        }
        return screenState;
    }
 
    public interface ScreenStateListener {
        public void onScreenOn();
 
        public void onScreenOff();
    }
    /**
     * 判断屏幕是否已被锁定
     * @param c
     * @return
     */
    public final static boolean isScreenLocked(Context c) 
    {  
        android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c  
                .getSystemService(Context.KEYGUARD_SERVICE);  
        return mKeyguardManager.inKeyguardRestrictedInputMode();  
    }  
     
    /**
     * 判断当前应用是否是本应用
     * @param context
     * @return
     */
    public static boolean isApplicationBroughtToBackground(final Context 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())) {
                return true;
            }
        }
        return false;
    }
}

然后在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
       private ScreenObservermScreenObserver;
        
       @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         
        mScreenObserver = new ScreenObserver(this);
        mScreenObserver.requestScreenStateUpdate(new ScreenStateListener() {
            @Override
            public void onScreenOn() {
                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))
                {
                    cancelAlarmManager();
                }
            }
 
            @Override
            public void onScreenOff() {
                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))
                {
                    cancelAlarmManager();
                    setAlarmManager();
                }
            }
        });
         
    }
         
///此处省略一大坨代码
/**
 * 设置定时器管理器
 */
private void setAlarmManager()
{
     
        long numTimeout = 300*1000;//5分钟
        LogUtils.d("isTimeOutMode=yes,timeout="+numTimeout);
        Intent alarmIntent = new Intent(MainActivity.this, TimeoutService.class);
        alarmIntent.putExtra("action""timeout"); //自定义参数
        PendingIntent pi = PendingIntent.getService(MainActivity.this1024, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); 
        long triggerAtTime =  (System.currentTimeMillis()+numTimeout); 
        am.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pi); //设定的一次性闹钟,这里决定是否使用绝对时间
        LogUtils.d("----->设置定时器");
    }
    /**
     * 取消定时管理器
     */
    private void cancelAlarmManager()
    {
        AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
        Intent intent = new Intent(MainActivity.this, TimeoutService.class); 
        PendingIntent pi = PendingIntent.getService(MainActivity.this1024, intent,PendingIntent.FLAG_UPDATE_CURRENT);
        // 与上面的intent匹配(filterEquals(intent))的闹钟会被取消 
        alarmMgr.cancel(pi);
        LogUtils.d("----->取消定时器");
    }
     
        @Override
    protected void onResume() {
        LogUtils.e("MainActivity-onResume");
        super.onResume();
        cancelAlarmManager();
        activityIsActive = true;
        LogUtils.d("activityIsActive="+activityIsActive);
    }
     
    @Override
    protected void onStop() {
        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
public class TimeoutService extends Service implements AppConstants {
 
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
 
    boolean isrun = true;
 
    @Override
    public void onCreate() {
        LogUtils.e("BindService-->onCreate()");
        super.onCreate();
    }
     
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.e("BindService-->onStartCommand()");
        forceApplicationExit();
        return super.onStartCommand(intent, flags, startId);
         
    }
     
    private void forceApplicationExit()
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ActivityListUtil.getInstence().cleanActivityList();
                stopSelf();
                    }
            }).start();
    }
 
    @Override
    public void onDestroy() {
        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
public class ActivityListUtil {
    private static ActivityListUtil instence;
    public ArrayList<Activity> activityList;
 
    public ActivityListUtil() {
        activityList = new ArrayList<Activity>();
    }
    public static ActivityListUtil getInstence() 
    {
        if (instence == null) {
            instence = new ActivityListUtil();
        }
        return instence;
    }
    public void addActivityToList(Activity activity) {
        if(activity!=null)
        {
            activityList.add(activity);
        }
    }
    public void removeActivityFromList(Activity activity)
    {
        if(activityList!=null && activityList.size()>0)
        {
            activityList.remove(activity);
        }
    }
    public void cleanActivityList() {
        if (activityList!=null && activityList.size() > 0) {
            for (int i = 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的更多相关文章

  1. iOS开发笔记--如何实现程序长时间未操作退出

    我们使用金融软件经常会发现手机锁屏或者长时间未操作就会退出程序或者需要重新输入密码等情况.下面让我们看一下如何实现这种功能.我们知道iOS有一个事件循环机制,也就是大家所说的runloop.我们在对程 ...

  2. web页面长时间未操作自动退出登录

    var lastTime = new Date().getTime(); var currentTime = new Date().getTime(); * * ; //设置超时时间: 10分 $(f ...

  3. vue项目前端限制页面长时间未操作超时退出到登录页

    之前项目超时判断是后台根据token判断的,这样判断需要请求接口才能得到返回结果,这样就出现页面没有接口请求时还可以点击,有接口请求时才会退出 现在需要做到的效果是:页面超过30分钟未操作时,无论点击 ...

  4. JavaScript长时间未操作自动退出登录

    主要是通过mouseover 来监听有没有进行当前页面操作,通过未操作时间和设定退出的时间做比较,从而退出登录. var oldTime = new Date().getTime(); var new ...

  5. WPF窗口长时间无人操作鼠标自动隐藏

    在软件开发中有时会有等待一段时间无人操作后隐藏鼠标,可能原因大致如下: 1.为了安全性,特别是那些需要用到用户名和密码登录服务端的程序,常常考虑长期无人操作,程序自动跳转到用户登录界面: 2.软件为了 ...

  6. iOS实现程序长时间未操作退出

    大部分银行客户端都有这样的需求,在用户一定时间内未操作,即认定为token失效,但未操作是任何判定的呢?我的想法是用户未进行任何touch时间,原理就是监听runloop事件.我们需要进行的操作是创建 ...

  7. jsp+js完成用户一定时间未操作就跳到登录页面

    <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" ...

  8. Web页面长时间无操作后再获取焦点时转到登录界面

    今天开始讲新浪博客搬到博客园.        在工作中遇到的小问题,感觉有点意思,就记录下来吧!        该问题分为两种情况,一.Web页面长时间无操作后,在对其进行操作,比如点击“首页”.“设 ...

  9. SSH连接服务器时,长时间不操作就会断开的解决方案

    最近在配置服务器相关内容时候,不同的事情导致长时间不操作,页面就断开了连接,不能操作,只能关闭窗口,最后通过以下命令解决. SSH连接linux时,长时间不操作就断开的解决方案: 1.修改/etc/s ...

随机推荐

  1. 使用Android Studio和Genymotion模拟器搭建Andriod开发环境

    一.Android Studio下载 1.打开http://www.android.com/ 2.依照下图步骤打开下载页面 a.在页脚部分点击“App Developer Resources” b.点 ...

  2. Frenetic Python实验(三)

    实验5 repeater 这个实验在HelloSDNWorld里面做的实验是一样的.HelloSDNWorld 目的:模拟一个有多个端口的中继器. This application implement ...

  3. adb & adb shell 相关命令

    在Mac上配置adb命令 在Mac OS中使用adb命令时,应进行变量配置,步骤如下: 一.终端中输入 cd ~ 二.输入touch .bash_profile 回车 touch:如果没有,则创建文件 ...

  4. Android 通过网页打开自己的APP(scheme)

    Android 通过网页打开自己的APP(scheme) 分类: android2014-07-09 17:35 8565人阅读 评论(2) 收藏 举报 通过用手机的浏览器(内置,第三方都可)访问一个 ...

  5. 20145235 《Java程序设计》第一次实验报告

    实验一Java开发环境的熟悉 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验知识点 1.JVM.JRE.JDK的安装位置与区 ...

  6. 浅谈XML

    什么是 XML? · XML 指可扩展标记语言(EXtensible Markup Language) · XML 是一种标记语言,很类似 HTML · XML 的设计宗旨是传输数据,而非显示数据 · ...

  7. MongoVUE的使用

    配置连接:   Ok,连接成功齐活儿~   下面来试一下,插入一个新的名为Message的Collection :     然后插入个Document  

  8. ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

    https://en.wikipedia.org/wiki/Base64 The Base64 index table: Value Char   Value Char   Value Char   ...

  9. 如何离线安装chrome插件【转】

    http://blog.csdn.net/shuideyidi/article/details/45674601 原文链接 前言------可以不看: 实习做web,要弄单点登录SSO和验证Contr ...

  10. ASP.Net网站程序在编译发布部署后的后期修改

    ASP.Net网站程序在发布部署后的后期修改 作者:东篱南山 这里说的后期修改是指网站编译发布并部署好之后,对程序进行的修改,即在不能更改现有代码的情况下,更改页面的显示或是更改业务逻辑.一般是在程序 ...