Android音頻焦點詳解(上)

轉(zhuǎn)載請注明出處:http://www.itdecent.cn/p/5d8d7b677690


2017年開年第一篇博客,很早就想總結(jié)一下Android音頻的相關(guān)知識。
今天我們先來看一下音頻焦點的相關(guān)內(nèi)容,分為上下篇,上篇主要介紹音頻焦點在媒體類應(yīng)用中的使用,下篇進(jìn)行源碼分析,我們學(xué)習(xí)源碼不僅僅是為了更深入的了解,更主要的目的是學(xué)習(xí)Android的設(shè)計架構(gòu),為我們在平時開發(fā)過程中提供一些優(yōu)秀的設(shè)計思想。

一 焦點在Android應(yīng)用中的作用

我們的手機里經(jīng)常會安裝一些媒體類的應(yīng)用,例如網(wǎng)易云音樂,QQ音樂,愛奇藝視頻,優(yōu)酷視頻等等,你有沒有想過,當(dāng)我們聽QQ音樂的歌曲時,切換到網(wǎng)易云音樂播放歌曲,或者打開愛奇藝觀看視頻時,QQ音樂播放的歌曲就會暫停,這是為什么呢?又是如何實現(xiàn)的呢?如果不暫停會是什么效果呢?
以上這些疑問都可以用音頻焦點來解釋,在下面的內(nèi)容中你將找到答案。

二 焦點講解

眾所周知Android是一個開放的系統(tǒng),為了協(xié)調(diào)各媒體應(yīng)用之間的關(guān)系,Android增加了音頻焦點管理機制,各應(yīng)用開發(fā)者應(yīng)盡量遵循該機制進(jìn)行開發(fā)。
我們通過一個例子來講解Android的焦點機制。
新建一個Activity,在其中增加一個播放暫停按鈕,來控制音樂播放。
看一下部分關(guān)鍵代碼,全部代碼在文末會給出

    private void initData() {
        //1 初始化AudioManager對象
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        //2 申請焦點
        mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        AssetFileDescriptor fileDescriptor;
        try {
            //3 獲取音頻文件,我從網(wǎng)上下載的歌曲,放到了assets目錄下
            fileDescriptor = this.getAssets().openFd("littlelucky.mp3");
            //4 實例化MediaPlayer對象
            mMediaPlayer = new MediaPlayer();
            //5 設(shè)置播放流類型
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            //6 設(shè)置播放源,有多個參數(shù)可以選擇,具體參考相關(guān)文檔,本文旨在介紹音頻焦點
            mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),
                    fileDescriptor.getStartOffset(),
                    fileDescriptor.getLength());
            //7 設(shè)置循環(huán)播放
            mMediaPlayer.setLooping(true);
            //8 準(zhǔn)備監(jiān)聽
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    //9 準(zhǔn)備完成后自動播放
                    mMediaPlayer.start();
                }
            });
            //10 異步準(zhǔn)備
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

涉及到的MediaPlayer播放音樂流程請自行查詢相關(guān)文檔,不在本文介紹范圍
我們重點看一下第2步 申請焦點
通過AudioManager對象調(diào)用requestAudioFocus方法,有三個參數(shù)
OnAudioFocusChangeListener l,int streamType,int durationHint
1 焦點變化的監(jiān)聽器

private AudioManager.OnAudioFocusChangeListener mAudioFocusChange = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch (focusChange){
                case AudioManager.AUDIOFOCUS_LOSS:
                    //長時間丟失焦點,當(dāng)其他應(yīng)用申請的焦點為AUDIOFOCUS_GAIN時,
                    //會觸發(fā)此回調(diào)事件,例如播放QQ音樂,網(wǎng)易云音樂等
                    //通常需要暫停音樂播放,若沒有暫停播放就會出現(xiàn)和其他音樂同時輸出聲音
                    Log.d(TAG, "AUDIOFOCUS_LOSS");
                    stop();
                    //釋放焦點,該方法可根據(jù)需要來決定是否調(diào)用
                    //若焦點釋放掉之后,將不會再自動獲得
                    mAudioManager.abandonAudioFocus(mAudioFocusChange);
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    //短暫性丟失焦點,當(dāng)其他應(yīng)用申請AUDIOFOCUS_GAIN_TRANSIENT或AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE時,
                    //會觸發(fā)此回調(diào)事件,例如播放短視頻,撥打電話等。
                    //通常需要暫停音樂播放
                    stop();
                    Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT");
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    //短暫性丟失焦點并作降音處理
                    Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    //當(dāng)其他應(yīng)用申請焦點之后又釋放焦點會觸發(fā)此回調(diào)
                    //可重新播放音樂
                    Log.d(TAG, "AUDIOFOCUS_GAIN");
                    start();
                    break;
            }
        }
    };

2 streamType音源類型,在AudioManager中定義

/** 通話 */
public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
/** 系統(tǒng)聲音 */
public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
/** 鈴聲 */
public static final int STREAM_RING = AudioSystem.STREAM_RING;
/** 音樂 */
public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
/** 鬧鈴聲 */
public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
/** 通知音 */
public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
/** @hide 藍(lán)牙電話 */
public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
/** @hide 強制的系統(tǒng)聲音 */
public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
/** DTMF撥號音 */
public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
/** @hide 文本識別音 */
public static final int STREAM_TTS = AudioSystem.STREAM_TTS;

3 durationHint 獲得焦點的時間長短
在AudioManager中定義了四種類型

AUDIOFOCUS_GAIN //長時間獲得焦點
AUDIOFOCUS_GAIN_TRANSIENT //短暫性獲得焦點,用完應(yīng)立即釋放
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK //短暫性獲得焦點并降音,可混音播放
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE //短暫性獲得焦點,錄音或者語音識別

我們可根據(jù)自己的應(yīng)用的使用場景來合理的配置每個參數(shù),并在焦點變化監(jiān)聽器來做相應(yīng)的處理。
調(diào)試代碼已上傳github,歡迎訪問

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,917評論 25 709
  • Media Playback Android多媒體框架包涵了對播放多種通用媒體的類型的支持,所以你可以很容易的集成...
    VegetableAD閱讀 977評論 0 0
  • 因為系統(tǒng)中可能會有多個應(yīng)用程序會播放音頻,所以需要考慮他們之間該如何交互,為了避免多個應(yīng)用程序同時播放音樂,...
    ZebraWei閱讀 3,327評論 0 1
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 7,317評論 0 17
  • 1、測試方法上必須使用@Test 注解 2、測試方法必須是 public void 進(jìn)行修飾,并且不帶參數(shù) 3、通...
    嘻嘻來打我閱讀 249評論 0 0

友情鏈接更多精彩內(nèi)容