日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android汽车音频焦点方案,管理音频焦点  |  Android 开发者  |  Android Developers

發布時間:2025/3/15 Android 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android汽车音频焦点方案,管理音频焦点  |  Android 开发者  |  Android Developers 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

兩個或兩個以上的 Android 應用可同時向同一輸出流播放音頻。系統會將所有音頻流混合在一起。雖然這是一項出色的技術,但卻會給用戶帶來很大的困擾。為了避免所有音樂應用同時播放,Android 引入了“音頻焦點”的概念。

一次只能有一個應用獲得音頻焦點。

當您的應用需要輸出音頻時,它需要請求獲得音頻焦點,獲得焦點后,就可以播放聲音了。不過,在您獲得音頻焦點后,您可能無法將其一直持有到播放完成。其他應用可以請求焦點,從而占有您持有的音頻焦點。如果發生這種情況,您的應用應暫停播放或降低音量,以便于用戶聽到新的音頻源。

音頻焦點采用合作模式。我們建議應用遵守音頻焦點準則,但系統不會強制執行這些準則。如果應用想要在失去音頻焦點后繼續大聲播放,系統無法阻止它。這是一種不好的體驗,用戶很可能會卸載具有這種不良行為的應用。

行為恰當的音頻應用應根據以下一般準則來管理音頻焦點:

在即將開始播放之前調用 requestAudioFocus(),并驗證調用是否返回 onPlay() 回調中調用 requestAudioFocus()。

在其他應用獲得音頻焦點時,停止或暫停播放,或降低音量。

播放停止后,放棄音頻焦點。

運行的 Android 版本不同,音頻焦點的處理方式也會不同:

對于以 Android 5.0(API 級別 21)及更高版本為目標平臺的應用,音頻應用應使用

面向 Android 8.0(API 級別 26)或更高版本的應用應使用 AudioFocusRequest 包含有關應用的音頻上下文和功能的信息。系統使用這些信息來自動管理音頻焦點的得到和失去。

Android 8.0 及更高版本中的音頻焦點

從 Android 8.0(API 級別 26)開始,當您調用 AudioFocusRequest 參數。要釋放音頻焦點,請調用 AudioFocusRequest 作為參數。在請求和放棄焦點時,應使用相同的 AudioFocusRequest 實例。

要創建

FocusGain 字段為必需字段;所有其他字段均為可選字段。

方法備注

每個請求中都必須包含此字段。此字段的值與 Android 8.0 之前的 requestAudioFocus() 調用中所使用的 durationHint 值相同:AUDIOFOCUS_GAIN、AUDIOFOCUS_GAIN_TRANSIENT、AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 或 AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE。

首先使用

如果未指定,則 AudioAttributes 默認為 AudioAttributes.USAGE_MEDIA。

當其他應用使用 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 請求焦點時,持有焦點的應用通常不會收到 自行降低音量。如果您需要暫停播放而不是降低音量,請調用 setWillPauseWhenDucked(true),然后創建并設置 OnAudioFocusChangeListener,具體如自動降低音量中所述。

當焦點被其他應用鎖定時,對音頻焦點的請求可能會失敗。此方法可實現延遲獲取焦點,即在焦點可用時異步獲取焦點。

請注意,要使“延遲獲取焦點”起作用,您還必須在音頻請求中指定

只有當您在請求中還指定了 willPauseWhenDucked(true) 或 setAcceptsDelayedFocusGain(true) 時,才需要 OnAudioFocusChangeListener。

有兩個方法可以設置監聽器:一個帶處理程序參數,一個不帶。處理程序是運行監聽器的線程。如果您未指定處理程序,則會使用與主

以下示例展示了如何使用 AudioFocusRequest.Builder 構建 AudioFocusRequest 來請求和放棄音頻焦點:

Kotlin

audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager

focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {

setAudioAttributes(AudioAttributes.Builder().run {

setUsage(AudioAttributes.USAGE_GAME)

setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)

build()

})

setAcceptsDelayedFocusGain(true)

setOnAudioFocusChangeListener(afChangeListener, handler)

build()

}

mediaPlayer = MediaPlayer()

val focusLock = Any()

var playbackDelayed = false

var playbackNowAuthorized = false

// ...

val res = audioManager.requestAudioFocus(focusRequest)

synchronized(focusLock) {

playbackNowAuthorized = when (res) {

AudioManager.AUDIOFOCUS_REQUEST_FAILED -> false

AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> {

playbackNow()

true

}

AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> {

playbackDelayed = true

false

}

else -> false

}

}

// ...

