android 手機與藍芽裝置之間連線與通訊,附DEMO下載地址
阿新 • • 發佈:2019-02-10
下載地址為文章最後面。。。
該文章主要用於手機藍芽App介面的操作和通訊,儲存到本地的通訊後資料txt文字檔案
1.主要包括介面
2.AndroidManifest.xml需要用到的許可權
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <!-- SD卡操作許可權 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3.主要的藍芽工具類:
package com.example.bluetooth; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import com.example.main.MainActivity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; /** * 藍芽服務類,包括藍芽連線監聽執行緒、連線執行緒、已連線執行緒 * @author Administrator * */ public class BluetoothService { private static final String TAG = "Service"; private static final boolean DEBUG = true; // 藍芽埠名 private static final String BT_NAME = "XULANG"; // 獲取裝置UUID private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int BtState; //藍芽狀態常量 public static final int IDLE = 0; // 閒置 public static final int LISTENING = 1; // 監聽 public static final int CONNECTING = 2; // 正在連線 public static final int CONNECTED = 3; // 已連線 public static boolean allowRec=true; /** * @param handler 線上程與UI間通訊 */ public BluetoothService(Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); BtState = IDLE; mHandler = handler; } /** * 設定當前藍芽狀態 * @param state 當前藍芽狀態 */ private synchronized void setState(int state) { BtState = state; } /** * 獲取當前藍芽狀態 * @return 當前藍芽狀態 */ public synchronized int getState() { return BtState; } /** * 啟動本地藍芽接收監聽 */ public synchronized void acceptWait() { if (DEBUG) Log.e(TAG, "進入acceptWait"); // 開啟外主藍芽接收監聽執行緒 if (mAcceptThread == null&&mConnectedThread==null) { mAcceptThread = new AcceptThread(); mAcceptThread.start(); } setState(LISTENING); } /** * 開啟連線執行緒方法 * @param device 欲連線的裝置 */ public synchronized void connect(BluetoothDevice device) { if (DEBUG) Log.e(TAG, "正在連線" + device); //關閉所有可能的藍芽服務執行緒以便開啟連線執行緒 cancelAllBtThread(); // 開啟連線執行緒 mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(CONNECTING); } /** * 開啟已連線執行緒的方法 * @param socket 已建立連線的藍芽埠 * @param device 已連線的藍芽裝置 */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { if (DEBUG) Log.e(TAG, "connected"); //關閉所有可能的藍芽服務執行緒以便開啟已連線執行緒 cancelAllBtThread(); // 開啟已連線執行緒 mConnectedThread = new ConnectedThread(socket); mConnectedThread.start(); //傳送已連線裝置名回UI sendString2UI(MainActivity.CONNECTED_DEVICE_NAME, MainActivity.DEVICE_NAME,device.getName()); setState(CONNECTED); } /** * 關閉所有藍芽服務執行緒 */ public synchronized void cancelAllBtThread() { if (DEBUG) Log.e(TAG, "cancelAllBtThread方法"); if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} setState(IDLE); } /** * 寫輸出資料 * @param out 輸出位元組流 * @see ConnectedThread#write(byte[]) */ public void write(byte[] out) { // object ConnectedThread r; // 同步 synchronized (this) { if (BtState != CONNECTED) return; r = mConnectedThread; } r.write(out); } /** * 連線失敗處理方法 */ private void connectionFailed() { setState(LISTENING); mConnectedThread=null; BluetoothService.this.acceptWait(); //向UI傳送連線失敗通知 sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"連線失敗"); } /** * 傳送字串會UI * @param what 什麼型別 * @param key 關鍵字 * @param str 字串 */ private void sendString2UI(int what,String key,String str){ Message msg = mHandler.obtainMessage(what); Bundle bundle = new Bundle(); bundle.putString(key, str); msg.setData(bundle); mHandler.sendMessage(msg); } /** * 連線斷開處理方法 */ private void connectionBreak() { setState(LISTENING); mConnectedThread=null; BluetoothService.this.acceptWait(); // 向UI傳送連線斷開通知 sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"連線斷開"); } /** * 監聽外部主藍芽裝置執行緒 */ private class AcceptThread extends Thread { private final BluetoothServerSocket mBtServSocket; public AcceptThread() { BluetoothServerSocket bss = null; // 獲取藍芽監聽埠 try { bss = mAdapter.listenUsingRfcommWithServiceRecord(BT_NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "listen() failed", e); } mBtServSocket = bss; } public void run() { if (DEBUG) Log.e(TAG, "Begin mAcceptThread"); setName("AcceptThread"); BluetoothSocket socket = null; // 監聽埠直到連線上 while (BtState != CONNECTED) { try { //成功連線時退出迴圈 socket = mBtServSocket.accept(); } catch (IOException e) { Log.e(TAG, "accept() failed", e); break; } // 成功接收主裝置 if (socket != null) { synchronized (BluetoothService.this) { switch (BtState) { case LISTENING: case CONNECTING: // 啟動已連線執行緒 connected(socket, socket.getRemoteDevice()); break; case IDLE: case CONNECTED: try { socket.close(); } catch (IOException e) { Log.e(TAG, "Could not close unwanted socket", e); } break; } } } } if (DEBUG) Log.e(TAG, "End mAcceptThread"); } public void cancel() { if (DEBUG) Log.e(TAG, "cancel " + this); try { mBtServSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of server failed", e); } } } /** * 連線藍芽裝置的執行緒 */ private class ConnectThread extends Thread { private final BluetoothSocket mBtSocket; private final BluetoothDevice mBtDevice; public ConnectThread(BluetoothDevice device) { mBtDevice = device; BluetoothSocket bs = null; // 根據UUID獲取欲連線裝置 try { bs = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "create() failed", e); } mBtSocket = bs; } public void run() { if (DEBUG) Log.e(TAG, "Begin mConnectThread"); setName("ConnectThread"); // 嘗試連線藍芽埠 try { mBtSocket.connect(); } catch (IOException e) { // 當連線失敗或異常 connectionFailed(); try { mBtSocket.close(); } catch (IOException e2) { Log.e(TAG, "close() fail", e2); } // 重新開啟連線監聽執行緒並退出連線執行緒 BluetoothService.this.acceptWait(); if (DEBUG) Log.d(TAG, "End mConnectThread"); return; } synchronized (BluetoothService.this) { mConnectThread = null; } // 啟動已連線執行緒 connected(mBtSocket, mBtDevice); if (DEBUG) Log.d(TAG, "End mConnectThread"); } public void cancel() { if (DEBUG) Log.e(TAG, "cancel " + this); try { mBtSocket.close(); } catch (IOException e) { Log.e(TAG, "close() fail", e); } } } /** * 已連線的相關處理執行緒 */ private class ConnectedThread extends Thread { private final BluetoothSocket mBtSocket; private final InputStream mInputStream; private final OutputStream mOutputStream; public ConnectedThread(BluetoothSocket socket) { if (DEBUG) Log.d(TAG, "construct ConnectedThread"); mBtSocket = socket; InputStream is = null; OutputStream os = null; // 獲取輸入輸出流 try { is = socket.getInputStream(); os = socket.getOutputStream(); } catch (IOException e) { Log.i(TAG, "get Stream fail", e); } mInputStream = is; mOutputStream = os; } public void run() { if (DEBUG) Log.i(TAG, "Begin mConnectedThread"); byte[] buffer=new byte[1024]; int bytes; // 監聽輸入流以備獲取資料 while (true) { try { bytes = mInputStream.read(buffer); // 將接受資料發回UI處理 if(bytes!=-1&&allowRec){ mHandler.obtainMessage(MainActivity.REC_DATA,bytes,-1,buffer).sendToTarget(); } } catch (IOException e) { Log.e(TAG, "connection break", e); connectionBreak(); break; } try { //執行緒睡眠20ms以避免過於頻繁工作 50ms->20ms 2017.12.2 //導致UI處理髮回的資料不及時而阻塞 Thread.sleep(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (DEBUG) Log.i(TAG, "End mConnectedThread"); } /** * 寫輸出流以傳送資料 * @param buffer 欲輸出位元組流 */ public void write(byte[] buffer) { try { mOutputStream.write(buffer); } catch (IOException e) { Log.e(TAG, "Exception during write", e); } } public void cancel() { if (DEBUG) Log.e(TAG, "cancel " + this); try { mBtSocket.close(); } catch (IOException e) { Log.e(TAG, "close() fail", e); } } } }