iOS背景音频无法播放

时间:2014-03-23 13:18:32

标签: ios objective-c audio avfoundation avaudioplayer

我有一个使用CoreBluetooth背景模式的应用。当某个事件发生时,我需要发出警报声。一切都在前台工作正常,所有蓝牙功能在后台工作正常。我也让它工作在后台安排UILocalNotification来发出警报,但是我不喜欢这些音量控制不足,所以想要使用AVAudioPlayer播放闹钟声音

我已将背景模式audio添加到我的.plist文件中,但无法正常播放声音。

我使用单例类进行闹钟并初始化声音如下:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                    pathForResource:soundName
                                    ofType:@"caf"]];

player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
player.numberOfLoops = -1;
[player setVolume:1.0];

我开始这样的声音:

-(void)startAlert
{
    playing = YES;
    [player play];
    if (vibrate)
        [self vibratePattern];
}

并将其用于振动:

-(void)vibratePattern
{
    if (vibrate && playing) {
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        [self performSelector:@selector(vibratePattern) withObject:nil afterDelay:0.75];
    }
}

振动在背景中工作正常,但没有声音。 如果我使用Systemsound播放这样的声音,它可以正常播放(但没有音量控制):

AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &_sound);
AudioServicesPlaySystemSound(_sound);

那么AVAudioPlayer没有播放声音文件的原因是什么呢?

由于

编辑-------

当应用程序背景时,声音将播放。然而,在背景下开始播放是行不通的。

5 个答案:

答案 0 :(得分:15)

在属性列表(.plist)文件中添加名为必需的背景模式的密钥..

如下图..

enter image description here 你能得到帮助吗?

并在

中添加以下代码

AppDelegate.h

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

AppDelegate.m

在应用程序didFinishLaunchingWithOptions

[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

UInt32 size = sizeof(CFStringRef);
CFStringRef route;
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route);
NSLog(@"route = %@", route);

如果您想根据事件进行更改,则必须在AppDelegate.m中添加以下代码

- (void)remoteControlReceivedWithEvent:(UIEvent *)theEvent {

    if (theEvent.type == UIEventTypeRemoteControl)  {
        switch(theEvent.subtype)        {
            case UIEventSubtypeRemoteControlPlay:
                [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil];
                break;
            case UIEventSubtypeRemoteControlPause:
                [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil];
                break;
            case UIEventSubtypeRemoteControlStop:
                break;
            case UIEventSubtypeRemoteControlTogglePlayPause:
                [[NSNotificationCenter defaultCenter] postNotificationName:@"TogglePlayPause" object:nil];
                break;
            default:
                return;
        }
    }
}
基于通知的

必须对其进行处理..

code.tutsplus.com提供tutorial

对于HandsetBluetooth,你必须在AppDelegate中添加以下代码

UInt32 size = sizeof(CFStringRef);
    CFStringRef route;
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &route);
    NSLog(@"route = %@", route);
    NSString *routeString=[NSString stringWithFormat:@"%@",route];
    if([routeString isEqualToString:@"HeadsetBT"]){
        UInt32 allowBluetoothInput = 1;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,sizeof (allowBluetoothInput),&allowBluetoothInput);
    }

答案 1 :(得分:8)

plist设置外,您还必须修改app delegate。

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}

同样在controller中写下以下代码。

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

答案 2 :(得分:3)

也许您应该让应用的音频会话比其他人更高。

除了设置后台模式的过程外,您还必须正确设置AudioSession。

有时这样做是不够的

[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];

因为在帮助文档中有关于setActive

的讨论
Discussion
If another active audio session has higher priority than yours (for example, a phone call), and neither audio session allows mixing, attempting to activate your audio session fails. Deactivating your session will fail if any associated audio objects (such as queues, converters, players, or recorders) are currently running.

所以,setActive:withOptions:error:是必需的。就像这样

[audioSession setCategory :AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error]  

那就是你必须让你的应用程序的音频会话高于其他人。

答案 3 :(得分:1)

默认情况下,AVAudioPlayer使用AVAudioSessionCategorySoloAmbient类别,该类别由振铃开关静音。 AVAudioSessionCategoryPlayback类别更适合您的情况,因为它不会被交换机静音,并会继续在后台播放:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                    pathForResource:soundName
                                    ofType:@"caf"]];

player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[player setCategory:AVAudioSessionCategoryPlayback error:nil];
player.numberOfLoops = -1;
[player setVolume:1.0];

答案 4 :(得分:0)

这(希望)可能就像保留音频一样简单。如果你可以检查你在哪里设置了强大的玩家属性。

@property (strong, nonatomic) AVAudioPlayer *player;

我希望这有帮助,

干杯,吉姆