1. 程式人生 > >Android基於藍芽串列埠程式設計實現HC-05通訊

Android基於藍芽串列埠程式設計實現HC-05通訊

Android基於藍芽串列埠程式設計實現HC-05通訊

最近接了個工程自動化的專案,需求是實時接收從微控制器傳過來的資料,並進行資料分析處理再進行顯示,在查閱大量的相關部落格和自己踩了不少的坑後,想說把自己的一些經驗分享出來給後來人做個參考www

先介紹下藍芽串列埠的定義

藍芽串列埠是基於SPP協議(Serial Port Profile),能在藍芽裝置之間建立串列埠進行資料傳輸的一種裝置。藍芽串列埠的目的是針對如何在兩個不同裝置(通訊的兩端)上的應用之間保證一條完整的通訊路徑。

目前應用商店可以下載到的藍芽串列埠app就是基於SPP協議,而有一些藍芽搜尋app搜尋不到HC-05就是由於沒有實現藍芽串列埠服務。要想要在自己的app內實現SPP協議需要服務對應的UUID,藍芽串列埠服務的UUID為:

SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}' 

更多的手機藍芽各類服務對應的UUID,可以通過下面這個網站進行查詢:
https://www.douban.com/group/topic/20009323/

順便講下藍芽串列埠app的使用,首先需要在系統設定裡,連線上HC-05的藍芽,預設配對密碼為1234,預設波特率為9600,預設名為HC-05。最好在連線後再看一下對應的MAC地址,因為我做的是單一連線,微控制器同一時間只能接入一個藍芽裝置,所以需求對更改連線藍芽模組需求要求不大,如果使用者不在建立專案時更改裝置MAC地址,則使用的就是預設的MAC地址,所以也沒有做選擇藍芽裝置的模組。

部落格附本專案截圖以及專案原始碼地址。

需要的許可權

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 6.0以上需要加的額外許可權 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

獲取藍芽介面卡

mBluetoothAdapter =
BluetoothAdapter.getDefaultAdapter();

不支援藍芽時

// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
	Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
	finish();
}

繫結藍芽裝置

// String MACAddr = "xx:xx:xx:xx:xx:xx";
BluetoothDevice bluetoothDevice = mBluetoothAdapter.getRemoteDevice(MACAddr);

*如果檢測到藍芽沒開啟,呼叫系統藍芽設定(可選)

Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intent);

連線裝置,開啟藍芽連線執行緒

public void connect(BluetoothDevice device) {
		printLog("connect to: " + device);
		// Start the thread to connect with the given device
		mConnectThread = new ConnectThread(device);
		mConnectThread.start();
	}

連線執行緒

/**
     * This thread runs while attempting to make an outgoing connection with a
     * device. It runs straight through; the connection either succeeds or
     * fails.
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            mmDevice = device;
            BluetoothSocket tmp = null;

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(App.SPP_UUID));
            } catch (IOException e) {
                printLog("create() failed" + e);
            }
            mmSocket = tmp;
        }

        public void run() {
            if (Thread.interrupted())
                return;
            setName("ConnectThread");

            // Always cancel discovery because it will slow down a connection
            mBluetoothAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                isBlueToothConnected = true;
                mmSocket.connect();
            } catch (IOException e) {

                printLog("unable to connect() socket " + e);
                handler.sendEmptyMessage(NOT_CONNECT);
                isBlueToothConnected = false;
                // Close the socket
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    printLog("unable to close() socket during connection failure" + e2);
                }
                return;
            }

            mConnectThread = null;

            isBlueToothConnected = true;

            // Start the connected thread
            // Start the thread to manage the connection and perform
            // transmissions
            handler.sendEmptyMessage(CONNECT_SUCCESS);

            mConnectedThread = new ConnectedThread(mmSocket);
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                printLog("close() of connect socket failed" + e);
            }
        }
    }

資料傳輸執行緒(可讀可寫,需求只用讀取)

**
     * This thread runs during a connection with a remote device. It handles all
     * incoming and outgoing transmissions.
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            printLog("create ConnectedThread");
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                printLog("temp sockets not created" + e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            if (Thread.interrupted()) {
                printLog("return");
                return;
            }
            printLog("BEGIN mConnectedThread");
            byte[] buffer = new byte[256];
            int bytes;

            // Keep listening to the InputStream while connected
            while (true) {
                synchronized (this) {
                    try {
                        // Read from the InputStream
                        bytes = mmInStream.read(buffer);
                        
                        Message msg = new Message();
                        msg.what = GET_DATA;
                        Bundle bundle = new Bundle();
                        bundle.putInt("data", buffer[0]);
                        msg.setData(bundle);
                        
                        handler.sendMessage(msg);
                    } catch (IOException e) {
                        printLog("disconnected " + e);
//                        handler.sendEmptyMessage(OUT_OF_CONNECTED);
                        break;
                    }
                }
            }
        }

        /**
         * Write to the connected OutStream.
         *
         * @param buffer The bytes to write
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

停止藍芽連線

private void stopBlutoothThread() {
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
    }

專案截圖
010203
原始碼可以在我的Github上看到
專案地址:https://github.com/WithLei/DistanceMeasure