1. 程式人生 > >曾經被我們忽略的AVAudioSession

曾經被我們忽略的AVAudioSession

AVAudioSession是用來管理和平衡多個App的(揚聲器、麥克瘋)的資源的使用。
例如裝置在背後進行播放音樂時,這時候使用者進入我們的App,需要播放一小段視訊時,這個時候,我們應該如何處理?

  • 中斷音樂播放?
  • 暫時中斷音樂播放,等小視訊播放完畢喚醒背後音樂繼續播放?
  • 與音樂混音一起播放?
  • 與音樂混音播放暫時壓低背後音樂的聲音,等小視訊播放完畢恢復背後音樂的聲音大小?
    這些處理方式都是依靠AVAudioSession來處理的。

1.AVAudioSession 的 Category

我們進入 AVAudioSession 的Category可以發現有7種 Category 可供選擇。

AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;

/*  Use this category for background sounds.  Other music will stop playing. */
AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;

/* Use this category for music tracks.*/
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;

/*  Use this category when recording audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryRecord;

/*  Use this category when recording and playing back audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryPlayAndRecord;

/*  Use this category when using a hardware codec or signal processor while
 not playing or recording audio. */
AVF_EXPORT NSString *const AVAudioSessionCategoryAudioProcessing NS_DEPRECATED_IOS(3_0, 10_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;

/*  Use this category to customize the usage of available audio accessories and built-in audio hardware.
 For example, this category provides an application with the ability to use an available USB output 
 and headphone output simultaneously for separate, distinct streams of audio data. Use of 
 this category by an application requires a more detailed knowledge of, and interaction with, 
 the capabilities of the available audio routes.  May be used for input, output, or both.
 Note that not all output types and output combinations are eligible for multi-route.  Input is limited
 to the last-in input port. Eligible inputs consist of the following:
    AVAudioSessionPortUSBAudio, AVAudioSessionPortHeadsetMic, and AVAudioSessionPortBuiltInMic.  
 Eligible outputs consist of the following: 
    AVAudioSessionPortUSBAudio, AVAudioSessionPortLineOut, AVAudioSessionPortHeadphones, AVAudioSessionPortHDMI, 
    and AVAudioSessionPortBuiltInSpeaker.  
 Note that AVAudioSessionPortBuiltInSpeaker is only allowed to be used when there are no other eligible 
 outputs connected.  */
AVF_EXPORT NSString *const AVAudioSessionCategoryMultiRoute
  • AVAudioSessionCategoryAmbient 僅支援播放,不會打斷不支援混音的App,使用這種模式,你的App的聲音會與背後的音樂App一起發出聲音。 如果是在鎖屏或者靜音鍵的情況下你App的音訊會終止。
  • AVAudioSessionCategorySoloAmbient 僅支援播放,會打斷不支援混音的App,使用這種模式,你的App的聲音會打斷背後的音樂App。 如果是在鎖屏或者靜音鍵的情況下你App的音訊會終止。 這種模式是系統的預設模式。
  • AVAudioSessionCategoryPlayback 僅支援播放,預設會打斷不支援混音的App。如果是在鎖屏或者靜音鍵的情況下你App的音訊不會終止。
  • AVAudioSessionCategoryRecord 僅支援錄製,會打斷不支援混音的App。如果是在鎖屏或者靜音鍵的情況下仍可錄製。
  • AVAudioSessionCategoryPlayAndRecord 支援播放且支援錄製,預設會打斷不支援混音的App。如果是在鎖屏或者靜音鍵的情況下仍可播放聲音或者錄製。
  • AVAudioSessionCategoryMultiRoute 支援播放且支援錄製,會打斷不支援混音的App。如果是在鎖屏或者靜音鍵的情況下仍可播放聲音或者錄製。
  • AVAudioSessionCategoryAudioProcessing 不支援播放且不支援錄音,會打斷不支援混音的App。iOS10 之後被棄用。

2.AVAudioSession 的 AVAudioSessionCategoryOptions

AVAudioSession 的AVAudioSessionCategoryOptions 同樣也是一個列舉。

    /* MixWithOthers is only valid with AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and  AVAudioSessionCategoryMultiRoute */
    AVAudioSessionCategoryOptionMixWithOthers           = 0x1,

    /* DuckOthers is only valid with AVAudioSessionCategoryAmbient, AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute */
    AVAudioSessionCategoryOptionDuckOthers              = 0x2,

    /* AllowBluetooth is only valid with AVAudioSessionCategoryRecord and AVAudioSessionCategoryPlayAndRecord */
    AVAudioSessionCategoryOptionAllowBluetooth  __TVOS_PROHIBITED __WATCHOS_PROHIBITED      = 0x4,

    /* DefaultToSpeaker is only valid with AVAudioSessionCategoryPlayAndRecord */
    AVAudioSessionCategoryOptionDefaultToSpeaker __TVOS_PROHIBITED __WATCHOS_PROHIBITED     = 0x8,

    /* InterruptSpokenAudioAndMixWithOthers is only valid with AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute */
    AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers NS_AVAILABLE_IOS(9_0) = 0x11,

    /* AllowBluetoothA2DP is only valid with AVAudioSessionCategoryPlayAndRecord */
    AVAudioSessionCategoryOptionAllowBluetoothA2DP API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0)) = 0x20,

    /* AllowAirPlay is only valid with AVAudioSessionCategoryPlayAndRecord */
    AVAudioSessionCategoryOptionAllowAirPlay API_AVAILABLE(ios(10.0), tvos(10.0)) __WATCHOS_PROHIBITED = 0x40,
  • AVAudioSessionCategoryOptionMixWithOthers 當你的App包含聲音播放時,設定這個選項在啟用會話時不會打斷其他App的音訊播放。
    適用於以下category:
    • AVAudioSessionCategoryPlayback
    • AVAudioSessionCategoryPlayAndRecord
    • AVAudioSessionCategoryMultiRoute
  • AVAudioSessionCategoryOptionDuckOthers 當你的App包含聲音播放時,設定這個選項在啟用會話時會降低其他App的聲音播放。
    適用於以下category:
    • AVAudioSessionCategoryAmbient
    • AVAudioSessionCategoryPlayAndRecord
    • AVAudioSessionCategoryPlayback
    • AVAudioSessionCategoryMultiRoute
  • AVAudioSessionCategoryOptionAllowBluetooth 允許可擴音藍芽裝置可使用輸入通道
    適用於以下category:
    • AVAudioSessionCategoryRecord
    • AVAudioSessionCategoryPlayAndRecord
  • AVAudioSessionCategoryOptionDefaultToSpeaker 在沒有其他通道的時候預設選擇內建揚聲器
    適用於以下category:
    • AVAudioSessionCategoryPlayAndRecord
  • AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers 你的App偶爾的使用音訊播放。
    適用於以下category:
    • AVAudioSessionCategoryPlayback
    • AVAudioSessionCategoryPlayAndRecord
    • AVAudioSessionCategoryMultiRoute
  • AVAudioSessionCategoryOptionAllowBluetoothA2DP 立體聲藍芽。
    適用於以下category:
    • AVAudioSessionCategoryPlayAndRecord
  • AVAudioSessionCategoryOptionAllowAirPlay 遠端AirPlay裝置。
    適用於以下category:
    • AVAudioSessionCategoryPlayAndRecord

