2

I'm searching for a way to update the Live Activity every second or every 2 seconds without using Push Notifications while keeping the app in background.

Do you have any suggestions? I tried something like this, but after few seconds it's stop working:

       var bgTask = UIBackgroundTaskIdentifier(rawValue: 1324)
        bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
            UIApplication.shared.endBackgroundTask(bgTask)
        })
        let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(updateInfo), userInfo: nil, repeats: true)
        RunLoop.current.add(timer, forMode: .default)
Pietro Messineo
  • 777
  • 8
  • 28

3 Answers3

2

It seems like there is no way to update the Live Activity every single second or in any other too frequent manner. Looks like battery saving is crucial here and system cuts off the updates after a few seconds, even if the application is running in the background.

If you need to display a timer on the LiveActivity, according to the docs, it's possible to use the following initializer of Text which seems to be dedicated for that use case:

init(timerInterval: ClosedRange<Date>, pauseTime: Date? = nil, countsDown: Bool = true, showsHours: Bool = true)

For example:

Text(timerInterval: context.state.deliveryTimer, countsDown: true)

It creates an instance that displays a timer counting within the provided interval. It just counts time automatically so it's not necessary to think about implementing timer on your own. However, there is no way of listening when timer ends to update the activity so looks like it might be necessary to schedule a notification or background task anyway and receive/run and handle it when timer ends.

Seems like apps mentioned here use a mechanism I described above. You have to consider your use case and decide whether Live Activities are suitable for your app.

marcinax
  • 1,067
  • 7
  • 10
0

As mentioned in the documentation, "The delay between the time you schedule a background task and when the system launches your app to run the task can be many hours".

Unfortunately, background tasks are not suitable for your needs. Using Push notifications is the only way (that I know of at least) to achieve what you are trying to do.

Morniak
  • 958
  • 1
  • 12
  • 37
  • I found some apps that are offering for example CPU usage or FPS in dynamic island. They have a refresh of about 2 seconds. Testing the app looks like they send the update from the app it self because when I kill the app, the Live Activity (the dynamic island) stuck with the previous value and there is no fetch anymore. How d you think it works? – Pietro Messineo Nov 29 '22 at 17:31
  • By using a simple repeating `Timer` in the "main" app and calling the `Activity.update(using:alertConfiguration:)` method every time the timer is fired, you can update the live activity every second. BUT, as soon as the app is killed, this doesn't work anymore. If you need your activity to be updated even when the app is not running, the only solutions are remote notifications and background tasks. As mentioned in my reply, you can't be certain of when the task will be executed. It seem you are trying to achieve something that is outside of the scope of what Live Activities are made for. – Morniak Nov 30 '22 at 10:18
  • 1
    @Morniak The issue is, there are apps on the App Store that achieved the same functionality. This does not seem to be outside of the scope of Live Activities (and it should have been what it was made for in the first place). I got it working using Audio, PIP, AirPlay Background Task in Simulator, but it does not work on real device due to Swift Concurrency. The apps on the App Store have done it, then why can't we? There must be a way for this and we just need to figure it out. – Joonwoo Kim Nov 30 '22 at 16:03
  • 1
    If you know an app doing one refresh per second or so, even after it as been killed, I would be really interested if you could give me it's name. – Morniak Nov 30 '22 at 17:05
  • 1
    Apple specifically calls out "Update a Live Activity only when new content is available, alerting people only if it’s essential to get their attention." The fact that an unnamed app seems to have gotten around the rule at some point in time does not mean there is any supported way to do it. Folks have done tricky things to work around the rules for years (play silent audio forever is the classic), until Apple broke them or removed them from the store. What in Apple's docs suggest there's a supported mechanism? How do you know the app you're citing isn't using push notifications? – Rob Napier Dec 01 '22 at 02:14
  • 1
    For details see "Understanding constraints" in https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities – Rob Napier Dec 01 '22 at 02:15
0

You should carefully read the Discussion part of the beginBackgroundTask method:

The most important information in that secrion is that if you begin the task too late (like termination handler, didEnterBackground, etc.) it might not get registered appropriately.

My app updates the live activity even faster than once-per-second, it performs image processing in the background and it works. I start the background task as early as the work scheduled by the user begins, not before the app would enter background. Background tasks should be created pro-actively, not retro-actively.

iSpain17
  • 2,502
  • 3
  • 17
  • 26