博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 实现App会话超时设计
阅读量:7115 次
发布时间:2019-06-28

本文共 7079 字,大约阅读时间需要 23 分钟。

hot3.png

这里要考虑3个问题,第一个是锁屏问题,第二个是app被切换至后台的问题,第三个是屏幕锁定和解除时app在后台时的问题

一,监听屏幕解锁,锁定

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
 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

       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.this, 1024, 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.this, 1024, 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

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类如下

public class ActivityListUtil {	private static ActivityListUtil instence;	public ArrayList
 activityList; public ActivityListUtil() { activityList = new ArrayList
(); } 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(); } } } }}

转载于:https://my.oschina.net/ososchina/blog/374050

你可能感兴趣的文章
NLPIR:数据挖掘深度决定大数据应用价值
查看>>
一个游戏拨账系统的数据库结算设计
查看>>
Blockchain和Tangle哪一个是未来?
查看>>
github 上有趣又实用的前端项目(持续更新,欢迎补充)
查看>>
【Under-the-hood-ReactJS-Part6】React源码解读
查看>>
matlab绘制peano(皮亚诺)曲线和koch(科赫曲线,雪花曲线)分形曲线
查看>>
Mybatis之设计模式之迭代器模式
查看>>
小程序TAB列表切换内容动态变化,scrollview高度根据内容动态获取
查看>>
swoole_table 实现原理剖析
查看>>
你需要知道面试中的10个JavaScript概念
查看>>
Java源码阅读之HashMap - JDK1.8
查看>>
Dell服务器系统安装后无法正常进入系统
查看>>
Silverlight/Windows8/WPF/WP7/HTML5周学习导读(9月17日-9月23日)
查看>>
Tap-Ahead:让移动搜索更加便捷的解决之道
查看>>
华为vlan划分,单臂路由以及静态路由
查看>>
3.VMware vsphere 5.0新体验-安装VMware Center
查看>>
趣题: 一道面试题的解法
查看>>
Android应用程序启动过程源代码分析(5)
查看>>
查询整个数据库中某个特定值所在的表和字段的方法
查看>>
在存储过程中编写正确的事务处理代码(SQL Server 2000 & 2005)
查看>>