android - 即使手机处于 sleep 状态,也要保持服务运行?

标签 android service background-process wakelock

我的应用程序中有一个服务,设计为每 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/

相关文章:

javascript - 为什么 PhoneGap inAppBrowser 事件仅在第二次触发?

android - 是否可以封装默认的android键盘

android - 2 服务通讯

python - Capistrano "do nohup python"有效, "do nohup ruby"无效

python - Jenkins 在后台运行脚本

android - 更改 Android 短信的文本

android - 为什么 Xamarin.Android 在运行时重建整个解决方案?

.net - 将 .NET 代码编译为一个 EXE,将其他命名空间编译为 DLL

android - 是否可以创建监听音量键(硬件)按下的服务?

objective-c - 如何手动中断 AVPlayer 来电