override fun onAudioFocusChange(focusChange: Int) {

when (focusChange) {

AudioManager.AUDIOFOCUS_GAIN ->

if (playbackDelayed || resumeOnFocusGain) {

synchronized(focusLock) {

playbackDelayed = false

resumeOnFocusGain = false

}

playbackNow()

}

AudioManager.AUDIOFOCUS_LOSS -> {

synchronized(focusLock) {

resumeOnFocusGain = false

playbackDelayed = false

}

pausePlayback()

}

AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {

synchronized(focusLock) {

resumeOnFocusGain = true

playbackDelayed = false

}

pausePlayback()

}

AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {

// ... pausing or ducking depends on your app

}

}

}Java

audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);

playbackAttributes = new AudioAttributes.Builder()

.setUsage(AudioAttributes.USAGE_GAME)

.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)

.build();

focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)

.setAudioAttributes(playbackAttributes)

.setAcceptsDelayedFocusGain(true)

.setOnAudioFocusChangeListener(afChangeListener, handler)

.build();

mediaPlayer = new MediaPlayer();

final Object focusLock = new Object();

boolean playbackDelayed = false;

boolean playbackNowAuthorized = false;

// ...

int res = audioManager.requestAudioFocus(focusRequest);

synchronized(focusLock) {

if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {

playbackNowAuthorized = false;

} else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

playbackNowAuthorized = true;

playbackNow();

} else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {

playbackDelayed = true;

playbackNowAuthorized = false;

}

}

// ...

@Override

public void onAudioFocusChange(int focusChange) {

switch (focusChange) {

case AudioManager.AUDIOFOCUS_GAIN:

if (playbackDelayed || resumeOnFocusGain) {

synchronized(focusLock) {

playbackDelayed = false;

resumeOnFocusGain = false;

}

playbackNow();

}

break;

case AudioManager.AUDIOFOCUS_LOSS:

synchronized(focusLock) {

resumeOnFocusGain = false;

playbackDelayed = false;

}

pausePlayback();

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:

synchronized(focusLock) {

resumeOnFocusGain = true;

playbackDelayed = false;

}

pausePlayback();

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:

// ... pausing or ducking depends on your app

break;

}

}

}

自動降低音量

在 Android 8.0(API 級別 26)中,當其他應用使用 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 請求焦點時,系統可以在不調用應用的 onAudioFocusChange() 回調的情況下降低和恢復音量。

雖然自動降低音量的行為對于音樂和視頻播放應用來說是可接受的,但在播放語音內容時(例如在聽書應用中)就沒什么用處了。在這種情況下,應用應該暫停播放。

如果您希望應用在被要求降低音量時暫停播放,請創建包含 onAudioFocusChange() 回調方法的 OnAudioFocusChangeListener,該回調方法可以實現所需的暫停/恢復行為。

調用

延遲獲取焦點

在有些情況下,系統不能批準對音頻焦點的請求,因為焦點被其他應用“鎖定”了,例如在通話過程中。在這種情況下,requestAudioFocus() 會返回 AUDIOFOCUS_REQUEST_FAILED。在這種情況下,您的應用將不會播放音頻,因為它未獲得焦點。

方法 AUDIOFOCUS_REQUEST_DELAYED。當鎖定音頻焦點的情況不再存在時(例如當通話結束時),系統會批準待處理的焦點請求,并調用 onAudioFocusChange() 來通知您的應用。

為了處理“延遲獲取焦點”,您必須創建包含 onAudioFocusChange() 回調方法的 OnAudioFocusChangeListener,該回調方法會通過調用

Android 8.0 之前的音頻焦點

當您調用

如果您計劃在可預見的將來播放音頻(例如在播放音樂時),并且希望前一個持有音頻焦點的應用停止播放,則應該請求永久性的音頻焦點 (AUDIOFOCUS_GAIN)。

如果您只希望在短時間內播放音頻,并且希望前一個持有音頻焦點的應用暫停播放,則應該請求暫時性的焦點 (AUDIOFOCUS_GAIN_TRANSIENT)。

請求附帶“降低音量”(AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) 的暫時性焦點,表示您只希望在短時間內播放音頻,并允許前一個持有焦點的應用在降低其音頻輸出的情況下繼續播放。這兩個音頻輸出會混合到音頻流中。降低音量特別適合于間歇性使用音頻流的應用,例如有聲的行車路線。

requestAudioFocus() 方法同樣需要 onAudioFocusChange() 回調,您的應用會在其他應用獲取或放棄音頻焦點時收到該回調。

以下代碼段會請求對 STREAM_MUSIC 流的永久性音頻焦點,并注冊 OnAudioFocusChangeListener 來處理音頻焦點的后續更改。(有關更改監聽器的說明,請參閱響應音頻焦點更改。)

Kotlin

audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager

