Android 藍(lán)牙(九)A2DP基本功能

轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/vnanyesheshou/article/details/71713786

本文主要是Android做為Audio Source端,A2DP的基本操作:包括連接、斷開(kāi)連接、設(shè)置優(yōu)先級(jí)、獲取優(yōu)先級(jí)、獲取A2DP連接狀態(tài)、獲取A2DP連接的設(shè)備列表等功能。


1 簡(jiǎn)介

A2DP全名是Advanced Audio Distribution Profile,高質(zhì)量音頻數(shù)據(jù)傳輸?shù)膮f(xié)議,其定義里了傳送單聲道或立體聲等高質(zhì)量音頻(區(qū)別于藍(lán)牙SCO鏈路上傳輸?shù)钠胀ㄕZ(yǔ)音)信息的協(xié)議和過(guò)程。A2DP的典型應(yīng)用是將音樂(lè)播放器的音頻數(shù)據(jù)發(fā)送到耳機(jī)或音箱。
A2DP定義了兩種角色:

Audio Source(音頻源) 音頻的輸入端對(duì)音頻數(shù)據(jù)進(jìn)行編碼,發(fā)送到Sink端。
Audio Sink(音頻接收器) 接收到音頻數(shù)據(jù)后,進(jìn)行解碼操作還原出音頻。


2 A2DP profile

要想操作A2DP相關(guān),首先要獲取A2DP代理對(duì)象,獲取代理對(duì)象的方法比較簡(jiǎn)單,如下:

mBtAdapter = BluetoothAdapter.getDefaultAdapter();
if(!mBtAdapter.isEnabled()){
    //彈出對(duì)話框提示用戶(hù)是后打開(kāi)  
    Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
    startActivityForResult(enabler, 1);
}
//獲取A2DP代理對(duì)象
mBtAdapter.getProfileProxy(mContext, mListener, BluetoothProfile.A2DP);

getProfileProxy并不會(huì)直接返回A2DP代理對(duì)象,而是通過(guò)mListener中回調(diào)獲取。

private ServiceListener mListener = new ServiceListener() {
    @Override
    public void onServiceDisconnected(int profile) {
        if(profile == BluetoothProfile.A2DP){
            mA2dp = null;
        }
    }
    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        if(profile == BluetoothProfile.A2DP){
            mA2dp = (BluetoothA2dp) proxy; //轉(zhuǎn)換
        }
    }
};

成功會(huì)回調(diào)mListener中的onServiceConnected函數(shù),判斷proflie是否為BluetoothProfile.A2DP,轉(zhuǎn)換為BluetoothA2dp對(duì)象。通過(guò)代理對(duì)象即可進(jìn)行A2DP的相關(guān)操作了。


3 A2DP操作

A2DP連接首先需要與藍(lán)牙耳機(jī)進(jìn)行配對(duì),如何配對(duì)這里就不細(xì)說(shuō)了。
我這里是連接到之前配對(duì)過(guò)的一個(gè)設(shè)備。設(shè)備名稱(chēng)為:

private final String BT_NAME = "QCY-QY7";

獲取該設(shè)備,首先獲取配對(duì)的藍(lán)牙設(shè)備,然后遍歷這些藍(lán)牙設(shè)備,找出藍(lán)牙名稱(chēng)符合條件的設(shè)備,就是要操作的設(shè)備,

//獲取配對(duì)的藍(lán)牙設(shè)備
Set<BluetoothDevice> bondDevice = mBtAdapter.getBondedDevices();
for(BluetoothDevice device:bondDevice){
    //獲取指定名稱(chēng)的設(shè)備
    if(BT_NAME.equals(device.getName())){
        mConnectDevice = device;
    }
}

mConnectDevice為要操作的設(shè)備。
1 A2DP連接

private void connectA2dp(BluetoothDevice device){
    setPriority(mConnectDevice, 100); //設(shè)置priority
    try {
        //通過(guò)反射獲取BluetoothA2dp中connect方法(hide的),進(jìn)行連接。
        Method connectMethod =BluetoothA2dp.class.getMethod("connect",
                BluetoothDevice.class);
        connectMethod.invoke(mA2dp, device);
    } catch (Exception e) {
        e.printStackTrace();
    } 
}

BluetoothA2dp中的connect方法是hide的,不能直接訪問(wèn),需要通過(guò)反射的機(jī)制獲取該方法進(jìn)行連接。連接成功后手機(jī)可以播放音樂(lè),聲音就會(huì)從藍(lán)牙耳機(jī)出來(lái)。
2 斷開(kāi)連接