3. 使用AVAudioSession 的 Category 和 AVAudioSessionCategoryOptions 調整各種音訊模式

1.播放音視訊的時候直接中斷背後的音樂播放。

這種情況下,我們直接將category 設定為 AVAudioSessionCategorySoloAmbient即可,當然你不做任何處理系統也會進行預設模式處理。很多App也是這種模式。

    AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError * error = nil;
    [session setCategory:AVAudioSessionCategorySoloAmbient error:&error];
    if (error) {
        NSLog(@"%@",error);
    }

2.播放音視訊的時候暫時中斷背後的音樂,播放完畢後再繼續背後的音樂。

這種情況下,category設定與1的相同,然後在播放前 增加下面的程式碼告訴背後的音樂App你將要佔用音訊焦點。

[[AVAudioSession sharedInstance] setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

在暫停播放或者App退到後臺後暫停播放前,告訴背後的音樂App你取消音訊焦點的佔用。

[[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

3.播放音視訊的時候與背後音樂App混音一起播放

這種情況下,我們直接將category 設定為 AVAudioSessionCategoryAmbient即可。

    AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError * error = nil;
    [session setCategory:AVAudioSessionCategoryAmbient error:&error];
    if (error) {
        NSLog(@"%@",error);
    }

4.播放音視訊的時候暫時壓低背後音樂的聲音,等音視訊播放完畢恢復背後音樂的聲音大小

這種情況下,需要設定category為AVAudioSessionCategoryAmbient,AVAudioSessionCategoryOptions設定為AVAudioSessionCategoryOptionDuckOthers

 AVAudioSession *session = [AVAudioSession sharedInstance];
    NSError * error = nil;
    [session setCategory:AVAudioSessionCategoryAmbient withOptions:AVAudioSessionCategoryOptionDuckOthers error:&error];
    if (error) {
        NSLog(@"%@",error);
    }

然後在播放前 增加下面的程式碼告訴背後的音樂App你將要佔用音訊焦點。

[[AVAudioSession sharedInstance] setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

在暫停播放或者App退到後臺後暫停播放前,告訴背後的音樂App你取消音訊焦點的佔用。

[[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

以上是一些AVAudioSession 的 Category 和 AVAudioSessionCategoryOptions 配合使用的幾種模式的舉例,具體要根據自己的實際需要進行調整。Demo下載地址