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)變化");
}
}
};
}