5 Replies
      Latest reply on Nov 7, 2019 12:04 AM by eskimo
      AvaloqKent Level 1 Level 1 (0 points)

        When our iOS app authenticates with the server, a background thread is initialized using the

        beginBackgroundTaskWithExpirationHandler: interface.

        The intention is that when the user backgrounds our application while in an authenticated state, the

        background task will end the authentication session with the server after 3 minutes of not returning to the foreground.

         

         

        This design has been working well for us for years.  Until the iPhoneX arrived and a small handful of clients started to

        complain that their session was being dropped after shortly sending our app to the background and returning to the app within a

        short time.  Which means that our expirationHandler is being called after an unexpectedly short amount of time (usually 15 seconds).

         

         

        when entering the background, our task calls

        [UIApplication sharedApplication].backgroundTimeRemaining

        which we typically expect to return something like 170.

        on the iPhoneX it returns 1.797693134862316e+308

         

         

        Why is the expirationHandler being called after 15 seconds on iPhoneX hardware?

        How can I allow for more time in the background before the expirationHandler is called?

         

        Thanks,

         

        |K<

        • Re: BackgroundTaskWithExpirationHandler: thread too short?
          eskimo Apple Staff Apple Staff (12,305 points)

          Why is the expirationHandler being called after 15 seconds on iPhoneX hardware?

          I very much doubt this is correlated to the iPhone X hardware, but rather to the iOS version they’re running.  Last I checked (iOS 13.0b2), iOS 13 had dropped the from-the-foreground background task time to 30 seconds (see my UIApplication Background Task Notes).

          Anyway, my advice right now is to reanalyse the reports you’ve received to see if they’re correlated to a specific iOS version.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: BackgroundTaskWithExpirationHandler: thread too short?
              AvaloqKent Level 1 Level 1 (0 points)

              Hi Quinn,

               

              Thank you very much for your response.

              I too was very suspicious of the hardware correlation of this problem (reported to us by our clients and verified by us).

              We could however verify that on iOS 11 (which is what the iPhoneX shipped on, no?) the behaviour for the iPhoneX was different than on every other hardware.  And yes: the behaviour is different when the device is connected to a usb power supply.  The discrepency between the iPhoneX and the older devices remained through iOS12 an is still present in iOS13.  According to DTS, the beginBackgroundTaskWithExpirationHandler: API is not suitable for our use case.  At this point it is also unclear on what API would be appropriate for this.  Specifically i am trying to fulfil the following requirement:

               

              When the iOS application is sent to the background, a thread needs to survive for up to 180 seconds which can perform cleanup duties including close server sessions, clean disk caches of sensitive data, and clear cookies.

               

              Your advice is much appreciated,

               

              |K<

              Kent Clelland

              Avaloq Evolution

              Zürich, Switzerland

                • Re: BackgroundTaskWithExpirationHandler: thread too short?
                  eskimo Apple Staff Apple Staff (12,305 points)

                  iPhone X and later?  Or just iPhone X?

                  I don’t have easy access to an iPhone X to test on right now, but I do have an iPhone 11 (running iOS 13.3).  It exhibits the standard (on iOS 13 and later) 30 second background task time.  Specifically:

                  1. I wrote a small test project with this code wired up to a button.

                    NSLog("QQQ task will begin")
                    var task = UIBackgroundTaskIdentifier.invalid
                    task = UIApplication.shared.beginBackgroundTask {
                        NSLog("QQQ task did expire")
                        UIApplication.shared.endBackgroundTask(task)
                    }
                    NSLog("QQQ task did begin")

                    .

                  2. I ran it on the device from Xcode, just to install it.

                  3. I stopped it.

                  4. I ran it from the home screen.

                  5. I tapped the button and then pressed Home (well, swiped up).

                  6. I monitored the device’s system log using Console on the Mac.

                  Here’s what I saw:

                  … 23:14:06.753939 +0000 … QQQ task will begin
                  … 23:14:06.754779 +0000 … QQQ task did begin
                  … 23:14:34.739034 +0000 … QQQ task did expire

                  As you can see, the background task runs for (roughly) 30 seconds before it expires.

                  I repeated this test on my iPhone 6s Plus (running iOS 13.1.3) and saw the same results:

                  … 23:15:46.053642 +0000 … QQQ task will begin
                  … 23:15:46.054297 +0000 … QQQ task did begin
                  … 23:16:14.063030 +0000 … QQQ task did expire

                  Earlier you wrote:

                  when entering the background, our task calls [UIApplication sharedApplication].backgroundTimeRemainingwhich we typically expect to return something like 170. on the iPhoneX it returns 1.797693134862316e+308

                  That value is DBL_MAX, which is the value you get back when there’s no limit to the background task time available.  You typically see this when your app is in the foreground.

                  In general you shouldn’t pay to much heed to backgroundTimeRemaining, as I explained in UIApplication Background Task Notes.  If you’re basing your analysis on backgroundTimeRemaining, you should go back and retest as I’ve shown above.  In networking, the only way to know whether you can connect to a service is to try the connect; with background tasks, the only way to know how much time you’ll get is to actually use it.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: BackgroundTaskWithExpirationHandler: thread too short?
                      AvaloqKent Level 1 Level 1 (0 points)

                      Hi Quinn,

                      Thanks for your continued support,

                      What i am missing from your console log above is a log entry when the app is sent to the background, so although your task ran for 30 seconds it is unclear how much of that time was spent in the background.

                       

                      also I wonder:  does the main thread checker throw a false positive when calling backgroundTimeRemaining?

                      Main Thread Checker: UI API called on a background thread: -[UIApplication backgroundTimeRemaining]

                      PID: 1413, TID: 1709021, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0

                       

                      when calling backgroundTimeRemaining from the foreground it returns DBL_MAX, when calling it in the background the Main Thread Checker kicks in.  So, is this a false positive then?

                       

                      Also, how does an app like Music.app play music in the background?  Can I use the same mechanism to achieve my goals as well?

                      Thanks,

                       

                      |K<

                        • Re: BackgroundTaskWithExpirationHandler: thread too short?
                          eskimo Apple Staff Apple Staff (12,305 points)

                          What i am missing from your console log above is a log entry when the app is sent to the background, so although your task ran for 30 seconds it is unclear how much of that time was spent in the background.

                          Pretty much all of it.  I combined “tapped the button” and “pressed Home” in step 5 in an attempt to make that clear.  Feel free to try this for yourself, adding a log point to your -applicationDidEnterBackground method to confirm this behaviour.

                          does the main thread checker throw a false positive when calling backgroundTimeRemaining?

                          The general rule for UIKit is that the entire framework is main thread only unless otherwise documented.  The docs for backgroundTimeRemaining don’t mention thread safety, so I think it’s better to err on the side of caution and only call it from the main thread.

                          Having said that, my preferred option is to not call it at all (-:

                          Also, how does an app like Music.app play music in the background?

                          iOS has tight restrictions on background execution.  Some facilities, like UIApplication background tasks, are available to all apps.  Others require that your app declare support for a specific background mode.  For example, a third-party music player app [1] would use the audio background mode so that it can run indefinitely after moving to the background in order to continue playing music.

                          IMPORTANT App Review is particularly strict about use of these background modes.  To quote clause 2.5.4 of the App Store Review Guidelines:

                          Multitasking apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc. If your app uses location background mode, include a reminder that doing so may dramatically decrease battery life.

                          Share and Enjoy

                          Quinn “The Eskimo!”
                          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                          let myEmail = "eskimo" + "1" + "@apple.com"

                          [1] I’m deliberately not addressing the Music app because it’s built in to the OS and thus doesn’t have to follow the same rules as third-party apps.