在 Android 開發中,經典藍牙(BT 2.1/3.0+)支持多種協議,其中?RFCOMM/SPP(串口通信)、A2DP(音頻流傳輸)和?HFP(免提通話)是最常用的。以下是它們在 Android 中的實現詳解:
-
經典藍牙(BT 2.1/3.0+)
-
協議棧:RFCOMM(串口模擬)、SPP(串行端口協議)、A2DP(音頻傳輸)、HFP(免提協議)。
-
用途:大文件傳輸、音頻設備(耳機/音箱)。
-
帶寬:1-3 Mbps,功耗較高。
-
1. RFCOMM & SPP(串口通信)
協議作用
-
RFCOMM(Serial Port Emulation):模擬串口通信,提供可靠的串行數據傳輸(類似 UART)。
-
SPP(Serial Port Profile):基于 RFCOMM,定義藍牙設備間的虛擬串口通信標準。
Android 實現
1.1 權限申請
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android 12+ 需要額外權限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
1.2 設備配對與連接
// 獲取 BluetoothAdapter
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// 發現設備(需先啟用藍牙)
bluetoothAdapter.startDiscovery();// 綁定到已配對設備
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
BluetoothDevice targetDevice = pairedDevices.iterator().next(); // 示例:選擇第一個設備// 通過 UUID 建立 RFCOMM 連接(SPP 標準 UUID:00001101-0000-1000-8000-00805F9B34FB)
UUID sppUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothSocket socket = targetDevice.createRfcommSocketToServiceRecord(sppUuid);
socket.connect(); // 阻塞式連接,需在子線程執行
1.3 數據傳輸
// 獲取輸入輸出流
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();// 發送數據
outputStream.write("Hello Bluetooth".getBytes());// 接收數據(需循環讀取)
byte[] buffer = new byte[1024];
int bytes = inputStream.read(buffer);
String receivedData = new String(buffer, 0, bytes);
2. A2DP(高級音頻分發協議)
協議作用
-
用于藍牙立體聲音頻傳輸(如音樂播放),單向傳輸(手機→音箱)。
-
不支持麥克風(錄音需結合 HFP 或 SCO)。
Android 實現
2.1 權限
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
2.2 連接 A2DP 設備
// 獲取 A2DP 代理
BluetoothA2dp bluetoothA2dp = BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {if (profile == BluetoothProfile.A2DP) {bluetoothA2dp = (BluetoothA2dp) proxy;}}}, BluetoothProfile.A2DP
);// 連接設備(需已配對)
List<BluetoothDevice> connectedDevices = bluetoothA2dp.getConnectedDevices();
if (!connectedDevices.isEmpty()) {BluetoothDevice audioDevice = connectedDevices.get(0);
}
2.3 音頻路由控制
Android 實現
-
音頻默認通過 A2DP 設備播放(系統自動處理)。
-
可通過?
AudioManager
?強制切換:AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager.setBluetoothA2dpOn(true); // 啟用 A2DP 輸出
3. HFP(免提協議)
協議作用
-
支持藍牙通話功能(雙向音頻):麥克風輸入 + 聽筒輸出。
-
常用于車載免提、耳機通話場景。
3.1 權限
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
3.2 連接 HFP 設備
// 獲取 HFP 代理
BluetoothHeadset bluetoothHeadset = BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {if (profile == BluetoothProfile.HEADSET) {bluetoothHeadset = (BluetoothHeadset) proxy;}}}, BluetoothProfile.HEADSET
);// 檢查設備連接狀態
List<BluetoothDevice> connectedDevices = bluetoothHeadset.getConnectedDevices();
boolean isConnected = (connectedDevices.size() > 0);
3.3 通話控制
-
接聽/掛斷電話(需系統級權限,普通應用無法直接調用):
// 通過 Intent 間接控制(部分設備支持) Intent answerIntent = new Intent(Intent.ACTION_HEADSET_PLUG); answerIntent.putExtra("state", 1); // 1 接聽,0 掛斷 context.sendBroadcast(answerIntent);
-
音頻路由切換:
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager.setBluetoothScoOn(true); // 啟用 SCO 通道(通話音頻) audioManager.startBluetoothSco(); // 啟動 SCO 連接
關鍵區別總結
協議 | 方向 | 用途 | 音頻類型 | Android API 類 |
---|---|---|---|---|
RFCOMM | 雙向 | 串口數據通信 | 無 | BluetoothSocket |
A2DP | 單向(輸出) | 音樂播放 | 立體聲(16-bit) | BluetoothA2dp |
HFP | 雙向 | 通話(麥克風+聽筒) | 單聲道(8kHz) | BluetoothHeadset |
注意事項
-
藍牙權限:Android 12+ 需動態申請?
BLUETOOTH_CONNECT
。 -
主線程限制:所有藍牙操作(如?
connect()
)需在子線程執行。 -
設備兼容性:部分舊設備可能不支持 A2DP 或 HFP 的完整功能。