Live Activity is starting app in the background while device is locked

Our team has recently added support to our app for Live Activities where the source of the data is driven from the app itself (not push notifications).

We've noticed a crash happening in our core data code caused by the following error thrown by the addPersistentStore function where it would attempt to recover and eventually crash. Here's an error we created to help us debug that contains the error details:

Domain: CoreData Code: 1 NSLocalizedDescription: Error performing migration for databaseName=mydb.sqlite. Error details=The file couldn’t be saved because you don’t have permission. - userinfo: ["reason": No permissions to create file; code = 1]

After some trouble shooting, we managed to reproduce the issue by doing a hard reboot while we're running a live activity. It appears that when the device starts back up, the Live Activity starts which triggers the app to hit didFinishLaunchingWithOptions which is where we get our Core Data store initialized.

The problem is that our app uses Data Protection using NSFileProtectionCompleteUntilFirstUserAuthentication and we'd prefer to keep it that way.

The Core Data db is present in the app sandbox and we're also seeing logs to suggest a failure trying to access NSUserDefaults as well.

Is there an accepted solution for this? Is it expected that a Live Activity would cause an application to launch prior to the device being unlocked for the first time? Is there a way to change that?

Answered by ForumsContributor in

Our engineering teams need to investigate this issue, as resolution may involve changes to Apple's software. I'd greatly appreciate it if you could open a bug report, include any relevant info and post the FB number here once you do. Bug Reporting: How and Why? has tips on creating your bug report.

I have confirmed this behavior is a bug.

Rico WWDR - DTS - Software Engineer

Is it expected that a Live Activity would cause an application to launch prior to the device being unlocked for the first time?

That's a very tricky question to answer... The problem here is that we've never formally documented what "should" be happening here, so there isn't actually an "official" answer. The broad behavior is that, outside of a few specific components (for example, voip apps and Notification Service Extensions), it "tries to avoid" launching anything prior to first unlock. However, I've seen many cases and exceptions to this going in both directions (launching things it "shouldn't" AND failing to launch things it "should").

Is there a way to change that?

If you haven't already, please file a bug on this and post the bug number here. I could make any argument on either side of what we "should" do, but no matter what the expected behavior should be documented. However, there's nothing your app can do to change the behavior here. That leads to here...,

Is there an accepted solution for this?

My basic advice for all data protection problems is the same:

  • Detect the problem as early as possibile and fail/behave in a way that protects your users data and your apps ability of function. For many app, that can simply mean detecting the issue by checking your ability to access a dedicated "check" file, notifying the user of the issue, and then stopping any further action until something changes.

  • Don't try to fix/change ANY of these issues unless you're in the foreground. In nearly every case I've looked at, the actual damage was caused by the app trying to modify/"fix" things, NOT the immediate failure.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

FB14562763

Thanks for looking into it!

  • Detect the problem as early as possibile and fail/behave in a way that protects your users data and your apps ability of function. For many app, that can simply mean detecting the issue by checking your ability to access a dedicated "check" file, notifying the user of the issue, and then stopping any further action until something changes.

  • Don't try to fix/change ANY of these issues unless you're in the foreground. In nearly every case I've looked at, the actual damage was caused by the app trying to modify/"fix" things, NOT the immediate failure.

Thanks for the suggestion, in our case the crash is due to our recovery solution, like you mentioned but we're having trouble coming up with a proper fix. Our app relies various services that depend on the file system to operate and we wouldn't want the app to launch without being able to access that information.

Due to our usage of the Data protection access level NSFileProtectionCompleteUntilFirstUserAuthentication any access to our entire app sandbox is inaccessible and forces the application to exhibit untestable and bad user experiences. In some cases we're seeing users be logged out due to us being unable to access auth tokens.

Couple of questions:

  • Are there other scenarios that may exist where our app could be launched without being user-initiated?
  • Would our issue be better suited for a code-level support ticket since it appears that the issue might be easier to discuss with more context?

I'm afraid my response is a bit late here...

Are there other scenarios that may exist where our app could be launched without being user-initiated?

Yes.
Over time we've added more and more APIs that can launch an app into the background. Prewarming also means that an app can end up being woken in the background without previously entering the foreground. At this point, I don't think an app can really assume it will "only" be launched into the foreground, nor do I think trying to predict and individually "handle" all of the background possibilities is really practical. The better approach is to be prepared that it might happen and adjust your apps behavior accordingly.

Due to our usage of the Data protection access level NSFileProtectionCompleteUntilFirstUserAuthentication any access to our entire app sandbox is inaccessible and forces the application to exhibit untestable and bad user experiences

First off, make sure that this is REALLY the issue. It may very well be the case here (I havne't checked), but I've had seen many cases where a developer thought the issue was caused by the device protection state (like running prior to first unlock) when the actual issue was that some data was being stored at the wrong protection level (complete).

However, if you're app cannot operate prior to first unlock and you're being launched prior to first unlock, then you only have two options:

  1. Block your apps "normal" operation until the device unlocks and you're able to access your data.
  2. Call exit() (or abort) to prevent further problems/harm.

In either case, you'd also want to "tell" the user what's going on (update your activity UI, post a notification, etc.) so that they can take action to resolve the issue.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Live Activity is starting app in the background while device is locked
 
 
Q