【问题标题】:Alarm not waking my service while the app is closed应用程序关闭时警报未唤醒我的服务
【发布时间】:2019-01-01 12:29:48
【问题描述】:

我希望每 n 分钟启动一次服务。这有效,但前提是应用程序正在运行(在屏幕上处于活动状态或处于非活动状态,最小化)。当我关闭它时(点击右下按钮并滑动到一侧),服务停止启动。

设置闹钟(MainActivity.onStart):

Intent startServiceIntent = new Intent(this, LogSyncService.class);
PendingIntent alarmIntent = PendingIntent.getService(this, 0, startServiceIntent, 0);

AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(
    AlarmManager.ELAPSED_REALTIME_WAKEUP,
    SystemClock.elapsedRealtime(),
    5 * 1000, // low for testing purposes
    alarmIntent);

AndroidManifest.xml:

<service
    android:name=".LogSyncService"
    android:description="@string/logSyncService_description"
    android:exported="false"/>

通过查看警报转储 (adb shell dumpsys alarm),我可以清楚地看到,即使应用程序关闭(唤醒次数正在增加),警报仍然有效,但没有调用服务,因为它是该应用程序已打开。当我手动重新打开应用程序时,一切正常。

我该如何解决这个问题?

【问题讨论】:

  • 请看这个链接,希望对你有帮助:- stackoverflow.com/questions/30525784/…
  • 你的接收器是什么样的?不是代码,是 xml
  • 您是在 android marshmallow 还是更高版本上进行测试?
  • @DroiDev 什么接收者?
  • @Benjamin 是的,奥利奥。

标签: android alarmmanager android-alarms repeatingalarm


【解决方案1】:

警报

您应该了解Doze and Standby 如何影响 Android 6.0 及更高版本设备上的警报。当手机进入打盹状态时,所有警报和后台作业都会停止,直到维护期到来。有新的警报可以在这些状态下运行,setAndAllowWhileIdle()setExactAndAllowWhileIdle() 所以基本上你应该创建新的方法,你将根据平台版本调用不同的警报方法:

    public void setExactAlarm(int alarmType, long triggerTime, PendingIntent operation) {

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    if (alarmManager != null) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(alarmType, triggerTime, operation);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(alarmType, triggerTime, operation);
        } else {
            alarmManager.set(alarmType, triggerTime, operation);
        }
    }
}

请注意如何在打盹状态下延迟警报:

在正常系统运行下,不会再派出这些告警 大约每分钟(此时每个此类未决警报都是 已发送);当处于低功耗空闲模式时,此持续时间可能是 明显更长,例如 15 分钟。


服务

最新的 SDK API 发生了一些变化。如果您在平台 26+ 上运行应用程序,则对后台服务有限制。

如果您的应用以 API 级别 26 或更高级别为目标,系统会对使用或创建后台服务施加限制,除非应用本身位于前台。如果应用需要创建前台服务,应用应该调用 startForegroundService()。该方法创建了一个后台服务,但该方法向系统发出信号,该服务将把自己提升到前台。创建服务后,服务必须在五秒内调用其 startForeground() 方法。

所以,如果你需要一些后台服务,现在你必须通过通知通知用户有一些服务在后台执行。

这是警报触发时广播接收器的一些示例代码:

Intent service= new Intent(this, ExampleService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            context.startForegroundService(service);
        else
            context.startService(intent);

最后,在 onStartCommand() 中的服务内部,您必须再次检查 SDK 版本,如果版本为 26+,则应调用 startForeground();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    Notification notification = new NotificationCompat.Builder(context, channalId);
    startForeground(NOTIFICATION_ID, notification);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    相关资源
    最近更新 更多