即使手机处于睡眠状态也要保持服务运行? [英] Keep a Service running even when phone is asleep?

查看:21
本文介绍了即使手机处于睡眠状态也要保持服务运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中有一项服务,该服务旨在每 10 分钟运行一次.它基本上会检查我们的服务器以查看一切是否正常运行并通知用户任何问题.我创建了这个应用程序供我们公司内部使用.

I have a Service in my application which is designed to run every 10 minutes. It basically checks up on our servers to see if everything is running properly and notifies the user of any problems. I created this application for internal use at our company.

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

My co-worker used the application over the long weekend and noticed that no checks were performed when the device went to sleep. I was under the impression that the Service was supposed to keep running in the background until I explicitly call stopService() in my code.

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

So ultimately, my goal is to have the service running until the user hits the off button in the application or kills the process.

我听说过一种叫做 WakeLock 的东西,它旨在防止屏幕关闭,这不是我想要的.然后我听说了另一种叫做 partial WakeLock 的东西,即使设备处于睡眠状态,它也能保持 CPU 运行.后者听起来更接近我所需要的.

I heard about something called WakeLock which is meant to keep the screen from turning off, which is not what I want. I then heard of another thing called a partial WakeLock, which keeps the CPU running even when the device is asleep. The latter sounds closer to what I need.

我如何获得这个 WakeLock,我应该什么时候释放它,还有其他方法可以解决这个问题吗?

How do I acquire this WakeLock and when should I release it and are there other ways around this?

推荐答案

注意:此帖子已更新以包含 Android Lollipop 版本的 JobScheduler API.以下仍然是一种可行的方法,但如果您的目标是 Android Lollipop 及更高版本,则可以认为已弃用.JobScheduler 替代方案的下半部分.

Note: This post has been updated to include the JobScheduler API of the Android Lollipop release. The following is still a viable way, but can be considered deprecated if you're targeting Android Lollipop and beyond. See the second half for the JobScheduler alternative.

执行重复任务的一种方法是:

One way to do recurrent tasks is this:

  • 创建一个类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 作为您的服务 ;-)

with YourService being your service ;-)

如果您的任务需要唤醒锁,建议从 WakefulBroadcastReceiver.在这种情况下,不要忘记在您的清单中添加 WAKE_LOCK 权限!

If you require a wake lock for your Task, it is advisable to extend from WakefulBroadcastReceiver. Don't forget to add the WAKE_LOCK permission in your Manifest in this case!

  • 创建待处理的意图

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

To start your recurrent polling, execute this code in your 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 的任务(第三个参数),但是 inexact 所以 CPU 确实在大约间隔后唤醒,但是不完全是(它让操作系统选择最佳时间,从而减少电池消耗).警报(以及服务)第一次启动的时间将是您选择的 updateTime.

This code sets up an alarm and a canceable pendingIntent. The alarmManager gets the job to repeat the recurringAlarm every day (third argument), but inexact so the CPU does wake up approximately after the interval but not exactly (It lets the OS choose the optimal time, which reduces battery drain). The first time the alarm (and thus the service) is started will be the time you choose to be updateTime.

  • 最后但并非最不重要的一点:这里是如何消除重复出现的警报

  • last but not least: here is how to kill the recurring alarm

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 取消所有此类警报.

This code creates a copy of your (probably) existing alarm and tells the alarmManager to cancel all alarms of that kind.

  • 当然在Manifest中还有一些事情要做:
  • of course there is also something to do in the Manifest:

包括这两行

  < receiver android:name=".AlarmReceiver"></receiver>
  < service android:name=".YourService"></service>

在<代码><应用程序>-标签.没有它,系统不接受服务的周期性报警启动.

inside the < application>-tag. Without it, the system does not accept the start of recurrent alarm of a service.

Android Lollipop 版本开始,有一种新方法可以优雅地解决此任务.这也使得仅在满足某些条件(例如网络状态)时才更容易执行操作.

Starting with the Android Lollipop release, there's a new way of solving this task elegantly. This also makes it easier to only perform an action if certain criteria such as network state are met.

// 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) 提供截止日期.

You may also provide a deadline with setOverrideDeadline(maxExecutionDelayMillis).

要摆脱这样的任务,只需调用 jobScheduler.cancel(mJobId);jobScheduler.cancelAll();.

To get rid of such a task, just call jobScheduler.cancel(mJobId); or jobScheduler.cancelAll();.

这篇关于即使手机处于睡眠状态也要保持服务运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