【问题标题】:iOS background audio not playingiOS背景音频不播放
【发布时间】:2014-04-30 17:57:35
【问题描述】:

我有一个使用 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 不播放声音文件的原因可能是什么?

谢谢

编辑-------

如果应用程序在后台运行时已在播放声音,则会播放该声音。然而,让它在后台运行时开始播放是行不通的。

【问题讨论】:

  • 不确定这是否是您的答案,但设置播放器的声音并不会设置全局音量。那么可能是你的音量被调低了吗? Apple 在 iOS7 中进行了更改,不允许您轻松设置全局音量。一个技巧是创建 MPMusicPlayerController 的实例并以编程方式设置音量。这已被弃用。
  • 我不确定这是田鼠问题,因为当应用程序处于前台时声音播放正常。更重要的是,我需要在手机的静音开关启用且本地通知不这样做时发出警报。
  • 我做到了。没用。似乎声音已经在播放,那么它会在后台继续播放。如果我开始在后台播放它就不会播放

标签: ios objective-c audio avfoundation avaudioplayer


【解决方案1】:

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

如下图..

你能得到帮助吗..

并在

中添加以下代码

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

对于手机蓝牙,您必须在 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);
    }

【讨论】:

  • 不幸的是,我在后台播放时仍然没有声音。振动仍然发生,但没有找到:(
  • 谢谢。我会奖励你的答案,因为它是最详细的。
  • 是的,它开始工作了,但我没有改变任何东西!我真的很困惑。
  • 是的,我已经完成了所有工作。最后一块是让手机播放警报声。我最初使用本地通知,但希望它在静音模式下也能工作。
  • @drink_android 我的应用程序处于可能需要的状态时,我最终以零音量播放警报声音。这样,它在后台保持playing,只需将音量设置为 1.0 即可听到,
【解决方案2】:

除了plist 设置,您还必须修改应用委托。

- (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];

【讨论】:

  • 我仍然只有振动,背景没有声音。我认为这与我在后台启动声音这一事实有关。
  • 好的,然后尝试在appdelegate中制作background player的对象,并将audioPlayerdelegate传递给appdelegate。当您弹出或导航出您已创建其对象及其委托的屏幕时,您的 audiPlayer 对象可能会在某处被释放。
  • 还可以通过检查 player.duration 属性来检查您是否在音频播放器中传递了正确的 url。
  • 振动由同一个物体播放,效果很好。 URL 也很好,因为它在前台播放。
【解决方案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]  

也就是说,你必须让你的应用的音频会话高于其他应用。

【讨论】:

  • 谢谢!我的问题已使用 withOptions:AVAudioSessionCategoryOptionMixWithOthers 解决。再次感谢你! :)
【解决方案4】:

默认情况下,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];

【讨论】:

  • 嗨,AVAudioPlayer 没有 setCategory 方法,但 AVAudioSession 有。我尝试使用这个[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];,但在后台仍然没有声音。
  • 如果闹钟已经在播放,我可以后台运行应用程序仍然可以听到,但是如果我从后台启动它就无法播放?
【解决方案5】:

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

@property (strong, nonatomic) AVAudioPlayer *player;

希望对你有帮助,

干杯,吉姆

【讨论】:

  • 我以为你在这里有东西,但不行:(
  • 是否有任何可以在 iOS 7 上运行的演示代码可供我查看?
猜你喜欢
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
相关资源
最近更新 更多