當前位置:首頁 > 嵌入式 > 嵌入式軟件
[導讀] 處理音頻焦點盡管某個時刻只有一個activity可以運行,Android卻是一個多任務環(huán)境.這對使用音頻的應用帶來了特殊的挑戰(zhàn),因為只有一個音頻輸出而可能多個媒體都想用它.在An

 處理音頻焦點

盡管某個時刻只有一個activity可以運行,Android卻是一個多任務環(huán)境.這對使用音頻的應用帶來了特殊的挑戰(zhàn),因為只有一個音頻輸出而可能多個媒體都想用它.在Android2.2之前,沒有內建的機制來處理這個問題,所以可能在某些情況下導致壞的用戶體驗.例如,當一個用戶正在聽音樂而另一個應用需要通知用戶一些重要的事情時,用戶可能由于音樂聲音大而不能聽的通知.從Android2.2開始,平臺為應用提供了一個協(xié)商它們如何使用設備音頻輸出的途徑,這個機制叫做音頻焦點.

當你的應用需要輸出像樂音和通知之類的音頻時,你應該總是請求音頻焦點.一旦應用具有了焦點,它就可以自由的使用音頻輸出.但它總是應該監(jiān)聽焦點的變化.如果被通知丟失焦點,它應該立即殺死聲音或降低到靜音水平(有一個標志表明應選擇哪一個)并且僅當重新獲得焦點后才恢復大聲播放.

將來的音頻焦點是合作的.所以,應用被希望(并被強列鼓勵)遵守音頻焦點的方針,但是卻不是被系統(tǒng)強制的.如果一個應用在丟失音頻焦點后依然想大聲播放音樂,系統(tǒng)不會去阻止它.然而用戶卻體驗很壞并且很想把這鳥應用卸載.

要請求音頻焦點,你必須從AudioManager調用requestAudioFocus(),如下所示:

[java]

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

int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,

AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

// 不能獲得音頻焦點

}

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

int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,

AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

// 不能獲得音頻焦點

}

requestAudioFocus()的第一個參數(shù)是一個AudioManager.OnAudioFocusChangeListener,它的onAudioFocusChange()方法在音頻焦點發(fā)改變時被調用.因此,你也應該在你的service和activity上實現(xiàn)此接口.例如:

[java]

class MyService extends Service

implements AudioManager.OnAudioFocusChangeListener {

// ....

public void onAudioFocusChange(int focusChange) {

// Do something based on focus change...

}

}

class MyService extends Service

implements AudioManager.OnAudioFocusChangeListener {

// ....

public void onAudioFocusChange(int focusChange) {

// Do something based on focus change...

}

}

參數(shù)focusChange告訴你音頻焦點如何發(fā)生了變化,它可以是以上幾種值(它們都是定義在AudioManager中的常量):

AUDIOFOCUS_GAIN:你已獲得了音頻焦點.

AUDIOFOCUS_LOSS:你已經(jīng)丟失了音頻焦點比較長的時間了.你必須停止所有的音頻播放.因為預料到你可能很長時間也不能再獲音頻焦點,所以這里是清理你的資源的好地方.比如,你必須釋放MediaPlayer.

AUDIOFOCUS_LOSS_TRANSIENT:你臨時性的丟掉了音頻焦點,很快就會重新獲得.你必須停止所有的音頻播放,但是可以保留你的資源,因為你可能很快就能重新獲得焦點.

AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:你臨時性的丟掉了音頻焦點,但是你被允許繼續(xù)以低音量播放,而不是完全停止.

下面是一個例子:

[java]

public void onAudioFocusChange(int focusChange) {

switch (focusChange) {

case AudioManager.AUDIOFOCUS_GAIN:

// resume playback

if (mMediaPlayer == null) initMediaPlayer();

else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();

mMediaPlayer.setVolume(1.0f, 1.0f);

break;

case AudioManager.AUDIOFOCUS_LOSS:

// Lost focus for an unbounded amount of time: stop playback and release media player

if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();

mMediaPlayer.release();

mMediaPlayer = null;

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:

// Lost focus for a short time, but we have to stop

// playback. We don't release the media player because playback

// is likely to resume

if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:

// Lost focus for a short time, but it's ok to keep playing

// at an attenuated level

if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);

break;

}

}

