How are some alarm apps such as Alarmy able to play a sound on iPhone when the app is in the background and the phone is on vibrate
Asked Answered
A

2

21

I am working on app that can alert users for some critical things. I use local notifications to alert the user. On iOS, I find that the notifications will not ring if the phone is on vibrate. This is a deal-breaker for many users of the app but I have been putting that question off till now since I thought that iOS doesn't allow an app to play a sound if the app is in the background.

Music apps are able to play songs even when the phone is on vibrate by enabling the audio background mode but it doesn't allow you to schedule a song to be played at a certain time.

Lately I have seen that some apps are able to play a sound at a certain time even though the app is in the background. One such app is Alarmy alarm app. I don't think that they are playing the music via the local notification when the alarm expires because the music continues to play even after I clear the notification. From the local notification documentation, I understood that I am can't run any code when local notification fires till the user clicks on the notification. So, I can't start an audio player which may be able to play the sound in vibrate.

How are such apps able to play a sound even though the phone is on vibate and the app is in background in iOS?

Araiza answered 1/6, 2018 at 13:52 Comment(1)
may be this link will help something : #24145886Pheasant
C
13

There are few methods to implement this kind of functionality.For reference I recommend this link.

For actually playing the sound while the device’s ringer switch is set to vibrate

First off make sure to include the audio background mode in the capabilities, in order to play audio in the background.

Then,

Swift 4

do {
  try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with: [.duckOthers, .defaultToSpeaker])
  try AVAudioSession.sharedInstance().setActive(true)
  UIApplication.shared.beginReceivingRemoteControlEvents()
} catch {
  NSLog("Audio Session error: \(error)")
}

Here we set the shared audio session’s category to AVAudioSessionCategoryPlayAndRecord, so that we can play sound, while the device’s ringer switch is set to vibrate.

The .duckOthers is specified to make other audio quieter, if there’s any mixable audio playing, so that our alarm can be heard. You can leave that out or use another option, if you prefer a different behavior.

The .defaultToSpeaker is specified, so that the volume would go to the speaker, where it’ll be much louder and should wake up our user with ease.

beginReceivingRemoteControlEvents makes it so that the app handles the remote control options, like the play/pause buttons on the lock screen, in order to make it easier for our user to mute their alarm, once they wake up.

Cadelle answered 6/6, 2018 at 12:36 Comment(10)
How do I schedule the music to start at a specific time while the app is in the background? The link suggests to disable multi-tasking mode for the app which is not desired.Araiza
@VarunGupta, your initial question "How are some alarm apps such as Alarmy able to play a sound on iPhone when the app is in the background and the phone is on vibrate" doesn't require this answer. Create a separate one for this.Cadelle
If you read the question, you will find this is one of the things I am looking for in the answer. I also mentioned it in the "What are you looking for section in the bounty" as "I am looking for a way to be able to play a sound at a certain point of time in iOS." But I got your point that I need to be more careful in writing the title of the section also.Araiza
@VarunGupta, ok, sorry, I didn't notice the bounty description at first, but still it would be nice if you will edit you question and include all the questions as a numbered list. It will help people to understand you better. I will take a look on this.Cadelle
@VarunGupta, github.com/natsu1211/Alarm-ios-swift - take a look on this Repo. This is an alarm clock clone, maybe it will help you. And I wanted to ask , "The link suggests to disable multi-tasking mode for the app which is not desired." - why it is not desired?Cadelle
Thanks @T.Pasichnyk. I will take a look at the repo. The reason why disabling multi-tasking mode is not desired is because as soon as user puts the app in the background, the app will be stopped completely and none of the alarms will ring.Araiza
@VarunGupta, I think it will work a bit different if you add the audio background mode in the capabilities, in order to play audio in the background. I assume you to read developer.apple.com/library/archive/documentation/iPhone/… As I understand this, you will still be able to play sound when you enable this capability in project settings, even with disabled multi-tasking. But I am not completely sure, please correct me, if you find the info on this somewhere.Cadelle
@VarunGupta were you able to figure out the solution for this question "I am looking for a way to be able to play a sound at a certain point of time in iOS?"Stingy
@NimeshChandramaniya if you are looking to play a sound at a certain point of time in iOS, you can just schedule a notification in that case. The sound file must be less than 30 seconds in that case. Another way of doing it is to play a silent sound in the background indefinitely such that you app is always running. This works but it consumes a lot of battery. So, I didn't go this route.Araiza
Using a push notification to launch the app in the background and play some audio using the audio background mode seems to be the case in Alarmy, except one thing I couldn't understand: If you set the device to airplane mode, then set a new alarm, and background the app (not terminating it) - a local notification pops up, but then the audio keeps playing even after you dismiss the local notification. This can't be due to a push notification arriving... so how are they doing this? Any ideas? Is it playing silence in the background? Would appreciate any thoughts.Wayside
W
7

The way this can be done (I have implemented this in my app) is by starting an AVAudioPlayer and specifying a specific time to play. So:

  1. Enable background audio in the app capabilities.

  2. Start and audio session with .playback mode, and start a player at the time you like it to play:

    do {
          //set up audio session
          try AVAudioSession.sharedInstance().setCategory(.playback, options: [.defaultToSpeaker, .duckOthers])
          try AVAudioSession.sharedInstance().setActive(true)
    
          //Start AVAudioPlayer
          player.play(at: time) //time is a TimeInterval after which the audio will start
        }
        catch {
        ...
        }
    

This does not play silence in the background, which violates Apple's rules. It actually starts the player, but the audio will only start at the right time. I think this is probably how Alarmy implemented their alarm, given that it's not a remote notification that triggers the audio nor is the audio played by a local notification (as its not limited to 30 seconds or silenced by the ringer switch).

Wayside answered 30/8, 2019 at 10:0 Comment(4)
This is a great set up. How were you able to get an audio to play when the phone is in background mode?Junejuneau
Exactly like its written above. Add background audio in the app capabilities. Then just start a AVAudioPlayer, and it will keep playing when the app is backgrounded.Wayside
Everyone please note, you must either enable .mixWithOthers or .duckOthers (which automatically enables .mixWithOthers too), or else if you open up another app that has audio, it will deactivate your background app's audio session. Enabling this option ensures it will still play (I.e. so that it can "mix with others").Foyer
I dont now if this was different with older switf versions but player.play as the parameter atTime and not at, which specifies at which second of the audio file it should begin playing, it doesn't answer the question of how to start playing the audio on a scheduled date/time.Tambac

© 2022 - 2024 — McMap. All rights reserved.