本来要昨天写的,但是昨天一忙倒是把写博客这件事给忘了,继续上一篇的写。
上一篇写了我把官方的结构给改了,下面就直接上各个线程分开的代码了!
public class AcceptThread extends Thread {
private Handler mHandler;
private ConnectedThread mConnectedThread;
private String TAG = "AcceptThread";
private boolean D = true;
private String NAME = "Service";
private BluetoothAdapter adpter;
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(Handler handler) {
adpter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
BluetoothServerSocket tmp = null;
try {
tmp = adpter.listenUsingRfcommWithServiceRecord(NAME,
Constant.MY_UUID);
// Method mthd = adpter.getClass().getMethod("listenUsingRfcommOn",
// new Class[] { int.class });
// tmp = (BluetoothServerSocket) mthd.invoke(adpter,
// new Object[] { 29 });
} catch (Exception e) {
Log.e(TAG, "listen() failed", e);
}
mmServerSocket = tmp;
System.out.println("+++++" + mmServerSocket);
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
if (D)
Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
try {
socket = mmServerSocket.accept();
System.out.println("socket---" + socket);
} catch (Exception e) {
Log.e(TAG, "accept() failed", e);
}
if (socket != null) {
connected(socket, socket.getRemoteDevice());
try {
mmServerSocket.close();
} catch (Exception e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
}
if (D)
Log.i(TAG, "END mAcceptThread");
}
public void cancel() {
if (D)
Log.d(TAG, "cancel " + this);
try {
mmServerSocket.close();
} catch (Exception e) {
Log.e(TAG, "close() of server failed", e);
}
}
public synchronized void connected(BluetoothSocket socket,
BluetoothDevice device) {
if (D)
Log.d(TAG, "connected");
mConnectedThread = new ConnectedThread(mHandler, socket);
mConnectedThread.start();
Constant.setConnectedThread(mConnectedThread);
Message msg = mHandler.obtainMessage(Constant.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constant.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}
上面这些代码是AcceptThread类,这个类主要是用来接收蓝牙连接请求,注释掉的几句是我在网上看到的,说是在系统版本比较高的时候就换成了那种方式进行连接的,我试了试,虽然请求方显示的是连接成功了,但是接收方却没什么反应,不知道是不是因为我测试的都是两个手机不是都是较高版本的原因,总之就先没用那种方式,以后有机会可以测试一下是否可用。
接下来贴上主动请求连接的线程的代码。
public class ConnectThread extends Thread {
private boolean D = true;
private Handler mHandler;
private ConnectedThread mConnectedThread;
private BluetoothAdapter adapter;
private String TAG = "ConnectThread";
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String failmesage;
public ConnectThread(Handler handler, BluetoothDevice device) {
mConnectedThread=Constant.getConnectedThread();
mHandler = handler;
mmDevice = device;
BluetoothSocket tmp = null;
try {
// Method method = device.getClass()
// .getMethod("createRfcommSocket",
// new Class[] { int.class });
// tmp = (BluetoothSocket) method.invoke(device,
// new Object[] { 29 });
tmp = device.createRfcommSocketToServiceRecord(Constant.MY_UUID);
} catch (Exception e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
adapter = BluetoothAdapter.getDefaultAdapter();
adapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (Exception e) {
failmesage = "无法连接到设备";
connectionFailed();
try {
mmSocket.close();
} catch (Exception e2) {
Log.e(TAG,
"unable to close() socket during connection failure",
e2);
}
return;
}
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (Exception e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
private void connectionFailed() {
Log.i(TAG, "conncet fail");
Message msg = mHandler.obtainMessage(Constant.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constant.TOAST, failmesage);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
public synchronized void connected(BluetoothSocket socket,
BluetoothDevice device) {
if (D)
Log.d(TAG, "connected");
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mHandler, socket);
mConnectedThread.start();
Constant.setConnectedThread(mConnectedThread);
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(Constant.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constant.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}
这个就是主动请求连接的线程,主要是用来实现请求连接那边已经等待连接的Socket,这很像网络里那种服务器端和客户端的概念,一个用来请求连接,一个用来接受连接。可以看到,无论是请求连接还是接受连接,它们在连接之前是一个线程,在连接之后这个线程就被终结了,而启动了另外一个线程,这个线程就是专门用来处理连接之后进行通信的线程,我把它命名为ConnectedThread,同时需要注意的是,
Constant.setConnectedThread(mConnectedThread);
这段代码是我将实例化之后的ConnectedThread对象存进了Constant这个类中,主要也是为了程序调用方面,也算是用到了单例模式,需要用到这个对象时候只需要在Constant类里面通过GetConnectedThread方法就可以获得。
下面是ConncetedThread类的源码部分
public class ConnectedThread extends Thread {
private Handler mHandler;
private String TAG = "ConnectedThread";
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(Handler handler, BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
mHandler = handler;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (Exception 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[1024];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(Constant.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (Exception e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
} catch (Exception e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (Exception e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
private void connectionLost() {
Log.i(TAG, "connect lost");
Constant.setConnectedThread(null);
Message msg = mHandler.obtainMessage(Constant.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constant.TOAST, "设备连接已断开");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}
这个就是用来处理连接之后进行通信的线程,用到了IO流对数据进行操作,要发送就调用write()方法,要接收就调用read()方法即可。它会向UI界面发送一个Message用来更新UI,下一篇附上UI接受的代码。