public void onAudioFocusChange(int focusChange) {

switch (focusChange) {

case AudioManager.AUDIOFOCUS_GAIN:

// resume playback

if (mMediaPlayer == null) initMediaPlayer();

else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();

mMediaPlayer.setVolume(1.0f, 1.0f);

break;

case AudioManager.AUDIOFOCUS_LOSS:

// Lost focus for an unbounded amount of time: stop playback and release media player

if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();

mMediaPlayer.release();

mMediaPlayer = null;

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:

// Lost focus for a short time, but we have to stop

// playback. We don't release the media player because playback

[!--empirenews.page--]

// is likely to resume

if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();

break;

case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:

// Lost focus for a short time, but it's ok to keep playing

// at an attenuated level

if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);

break;

}

}

記住音頻焦點API僅在APIlevel 8 (Android2.2)及更高版本上可以,所以如果你想支持更早的Android版本,你必須在可能時采取兼容性的策略使用特性,如果不可能,you should adopt a backward compatibility strategy that allows you touse this feature if available, and fall back seamlessly if not.

你可以用反射的方式調用音頻焦點方法或自己在一個單獨的類(叫做AudioFocusHelper)中實現(xiàn)所有的音頻焦點功能來達到向前兼容.下面是一個這樣的類:

[java]

public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {

AudioManager mAudioManager;

// 這里是其它的字段,你可能要保存一個接口的引用,這個接口

// 被用于與你的service通訊以報告焦點的變化.

public AudioFocusHelper(Context ctx, ) {

mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

// ...

}

public boolean requestFocus() {

return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==

mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,

AudioManager.AUDIOFOCUS_GAIN);

}

public boolean abandonFocus() {

return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==

mAudioManager.abandonAudioFocus(this);

}

@Override

public void onAudioFocusChange(int focusChange) {

// 讓你的service知道焦點變化了

}

}

你可以僅在檢測到系統(tǒng)運行的是API level 8 或更早的版本時才創(chuàng)建AudioFocusHelper類的實例.例如:

if (android.os.Build.VERSION.SDK_INT >= 8) {

mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);

} else {

mAudioFocusHelper = null;

}

public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {

AudioManager mAudioManager;

// 這里是其它的字段,你可能要保存一個接口的引用,這個接口

// 被用于與你的service通訊以報告焦點的變化.

public AudioFocusHelper(Context ctx, ) {

mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

// ...

}

public boolean requestFocus() {

return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==

mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,

AudioManager.AUDIOFOCUS_GAIN);

}

public boolean abandonFocus() {

return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==

mAudioManager.abandonAudioFocus(this);

}

@Override

public void onAudioFocusChange(int focusChange) {

// 讓你的service知道焦點變化了

}

}

你可以僅在檢測到系統(tǒng)運行的是API level 8 或更早的版本時才創(chuàng)建AudioFocusHelper類的實例.例如:

if (android.os.Build.VERSION.SDK_INT >= 8) {

mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);

} else {

mAudioFocusHelper = null;

}

清理

前面提到過,一個MediaPlayer對象可以消耗掉大量的系統(tǒng)資源,所以你應該僅在需要它時保持它并在用完時立即釋放.明確的調用清理方法而不是依靠系統(tǒng)的垃圾收集機制是很重要的,因為在被收集之前MediaPlayer可能會存在很長時間,雖然此時它只是占用內存而不影響其它的媒體相關的資源.所以,當你使用一個service時,你應該總四重寫onDestroy()方法來保證釋放MediaPlayer:

[java]

public class MyService extends Service {

MediaPlayer mMediaPlayer;

// ...

@Override

public void onDestroy() {

if (mMediaPlayer != null) mMediaPlayer.release();

}

}

public class MyService extends Service {

MediaPlayer mMediaPlayer;

// ...

@Override

public void onDestroy() {

if (mMediaPlayer != null) mMediaPlayer.release();

}www.2cto.com

}

你也應該尋找其它需要釋放你的MediaPlayer的時機.例如,如果你預料到長時間不能播放媒體(比如丟掉音頻焦點以后),你應該明確地釋放你的MediaPlayer,然后在后面重新創(chuàng)建它.反過來,如果你預測到只會短時間停止播放,你應該保持你的MediaPlayer來避免過多的創(chuàng)建,而不是重新"準備"它.

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