Android系统休眠对程序的影响以及处理

2019-07-14 02:32发布

Android系统在用户长时间不操作时,为了节省资源,系统会选择休眠。在休眠过程中自定义的Timer、Handler、Thread、Service等都会暂停。而有时候这种机制会影响到我们程序的正常运行。 1、获取电源锁,并在执行完毕释放电源锁 public class WakeLockUtil { public static WakeLock wakeLock = null; public static void acquireWakeLock(Activity myActivity) { if (null == wakeLock) { PowerManager pm = (PowerManager) myActivity.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.ON_AFTER_RELEASE | PowerManager.PARTIAL_WAKE_LOCK, "wakeLockUtil"); // PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的 -- 最常用,保持CPU运转 // SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯 // SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯 // FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度 // ACQUIRE_CAUSES_WAKEUP:强制使屏幕亮起,这种锁主要针对一些必须通知用户的操作. // ON_AFTER_RELEASE:当锁被释放时,保持屏幕亮起一段时间 if (null != wakeLock) { wakeLock.acquire(); // 立即获取电源锁 // wakeLock.acquire(2000); // 2秒后获取电源锁 } } } public static void releaseWakeLock(Activity myActivity) { if (null != wakeLock) { wakeLock.release(); wakeLock = null; } } } 2、利用系统闹钟定时启动service
在service的onStartCommand方法中,定时10分钟后启动自己。
如果该service进程被系统杀死,闹钟事件可能不会触发,所以将此service设置为独立进程,并加入系统自启动中。 @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e("LocationService","onStartCommand"); AlarmManager alarmService = (AlarmManager) getSystemService(ALARM_SERVICE); Intent alarmIntent = new Intent(this, LocationService.class); //四个参数Flags:Flags为0代表该PendingIntent不带数据 //Flags为FLAG_CANCEL_CURRENT :如果AlarmManager管理的PendingIntent已经存在,那么将会取消当前的PendingIntent,从而创建一 个新的PendingIntent //Flags为PendingIntent.FLAG_UPDATE_CURRENT,要通过extra数据来区分intent,应采用PendingIntent.FLAG_UPDATE_CURRENT,且每次num不一样 PendingIntent intentService = PendingIntent.getService(this, REQUESTCODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT); //(1)set(int type,long startTime,PendingIntent pi);该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。 //(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。 //(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。 alarmService.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10*60*1000,intentService); // startLoc(); return super.onStartCommand(intent, flags, startId); }
type: 闹钟的类型,有五种: AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始); AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间; AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间(
让定时任务的触发时间从1970年1月1日0点开始算起); AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0; AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间;不过本状态好像受SDK版本影响,某些版本并不支持; intervalTime:闹钟的第一次执行时间,以毫秒为单位,它必须和type相对应,比如type是AlarmManager.ELAPSED_REALTIME_WAKEUP类型,代表是使用的是相对时间,所以intervalTime必须也得是相对时间: SystemClock.elapsedRealtime()。 SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数, System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数
同时定义开机广播接收和网络状态改变广播接收,启动service,来确保关机等因素导致闹钟动作不执行 public class BootCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //收到开机广播 Intent intentService = new Intent(); intentService.setClass(context,LocationService.class); context.startService(intentService); } } public class NetworkConnectChangedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { ConnectivityManager manager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); Log.e("ConnectChangedReceiver", "CONNECTIVITY_ACTION"); NetworkInfo activeNetwork = manager.getActiveNetworkInfo(); if (activeNetwork != null) { // connected to the internet if (activeNetwork.isConnected()) { if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { // connected to wifi Log.e("ConnectChangedReceiver", "当前WiFi连接可用 "); FileHelper fHelper = new FileHelper(context); fHelper.writeTxtToFile("当前为WiFi连接", "快递定位/", "location.txt"); Intent intentService = new Intent(); intentService.setClass(context,LocationService.class); context.startService(intentService); } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { // connected to the mobile provider's data plan Log.e("ConnectChangedReceiver", "当前移动网络连接可用 "); FileHelper fHelper = new FileHelper(context); fHelper.writeTxtToFile("当前移动网络连接", "快递定位/", "location.txt"); Intent intentService = new Intent(); intentService.setClass(context,LocationService.class); context.startService(intentService); } } else { Log.e("ConnectChangedReceiver", "当前没有网络连接,请确保你已经打开网络 "); FileHelper fHelper = new FileHelper(context); fHelper.writeTxtToFile("当前没有网络连接", "快递定位/", "location.txt"); } Log.e("ConnectChangedReceiver", "info.getTypeName()" + activeNetwork.getTypeName()); Log.e("ConnectChangedReceiver", "getSubtypeName()" + activeNetwork.getSubtypeName()); Log.e("ConnectChangedReceiver", "getState()" + activeNetwork.getState()); Log.e("ConnectChangedReceiver", "getDetailedState()" + activeNetwork.getDetailedState().name()); Log.e("ConnectChangedReceiver", "getDetailedState()" + activeNetwork.getExtraInfo()); Log.e("ConnectChangedReceiver", "getType()" + activeNetwork.getType()); } else { // not connected to the internet Log.e("ConnectChangedReceiver", "当前没有网络连接,请确保你已经打开网络 "); FileHelper fHelper = new FileHelper(context); fHelper.writeTxtToFile("当前没有网络连接", "快递定位/", "location.txt"); } } } }