Android藍芽串列埠通訊

weixin_33978044發表於2017-06-11

藍芽串列埠模組是嵌入式裝置上的常用模組,它可以方便地和手機建立連線,實時傳輸資料。本文介紹Android裝置與藍芽串列埠通訊的具體實現。

一、流程圖

本文以Android藍芽客戶端為例介紹從開啟藍芽到收發資料的完整流程,對藍芽服務端程式不作介紹,請讀者舉一反三。下圖為Android藍芽客戶端的流程圖。

1186132-6e846c60ac9ffcfb.png

下面分步詳細介紹。文中只給出每一步的關鍵程式碼,整個例程的完整程式碼將在文末給出。

二、開啟藍芽

通過啟動指定的Action來請求系統開啟藍芽。這幾行程式碼的效果相當於點選手機頂部下拉框中的藍芽按鈕。

// 獲取藍芽介面卡
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

//請求開啟藍芽
if (!mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

三、搜尋裝置

首先找出已匹配的藍芽裝置列表。

// 將已配對的裝置新增到列表中
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
    for (BluetoothDevice device : pairedDevices) {
        mDevicesArray.add(device.getName() + "\n" + device.getAddress());
        deviceList.add(device);
    }
}

再開始搜尋附近的藍芽裝置,建立一個廣播接收器以獲取搜尋結果。

// 註冊廣播接收器,以獲取藍芽裝置搜尋結果
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
// 搜尋藍芽裝置
mBluetoothAdapter.startDiscovery();

這裡用到的廣播接收器定義如下。注意最後需要呼叫notifyDataSetChanged方法,否則新搜尋到的裝置不會更新到ListView中。

// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        // When discovery finds a device
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            deviceList.add(device);
            // Add the name and address to an array adapter to show in a ListView
            mDevicesArray.add(device.getName() + "\n" + device.getAddress());
            // Notify ListView to update
            devicesListAdapter.notifyDataSetChanged();
        }
    }
};

四、匹配並建立連線

通過呼叫BluetoothDevice物件的createRfcommSocketToServiceRecord方法可以獲取一個socket。該方法需要傳入藍芽裝置的UUID。通常,對於不同的服務需要設定不同的UUID,本文設定為針對藍芽串列埠服務的UUID,其它常用的UUID可見文末的參考資料。成功獲得socket物件之後,呼叫其上的connet方法即可匹配並建立連線。在Android系統中,不需要執行單獨的匹配操作,建立連線時,系統會自動對未匹配的裝置嘗試匹配,必要時會要求使用者輸入Pin碼。

BluetoothSocket socket = null;
try {
    // 藍芽串列埠服務對應的UUID。如使用的是其它藍芽服務,需更改下面的字串
    UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    socket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (Exception e) {
    Log.d("log", "獲取Socket失敗");
    return;
}
try {
    // Connect the device through the socket. This will block
    // until it succeeds or throws an exception
    socket.connect();
    Log.d("log", "連線成功");
} catch (IOException connectException) {
    // Unable to connect; close the socket and get out
    Log.d("log", "連線失敗");
    try {
        socket.close();
    } catch (IOException closeException) { }
    return;
}

五、收發資料

只需要從socket中獲取輸入輸出流,再呼叫read和write方法就可以實現資料的傳送與接收。原理很簡單,不過具體使用時需要考慮如何迴圈讀取資料。一般是建立一個新執行緒專門用於讀取資料,否則read方法將會阻塞主執行緒。下面的程式碼只說明瞭資料收發的基本用法。

mmInStream = socket.getInputStream();
mmOutStream = socket.getOutputStream();

//接收資料
byte[] buffer = new byte[1024];
try {
    bytes = mmInStream.read(buffer);
} catch (IOException e) {
    break;
}

//傳送資料
try {
    mmOutStream.write(bytes);
} catch (IOException e) { }

六、總結

本文把Android與藍芽串列埠通訊的整個流程做了最大程度上的簡化,只突出核心功能程式碼。而具體應用時則需要考慮更多的實際情況,包括介面的佈局等等。關於Android系統針對藍芽裝置提供的API的總體介紹,建議閱讀參考資料中的第一篇。

完整程式碼下載地址:https://github.com/jingedawang/BluetoothDemo

下圖是在華為手機上的執行效果。

1186132-779a6eca28ee368f.png
QQ圖片20170611204323.png

七、參考資料

Android經典藍芽開發簡介 Chuckiefan
關於藍芽服務對應的UUID碼 ZF_Chen

相關文章