Android藍(lán)牙-A2DP開(kāi)發(fā)

A2DP簡(jiǎn)介

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

開(kāi)發(fā)流程

1.獲取藍(lán)牙適配器
mAdapter = BluetoothAdapter.getDefaultAdapter();
2.獲取A2DP代理
不能直接獲取proxy,只能在onServiceConnected()回調(diào)中獲取

mAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                mA2dp = (BluetoothA2dp) proxy;
            }

            @Override
            public void onServiceDisconnected(int profile) {

            }
        }, BluetoothProfile.A2DP);

3.注冊(cè)藍(lán)牙接收廣播
開(kāi)啟搜索設(shè)備后,搜索結(jié)果通過(guò)廣播傳輸
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
4.搜索設(shè)備
mAdapter.startDiscovery();
5.獲取搜索結(jié)果
從BluetoothDevice.ACTION_FOUND廣播中獲取
6.連接設(shè)備
mA2dp.getClass().getMethod("connect",BluetoothDevice.class).invoke(mA2dp, device);

3.代碼實(shí)現(xiàn)

public class A2DPManager {
    public static final String TAG = A2DPManager.class.getName();
    private static A2DPManager mManager;
    private BluetoothAdapter mAdapter;
    private BluetoothA2dp mA2dp;
    private List<BluetoothDevice> result;

    public static A2DPManager getInstance(Context context) {
        if (mManager == null) {
            mManager = new A2DPManager(context);
        }
        return mManager;
    }

    private A2DPManager(Context context) {
        result = new ArrayList<>();
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                mA2dp = (BluetoothA2dp) proxy;
            }

            @Override
            public void onServiceDisconnected(int profile) {

            }
        }, BluetoothProfile.A2DP);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        context.registerReceiver(mReceiver,intentFilter);
    }

    /**
     * 打開(kāi)藍(lán)牙
     */
    public void enableA2DP() {
        if (!mAdapter.isEnabled()) {
            mAdapter.enable();
        }
    }

    /**
     * 關(guān)閉藍(lán)牙
     */
    public void disableA2DP() {
        if (mAdapter.isEnabled()) {
            mAdapter.disable();
        }
    }

    public void discovery() {
        if (mAdapter.isDiscovering()) {
            mAdapter.cancelDiscovery();
        }
        if (!result.isEmpty()) {
            result.clear();
        }
        if (mAdapter.isEnabled()) {
            mAdapter.startDiscovery();
        } else {
            //如果剛打開(kāi)藍(lán)牙,藍(lán)牙還沒(méi)有初始化成功,需要等待藍(lán)牙初始化成功后才能搜索藍(lán)牙設(shè)備
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mAdapter.startDiscovery();
                }
            }, 1000);
        }


    }

    /**
     * 連接設(shè)備
     *
     * @param device
     */
    public void connect(BluetoothDevice device) {
        if (device == null) {
            return;
        }
        if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
            //如果設(shè)備未配對(duì),先進(jìn)行配對(duì),收到配對(duì)成功廣播后,連接設(shè)備
            pair(device);
        } else {
            if (mA2dp != null) {
                if (mA2dp.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
                    try {
                        boolean connect = (boolean) mA2dp.getClass()
                                .getMethod("connect", BluetoothDevice.class)
                                .invoke(mA2dp, device);
                        Log.d(TAG, "connect:" + connect);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    Log.d(TAG, "設(shè)備已經(jīng)連接");
                }
            }
        }
    }


    /**
     * 斷開(kāi)設(shè)備
     *
     * @param device
     */
    public boolean disConnect(BluetoothDevice device) {
        if (device == null) {
            return false;
        }
        boolean disConnect = false;
        if (mA2dp != null) {
            if (mA2dp.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) {
                try {
                    disConnect = (boolean) mA2dp.getClass()
                            .getMethod("disconnect", BluetoothDevice.class)
                            .invoke(mA2dp, device);
                    Log.d(TAG, "disconnect:" + disConnect);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return disConnect;
    }

    /**
     * 藍(lán)牙配對(duì)
     *
     * @param device
     */
    public void pair(final BluetoothDevice device) {
        HandlerThread handlerThread = new HandlerThread("pair");
        handlerThread.start();
        Handler pairHandler = new Handler(handlerThread.getLooper());
        pairHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    Method method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
                    BluetoothSocket socket = (BluetoothSocket) method.invoke(device, 1);
                    socket.connect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 獲取已經(jīng)配對(duì)的設(shè)備
     */
    public Set<BluetoothDevice> getBondeDevices() {
        return mAdapter.getBondedDevices();
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "action:" + action);
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (action.equals(BluetoothDevice.ACTION_FOUND)) {
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    if (device.getName() != null) {
                        result.add(device);
                        Log.d(TAG, "deviceName:" + device.getName());
                    }
                }
            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "正在配對(duì)");
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "完成配對(duì)");
                        A2DPManager.getInstance(context).connect(device);
                        break;
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "取消配對(duì)");
                        break;
                    default:
                        break;
                }
            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                Log.d(TAG, "搜索完成");
                result.addAll(A2DPManager.getInstance(context).getBondeDevices());
                EventBus.getDefault().post(result);
            } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
                Log.d(TAG, "狀態(tài)變化");
            }
        }
    };

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容