/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bingo.assistant.common.remoteControl.bluetooth.client;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import com.infrastructure.util.LogUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 蓝牙通信基础客户端框架
* BluetoothBaseClient
*/
public class BBC {
private static final UUID MY_UUID_SECURE = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
//private static final UUID MY_UUID_INSECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
private static final int MSG_BLUETOOTH_START = 0; //蓝牙开始
private static final int MSG_BLUETOOTH_CONNECT = 1; //蓝牙连接
private static final int MSG_BLUETOOTH_CONNECTED = 2; //蓝牙连接成功
private static final int MSG_BLUETOOTH_CONNECT_TIMEOUT = 3; //蓝牙连接超时
private static final int MSG_BLUETOOTH_CLOSE = 4; //蓝牙连接关闭
private final BluetoothAdapter mBluetoothAdapter;
private ConnectManagerThread mConnectManagerThread;
private BluetoothStatusChangeHandler mBluetoothStatusChangeHandler;
private BluetoothReadHandler mBluetoothReadHandler;
private volatile ConnectedHandler mConnectedHandler;
private BluetoothDevice device;
public BBC() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
HandlerThread handlerThread1 = new HandlerThread("BluetoothStatusChangeHandler");
handlerThread1.start();
mBluetoothStatusChangeHandler = new BluetoothStatusChangeHandler(handlerThread1.getLooper());
HandlerThread handlerThread2 = new HandlerThread("BluetoothReadHandler");
handlerThread2.start();
mBluetoothReadHandler = new BluetoothReadHandler(handlerThread2.getLooper());
}
private void clean(){
if(mBluetoothStatusChangeHandler != null){
mBluetoothStatusChangeHandler.removeMessages(MSG_BLUETOOTH_START);
mBluetoothStatusChangeHandler.removeMessages(MSG_BLUETOOTH_CONNECT);
mBluetoothStatusChangeHandler.removeMessages(MSG_BLUETOOTH_CLOSE);
mBluetoothStatusChangeHandler.removeMessages(MSG_BLUETOOTH_CONNECT_TIMEOUT);
mBluetoothStatusChangeHandler.removeMessages(MSG_BLUETOOTH_CONNECTED);
}
}
/**
* 设置设备
*/
public synchronized void switchDevice(BluetoothDevice device){
this.device = device;
}
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("读取流....");
try{
if(mConnectedHandler != null){
mConnectedHandler.read();
}
sendEmptyMessage(READ);
}catch (Exception e){
e.printStackTrace();
bluetoothErrorHandler(ERROR_BLUETOOTH_READ, e);
}
}
break;
case READ_OPEN:
isOpen.set(true);
synchronized (this){
notify();
}
sendEmptyMessage(READ);
break;
case READ_CLOSE:
removeMessages(READ);
isOpen.set(false);
break;
}
}
public void open(){
synchronized (this){
try {
sendEmptyMessage(READ_OPEN);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void close(){
sendEmptyMessage(READ_CLOSE);
isOpen.set(false);
}
}
private class BluetoothStatusChangeHandler extends Handler{
private int BBCmsg;
BluetoothStatusChangeHandler(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){
BBCmsg = MSG_BLUETOOTH_START; //设置状态为蓝牙打开
bluetoothStatusChangeHandler(STATUS_BLUETOOTH_OPEN, "蓝牙打开!");
sendEmptyMessage(MSG_BLUETOOTH_CONNECT);
}else {
bluetoothErrorHandler(ERROR_BLUETOOTH_UNABLE, new RuntimeException("蓝牙不可用!"));
}
break;
case MSG_BLUETOOTH_CONNECT:
if(BBCmsg == MSG_BLUETOOTH_START){
BBCmsg = MSG_BLUETOOTH_CONNECT;
connectBluetoothDeviceHandler();
bluetoothStatusChangeHandler(STATUS_BLUETOOTH_CONNECTING, "蓝牙正在建立连接!");
}else {
LogUtils.bluetooth("状态不符合,不做处理:" + BBCmsg);
}
break;
case MSG_BLUETOOTH_CONNECTED:
//开始建立流
if(BBCmsg == MSG_BLUETOOTH_CONNECT){
Object o = msg.obj;
if(o != null){
BluetoothSocket mmSocket = (BluetoothSocket) o;
mConnectedHandler = new ConnectedHandler(mmSocket);
if(mConnectedHandler.connectedSuccess()){
//打开读数据
mBluetoothReadHandler.open();
BBCmsg = MSG_BLUETOOTH_CONNECTED;
bluetoothStatusChangeHandler(STATUS_BLUETOOTH_CONNECTED, "蓝牙连接成功!");
}else {
bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("蓝牙连接异常!"));
}
}else {
bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("蓝牙连接异常!"));
}
}else {
LogUtils.bluetooth("状态不符合,不做处理:" + BBCmsg);
}
break;
case MSG_BLUETOOTH_CONNECT_TIMEOUT:
break;
case MSG_BLUETOOTH_CLOSE:
closeBluetoothDeviceHandler();
BBCmsg = MSG_BLUETOOTH_CLOSE;
bluetoothStatusChangeHandler(STATUS_BLUETOOTH_CLOSE, "蓝牙关闭!");
break;
}
}
}
/**
* 打开蓝牙
*/
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;
}
/**
* 关闭蓝牙
*/
public void closeBluetoothDeviceHandler() {
//停止读数据
mBluetoothReadHandler.close();
LogUtils.bluetooth("停止蓝牙连接服务");
if (mConnectedHandler != null) {
mConnectedHandler.cancel();
mConnectedHandler = null;
}
if (mConnectManagerThread != null) {
mConnectManagerThread.cancel();
mConnectManagerThread = null;
}
}
/**
* 连接远程蓝牙设备
*/
public synchronized void connectBluetoothDeviceHandler() {
closeBluetoothDeviceHandler();
mConnectManagerThread = new ConnectManagerThread();
mConnectManagerThread.start();
}
/**
* 打开
*/
public void open(){
mBluetoothStatusChangeHandler.sendEmptyMessage(MSG_BLUETOOTH_START);
}
/**
* 关闭
*/
public void close(){
LogUtils.bluetooth("发送蓝牙关闭信息!");
clean();
mBluetoothStatusChangeHandler.sendEmptyMessage(MSG_BLUETOOTH_CLOSE);
}
private class ConnectManagerThread extends Thread{
//private final ConnectThread mSecureThread;
private final ConnectThread mInSecureThread;
ConnectManagerThread(){
//mSecureThread = new ConnectThread(device, true);
mInSecureThread = new ConnectThread(device, false);
}
public void cancel(){
//mSecureThread.cancel();
mInSecureThread.cancel();
}
@Override
public void run() {
//Future<BluetoothSocket> f1 = pool.submit(mSecureThread);
Future<BluetoothSocket> f2 = pool.submit(mInSecureThread);
try {
//BluetoothSocket socket1 = f1.get();
BluetoothSocket socket2 = f2.get(20, TimeUnit.SECONDS);
LogUtils.bluetooth("获得SOCKET");
// 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;
// mBluetoothStatusChangeHandler.sendMessage(message);
// }else {
// bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("蓝牙服务建立失败!"));
// }
if(socket2 != null){
Message message = Message.obtain();
if(f2.get() != null){
message.obj = f2.get();
message.what = MSG_BLUETOOTH_CONNECTED;
mBluetoothStatusChangeHandler.sendMessage(message);
}else {
bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, new RuntimeException("蓝牙服务建立失败!"));
}
}
} catch (Exception e) {
e.printStackTrace();
bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, e);
}
}
}
private static final ExecutorService pool = Executors.newFixedThreadPool(2);
private class ConnectThread implements Callable<BluetoothSocket> {
private final BluetoothSocket mmSocket;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
}
} catch (IOException e) {
LogUtils.bluetooth("Socket Type: " + mSocketType + "create() failed " + e);
}
mmSocket = tmp;
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
LogUtils.bluetooth("close error :" + e.getMessage());
bluetoothErrorHandler(ERROR_BLUETOOTH_CLOSE, e);
}
}
@Override
public BluetoothSocket call() throws Exception {
mBluetoothAdapter.cancelDiscovery();
try {
LogUtils.bluetooth("等待服务端响应 mmSocket :" + mmSocket);
//开始连接
mmSocket.connect();
LogUtils.bluetooth("收到服务端响应");
return mmSocket;
} catch (IOException e) {
e.printStackTrace();
LogUtils.bluetoothError(e);
cancel();
bluetoothErrorHandler(ERROR_BLUETOOTH_CONNECT, e);
return null;
}
}
}
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);
if(onBluetoothStatusChangeListener != null) {
onBluetoothStatusChangeListener.bluetoothSendSuccess(buffer);
}
}
public void cancel() {
try {
mmOutStream.close();
mmInStream.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 = 1; //蓝牙不可用异常
private static final int ERROR_BLUETOOTH_CLOSE = 2; //蓝牙关闭异常
private static final int ERROR_BLUETOOTH_READ = 3; //蓝牙读取异常
private static final int ERROR_BLUETOOTH_WRITE = 4; //蓝牙写异常
private static final int ERROR_BLUETOOTH_CONNECT = 5; //蓝牙连接异常
private void bluetoothErrorHandler(int statusCount, Exception e){
switch (statusCount){
case ERROR_BLUETOOTH_UNABLE:
if(onBluetoothErrorListener != null){
onBluetoothErrorListener.bluetoothUnableError(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 static final int STATUS_BLUETOOTH_OPEN = 6; //蓝牙打开
private static final int STATUS_BLUETOOTH_CONNECTING = 7; //蓝牙正在建立连接
private static final int STATUS_BLUETOOTH_CONNECTED = 8; //蓝牙连接建立
private static final int STATUS_BLUETOOTH_CLOSE = 9; //蓝牙关闭
private void bluetoothStatusChangeHandler(int statusCount, String statusMessage){
LogUtils.bluetooth(statusMessage + " 状态号: " + statusCount);
switch (statusCount){
case STATUS_BLUETOOTH_OPEN:
if(onBluetoothStatusChangeListener != null){
//获取本机蓝牙信息
String localAddress = mBluetoothAdapter.getAddress();
String localName = mBluetoothAdapter.getName();
LogUtils.bluetooth("本机蓝牙信息[address:" + localAddress + ",name:" + localName);
onBluetoothStatusChangeListener.bluetoothOpened(statusMessage, localAddress, localName);
}
break;
case STATUS_BLUETOOTH_CONNECTED:
if(onBluetoothStatusChangeListener != null){
LogUtils.bluetooth("蓝牙建立连接:" + mConnectedHandler.getMmDevice());
onBluetoothStatusChangeListener.bluetoothConnected(mConnectedHandler.getMmDevice());
}
break;
case STATUS_BLUETOOTH_CLOSE:
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothClosed(statusMessage);
}
break;
default:
break;
}
}
public void setOnBluetoothStatusChangeListener(OnBluetoothStatusChangeListener onBluetoothStatusChangeListener) {
this.onBluetoothStatusChangeListener = onBluetoothStatusChangeListener;
}
private volatile OnBluetoothStatusChangeListener onBluetoothStatusChangeListener;
interface OnBluetoothStatusChangeListener {
void bluetoothOpened(String message, String localAddress, String localName);
void bluetoothConnected(String message);
void bluetoothClosed(String message);
void bluetoothSendSuccess(byte[] b);
}
public void setOnBluetoothErrorListener(OnBluetoothErrorListener onBluetoothErrorListener) {
this.onBluetoothErrorListener = onBluetoothErrorListener;
}
private volatile OnBluetoothErrorListener onBluetoothErrorListener;
interface OnBluetoothErrorListener{
void bluetoothUnableError(Exception error);
void bluetoothConnectError(Exception error);
void bluetoothReadError(Exception error);
void bluetoothWriteError(Exception error);
void bluetoothCloseError(Exception error);
}
public void setOnPushListener(OnPushListener onPushListener) {
this.onPushListener = onPushListener;
}
private volatile OnPushListener onPushListener;
interface OnPushListener{
void onDecode(byte[] datas);
}
}
package com.bingo.assistant.common.remoteControl.bluetooth.client;
import android.bluetooth.BluetoothDevice;
import com.infrastructure.util.LogUtils;
public class BBCCommander implements
BBC.OnBluetoothStatusChangeListener,
BBC.OnBluetoothErrorListener,
BBC.OnPushListener{
private static final BBC BBC = new BBC();
@Override
public void bluetoothUnableError(Exception error) {
LogUtils.bluetooth("蓝牙不能使用!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothUnable(error);
}
}
@Override
public void bluetoothConnectError(Exception error) {
LogUtils.bluetooth(error + "蓝牙连接异常!:" + onBluetoothStatusChangeListener);
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothError(error);
}
}
@Override
public void bluetoothReadError(Exception error) {
LogUtils.bluetooth(error + "蓝牙读异常!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothError(error);
}
}
@Override
public void bluetoothWriteError(Exception error) {
LogUtils.bluetooth(error + "蓝牙写异常!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothError(error);
}
}
@Override
public void bluetoothCloseError(Exception error) {
LogUtils.bluetooth("蓝牙关闭异常!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothError(error);
}
}
private static class SingletonInstance {
private static final BBCCommander mInstance = new BBCCommander();
}
public static BBCCommander getInstance(){
return SingletonInstance.mInstance;
}
@Override
public void bluetoothOpened(String message, String localAddress, String localName) {
LogUtils.bluetooth("蓝牙打开!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothOpened(message);
}
}
@Override
public void bluetoothConnected(String device) {
LogUtils.bluetooth("蓝牙建立连接!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothConnected(device);
}
}
@Override
public void bluetoothClosed(String message) {
LogUtils.bluetooth("蓝牙关闭!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothClosed(message);
}
}
@Override
public void bluetoothSendSuccess(byte[] b) {
LogUtils.bluetooth("蓝牙发送成功!");
if(onBluetoothStatusChangeListener != null){
onBluetoothStatusChangeListener.bluetoothSendSuccess(b);
}
}
public void switchDevice(BluetoothDevice device){
BBC.switchDevice(device);
}
public void init(){
BBC.setOnBluetoothStatusChangeListener(this);
BBC.setOnBluetoothErrorListener(this);
BBC.setOnPushListener(this);
}
public void open(){
BBC.open();
}
public void close(){
BBC.close();
}
public void write(byte[] bytes){
BBC.write(bytes);
}
@Override
public void onDecode(byte[] datas) {
if(mOnDecoder != null){
mOnDecoder.onDecode(datas);
}
}
public void setOnBluetoothStatusChangeListener(OnBluetoothStatusChangeListener onBluetoothStatusChangeListener) {
this.onBluetoothStatusChangeListener = onBluetoothStatusChangeListener;
}
private volatile OnBluetoothStatusChangeListener onBluetoothStatusChangeListener;
public interface OnBluetoothStatusChangeListener{
void bluetoothUnable(Exception e);
void bluetoothError(Exception e);
void bluetoothOpened(String message);
void bluetoothConnected(String message);
void bluetoothClosed(String message);
void bluetoothSendSuccess(byte[] b);
}
private volatile OnDecoder mOnDecoder;
public void setOnDecoder(OnDecoder mOnDecoder) {
this.mOnDecoder = mOnDecoder;
}
public interface OnDecoder {
void onDecode(byte[] bytes);
}
}