我的应用程序中有一个服务,设计为每 10 分钟运行一次。它基本上会检查我们的服务器以查看一切是否正常运行并通知用户任何问题。我创建了这个应用程序供我们公司内部使用。
我的同事在长周末使用了该应用程序,并注意到设备进入休眠状态时未执行任何检查。我的印象是服务应该一直在后台运行,直到我在代码中明确调用 stopService()
。
所以最终,我的目标是让服务一直运行,直到用户点击应用程序中的关闭按钮或终止进程。
我听说过一种叫做 WakeLock
的东西,它旨在防止屏幕关闭,这不是我想要的。然后我听说了另一种叫做 partial WakeLock 的东西,即使设备处于 sleep 状态,它也能让 CPU 保持运行。后者听起来更接近我的需要。
我如何获得这个 WakeLock,我应该什么时候释放它,还有其他方法可以解决这个问题吗?
最佳答案
注意:这篇文章已更新为包含 JobScheduler
Android Lollipop 版本的 API。以下仍然是一种可行的方法,但如果您的目标是 Android Lollipop 及更高版本,则可能被视为已弃用。 JobScheduler
见后半部分替代。
执行循环任务的一种方法是:
创建一个类
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent myService = new Intent(context, YourService.class); context.startService(myService); } }
与
YourService
为您服务 ;-)
如果您的任务需要唤醒锁,建议从 WakefulBroadcastReceiver
扩展。 .不要忘记添加 WAKE_LOCK
在这种情况下,您的 list 中的权限!
- 创建待处理的 Intent
要开始您的循环轮询,请在您的 Activity 中执行以下代码:
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0); //set time to start first occurence of alarm
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course
此代码设置 alarm
和一个可取消的 pendingIntent
. alarmManager
得到重复 recurringAlarm
的工作每天(第三个参数),但 不精确 所以 CPU 确实会在间隔后大约唤醒,但不准确(它让操作系统选择最佳时间,从而减少电池消耗)。第一次启动警报(以及服务)将是您选择的时间 updateTime
.
最后但并非最不重要的一点:这里是如何消除反复出现的警报
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class); //myAlarm.putExtra("project_id",project_id); //put the SAME extras PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarms.cancel(recurringAlarm);
此代码创建您(可能)现有警报的副本,并告诉 alarmManager
取消所有此类警报。
- 当然,
Manifest
中也有一些事情要做。 :
包括这两行
< receiver android:name=".AlarmReceiver"></receiver>
< service android:name=".YourService"></service>
在< application>
里面-标签。没有它,系统不接受服务的周期性警报的启动。
从 Android Lollipop 版本开始,有一种新方法可以优雅地解决此任务。 这也使得仅在满足某些条件(例如网络状态)时才执行操作变得更加容易。
// wrap your stuff in a componentName
ComponentName mServiceComponent = new ComponentName(context, MyJobService.class);
// set up conditions for the job
JobInfo task = JobInfo.Builder(mJobId, mServiceComponent)
.setPeriodic(mIntervalMillis)
.setRequiresCharging(true) // default is "false"
.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED"
.build();
// inform the system of the job
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(task);
您也可以通过 setOverrideDeadline(maxExecutionDelayMillis)
提供截止日期.
要摆脱这样的任务,只需调用jobScheduler.cancel(mJobId);
或 jobScheduler.cancelAll();
.
关于android - 即使手机处于 sleep 状态,也要保持服务运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8713361/