简体   繁体   English

Android前台服务通知延迟

[英]Android Foreground Service Notification Delayed

I've run into a peculiar issue with the app I am building (compile/target SDK 31, min SDK 24).我正在构建的应用程序遇到了一个特殊问题(编译/目标 SDK 31,最小 SDK 24)。 I have a timer service that needs to run if the app/activity is no longer in the foreground.如果应用程序/活动不再在前台,我有一个需要运行的计时器服务。 On the onPause of my activity I launch my service as such:在我的活动的 onPause 上,我启动了我的服务:

Intent serviceIntent = new Intent(activity, TimerService.class);
startService(serviceIntent);

The service launches perfectly fine as when I observe the console logs it is doing the proper calculations for calculating the remaining time.该服务启动得非常好,因为当我观察控制台日志时,它正在为计算剩余时间进行正确的计算。

The problem I have run into is that when the app first launches, or strangely enough if it has been idle for say 5+ minutes (usually idle in the background while I use other apps), when I first launch the service the first notification is delayed by upwards of 15 seconds.我遇到的问题是,当应用程序首次启动时,或者奇怪的是,如果它已经空闲了 5 分钟以上(通常在我使用其他应用程序时在后台空闲),当我第一次启动服务时,第一个通知是延迟 15 秒以上。 Since the service is indeed running, it's as if all the notification requests in those 15 seconds are being ignored by the phone because the first notification that appears will start at the right time (eg 45 seconds remaining if the timer is set to 1 minute).由于服务确实在运行,就好像这 15 秒内的所有通知请求都被手机忽略了,因为出现的第一个通知将在正确的时间开始(例如,如果计时器设置为 1 分钟,则剩余 45 秒) .

The service looks like this:该服务如下所示:

    public static final int timerRunningId = 1;

    private Timer timer;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        startForeground(timerRunningId, timerRunningNotification("Timer starting..."));
        super.onCreate();
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // timer logic, ignored for brevity but it would be calculate the timestamp needed for method below
                Notification notification = timerRunningNotification("dummyTimestamp");
                updateNotification(displayTime);
            }
        }, 0, 500);
        return START_REDELIVER_INTENT;
    }

    private void updateNotification(Notification notification ) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(timerRunningId, notification);
    }

    private Notification timerRunningNotification(String content) {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this,
                65, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
        return new NotificationCompat.Builder(this, Variables.TIMER_RUNNING_CHANNEL) // note i define this in my MainActivity according to the docs
                .setContentTitle("Timer")
                .setContentText(content)
                .setSmallIcon(R.drawable.notification_icon)
                .setSound(null)
                .setContentIntent(contentIntent)
                .setOnlyAlertOnce(true)
                .build();
    }

It was my understanding that the service would start in the onCreate() and initialize a notification with id=1 saying "Timer starting" and would immediately get replaced by the counting down timer notifications since the updateNotification method updates to the same id=1.据我了解,该服务将在 onCreate() 中启动并初始化一个 id=1 的通知,说“定时器正在启动”,并且由于 updateNotification 方法更新为相同的 id=1,它将立即被倒计时定时器通知所取代。

Since this bug only happens if the app first launched or has been idle for a while, I am having a hard time debugging what could be wrong.由于此错误仅在应用程序首次启动或闲置一段时间时才会发生,因此我很难调试可能出现的问题。 After the bug occurs I can use the timer perfectly and the moment the service starts the notification shows properly.错误发生后,我可以完美地使用计时器,并且在服务启动的那一刻,通知会正确显示。

Anyone have any ideas as to what is happening?有人对正在发生的事情有任何想法吗? I wrote the code for this nearly two years ago so it's possible there is a better way of launching notifications, but from what I saw in the docs my updateNotification method should be valid.我在将近两年前为此编写了代码,因此可能有更好的方法来启动通知,但从我在文档中看到的内容来看,我的 updateNotification 方法应该是有效的。

The device I am testing this on is running Android 12, so I'm also curious if maybe it is only specific to certain devices (I don't ever remember seeing this bug in my version I released two years ago before Android 12)我正在测试它的设备正在运行 Android 12,所以我也很好奇它是否只特定于某些设备(我不记得在我两年前在 Android 12 之前发布的版本中看到过这个错误)

Add the method to NotificationCompat.Builder:将方法添加到 NotificationCompat.Builder:

new NotificationCompat.Builder(...)
                .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)

From docs :来自文档

Devices that run Android 12 (API level 31) or higher provide a streamlined experience for short-running foreground services.运行 Android 12(API 级别 31)或更高版本的设备可为短期运行的前台服务提供简化的体验。 On these devices, the system waits 10 seconds before showing the notification associated with a foreground service.在这些设备上,系统会等待 10 秒,然后才会显示与前台服务关联的通知。 There are a few exceptions;有几个例外; several types of services always display a notification immediately.几种类型的服务总是立即显示通知。

If a foreground service has at least one of the following characteristics, the system shows the associated notification immediately after the service starts, even on devices that run Android 12 or higher:如果前台服务至少具有以下特征之一,则系统会在服务启动后立即显示相关通知,即使在运行 Android 12 或更高版本的设备上也是如此:

  • The service is associated with a notification that includes action buttons.该服务与包含操作按钮的通知相关联。
  • The service has a foregroundServiceType of mediaPlayback, mediaProjection, or phoneCall.该服务具有 mediaPlayback、mediaProjection 或 phoneCall 的foregroundServiceType。
  • The service provides a use case related to phone calls, navigation, or media playback, as defined in the notification's category attribute.该服务提供与电话呼叫、导航或媒体播放相关的用例,如通知的类别属性中所定义。
  • The service has opted out of the behavior change by passing FOREGROUND_SERVICE_IMMEDIATE into setForegroundServiceBehavior() when setting up the notification.在设置通知时,该服务已通过将 FOREGROUND_SERVICE_IMMEDIATE 传递给 setForegroundServiceBehavior() 来选择退出行为更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM