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);
}
}