AVAudioPlayer cannot play music with a NSTimer in background

自作多情 提交于 2020-01-23 03:59:25

问题


I want to play music with an AVAudioPlayer using an NSTimer, but [player prepareToPlay] returns NO & doesn't play in the background.

Can somebody give me some idea?

Here's my code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(playMusic:) userInfo:nil repeats:NO];
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)playMusic:(NSTimer *)timer{
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    NSString *fileName = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Apologize.mp3"];
    NSURL *fileUrl = [NSURL fileURLWithPath:fileName];
    NSError *error;
    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileUrl error:&error];
    if ([player prepareToPlay]) {
        [player play];
        NSLog(@"start!");
    }else{
        NSLog(@"error msg :%@",error);
    }
}

- (void)applicationDidEnterBackground:(UIApplication *)application {

    if ([[UIApplication sharedApplication] respondsToSelector:@selector(beginReceivingRemoteControlEvents)]){
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
    }

    UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    //        /* just fail if this happens. */
        [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
    }];
}

回答1:


You need to do this init in the viewDidLoad :

NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"test"
                                                          ofType:@"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL
                                                          error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];

This is for the audio initialization. Here, with a MP3 named test, imported in the project. Note that the beginReceivingRemoteControlEvents part is very important. Without it, you cannot start playing from background, just keep on listening to music already playing from foreground.

Now you need to listen to the event didEnterInBackGround (you could go with the applicationDidEnterBackground of your app delegate, but this way you can put the code in the class it belongs to):

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didEnterBG:)
                                             name:UIApplicationDidEnterBackgroundNotification
                                           object:nil];

And now in that didEnterBG method :

self.backgroundTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(backgroundWork) userInfo:nil repeats:YES];
[self.backgroundTimer fire];

Here i make this sound repeat every 10s for personal reasons, but do whatever you need. Finally, the backgroundWork method :

- (void)backgroundWork{
    [self.audioPlayer prepareToPlay];
    [self.audioPlayer play];
}

Now your audio file is playing in background :-)

You should also note that your app need to have specific rights to keep doing jobs in background. You need to check the box under 'YourTarget' -> Capabilities -> Background Modes : Audio and AirPlay. Otherwise, the OS will terminate you app in a few minutes in real conditions (with no debugger or instrument).




回答2:


before going to code. you need to tell the OS that you want permission to play music in background. you can do that by setting a Key in your app's info.plist

<key>UIBackgroundModes</key>
    <array>
            <string>audio</string>
    </array>

doing so, you will be able to play audio when app moves to background.




回答3:


I have the same issue, but I found the solution from this post: http://developer.apple.com/library/ios/#qa/qa1668/_index.html

#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>

AVAudioSession *audioSession = [AVAudioSession sharedInstance];

NSError *setCategoryError = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if (setCategoryError) { /* handle the error condition */ }

NSError *activationError = nil;
[audioSession setActive:YES error:&activationError];
if (activationError) { /* handle the error condition */ }


来源:https://stackoverflow.com/questions/7816166/avaudioplayer-cannot-play-music-with-a-nstimer-in-background

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!