即使手机处于睡眠状态也能保持服务运行吗?

2023-11-22

我的应用程序中有一个服务,设计为每 10 分钟运行一次。它主要检查我们的服务器,看看一切是否正常运行,并通知用户任何问题。我创建了这个应用程序供我们公司内部使用。

我的同事在长周末使用了该应用程序,并注意到设备进入睡眠状态时没有执行任何检查。我的印象是该服务应该在后台继续运行,直到我明确调用stopService()在我的代码中。

因此,最终,我的目标是让服务运行,直到用户点击应用程序中的关闭按钮或终止进程。

我听说过一个叫做WakeLock这是为了防止屏幕关闭,这不是我想要的。然后我听说了另一种东西,叫做部分唤醒锁定,即使设备处于睡眠状态,CPU 也能保持运行。后者听起来更接近我的需要。

我如何获取此 WakeLock,何时应该释放它,还有其他方法可以解决此问题吗?


注意:这篇文章已更新,包括JobSchedulerAndroid 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);
        }
    }
    

    with YourService为您服务;-)

如果您的任务需要唤醒锁,建议从WakefulBroadcastReceiver。不要忘记添加WAKE_LOCK在这种情况下,请在您的清单中获得许可!

  • 创建待处理的意图

要开始定期轮询,请在您的活动中执行以下代码:

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. The alarmManager得到重复的工作recurringAlarm每天(第三个参数),但是inexact因此 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>-标签。如果没有它,系统不接受服务的周期性警报的启动。


安卓棒棒糖发布后,有一种新方法可以优雅地解决此任务。 这也使得仅在满足某些标准(例如网络状态)时才执行操作变得更加容易。

// 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); or jobScheduler.cancelAll();.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使手机处于睡眠状态也能保持服务运行吗? 的相关文章