Android 藍芽服務端實現
阿新 • • 發佈:2019-02-01
package com.ibrobo.robotbingo.common.bluetooth.service; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothAdapter; import com.infrastructure.utils.LogUtils; import android.bluetooth.BluetoothSocket; import android.os.HandlerThread; import java.io.OutputStream; import java.io.InputStream; import android.os.Message; import android.os.Handler; import android.os.Looper; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; /** * 藍芽通訊基礎服務框架 * BluetoothBaseService */ public class BBS { private static final int MSG_BLUETOOTH_START = 0; //藍芽開始 private static final int MSG_BLUETOOTH_CLOSE = 1; //藍芽關閉 private static final int MSG_BLUETOOTH_LISTEN = 2; //藍芽監聽 private static final int MSG_BLUETOOTH_CONNECTED = 3; //藍芽連線 private final BluetoothAdapter mBluetoothAdapter; //藍芽操作Adapter private BluetoothStatusHandler mBluetoothStatusHandler = null; //藍芽工作處理集 private BluetoothReadHandler mBluetoothReadHandler = null; //藍芽工作處理集 public BBS(){ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); HandlerThread handlerThread1 = new HandlerThread("BluetoothStatusHandler"); handlerThread1.start(); mBluetoothStatusHandler = new BluetoothStatusHandler(handlerThread1.getLooper()); HandlerThread handlerThread2 = new HandlerThread("BluetoothReadHandler"); handlerThread2.start(); mBluetoothReadHandler = new BluetoothReadHandler(handlerThread2.getLooper()); } private static final int READ_OPEN = 1; private static final int READ_CLOSE = 2; private static final int READ = 3; private class BluetoothReadHandler extends Handler{ private AtomicBoolean isOpen = new AtomicBoolean(false); BluetoothReadHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg) { int what = msg.what; switch (what){ case READ: if(isOpen.get() && onPushListener != null){ LogUtils.bluetooth("read input stream...."); try{ if (mConnectedHandler != null) { mConnectedHandler.read(); } sendEmptyMessage(READ); }catch (Exception e){ e.printStackTrace(); bluetoothErrorHandler(ERROR_BLUETOOTH_READ, new RuntimeException("bluetooth read stream fail!")); } } break; case READ_OPEN: isOpen.set(true); synchronized (this){ notify(); } sendEmptyMessage(READ); break; case READ_CLOSE: removeMessages(READ); isOpen.set(false); synchronized (this){ notify(); } break; } } public void open(){ synchronized (this){ try { sendEmptyMessage(READ_OPEN); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void close(){ synchronized (this){ try { sendEmptyMessage(READ_CLOSE); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 藍芽狀態管理 */ private class BluetoothStatusHandler extends Handler{ private int BBSmsg; //連線流程控制 BluetoothStatusHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg) { int what = msg.what; switch (what){ case MSG_BLUETOOTH_START: closeBluetoothDeviceHandler(); boolean openSucess = openBluetoothDeviceHandler(); if(openSucess){ BBSmsg = MSG_BLUETOOTH_START; //設定狀態為藍芽開啟 bluetoothStatusChangeHandler(STATUS_BLUETOOTH_OPEN, "bluetooth opend!"); sendEmptyMessage(MSG_BLUETOOTH_LISTEN); }else { bluetoothErrorHandler(ERROR_BLUETOOTH_UNABLE, new RuntimeException("bluetooth unable!")); } break; case MSG_BLUETOOTH_LISTEN: if(BBSmsg == MSG_BLUETOOTH_START){ BBSmsg = MSG_BLUETOOTH_LISTEN; acceptBluetoothConnectHandler(); bluetoothStatusChangeHandler(STATUS_BLUETOOTH_SERVICE_ACCEPTED, "bluetooth service accepted!"); }else { LogUtils.bluetooth("status error no handle:" + BBSmsg); } break; case MSG_BLUETOOTH_CONNECTED: if(BBSmsg == MSG_BLUETOOTH_LISTEN){ Object socket = msg.obj; if (socket != null) { closeBluetoothDeviceHandler(); mConnectedHandler = new ConnectedHandler((BluetoothSocket) socket); if (mConnectedHandler.connectedSuccess()) { //開啟讀資料 mBluetoothReadHandler.open(); BBSmsg = MSG_BLUETOOTH_CONNECTED; bluetoothStatusChangeHandler(STATUS_BLUETOOTH_CONNECTED, "bluetooth build connect!"); } else { bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("bluetooth service build error!")); } } else { bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("bluetooth service build error!")); } }else { LogUtils.bluetooth("status error no handle:" + BBSmsg); } break; case MSG_BLUETOOTH_CLOSE: BBSmsg = MSG_BLUETOOTH_CLOSE; closeBluetoothDeviceHandler(); bluetoothStatusChangeHandler(STATUS_BLUETOOTH_CLOSE, "bluetooth close!"); break; default: break; } } } /** * 傳送開啟藍芽命令 */ public void open(){ LogUtils.bluetooth("open"); mBluetoothStatusHandler.sendEmptyMessage(MSG_BLUETOOTH_START); } /** * 傳送關閉藍芽命令 */ public void close(){ LogUtils.bluetooth("close"); mBluetoothStatusHandler.sendEmptyMessage(MSG_BLUETOOTH_CLOSE); } //private 檢查藍芽狀態並開啟藍芽,整體檢查返回狀態 private boolean openBluetoothDeviceHandler() { if (mBluetoothAdapter == null) { //藍芽模組不可用 return false; } //確保藍芽開啟 if (!mBluetoothAdapter.isEnabled()) { mBluetoothAdapter.enable(); int MAX_COUNT = 10; int tryCount = 0; boolean enable = false; while(!enable){ //檢查是否開啟完成 enable = mBluetoothAdapter.isEnabled(); if(tryCount > MAX_COUNT){ return false; } try { tryCount++; Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } return true; } /** * private 關閉藍芽,整體檢查返回狀態 */ private void closeBluetoothDeviceHandler() { //關閉讀資料 mBluetoothReadHandler.close(); if (mConnectedHandler != null) { mConnectedHandler.cancel(); mConnectedHandler = null; } if (mAcceptManagerThread != null) { mAcceptManagerThread.cancel(); mAcceptManagerThread = null; } } private static final String NAME_SECURE = "BluetoothChatSecure"; private static final String NAME_INSECURE = "BluetoothChatInsecure"; private static final UUID MY_UUID_SECURE = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); //private static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private volatile ConnectedHandler mConnectedHandler; /** * private 進入藍芽監聽模式 * 開始啟動監聽模式 */ private void acceptBluetoothConnectHandler(){ closeBluetoothDeviceHandler(); mAcceptManagerThread = new AcceptManagerThread(); mAcceptManagerThread.start(); } private AcceptManagerThread mAcceptManagerThread; private class AcceptManagerThread extends Thread{ //private final AcceptThread mSecureAcceptThread; private final AcceptThread mInsecureAcceptThread; AcceptManagerThread(){ //mSecureAcceptThread = new AcceptThread(true); mInsecureAcceptThread = new AcceptThread(false); } @Override public void run() { //Future<BluetoothSocket> f1 = pool.submit(mSecureAcceptThread); Future<BluetoothSocket> f2 = pool.submit(mInsecureAcceptThread); try { // BluetoothSocket socket1 = f1.get(); // BluetoothSocket socket2 = f2.get(); // if(socket1 != null || socket2 != null){ // //啟動連結流程 // Message message = Message.obtain(); // if(f1.get() != null){ // message.obj = f1.get(); // }else { // message.obj = f2.get(); // } // message.what = MSG_BLUETOOTH_CONNECTED; // mBluetoothStatusHandler.sendMessage(message); // }else { // throw new RuntimeException("bluetooth service build error!"); // } BluetoothSocket socket2 = f2.get(); if(socket2 != null){ //啟動連結流程 Message message = Message.obtain(); message.obj = f2.get(); message.what = MSG_BLUETOOTH_CONNECTED; mBluetoothStatusHandler.sendMessage(message); }else { throw new RuntimeException("bluetooth service build error!"); } } catch (Exception e) { e.printStackTrace(); bluetoothErrorHandler(ERROR_BLUETOOTH_SERVICE_ACCEPT, new RuntimeException("bluetooth service build error!")); } } public void cancel() { //mSecureAcceptThread.cancel(); mInsecureAcceptThread.cancel(); } } private static final ExecutorService pool = Executors.newFixedThreadPool(2); private class AcceptThread implements Callable<BluetoothSocket> { private final BluetoothServerSocket mmServerSocket; private String mSocketType; public AcceptThread(boolean secure) { BluetoothServerSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure"; try { if (secure) { tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE); } else { tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord( NAME_INSECURE, MY_UUID_INSECURE); } } catch (Exception e) { e.printStackTrace(); } mmServerSocket = tmp; } @Override public BluetoothSocket call() throws Exception { //進入監聽狀態 BluetoothSocket socket; try { if (mmServerSocket != null) { LogUtils.bluetooth("accept start"); socket = mmServerSocket.accept(); LogUtils.bluetooth("accept end"); } else { LogUtils.bluetooth("mmServerSocket = null"); return null; } } catch (Exception e) { e.printStackTrace(); LogUtils.bluetooth("accept error"); return null; } LogUtils.bluetooth("return:" + socket); //取消 mAcceptManagerThread.cancel(); return socket; } public void cancel() { LogUtils.bluetooth("Socket Type" + mSocketType + "cancel" + this); try { mmServerSocket.close(); } catch (Exception e) { e.printStackTrace(); bluetoothErrorHandler(ERROR_BLUETOOTH_CLOSE, e); } } } private class ConnectedHandler { private static final int READ_MAX = 256; private final byte[] bytes = new byte[READ_MAX]; private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private final String mmDevice; public ConnectedHandler(BluetoothSocket socket) { mmSocket = socket; mmDevice = socket.getRemoteDevice().getName(); InputStream tmpIn = null; OutputStream tmpOut = null; try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (Exception e) { e.printStackTrace(); } mmInStream = tmpIn; mmOutStream = tmpOut; } public boolean connectedSuccess(){ return mmInStream != null && mmOutStream != null; } public void read() throws Exception { int readCount = mmInStream.read(bytes); if(onPushListener != null){ byte[] datas = new byte[readCount]; System.arraycopy(bytes, 0, datas, 0, readCount); onPushListener.onDecode(datas); } } public void write(byte[] buffer) throws Exception { mmOutStream.write(buffer); } public void cancel() { try { mmInStream.close(); mmOutStream.close(); mmSocket.close(); } catch (Exception e) { e.printStackTrace(); bluetoothErrorHandler(ERROR_BLUETOOTH_CLOSE, e); } } public String getMmDevice() { return mmDevice; } } /** * 傳送訊息 */ public void write(byte[] out) { try{ if (mConnectedHandler != null) { mConnectedHandler.write(out); } }catch (Exception e){ e.printStackTrace(); bluetoothErrorHandler(ERROR_BLUETOOTH_WRITE, e); } } /** * 藍芽狀態變化 */ private static final int ERROR_BLUETOOTH_UNABLE = 2; //藍芽不可用異常 private static final int ERROR_BLUETOOTH_CLOSE = 3; //藍芽關閉異常 private static final int ERROR_BLUETOOTH_READ = 4; //藍芽讀取異常 private static final int ERROR_BLUETOOTH_WRITE = 5; //藍芽寫異常 private static final int ERROR_BLUETOOTH_CONNECT = 6; //藍芽連線異常 private static final int ERROR_BLUETOOTH_SERVICE_ACCEPT = 7; //藍芽服務建立異常 private static final int STATUS_BLUETOOTH_OPEN = 8; //藍芽開啟 private static final int STATUS_BLUETOOTH_SERVICE_ACCEPTED = 9; //藍芽服務建立 private static final int STATUS_BLUETOOTH_CONNECTED = 10; //藍芽連線建立 private static final int STATUS_BLUETOOTH_CLOSE = 11; //藍芽關閉 private void bluetoothErrorHandler(int errorCount, Exception e){ switch (errorCount){ case ERROR_BLUETOOTH_UNABLE: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothUnableError(e); } break; case ERROR_BLUETOOTH_SERVICE_ACCEPT: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothServiceAcceptError(e); } break; case ERROR_BLUETOOTH_CONNECT: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothConnectError(e); } break; case ERROR_BLUETOOTH_READ: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothReadError(e); } break; case ERROR_BLUETOOTH_WRITE: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothWriteError(e); } break; case ERROR_BLUETOOTH_CLOSE: if(onBluetoothErrorListener != null){ onBluetoothErrorListener.bluetoothCloseError(e); } break; default: break; } } private void bluetoothStatusChangeHandler(int statusCount, String statusMessage){ LogUtils.bluetooth(statusMessage + " status count: " + statusCount); switch (statusCount){ case STATUS_BLUETOOTH_OPEN: if(onBluetoothStatusListener != null){ //獲取本機藍芽資訊 String localAddress = mBluetoothAdapter.getAddress(); String localName = mBluetoothAdapter.getName(); LogUtils.bluetooth("local bluetooth message [address:" + localAddress + ",name:" + localName); onBluetoothStatusListener.bluetoothOpened(statusMessage, localAddress, localName); } break; case STATUS_BLUETOOTH_SERVICE_ACCEPTED: if(onBluetoothStatusListener != null){ LogUtils.bluetooth("bluetooth accepted:"); onBluetoothStatusListener.bluetoothAccepted(statusMessage); } break; case STATUS_BLUETOOTH_CONNECTED: if(onBluetoothStatusListener != null){ LogUtils.bluetooth("bluetooth connected:" + mConnectedHandler.getMmDevice()); onBluetoothStatusListener.bluetoothConnected(mConnectedHandler.getMmDevice()); } break; case STATUS_BLUETOOTH_CLOSE: if(onBluetoothStatusListener != null){ onBluetoothStatusListener.bluetoothClosed(statusMessage); } break; default: break; } } public void setOnBluetoothErrorListener(OnBluetoothErrorListener onBluetoothErrorListener) { this.onBluetoothErrorListener = onBluetoothErrorListener; } private volatile OnBluetoothErrorListener onBluetoothErrorListener; interface OnBluetoothErrorListener{ void bluetoothUnableError(Exception e); void bluetoothServiceAcceptError(Exception e); void bluetoothConnectError(Exception e); void bluetoothReadError(Exception e); void bluetoothWriteError(Exception e); void bluetoothCloseError(Exception e); } public void setOnBluetoothStatusListener(OnBluetoothStatusListener onBluetoothStatusListener) { this.onBluetoothStatusListener = onBluetoothStatusListener; } private volatile OnBluetoothStatusListener onBluetoothStatusListener; interface OnBluetoothStatusListener { void bluetoothOpened(String message, String localAddress, String localName); void bluetoothAccepted(String message); void bluetoothConnected(String message); void bluetoothClosed(String message); } public void setOnPushListener(OnPushListener onPushListener) { this.onPushListener = onPushListener; } private volatile OnPushListener onPushListener; interface OnPushListener{ void onDecode(byte[] datas); } }
package com.ibrobo.robotbingo.common.bluetooth.service; import com.infrastructure.utils.LogUtils; /** * 藍芽框架控制介面 */ public class BBSCommander implements BBS.OnPushListener, BBS.OnBluetoothErrorListener, BBS.OnBluetoothStatusListener{ private static final BBS BBS = new BBS(); @Override public void bluetoothOpened(String message, String localAddress, String localName) { LogUtils.bluetooth("bluetooth open!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothOpened(message); } } @Override public void bluetoothAccepted(String message) { LogUtils.bluetooth("bluetooth bluetoothAccepted!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothAccepted(message); } } @Override public void bluetoothConnected(String device) { LogUtils.bluetooth("bluetooth connected!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothConnected(device); } } @Override public void bluetoothClosed(String message) { LogUtils.bluetooth("bluetooth close!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothClosed(message); } } @Override public void bluetoothServiceAcceptError(Exception error) { LogUtils.bluetooth(error + "bluetooth service build error!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothError(error); } BBS.open(); } @Override public void bluetoothConnectError(Exception error) { LogUtils.bluetooth(error + "bluetooth connect error!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothError(error); } BBS.open(); } @Override public void bluetoothReadError(Exception error) { LogUtils.bluetooth(error + "bluetooth read error!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothError(error); } BBS.open(); } @Override public void bluetoothWriteError(Exception error) { LogUtils.bluetooth(error + "bluetooth write error!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothError(error); } BBS.open(); } @Override public void bluetoothUnableError(Exception error) { LogUtils.bluetooth("bluetooth unable!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothUnable(error); } } @Override public void bluetoothCloseError(Exception error) { LogUtils.bluetooth("bluetooth close error!"); if(onBluetoothStatusChangeListener != null){ onBluetoothStatusChangeListener.bluetoothError(error); } } @Override public void onDecode(byte[] datas) { if(mOnDecoder != null){ mOnDecoder.onDecode(datas); } } private static class SingletonInstance { private static final BBSCommander mInstance = new BBSCommander(); } public static BBSCommander getInstance(){ return SingletonInstance.mInstance; } public void init(){ BBS.setOnBluetoothStatusListener(this); BBS.setOnBluetoothErrorListener(this); BBS.setOnPushListener(this); } public void open(){ BBS.open(); } public void close(){ BBS.close(); } public void write(byte[] bytes){ BBS.write(bytes); } public void setOnBluetoothStatusChangeListener(OnBluetoothStatusChangeListener onBluetoothStatusChangeListener) { this.onBluetoothStatusChangeListener = onBluetoothStatusChangeListener; } private volatile OnBluetoothStatusChangeListener onBluetoothStatusChangeListener; public interface OnBluetoothStatusChangeListener{ void bluetoothUnable(Exception message); void bluetoothError(Exception error); void bluetoothOpened(String message); void bluetoothAccepted(String message); void bluetoothConnected(String message); void bluetoothClosed(String message); } private volatile OnDecoder mOnDecoder; public void setOnDecoder(OnDecoder mOnDecoder) { this.mOnDecoder = mOnDecoder; } public interface OnDecoder { void onDecode(byte[] bytes); } }