1. 程式人生 > >Android 藍芽連線之 A2dp

Android 藍芽連線之 A2dp

      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)

最後祝大家過去快樂!