概述
最近做了一个预约提醒的需求,跟闹钟差不多,设置一个时间,到时间了发送一个通知给用户。刚听到稍有点懵逼,因为需要开关机、杀掉进程后仍然能接收到通知。一听就感觉像QQ、微信一样强大了鸟。其实有些手机微信、QQ杀掉进程了也不能收到,网上很多人说大多数手机杀掉进程能收到微信消息是因为微信直接被厂商加入白名单了,这个就不去深究了。毕竟我们的大多数程序没法跟微信比,人家的用户数量在那。
回归正题,对于这个需求,之前没怎么接触过相关的,就先网上查了下,能找到一些关键词,jobScheduler、AlarmManager、进程保活。
jobScheduler:
对于jobScheduler的使用,可以参考此篇文章—-在Android 5.0中使用JobScheduler 。在这里我自己也对jobScheduler的使用做一下总结。jobScheduler官方文档
首先必须要说的一点是,jobScheduler的使用要求是API21(Android 5.0,即Lollipop )以上。看到了一个jobScheduler的介绍:系统级的任务,开关机、杀掉进程后仍然可以继续工作,心里顿时就窃喜了一下,哥哥要的就是它啊。可惜好景不长,弄完了才发现他的坑人之处(后面再介绍),先说下它的使用。
1、创建一个类继承JobService
继承jobService的服务是一个系统服务,与进程是否存在无关。必须实现的方法有两个,public boolean onStartJob(JobParameters params)
和 public boolean onStopJob(JobParameters params)
;
public class MyService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
见名之意,一个是开始任务的时候调用,一个是结束任务的时候调用。返回值为布尔值,false表示系统假设这个方法返回时任务已经执行完毕。如果返回值是true,那么系统假定这个任务正要被执行,执行任务的重担就落在了你的肩上。
注意一点,既然是JobService那也是一个Service,说明它是运行在主线程中的。如果要执行耗时操作请另开子线程。
2、创建一个jobScheduler对象
JobScheduler jobScheduler =(JobScheduler)getSystemService(Context.JOB_SCHEDULER_SERVICE);
获取到jobScheduler对象后,我们再创建一个jobInfo对象。
JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(this, MyService.class));
第一个参数是jobId,标志此时创建的任务;第二个参数是继承JobService的类的ComponentName。
然后对builder配置相关属性,常用的有
builder.setPersisted(true)//手机重启后是否继续执行任务
.setPeriodic(10*1000);//重复执行任务,间隔时间为10秒
其他设置方法 :
setMinimumLatency(long minLatencyMillis):
这个函数能让你设置任务的延迟执行时间(单位是毫秒),这个函数与setPeriodic(long time)方法不兼容,如果这两个方法同时调用了就会引起异常;setOverrideDeadline(long maxExecutionDelayMillis):
这个方法让你可以设置任务最晚的延迟时间。如果到了规定的时间时其他条件还未满足,你的任务也会被启动。这个方法也会与setPeriodic(long time)
冲突,同时调用这两个方法会引发异常。setPersisted(boolean isPersisted)
: 这个方法告诉系统当你的设备重启之后你的任务是否还要继续执行。setRequiredNetworkType(int networkType):
这个方法让你这个任务只有在满足指定的网络条件时才会被执行。默认条件是JobInfo.NETWORK_TYPE_NONE
,这意味着不管是否有网络这个任务都会被执行。另外两个可选类型,一种是JobInfo.NETWORK_TYPE_ANY
,它表明需要任意一种网络才使得任务可以执行。另一种是JobInfo.NETWORK_TYPE_UNMETERED
,它表示设备不是蜂窝网络(比如在WIFI连接时 )时任务才会被执行。setRequiresCharging(boolean requiresCharging)
:
这个方法告诉你的应用,只有当设备在充电时这个任务才会被执行。setRequiresDeviceIdle(boolean requiresDeviceIdle)
:
这个方法告诉你的任务只有当用户没有在使用该设备且有一段时间没有使用时才会启动该任务。
builder设置完后,最后调用:
int schedule = jobScheduler.schedule(builder.build());
该方法返回一个int值,0表示失败,1表示成功。
既然有schedule()方法,当然得有对应的cancel()方法。
jobScheduler.cancel(int JobId);//取消对应Id的任务
jobScheduler.cancelAll();//取消所有
基本使用就是如上所说。现在来说下遇到的坑,测试了下6.0以下手机能正常运行,问题就出在6.0及以上。此时6.0的休眠模式跳了出来,简单介绍下休眠模式。
休眠模式:当设备一段时间不用的时候,当屏幕关闭的时候,系统会自动进入休眠模式。这样所有的App都将进入挂起模式,不能在接入 网络等一些操作。
当然系统也会定期的退出休眠模式,来完成App延迟的工作,在这个空窗期(我暂且就这么叫),系统会运行所有同步,工作,提醒等,并允许app接入网络。
当过了空窗期后,系统会重新进入休眠期,App也会随着挂起状态,随着时间的推移,空窗期越来越少,是为了帮助没有接入充电器的长期闲置的设备减少电池消耗。
只要用户唤醒设备,打开屏幕或者接入电源,系统会自动退出休眠模式,所有的活动都会恢复正常状态。
下面是当进入休眠期时的约束:
1. 延迟网络请求;
2. 系统忽略唤醒锁;
3. 标准的闹钟提醒(包括setExat()和setWindow())会被延时到下一个空窗期;
如果一定要在休眠期唤醒闹钟,可以用setAndAllowWhileIdle() 或者 setExactAndAllowWhileIdle();
闹钟设置setAlarmClock() 则继续保持常态,在唤醒这个闹钟前系统推出休眠期一段时间;
4. 禁用wifi scan;
5. 不允许同步;
6. 禁用JobScheduler ;
由此可见,坑大了。6.0以上手机息屏后JobScheduler 直接就不工作了,没得搞了啊。
又继续换个思路研究需求,下回再分解下AlarmManager。
最后
以上就是整齐柜子为你收集整理的预约提醒功能(类似闹钟)总结的全部内容,希望文章能够帮你解决预约提醒功能(类似闹钟)总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复