用戶點擊了播放視頻,但是此時手機是靜音狀態,產品說靜音狀態下也需要把聲音給播放出來,so~ 原文: https://www.jianshu.com/p/998709165dfd
首先你要確保player的屬性muted爲NO,即非靜音,當然NO是系統默認的。然後設置一下category即可
//靜音狀態下播放
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
AVAudioSessionCategory是一個字符串枚舉,講一下幾個常用的category的含義:
// app的聲音可與其它app共存,但鎖屏和靜音模式會被靜音,除非當前app是唯一播放的app
AVAudioSessionCategoryAmbient
// 會停止其他程序的音頻播放。當設備被設置爲靜音模式,音頻會隨之靜音
AVAudioSessionCategorySoloAmbient
// 僅用來錄音,無法播放音頻
AVAudioSessionCategoryRecord
// 會停止其它音頻播放,並且能在後臺播放,鎖屏和靜音模式都能播放聲音
AVAudioSessionCategoryPlayback
// 能播也能錄,播放默認聲音是從聽筒出來
AVAudioSessionCategoryPlayAndRecord
上面提到的靜音模式,指的是點擊了iPhone手機上的靜音按鈕(靜音按鈕在AssistiveTouch,就是屏幕上的虛擬home鍵中比較容易找到),並不是指慢慢慢慢地降低聲音直到靜音,那不是靜音模式,只是聲音降到了0而已
AVAudioSessionCategoryPlayAndRecord 有個小坑, 默認是聽筒的聲音,需要在設置下輸出端口
- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride error:(NSError * _Nullable *)outError;
其中portOverride參數有2個可選參數:
AVAudioSessionPortOverrideNone:我的理解是將音頻輸出設置聽筒,系統默認應該就是聽筒,因爲官方文檔給出的解釋是:
AVAudioSessionPortOverrideSpeaker:音頻輸出設置爲揚聲器。
3.App佔用聽筒或揚聲器
由於你的APP使用音頻通道時其他App可能正在使用它,所以需要調用這個方法。
- (BOOL)setActive:(BOOL)active error:(NSError * _Nullable *)outError;
使用方法:
//拿到AVAudioSession的單例對象
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
//設置爲聽筒模式
//[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
//設置爲公放模式
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
//讓我的App佔用聽筒或揚聲器
[audioSession setActive:YES error:nil];
https://www.jianshu.com/p/47c7144db817 , 後臺播放音樂,耳機控制,鎖屏顯示音樂信息,https://www.jianshu.com/p/771b45e53619
平時經常用到頭條來看新聞和視頻,如果後臺還在播放着音樂,在播放視頻的時候,音樂會被中斷,視頻播放結束或者退出頁面,音樂就會再次響起,很好奇這是怎麼做到的,今天看到了.
其它App播放聲音打斷
如果用戶當時在後臺聽音樂,如QQ音樂,或者喜馬拉雅這些App,這個時候播放視頻後,其會被我們打斷,當我們不再播放視頻的時候,自然需要繼續這些後臺聲音的播放。
首先,我們需要先向設備註冊激活聲音打斷AudioSessionSetActive(YES);,當然我們也可以通過 [AVAudioSession sharedInstance].otherAudioPlaying;這個方法來判斷還有沒有其它業務的聲音在播放。 當我們播放完視頻後,需要恢復其它業務或App的聲音,這時我們可以調用如下方法:
// AVplayer初始化的時候記錄下是否有別的播放器在播放
if ([AVAudioSession sharedInstance].isOtherAudioPlaying) {
NSLog(@"當前有其他播放器在播放!!");
}
// 如果有別的播放器,在用戶暫停或者退出頁面,恢復其他播放器的播放
NSError *error =nil;
BOOL isSuccess = [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
if (!isSuccess) {
NSLog(@"__%@",error);
}else{
NSLog(@"成功播放了後臺音樂");
}
當有打電話,鬧鈴等其他的事件導致了播放暫停
//中斷的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
//中斷事件
- (void)handleInterruption:(NSNotification *)notification{
NSDictionary *info = notification.userInfo;
//一箇中斷狀態類型
AVAudioSessionInterruptionType type =[info[AVAudioSessionInterruptionTypeKey] integerValue];
//判斷開始中斷還是中斷已經結束
if (type == AVAudioSessionInterruptionTypeBegan) {
//停止播放
[self.player pause];
}else {
//如果中斷結束會附帶一個KEY值,表明是否應該恢復音頻
AVAudioSessionInterruptionOptions options =[info[AVAudioSessionInterruptionOptionKey] integerValue];
if (options == AVAudioSessionInterruptionOptionShouldResume) {
//恢復播放
[self.player play];
}
}
}
在用戶插入和拔出耳機時,導致視頻暫停,解決方法如下
//耳機插入和拔掉通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
//耳機插入、拔出事件
- (void)audioRouteChangeListenerCallback:(NSNotification*)notification {
NSDictionary *interuptionDict = notification.userInfo;
NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
switch (routeChangeReason) {
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
{
//判斷爲耳機接口
AVAudioSessionRouteDescription *previousRoute =interuptionDict[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *previousOutput =previousRoute.outputs[0];
NSString *portType =previousOutput.portType;
if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
// 拔掉耳機繼續播放
if (self.playing) {
[self.player play];
}
}
}
break;
case AVAudioSessionRouteChangeReasonCategoryChange:
// called at start - also when other audio wants to play
break;
}
}
正常情況下,音頻退到後臺繼續播放需要這麼做.申請後臺運行權限
-(void)applicationWillResignActive:(UIApplication *)application{
//開啓後臺處理多媒體事件
AVAudioSession *session=[AVAudioSession sharedInstance];
[session setActive:YES error:nil];
//後臺播放
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
}
但是我在前面做了靜音狀態下播放,[AVAudioSession sharedInstance]的Category已經是AVAudioSessionCategoryPlayback,所以在applicationWillResignActive就可以不用寫了.
對了,還有一個小坑,就是AVPlayer光這麼設置是不行的, 這個是針對音頻的,視頻的話,需要在applicationDidEnterBackground把AVPlayer的AVPlayerLayer設置爲nil , 如果AVPlayerLayer還存在的話 , 是不能進行後臺播放的. 同理,applicationWillEnterForeground需要在把AVPlayerLayer與AVPlayer關聯起來.