lateinit var afChangeListener AudioManager.OnAudioFocusChangeListener

...

// Request audio focus for playback

val result: Int = audioManager.requestAudioFocus(

afChangeListener,

// Use the music stream.

AudioManager.STREAM_MUSIC,

// Request permanent focus.

AudioManager.AUDIOFOCUS_GAIN

)

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

// Start playback

}Java

AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

AudioManager.OnAudioFocusChangeListener afChangeListener;

...

// Request audio focus for playback

int result = audioManager.requestAudioFocus(afChangeListener,

// Use the music stream.

AudioManager.STREAM_MUSIC,

// Request permanent focus.

AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

// Start playback

}

Kotlin

audioManager.abandonAudioFocus(afChangeListener)Java

// Abandon audio focus when playback complete

audioManager.abandonAudioFocus(afChangeListener);

這會通知系統您不再需要焦點,并注銷關聯的 OnAudioFocusChangeListener。如果您請求的是暫時性焦點,則會通知已暫停或降低音量的應用它可以繼續播放或恢復其音量。

響應音頻焦點更改

當應用獲得音頻焦點后,它必須能夠在其他應用為自己請求音頻焦點時釋放該焦點。出現這種情況時,您的應用會收到對 AudioFocusChangeListener 中的 requestAudioFocus() 時指定的。

傳遞給 onAudioFocusChange() 的 focusChange 參數表示所發生的更改類型。它對應于獲取焦點的應用所使用的持續時間提示。您的應用應該做出適當的響應。

暫時性失去焦點

如果焦點更改是暫時性的(AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK 或 AUDIOFOCUS_LOSS_TRANSIENT),您的應用應該降低音量(如果您不依賴于自動降低音量)或暫停播放,否則保持相同的狀態。

在暫時性失去音頻焦點時,您應該繼續監控音頻焦點的變化,并準備好在重新獲得焦點后恢復正常播放。當搶占焦點的應用放棄焦點時,您會收到一個回調 (AUDIOFOCUS_GAIN)。此時,您可以將音量恢復到正常水平或重新開始播放。永久性失去焦點

如果是永久性失去音頻焦點 (AUDIOFOCUS_LOSS),則其他應用會播放音頻。您的應用應立即暫停播放,因為它不會收到 AUDIOFOCUS_GAIN 回調。要重新開始播放,用戶必須執行明確的操作,例如在通知或應用界面中按播放傳輸控件。

以下代碼段展示了如何實現 OnAudioFocusChangeListener 及其 onAudioFocusChange() 回調。請注意這里使用 Handler 延遲了對永久性失去音頻焦點的停止回調。

Kotlin

private val handler = Handler()

private val afChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->

when (focusChange) {

AudioManager.AUDIOFOCUS_LOSS -> {

// Permanent loss of audio focus

// Pause playback immediately

mediaController.transportControls.pause()

// Wait 30 seconds before stopping playback

handler.postDelayed(delayedStopRunnable, TimeUnit.SECONDS.toMillis(30))

}

AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {

// Pause playback

}

AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {

// Lower the volume, keep playing

}

AudioManager.AUDIOFOCUS_GAIN -> {

// Your app has been granted audio focus again

// Raise volume to normal, restart playback if necessary

}

}

}Java

private Handler handler = new Handler();

AudioManager.OnAudioFocusChangeListener afChangeListener =

new AudioManager.OnAudioFocusChangeListener() {

public void onAudioFocusChange(int focusChange) {

if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {

// Permanent loss of audio focus

// Pause playback immediately

mediaController.getTransportControls().pause();

// Wait 30 seconds before stopping playback

handler.postDelayed(delayedStopRunnable,

TimeUnit.SECONDS.toMillis(30));

}

else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {

// Pause playback

} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {

// Lower the volume, keep playing

} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {

// Your app has been granted audio focus again

// Raise volume to normal, restart playback if necessary

}

}

};

處理程序使用如下所示的 Runnable:

Kotlin

private var delayedStopRunnable = Runnable {

mediaController.transportControls.stop()

}Java

private Runnable delayedStopRunnable = new Runnable() {

@Override

public void run() {

getMediaController().getTransportControls().stop();

}

};

為了確保在用戶重新開始播放時不會觸發延遲停止,請調用 mHandler.removeCallbacks(mDelayedStopRunnable) 來響應任何狀態變化。例如,在回調的 onPlay()、onSkipToNext() 等中調用 removeCallbacks()。此外,在清理服務使用的資源時,您也應該在服務的 onDestroy() 回調中調用此方法。

總結

以上是生活随笔為你收集整理的android汽车音频焦点方案,管理音频焦点  |  Android 开发者  |  Android Developers的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。