我希望每n分钟启动一次服务。此方法有效,但仅在应用程序正在运行时(在屏幕上处于活动状态或最小化处于活动状态)。当我关闭它时(点击右下角的按钮并滑动到侧面),该服务停止启动。
设置闹钟(在--restart
中):
MainActivity.onStart
AndroidManifest.xml:
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);
通过查看警报转储(<service
android:name=".LogSyncService"
android:description="@string/logSyncService_description"
android:exported="false"/>
),我可以清楚地看到,即使关闭了该应用程序(唤醒次数在增加),该警报仍然有效,但由于该服务没有被调用是打开应用程序的时间。当我手动重新打开应用程序时,一切都可以正常工作。
我该如何解决这个问题?
答案 0 :(得分:0)
您应该阅读Doze and Standby如何影响装有Android 6.0及更高版本的设备上的警报。当电话进入打ze状态时,所有警报和后台作业都将停止,直到进入维护期为止。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);
}