package com.eztlib;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.ectrip.cyt.config.MyApp;
import com.ectrip.cyt.utils.LogUtil;
/**
* 这个类处理所有工作的设置和管理蓝牙连接其他设备 它有一个线程,监听传入连接 一个线程用于连接设备和一个线程用于执行数据传输连接时
* */
public class BluetoothService
{
static
{
try {
System.loadLibrary("EZTLIB");
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
///
/// 端口发送数据
///
/// 要写入的数据
/// 数据长度
/// 返回写入的数据长度
public static native int BluSendBytes(byte[] pDataIn, int Inlen);
///
/// 端口读取数据
///
/// 返回数据
/// 想要读取长度
/// 返回读取到的数据长
public static native int BluReadBytes(byte[] pDataOut, int len);
//从BluetoothService处理程序发送消息类型
public static final int MESSAGE_STATE_CHANGE=1;
public static final int MESSAGE_READ=2;
public static final int MESSAGE_WRITE=3;
public static final int MESSAGE_DEVICE_NAME=4;
public static final int MESSAGE_TOAST=5;
// BluetoothService收到的处理程序关键的名字
public static final String DEVICE_NAME="device_name";
public static final String TOAST="toast";
public static final String TAG = "BluetoothService";
public static final boolean LogEnablD = false;
// 在创建服务器套接字记录SDP的名字
private static final String NAME = "EZTPrinter";
// 给这个应用程序设置一个独特的UUID
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// 当前连接状态的常量
public static final int STATE_NONE = 0; // 默认的,什么都没做
public static final int STATE_LISTEN = 1; // 进入连接的监听
public static final int STATE_CONNECTING = 2;// 启动一个外向连接
public static final int STATE_CONNECTED = 3; // 连接到一个远程设备
public static final int STATE_FAILL=8;//失败
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
// private AcceptThread mAcceptThread= null;
private ConnectThread mConnectThread= null;
private static ConnectedThread mConnectedThread= null;
private static int mState= STATE_NONE;
private static boolean stop=false;
//构造函数。准备一个新的BTPrinter会话 ontext UI活动上下文 handler 处理程序发送消息发送回UI活动
public BluetoothService(Context context, Handler handler) {
stop=true;
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
try {
COMPacket.COMClose();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
Thread thread=new Thread(new Runnable()
{
byte[] buffer = new byte[4096];
int bytes;
@Override
public void run()
{
while (!stop)
{
if ((mState==BluetoothService.STATE_CONNECTED) && (mConnectedThread != null))
{
bytes=BluReadBytes(buffer,buffer.length);
if(bytes>0)
{
mConnectedThread.write(buffer, 0, bytes);
}
}
}
}
});
stop=false;
thread.start();
}
//设置当前状态的连接 state 定义当前的连接状态
private synchronized void setState(int state) {
if (LogEnablD)
{Log.d(TAG, "setState()" + mState + "->" + state);}
mState = state;
// 给新状态Handler让UI可以更新
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, state,-1).sendToTarget();
}
//返回当前的连接状态
public synchronized int getState() {return mState;}
//启动服务。特别是在聆听(服务器)模式开始AcceptThread 会话,调用活动onResume()
public synchronized void start() {
if (LogEnablD){Log.d(TAG, "start");}
// 取消任何线程试图连接
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// 在运行一个连接时取消任何线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// 启动线程来监听BluetoothServerSocket
// if (mAcceptThread == null) {
// mAcceptThread = new AcceptThread();
// mAcceptThread.start();
// }
setState(STATE_LISTEN);
try {
COMPacket.COMClose();
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
}
//启动ConnectThread发起连接到一个远程设备。 device BluetoothDevice的连接
public synchronized void connect(BluetoothDevice device) {
if (LogEnablD){LogUtil.d(TAG, "connect to:" + device);}
// 取消任何线程试图连接
if (mState == STATE_CONNECTING)
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
}
// 正在运行一个连接时取消任何线程
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
// 启动线程与给定的设备
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
COMPacket.COMClose();
}
//启动ConnectedThread开始管理一个蓝牙连接
//@param socket BluetoothSocket上的连接
//@param device 这个BluetoothDevice已经连接
public synchronized void connected(BluetoothSocket socket,BluetoothDevice device)
{
if (LogEnablD){LogUtil.d(TAG, "Connected");}
// 取消线程完成连接
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// 正在运行一个连接取消任何线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// 取消接受线程,因为只是想连接到一个设备
// if (mAcceptThread != null) {
// mAcceptThread.cancel();
// mAcceptThread = null;
// }
// 启动线程来管理连接和执行传输
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// 发送连接设备的名称回到UI活动
Message msg = mHandler.obtainMessage(MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
COMPacket.COMOpen("Bluetooth",0,0);
}
//停止所有的线程
public synchronized void stop()
{
if (LogEnablD){Log.d(TAG, "stop");}
setState(STATE_NONE);
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// if (mAcceptThread != null) {
// mAcceptThread.cancel();
// mAcceptThread = null;
// }
COMPacket.COMClose();
}
//启动ConnectThread发起连接到一个远程设备
//@param device BluetoothDevice的连接
//连接请求失败并通知UI活动
private void connectionFailed() {
setState(STATE_FAILL);
// 一条失败消息发送回活动
MyApp.getInstance().setBluConnection(false);
Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(TOAST, "不能连接到设备!");
bundle.putBoolean("sucess", false);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
//表示这个连接丢失并通知UI活动。
private void connectionLost() {
// 一条失败消息发送给Activity
Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(TOAST, "已断开与打印机的连接!");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
//启动ConnectedThread开始管理一个蓝牙连接 socket BluetoothSocket上的连接 device
//装置的BluetoothDevice已经连接
//这个线程运行试图使一个外向连接一个设备。它运行直通要么连接成功要么失败。
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
@SuppressLint("NewApi") public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// 为一个连接的BluetoothDevice得到一个BluetoothSocket
try {
Method m = null;
try {
m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
tmp.connect();
MyApp.getInstance().setBluConnection(true);
} catch (IllegalAccessException e) {
e.printStackTrace();
connectionFailed();
return;
} catch (IllegalArgumentException e) {
e.printStackTrace();
connectionFailed();
return;
} catch (Exception e){
e.printStackTrace();
connectionFailed();
return;
}
} catch (Exception e) {
connectionFailed();
Log.e(TAG, "create failed"+e);
return;
}
mmSocket = tmp;
}
public void run() {
LogUtil.i(TAG, "BEFIN mConnectThrread");
setName("ConnectThread");
mAdapter.cancelDiscovery();
// 让BluetoothSocket的连接
try {
// 一个阻塞调用返回成功连接或一个例外
if(!MyApp.getInstance().isBluConnection()){
if(mmSocket!=null){
mmSocket.connect();
}else{
setState(STATE_FAILL);
return;
}
if(mmSocket==null){
setState(STATE_FAILL);
return;
}
}
} catch (IOException e) {
e.printStackTrace();
// 关闭socket
connectionFailed();
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG,
"unable to close() socket during connection failure",
e2);
}
// 启动服务到重启的听力模式
// BluetoothService.this.start();
return;
}
if(MyApp.getInstance().isBluConnection()){
// 重置ConnectThread
synchronized (BluetoothService.this) {
mConnectThread = null;
}
// 启动连接的线程
connected(mmSocket, mmDevice);
}
}
public void cancel() {
try {
mmDevice.describeContents();
if(mmSocket!=null){
mmSocket.close();
mmSocket=null;
}
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
//这个线程运行在连接一个远程的设备上 它处理所有传入和传出的传输。
private class ConnectedThread extends Thread {
private BluetoothSocket mmSocket;
private InputStream mmInStream;
private OutputStream mmOutStream;
boolean stop=false;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// BluetoothSocket输入和输出流
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run()
{
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[4096];
int bytes;
while (!stop)
{
try
{
// 从InputStream中阅读
bytes = mmInStream.read(buffer);
BluSendBytes(buffer,bytes);
//mHandler.obtainMessage(MainActivity.MESSAGE_READ,bytes, -1, buffer).sendToTarget();
}
catch (IOException e)
{
Log.e(TAG, "disconnected", e);
connectionLost();
if (mState != STATE_NONE)
{
BluetoothService.this.start();
}else{
connectionLost();
}
break;
}
}
}
//OutStream写入连接
//@param buffer 写的字节
public void write(byte[] buffer,int offset, int count) {
try
{
mmOutStream.write(buffer,offset,count);
// 分享所发送的消息回到UI的Activity
//mHandler.obtainMessage(MESSAGE_WRITE, -1, -1,buffer).sendToTarget();
} catch (IOException e)
{
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmInStream.close();
mmInStream=null;
mmOutStream.close();
mmOutStream=null;
stop=true;
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
// 与设备配对 参考源码:platform/packages/apps/Settings.git
// \Settings\src\com\android\settings\bluetooth\CachedBluetoothDevice.java
public static boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {
Method createBondMethod = btClass.getMethod("createBond");
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
return returnValue.booleanValue();
}
// 与设备解除配对 参考源码:platform/packages/apps/Settings.git
// \Settings\src\com\android\settings\bluetooth\CachedBluetoothDevice.java
public static boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
Method removeBondMethod = btClass.getMethod("removeBond");
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
return returnValue.booleanValue();
}
}