2

I am stuck a point from days. Basically, i am developing an application which play some audios to guide user (user can not control these audios no play/pause) and with paying audios it also using accelerometer to get data and calculate some results from this data with regular interval. Means i am playing some audios and then start accelerometer about 4 times alternatively
Every thing is working as expected but when application enters into background application is kept alive for some time and the OS terminate/kill application.
Basically this whole flow take about 6 to 7 minutes at-least meaning that my application needed to alive in background mode at-least 7 minutes. I have seen stackOverFlow questions but not success.
What i am using when user start

self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {
            // End the task if time expires.
            UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
            self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
            
        }
        
        self.startForFirsPhase()

When first phase over I start second phase and third phase after end of previous

  • I have added Required background modes in info.plist
  • Background Process and Audio, AirePlay and Picture in Picture in the Signing & Capabilities

and code to play audios is blow

func play(name: String, volumeLevel: Float? = 1) {
    //        print("NameForAudio: ", name)
        guard let path = Bundle.main.path(forResource: name, ofType: nil) else {
            print("can not find path")
            return
        }
        let url = URL(fileURLWithPath: path)
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback)
            try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
            self.audioPlayer = try AVAudioPlayer(contentsOf: url)
            self.audioPlayer.volume = volumeLevel ?? 1
            self.audioPlayer!.play()
        } catch {
            print("some thing went wrong Name: \(error)")
        }
}

all the audios are liked with the accelerometer I play some audio after one an other using DispatchQueue.main.asyncAfter(deadline: .now() + durationOfPreviousAudio)

What i am trying to do is. I play some audios one after another then start accelerometer to get some motion sensor data for 1 minute and then i again want to play some audio after that which do not play without UIApplication.shared.beginBackgroundTask.

Sultan Ali
  • 2,497
  • 28
  • 25

2 Answers2

1

You don't need (and should not use) beginBackgroundTask for this. That is an hint to the system that you're beginning a short-lived task that, should the app go into the background before the task is ended, would benefit by getting a little extra time to complete. This is used for things like saving data to the file system or finishing a network operation.

"Background Process" is a completely different tool, used for long-running utility processes such as optimizing databases or running learning algorithms. You should not use that for this.

If you're playing background audio, then you must use the background audio mode. See the linked docs on how to configure this, and how to control background audio. (You have likely already checked the correct configuration box in Xcode, but you also need to make sure you've configured and activated an AVAudioSession that matches your use case. You likely want .playback and may want .mixWithOthers.) It generally needs to continuously play. You cannot easily start audio at an arbitrary time in the future, for example.

You likely will also benefit from enabling background location events.

There is no general-purpose "run in the background" tool in iOS. There are several specialized tools for solving specific problems, and you need to use ones that match your use case. Background operations are complex in iOS, and you'll want to read the documentation on each tool you use to see how to configure it and what it does and doesn't allow.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks for the reply, i applied your suggestion but it play audio and start accelerometer and when accelerometer end next audio is not played in the background mode and i also updated my question for playing the audio code – Sultan Ali Apr 19 '21 at 14:50
  • You're configuring your AVAudiosSession, but you never activate it. Also there is no reason to call `prepareToPlay` immediately before `play`. The only point of `prepareToPlay` is to get things ready sooner when you know you'll want to play later. – Rob Napier Apr 19 '21 at 16:09
  • i removed `prepareToPlay` and also updated the player as your description (please see updated question) but when screen is locked audios are not played. I means i used despatch queue and played an audio after 30 secods `DispatchQueue.main.asyncAfter(deadline: .now() + 30)` it do not played in the locked screen but when i open the lock and it play instantly – Sultan Ali Apr 19 '21 at 18:28
  • "It generally needs to continuously play. You cannot easily start audio at an arbitrary time in the future, for example." – Rob Napier Apr 19 '21 at 19:17
  • 1
    I'm not quite clear what you mean. You will need to redesign. It depends on exactly what your user-facing goal is. For example, if you want to play a piece of audio at a specific time, there are UNNotifications, but they impose other restrictions. If you want to play some audio continuously, then you can do that (as I recall, iOS will notice if you're playing silence, and treat that as "not playing" because people abused this). I don't believe there's a way to do what you've literally asked, so you'll need to go back to your underlying requirements and design something else. – Rob Napier Apr 22 '21 at 12:22
1

this whole flow take about 6 to 7 minutes at-least meaning that my application needed to alive in background mode at-least 7 minutes

You can’t do it. There is no iOS feature that permits an app to stay active in the background for 7 minutes to read the accelerometer. You need to change your spec to accommodate reality.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • how much exactly an app can run in background ? – Sultan Ali Apr 21 '21 at 05:15
  • About 30 seconds if you’re lucky. The other answer explains about continuing to play a single sound in the background, as an exceptional case. But your idea of staying alive long term to periodically read a sensor will not work. – matt Apr 21 '21 at 05:37
  • hmm... but i need a solution for it. Do, you have any suggestion how to resolve ? Thanks – Sultan Ali Apr 22 '21 at 11:33