天天看點

Android 藍牙開發(九)A2DP基本功能

轉載請注明出處:http://blog.csdn.net/vnanyesheshou/article/details/71713786

本文主要是Android做為Audio Source端,A2DP的基本操作:包括連接配接、斷開連接配接、設定優先級、擷取優先級、擷取A2DP連接配接狀态、擷取A2DP連接配接的裝置清單等功能。

##

1 簡介 ##

A2DP全名是Advanced Audio Distribution Profile,高品質音頻資料傳輸的協定,其定義裡了傳送單聲道或立體聲等高品質音頻(差別于藍牙SCO鍊路上傳輸的普通語音)資訊的協定和過程。A2DP的典型應用是将音樂播放器的音頻資料發送到耳機或音箱。

A2DP定義了兩種角色:

Audio Source(音頻源) 音頻的輸入端對音頻資料進行編碼,發送到Sink端。

Audio Sink(音頻接收器) 接收到音頻資料後,進行解碼操作還原出音頻。

##

2 A2DP profile ##

要想操作A2DP相關,首先要擷取A2DP代理對象,擷取代理對象的方法比較簡單,如下:

mBtAdapter = BluetoothAdapter.getDefaultAdapter();
if(!mBtAdapter.isEnabled()){
	//彈出對話框提示使用者是後打開  
	Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
	startActivityForResult(enabler, 1);
}
//擷取A2DP代理對象
mBtAdapter.getProfileProxy(mContext, mListener, BluetoothProfile.A2DP);
           

getProfileProxy并不會直接傳回A2DP代理對象,而是通過mListener中回調擷取。

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; //轉換
		}
	}
};
           

成功會回調mListener中的onServiceConnected函數,判斷proflie是否為BluetoothProfile.A2DP,轉換為BluetoothA2dp對象。通過代理對象即可進行A2DP的相關操作了。

##

3 A2DP操作 ##

A2DP連接配接首先需要與藍牙耳機進行配對,如何配對這裡就不細說了。

我這裡是連接配接到之前配對過的一個裝置。裝置名稱為:

private final String BT_NAME = "QCY-QY7";
           

擷取該裝置,首先擷取配對的藍牙裝置,然後周遊這些藍牙裝置,找出藍牙名稱符合條件的裝置,就是要操作的裝置,

//擷取配對的藍牙裝置
Set<BluetoothDevice> bondDevice = mBtAdapter.getBondedDevices();
for(BluetoothDevice device:bondDevice){
	//擷取指定名稱的裝置
	if(BT_NAME.equals(device.getName())){
		mConnectDevice = device;
	}
}
           

mConnectDevice為要操作的裝置。

1 A2DP連接配接

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

BluetoothA2dp中的connect方法是hide的,不能直接通路,需要通過反射的機制擷取該方法進行連接配接。連接配接成功後手機可以播放音樂,聲音就會從藍牙耳機出來。

2 斷開連接配接

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

BluetoothA2dp中的disconnect方法也是hide的,與connect類似。

3 設定優先級

變量
PRIORITY_OFF
PRIORITY_ON 100
PRIORITY_AUTO_CONNECT 1000
PRIORITY_UNDEFINED -1

設定優先級是必要的,否則可能導緻連接配接或斷開連接配接失敗等問題。

public void setPriority(BluetoothDevice device, int priority) {
    if (mA2dp == null) return;
    try {//通過反射擷取BluetoothA2dp中setPriority方法(hide的),設定優先級
    	Method connectMethod =BluetoothA2dp.class.getMethod("setPriority", 
    			BluetoothDevice.class,int.class);
    	connectMethod.invoke(mA2dp, device, priority);
    } catch (Exception e) {
		e.printStackTrace();
	}
}
           

4 擷取優先級

public int getPriority(BluetoothDevice device) {
	int priority = 0;
    if (mA2dp == null) return priority;
    try {//通過反射擷取BluetoothA2dp中getPriority方法(hide的),擷取優先級
    	Method connectMethod =BluetoothA2dp.class.getMethod("getPriority", 
    			BluetoothDevice.class);
    	priority = (Integer) connectMethod.invoke(mA2dp, device);
    } catch (Exception e) {
		e.printStackTrace();
	}
    return priority;
}
           

5 擷取與某裝置A2DP連接配接狀态

mA2dp.getConnectionState(device);
           

6 擷取連接配接裝置清單

//傳回值類型List<BluetoothDevice>
mA2dp.getConnectedDevices();
           

7 A2DP是否正在發送音頻流

//傳回值類型boolean,表示裝置是否在通過A2DP發送音頻流。
mA2dp.isA2dpPlaying(device);
           

##

4 狀态監聽 ##

通過廣播接收者監聽A2DP連接配接狀态的改變,A2DP播放狀态的改變。

private void initReceiver(){
	//注冊廣播接收者監聽狀态改變
	IntentFilter filter = new IntentFilter(BluetoothA2dp.
			ACTION_CONNECTION_STATE_CHANGED);
	filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
	registerReceiver(mReceiver, filter);
}
           

廣播接收者,通過intent擷取狀态值。

private BroadcastReceiver mReceiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		Log.i(TAG,"onReceive action="+action);
		//A2DP連接配接狀态改變
		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播放狀态改變
			int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_NOT_PLAYING);
			Log.i(TAG,"play state="+state);
		}
	}
};
           

有問題歡迎交流指正。

連接配接小demo:http://www.demodashi.com/demo/14624.html

歡迎掃一掃關注我的微信公衆号,定期推送優質技術文章:
Android 藍牙開發(九)A2DP基本功能