AVAudioPlayer is not playing in Background when iPhone is locked - ios

Actually i fetching the songs from Documents Directory.
I referred this Link:- http://www.raywenderlich.com/29948/backgrounding-for-ios , But it will play the songs from bundle only. but i want to play the songs from documents Directory.
I tried
Background modes in the Plist
Application Does not in background = No in Plist
In Appdelegate didFinishLaunchingWithOptions:-
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
PlayMethod()
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:saveFileName];
NSURL *url1 = [[NSURL alloc] initFileURLWithPath: path];
self.audioPlayer=[[AVAudioPlayer alloc] initWithContentsOfURL:url1 error:NULL];
[self.audioPlayer play];
self.seekBarSlider.minimumValue = 0.0f;
self.seekBarSlider.maximumValue = self.audioPlayer.duration;
//[self updateTime];
self.isPlaying=YES;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
_audioPlayer.delegate=self;
NSError *error;
UIBackgroundTaskIdentifier bgTaskId = 0;
if (_audioPlayer == nil)
NSLog([error description]);
else{
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
[_audioPlayer prepareToPlay];
if([_audioPlayer play]){
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
if (newTaskId != UIBackgroundTaskInvalid && bgTaskId != UIBackgroundTaskInvalid)
[[UIApplication sharedApplication] endBackgroundTask: bgTaskId];
bgTaskId = newTaskId;
}
}
DATA PROTECTION:
Under the Xcode -> capabilities .
All I tried But not working!. Can anyone help me.

Does it work in the background when your device is unlocked?
If so, it sounds like a permissions issue. If you have enabled data-protection for your app at developer.apple.com. Whilst the device is locked with a passcode you will not be able to read the documents directory because the files are encrypted.
We got stuck trying to write to a database whilst the device was locked. Wasted a good two days to figure that one out.
W
Edit - Also may find the setting in Xcode under capabilities