private void disConnectA2dp(BluetoothDevice device){
    setPriority(mConnectDevice, 0);
    try {
        //通過(guò)反射獲取BluetoothA2dp中connect方法(hide的),斷開(kāi)連接。
        Method connectMethod =BluetoothA2dp.class.getMethod("disconnect",
                BluetoothDevice.class);
        connectMethod.invoke(mA2dp, device);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

BluetoothA2dp中的disconnect方法也是hide的,與connect類(lèi)似。
3 設(shè)置優(yōu)先級(jí)

變量
PRIORITY_OFF 0
PRIORITY_ON 100
PRIORITY_AUTO_CONNECT 1000
PRIORITY_UNDEFINED -1

設(shè)置優(yōu)先級(jí)是必要的,否則可能導(dǎo)致連接或斷開(kāi)連接失敗等問(wèn)題。

public void setPriority(BluetoothDevice device, int priority) {
    if (mA2dp == null) return;
    try {//通過(guò)反射獲取BluetoothA2dp中setPriority方法(hide的),設(shè)置優(yōu)先級(jí)
        Method connectMethod =BluetoothA2dp.class.getMethod("setPriority", 
                BluetoothDevice.class,int.class);
        connectMethod.invoke(mA2dp, device, priority);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4 獲取優(yōu)先級(jí)

public int getPriority(BluetoothDevice device) {
    int priority = 0;
    if (mA2dp == null) return priority;
    try {//通過(guò)反射獲取BluetoothA2dp中g(shù)etPriority方法(hide的),獲取優(yōu)先級(jí)
        Method connectMethod =BluetoothA2dp.class.getMethod("getPriority", 
                BluetoothDevice.class);
        priority = (Integer) connectMethod.invoke(mA2dp, device);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return priority;
}

5 獲取與某設(shè)備A2DP連接狀態(tài)

mA2dp.getConnectionState(device);

6 獲取連接設(shè)備列表

//返回值類(lèi)型List<BluetoothDevice>
mA2dp.getConnectedDevices();

7 A2DP是否正在發(fā)送音頻流

//返回值類(lèi)型boolean,表示設(shè)備是否在通過(guò)A2DP發(fā)送音頻流。
mA2dp.isA2dpPlaying(device);

4 狀態(tài)監(jiān)聽(tīng)

通過(guò)廣播接收者監(jiān)聽(tīng)A2DP連接狀態(tài)的改變,A2DP播放狀態(tài)的改變。

private void initReceiver(){
    //注冊(cè)廣播接收者監(jiān)聽(tīng)狀態(tài)改變
    IntentFilter filter = new IntentFilter(BluetoothA2dp.
            ACTION_CONNECTION_STATE_CHANGED);
    filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
    registerReceiver(mReceiver, filter);
}

廣播接收者,通過(guò)intent獲取狀態(tài)值。

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.i(TAG,"onReceive action="+action);
        //A2DP連接狀態(tài)改變
        if(action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)){
            int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED);
            Log.i(TAG,"connect state="+state);
        }else if(action.equals(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)){
            //A2DP播放狀態(tài)改變
            int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING);
            Log.i(TAG,"play state="+state);
        }
    }
};

有問(wèn)題歡迎交流指正。

歡迎大家關(guān)注、評(píng)論、點(diǎn)贊。
你們的支持是我堅(jiān)持的動(dòng)力。

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

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

  • 轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/vnanyesheshou/article/detail...
    朋永閱讀 4,707評(píng)論 0 0
  • A2DP簡(jiǎn)介 A2DP(Advanced Audio Distribution Profile):高質(zhì)量音頻數(shù)據(jù)傳...
    YoungTa0閱讀 3,162評(píng)論 1 4
  • 最近項(xiàng)目使用藍(lán)牙,之前并沒(méi)有接觸,還是發(fā)現(xiàn)了很多坑,查閱了很多資料,說(shuō)的迷迷糊糊,今天特查看官方文檔。 說(shuō)下遇到的...
    King9527閱讀 1,919評(píng)論 0 1
  • Android 平臺(tái)包含藍(lán)牙網(wǎng)絡(luò)堆棧支持,憑借此項(xiàng)支持,設(shè)備能以無(wú)線方式與其他藍(lán)牙設(shè)備交換數(shù)據(jù)。應(yīng)用框架提供了通過(guò)...
    虎三呀閱讀 881評(píng)論 0 1
  • 1 藍(lán)牙基礎(chǔ)知識(shí) 1.1 藍(lán)牙相關(guān)的權(quán)限 1.2 BluetoothAdapter兩種獲取對(duì)象的方法 1.3 藍(lán)牙...
    秀葉寒冬閱讀 850評(píng)論 0 3

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