Android 藍芽連線之 A2dp
阿新 • • 發佈:2018-12-12
A2DPProfile 定義了高質量音訊資料傳輸的協議和過程,包括立體聲和單聲道資料的傳輸。這裡的高質量音訊指的是單聲道(Mono)和立體聲(Sterco) 的音訊,主要區別於藍牙 SCO 鏈路上傳輸的普通語音。A2DP 的典型應用是將音樂播放器的音訊資料傳送到耳機或音箱。
由於藍芽提供的頻寬較窄,音訊資料可能需要進行有效的壓縮才能保證接收端的實時播放。
目前 A2DP 只定義了點對點的音訊傳輸,沒有定義廣播式的音訊傳輸,可能是由於速率的原因。 A2DP 建立在 AVDTP 傳輸協議的基礎之上,AVDTP 規定了連結是如何建立的,連線建立好之後,音訊資料經過壓縮之後,便可以收發了。
直接上程式碼的吧,有很詳細的註釋,各位看官應該看起來問題不大:
public class BluetoothChatA2dpService { private BluetoothA2dp mA2dp; private String TAG = "BluetoothChatA2dpService"; private BluetoothDevice mConnectDevice; private BluetoothAdapter mBtAdapter; private static Context mContext; private static BluetoothChatA2dpService bluetoothA2dpChatService; private int callBackState = 0; public interface OnConnectionListener { void onConnectionStateChanged( BluetoothDevice bluetoothDevice, int state); } public interface OnBluetoothA2dpReadyListener { void onBluetoothA2dpReady(); } private OnBluetoothA2dpReadyListener onBluetoothA2dpReadyListener; public void setOnBluetoothA2dpReadyListener(OnBluetoothA2dpReadyListener listener) { onBluetoothA2dpReadyListener = listener; } private OnConnectionListener onConnectionListener; public void setOnConnectionListener(OnConnectionListener listener) { onConnectionListener = listener; } private BluetoothChatA2dpService() { initReceiver(); initBluetooth(); } public int getBluetoothDeviceA2dpStatus(BluetoothDevice bluetoothDevice) { if (mA2dp == null) { return -2; } return mA2dp.getConnectionState(bluetoothDevice); } private void initBluetooth() { mBtAdapter = BluetoothAdapter.getDefaultAdapter(); if (!mBtAdapter.isEnabled()) { return; } //獲取A2DP代理物件 mBtAdapter.getProfileProxy(mContext, mListener, BluetoothProfile.A2DP); } private void initReceiver() { //廣播接收者監聽狀態 IntentFilter filter = new IntentFilter(BluetoothA2dp. ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED); mContext.registerReceiver(mReceiver, filter); } public static BluetoothChatA2dpService getInstance(Context context) { if (context != null) { mContext = context.getApplicationContext(); if (bluetoothA2dpChatService == null) { bluetoothA2dpChatService = new BluetoothChatA2dpService(); } } else { throw new RuntimeException("The context is null!"); } return bluetoothA2dpChatService; } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); //A2DP連線狀態改變 if (action != null) { if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, BluetoothA2dp.STATE_DISCONNECTED); callBackA2dpConnectState(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); } } } }; private int callBackA2dpConnectState(int state) { if (onConnectionListener != null) { if (mA2dp == null) { //獲取A2DP代理物件 mBtAdapter.getProfileProxy(mContext, mListener, BluetoothProfile.A2DP); } if (state == BluetoothA2dp.STATE_DISCONNECTED) { getDisconnectDevices(); callBackState = ConnectionState.A2DP_DISCONNECTED; } else if (state == BluetoothA2dp.STATE_CONNECTING) { callBackState = ConnectionState.A2DP_CONNECTING; } else if (state == BluetoothA2dp.STATE_CONNECTED) { getConnectedDevices(); callBackState = ConnectionState.A2DP_CONNECTED; } else { callBackState = state; } Log.i(TAG, "connect state=" + state); if (onConnectionListener != null) { onConnectionListener.onConnectionStateChanged(mConnectDevice, callBackState); } } return callBackState; } private void getConnectedDevices() { if (mA2dp != null && mA2dp.getConnectedDevices() != null && mA2dp.getConnectedDevices().size() > 0) { for (int i = 0; i < mA2dp.getConnectedDevices().size(); i++) { Log.i(TAG, "connect device=" + mA2dp.getConnectedDevices().get(i)); mConnectDevice = mA2dp.getConnectedDevices().get(i); } } } private void getDisconnectDevices() { if (mA2dp != null && mA2dp.getConnectedDevices() != null && mA2dp.getConnectedDevices().size() > 0) { for (int i = 0; i < mA2dp.getConnectedDevices().size(); i++) { Log.i(TAG, "connect device=" + mA2dp.getConnectedDevices().get(i)); mConnectDevice = mA2dp.getConnectedDevices().get(i); getA2dpConnectState(); } } } private BluetoothProfile.ServiceListener mListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceDisconnected(int profile) { Log.i(TAG, "onServiceDisconnected profile=" + profile); if (profile == BluetoothProfile.A2DP) { mA2dp = null; } } @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { Log.i(TAG, "onServiceConnected profile=" + profile); if (profile == BluetoothProfile.A2DP) { mA2dp = (BluetoothA2dp) proxy; //轉換 if (onBluetoothA2dpReadyListener != null) { onBluetoothA2dpReadyListener.onBluetoothA2dpReady(); } } } }; public BluetoothDevice getCurrentConnectedA2dpDevice() { return mConnectDevice; } public void connectA2dp(BluetoothDevice device) { Log.i(TAG, "connect to device :" + device); mConnectDevice = device; setPriority(device, 100); //設定priority try { //通過反射獲取BluetoothA2dp中connect方法(hide的),進行連線。 Method connectMethod = BluetoothA2dp.class.getMethod("connect", BluetoothDevice.class); connectMethod.invoke(mA2dp, device); } catch (Exception e) { e.printStackTrace(); } } public void disConnectA2dp(BluetoothDevice device) { mConnectDevice = null; setPriority(device, 0); try { //通過反射獲取BluetoothA2dp中connect方法(hide的),斷開連線。 Method connectMethod = BluetoothA2dp.class.getMethod("disconnect", BluetoothDevice.class); connectMethod.invoke(mA2dp, device); } catch (Exception e) { e.printStackTrace(); } } 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; } 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(); } } public boolean isA2dpConnect(){ if(mA2dp != null && callBackState == ConnectionState.A2DP_CONNECTED){ return true; } return false; } public boolean isNativeA2dpConnect(){ LogManager.i(TAG, "isNativeA2dpConnect = " + mBtAdapter.getProfileConnectionState(BluetoothProfile.A2DP)); if(mA2dp!= null && mBtAdapter.getProfileConnectionState(BluetoothProfile.A2DP) == BluetoothA2dp.STATE_CONNECTED){ return true; } return false; } public int getA2dpConnectState() { int a2dpState = 0; if (mBtAdapter.isEnabled()) { a2dpState = mBtAdapter.getProfileConnectionState(BluetoothProfile.A2DP); // 可操控藍芽裝置,如帶播放暫停功能的藍芽耳機 LogManager.i(TAG, "getA2dpConnectState 當前a2dp狀態為 = " + a2dpState); } else { LogManager.e(TAG, "藍芽未開啟,查詢藍芽a2dp狀態失敗"); } return callBackA2dpConnectState(a2dpState); } }
使用:
BluetoothChatA2dpService.getInstance(this).connectA2dp(device)
最後祝大家過去快樂!