I used Data Protection mechanism and particularly before I am going to write the NSDATA into Documents directory. I need to set the Protection None to particular file path. So I used NSProtectionNone Property for the file path. If we won't set the ProtentionNone property the Apple won't allow to access the file on Locked State.
NSDictionary *protection = [NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey];
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:_path error:nil];
if( [_rawData writeToFile:_path atomically:YES])
{
NSLog(#"HOpefully written into Documentz directory..");
}
else
{
NSLog(#"Writting file mechanism - Failed!");
}
And I used to play the Dummy audio file in infinite loop from App Bundle. so the dummy audio file is playing continuously using AVFoundation Framework. So I can able to access the Documents directory audio files continuously. one by one.

If you set the UIBackgroundModes key in you app's Info.plist to audio, audio will keep playing while backgrounded.
audio : The app plays audible content in the background.
More on UIBackgroundModes keys check here

Are there other audio/video apps currently running on your device? Some of them that also use AVAudioSessionCategoryPlayback can interrupt your audio session.
How it is said on Apple Developer:
By default, using this category implies that your app’s audio is nonmixable—activating your session will interrupt any other audio sessions which are also nonmixable. To allow mixing for this category, use the AVAudioSessionCategoryOptionMixWithOthers option.

Related

Why does the volume of my sound go down?

I have a voip app and for an incoming call I redirect to a separate view where the user can accept or reject the call. I want a sound to be played while in this view, so I load a sound file:
NSString *ringtoneSoundPath = [[NSBundle mainBundle] pathForResource:#"ringtone" ofType:#"wav"];
NSURL *ringtoneSoundUrl = [NSURL fileURLWithPath:ringtoneSoundPath];
ringtone = [[AVAudioPlayer alloc] initWithContentsOfURL:ringtoneSoundUrl error:nil];
ringtone.numberOfLoops = -1;
and then in the viewcontroller where I want the sound to be played I have these methods:
- (void)viewWillAppear:(BOOL)animated {
[ringtone play];
}
- (void)viewWillDisappear:(BOOL)animated {
[ringtone stop];
}
This works, but when the call is finished and I call a second time the volume of the sound is suddenly very low. I checked the device's volume settings, but it's still at max. Why does the volume go down when stopping the sound and then playing it again? It doesn't repeat, so the third time, it's just as low as the second time.
We had the similar issue. If you have voip app it means that you use setCategory: in AVAudioSession.
So, you have the code like:
AVAudioSession *aSession = [AVAudioSession sharedInstance];
if ([aSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]) {
[aSession setMode:AVAudioSessionModeVoiceChat error:nil];
[aSession setActive: YES error:nil];
}
But when you use AVAudioSessionCategoryPlayAndRecord the volume becomes low.
So, before rington play you should set e.g.:
if ([aSession setCategory:AVAudioSessionCategoryPlayback error:nil]) {
[aSession setMode:AVAudioSessionModeDefault error:nil];
[aSession setActive:YES error:nil];
}
Hope this helps

Audio playing while app in background iOS

I have an app mostly based around Core Bluetooth.
When something specific happens, the app is woken up using Core Bluetooth background modes and it fires off an alarm, however I can't get the alarm working when the app is not in the foreground.
I have an Alarm Singleton class which initialises AVAudioPlayer like this:
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:soundName
ofType:#"caf"]];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[self.player prepareToPlay];
self.player.numberOfLoops = -1;
[self.player setVolume:1.0];
NSLog(#"%#", self.player);
This is the method that is called when my alarm code is called:
-(void)startAlert
{
NSLog(#"%s", __FUNCTION__);
playing = YES;
[self.player play];
NSLog(#"%i", self.player.playing);
if (vibrate) {
[self vibratePattern];
}
}
Now when the app is in the foreground, self.player.playing returns 1 however when the app is in the background self.player.playing returns 0. Why would this be?
All the code is being called, so the app is awake and functioning.
The vibrate works perfectly which uses AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
Any idea why this sound won't play?
Thanks
Apple has a nice Technical Q&A article about this in its documentation (see also Playing and Recording Background Audio).
I think one big thing missing is that you haven't activated the Audio Background Mode in the Xcode settings:
Maybe also adding [self.player prepareToPlay] in your alert method is helpful.
I have an App than also needs background audio but my App works with the App background mode "Voice over IP" as it needs to record sometimes. I play background audio telling the App singleton I need to play audio in background:
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
if([thePlayer play]){
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
EDIT: You must call [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL]; before your app goes to background. In my app, it is at the same time you start playing, in yours, if the player might be started in background, you should do:
- (void)applicationDidEnterBackground:(UIApplication *)application{
// You should retain newTaskId to check for background tasks and finish them
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
Apple docs
Either enable audio support from the Background modes section of the Capabilities tab
Or enable this support by including the UIBackgroundModes key with the audio value in your app’s Info.plist file
I take it you have the audio background mode specified for the app. Even so, I'm not sure you can set an audio session to be active while in the background. You need to have activated it before going into the background. You may also need to play some silent audio to keep this active, but this is seems like bad practice (it may drain the battery). Looking at the docs for notifications there seems to be a way to have a local notification play an audio sample that's included in your bundle, which seems to be what you want to do, so maybe that's the way to go.
Try this :
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
link
Try this http://www.sagorin.org/ios-playing-audio-in-background-audio/
You need to enable your app to handle audiosession interruptions (and ended interruptions) while in the background. Apps handle audio interruptions through notification center:
First, register your app with the notification center:
- (void) registerForMediaPlayerNotifications {
[notificationCenter addObserver : self
selector: #selector (handle_iPodLibraryChanged:)
name: MPMediaLibraryDidChangeNotification
object: musicPlayer];
[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications];
}
Now save player state when interruption begins:
- (void) audioPlayerBeginInterruption: player {
NSLog (#"Interrupted. The system has paused audio playback.");
if (playing) {
playing = NO;
interruptedOnPlayback = YES;
}
}
And reactivate audio session and resume playback when interruption ends:
-(void) audioPlayerEndInterruption: player {
NSLog (#"Interruption ended. Resuming audio playback.");
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (interruptedOnPlayback) {
[appSoundPlayer prepareToPlay];
[appSoundPlayer play];
playing = YES;
interruptedOnPlayback = NO;
}
}
Here's Apple's sample code with full implementation of what you're trying to achieve:
https://developer.apple.com/library/ios/samplecode/AddMusic/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008845
I was also facing the same problem, but i was only facing it only during initial time when i was trying to play a sound while app was in background, once the app comes in foreground and i play the sound once than it works in background also.
So as soon as app is launched/ login is successful in my case, i was running this code:
[self startRingcall];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self stopRingcall];
});
- (void)startRingcall
{
if( self.audioPlayer )
[self.audioPlayer stop];
NSURL* musicFile = [NSURL fileURLWithPath:[[[UILayer sharedInstance] getResourceBundle] pathForResource:#"meetcalling" ofType:#"caf"]];
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:&error];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (error != nil) {
NSLog(#"meetringer sound error -> %#",error.localizedDescription);
}
self.audioPlayer.volume = 0;
[self.audioPlayer play];
self.audioPlayer.numberOfLoops = 1;
}
- (void)stopRingcall
{
if( self.audioPlayer )
[self.audioPlayer stop];
self.audioPlayer = nil;
}

iOS - Unable to play a sound in background

I'm currently trying to implement a system like the alarm one to alert the phone when an event occurred (in my case a bluetooth event). I want this alert to occur even if the phone is in silent and in background.
I create a local notification but i can't get sound played if the phone is in silent mode (which seems to be normal since we put the phone in silent).
So i tried to manage the sound by myself and i'm struggling with playing sound in background. So far i implement the "App plays audio or streams audio/video using AirPlay" key in my plist and i'm using this code.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
BOOL result = [audioSession setActive:YES error:&error];
if ( ! result && error) {
NSLog(#"Error For AudioSession Activation: %#", error);
}
error = nil;
result = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
if ( ! result && error) {
NSLog(#"Error For AudioSession Category: %#", error);
}
if (player == nil) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"bell" ofType:#"wav"];
NSURL *url = [NSURL fileURLWithPath:path];
NSError *err = nil;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err];
if(err)
{
NSLog(#"Error Player == %#", err);
}
else {
NSLog(#"Play ready");
}
}
[player prepareToPlay];
[player setVolume:1.0];
if([player play])
{
NSLog(#"YAY sound");
}
else {
NSLog(#"Error sound");
}
The sound works great in foreground, even in silent mode, but i got no sound at all in background. Any ideas ?
Thanks
EDIT:
Finally i got it working with the above code. The only missing point is that i was trying to play the sound in somewhat appeared to be a different thread, when i play it right in my bluetooth event and not my function call it's working.
An app that plays audio continuously (even while the app is running in the background) can register as a background audio app by including the UIBackgroundModes key (with the value audio) in its Info.plist file. Apps that include this key must play audible content to the user while in the background.
Apple reference "Playing Background Audio"
Ensuring That Audio Continues When the Screen Locks
Found here
I'm not sure if your problem is that you have not configure correctly the audio session output. I had similar problem while playing .wav in my app. I only listened them with earphones. This method helped me:
- (void) configureAVAudioSession {
//get your app's audioSession singleton object
AVAudioSession *session = [AVAudioSession sharedInstance];
//error handling
BOOL success;
NSError* error;
//set the audioSession category.
//Needs to be Record or PlayAndRecord to use audioRouteOverride:
success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
error:&error];
if (!success) NSLog(#"AVAudioSession error setting category:%#",error);
//set the audioSession override
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
if (!success) NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
//activate the audio session
success = [session setActive:YES error:&error];
if (!success) NSLog(#"AVAudioSession error activating: %#",error);
else NSLog(#"audioSession active"); }
Try it out!
You need to make couple of changes in plist file.
for enabling sound when the app enter's Background.
1) Set Required background mode to App plays audio
2) set Application does not run in background to YES.
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Then, you need to write these much code in AppDelegate
Now, you can easily run audio while phone screen locks or in background.
It works fine for me. :)
for more please refer to Playing Audio in background mode and Audio Session Programming Guide

Can't play sound when app is in background mode

In Info.plist I added:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>location</string>
</array>
...
I load the sound like this:
NSURL *urlFail = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/criticalSound.wav", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:urlFail error:&error];
[audioPlayer setDelegate:self];
audioPlayer.numberOfLoops = 0;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[audioPlayer setVolume:1.0];
if (audioPlayer == nil){
}else{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
if (musicPlayer.playbackState == MPMusicPlaybackStatePlaying)
{
self.wasMusicAppOn = YES;
[musicPlayer pause];
}else{
self.wasMusicAppOn = NO;
}
[audioPlayer play];
}
This works fine when app is active.
But I have a location update when application is in background and from time to time (like when user pass 500m) I should play this sound.
So I put this code there.
Anyway problem is that sound plays when app is in foreground but doesn't work when it is in background.
What am I doing wrong here?
As far as I've been able to tell, you must actually be playing sound while going into the background to be able to continue playing sound in the background.
Also, the description for AVAudioSessionCategoryAmbient states that "Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone)".
You need to make couple of changes in plist file.
1) Set Required background mode to App plays audio
2) set Application does not run in background to YES.
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
Then, you need to write these much code in AppDelegate
Now, you can easily run audio while phone screen locks or in background.
It works fine for me. :)
for more please refer to Playing Audio in background mode and Audio Session Programming Guide

AVAudioPlayer background task is not working on iOS 5.0.1 device but it is working on iOS 5 Simulator

I am doing sample application that play a song and that song will still playing even the application goes background.
In iOS 5 xcode simulator, it still play the song when app goes to background but when I run on iOS 5.0.1 iPad2 device, app stop playing sound when it goes to background.
The following are the code to play a song and do background task. Do you face this kind of issue in iOS 5.0.1? or am I missing something in code? But I am wondering how it is working in simulator?
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url=[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"01-Track" ofType:#"mp3"]];
NSError *error;
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
if(error)
{
NSLog(#"Error in audio palyer: %#", [error localizedDescription]);
}
else
{
audioPlayer.delegate =self;
[audioPlayer prepareToPlay];
trackControl.maximumValue=[audioPlayer duration];
trackControl.value=0.0;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
}
}
-(IBAction)playAudio:(id)sender
{
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
if([audioPlayer play]){
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
Thanks!
For audio to continue working in background you should add a key called Required Background
Modes in your info.plist with value App plays audio.But it's use is not very much promoted by apple unless it's absolutely necessary.

Resources