本来想自己写一个蓝牙聊天的程序的,可是看了好几天官方提供的源码,真的看得想哭,真的太蛋筒了,终于明白,基础差,在做稍微复杂写的程序的时候,就能看出自己的不足,就有瓶颈。从这个蓝牙开发来说,可以说是我做这个Android以来遇到的第一个比较头痛的问题,但是由于项目要用到蓝牙,所以这些天只能硬着皮头看下去,不得不说,越看,学到的东西越多,但是我也不能一一说出来,但是,不得不说,任然还有不懂的地方。尤其是多线程那一块,一定要重新认真看。不得不说,这个程序,给我了很大的刺激,让我明白,我还有太多要学习的。
我这里把我这几天看的,然后今天整理的官方的程序写上了我自己的注释,不是很多,但是最主要的是,我把程序的部分调序了,因为我觉得这是一个理解问题,就是按照什么样的顺序和思路来设计程序的。这样调序,可以很方便理解。但是,我不能保证我的理解思路就是适合别人的,但是至少适合我。还有就是service里面的几个线程的程序,我没有注释,因为真的不知道怎么注释比较好,不想直接翻译他提供的英语。
我依次说下他这三个代码的思路吧,我觉得第一个DeviceListActivity这个是最容易理解的,也是思路最明确的,内容也最少。大的方面就是两点,一个是显示本地已配对设备;二是显示搜索到的设备。先说第一个,显示本地已配对设备就直接通过一个set集合把pairedDevices遍历一遍,然后显示在listview里面。第二个稍微复杂点,因为要先查找,然后再显示出来。查找直接用startDiscovery就可以了。至于显示就比较麻烦,因为查找的过程是查找一个就发送一个广播,然后继续查找,直到查找结束。这就有一个问题,怎么把查找到一个就显示出一个呢?这就要用到BroadcastReceiver,这里要设置两个过滤器,用来处理不同的广播,一个是用来处理查找到新设备的广播,一个是用来处理结束查找的广播。第一个广播是最重要的,就是查到一个,通过这个过滤器,然后如果是这个广播,就执行显示操作。不过这里显示有两部分,一个是显示name,一个是MAC地址。不过这还么有完,因为你只是显示在listview里面了,但是你还要设置listview的选项监听器,因为我们要能选择一个设备,然后就进行和设备的配对,至于怎么配对待会再说,这里要能响应,然后把MAC地址返回到BluetoothChat这个activity里面,然后执行配对。所以这里使用的是setResult,把Intent的内容传回到主activity。这就是这个DeviceListActivity的全部功能。
接下来说BluetoothChat这个activity。总的来说是一下几个步骤,检测蓝牙,蓝牙是否打开,蓝牙的可被检测性,建立连接,开始聊天服务,但是有一个是贯穿整个流程的,就是UI的动态更新。蓝牙的检测和打开,可被检测这都很简单,不多说了。主要是怎么建立连接,这个要在service里面说;这个activity最最主要的有两点,一个是把信息显示在在listview上,就是发送和接收到的信息都要显示出来,这个其实也是在service的connectedThread里面做的,但是显示部分是在这个里面,service里只是通过handler把信息传给这个activity,BluetoothChat这个activity只是负责显示。另外一点就是连接状态的显示,分为四个状态,没有操作,连接中,连接了,和接收监听,我这个翻译也许不准确,但是应该能理解这四个状态,不过你从显示上看,只能看到三个,而监听这个是看不出来的。这四个状态也是通过handler传递信息,然后显示在状态栏的。其实这里面最难的就是这个handler的使用,因为他有两个功能,就是上面两类信息的显示。而第二类的显示就是所谓的UI的更新,也就是界面里能看到的动态listview和textview的显示。不过我也不能一下子说清楚这个handler,(我也还在学习中),所以希望我们都能好好学习,嘻嘻。。。
最后要说的就是这个service,也是最复杂的部分,其实这部分之所以复杂,主要是用到多线程,因为,这里面的很多方法都是阻塞线程的。大体上来说,我也只是说我知道的,这个服务,就是建立连接,那么中间有那些可能性呢?connect,connectionFailed,connected,connectionLost。而这四种可能性我想大家也都可以有自己的理解,我的理解就是,第一个是连接两个设备,第二个是连接失败,第三个是连接成功了,第四个也是连接失败,不过这个和第二个的区别在于,这个的前一状态是第三个,而不是第一个。由这四个引出的是两个线程,也是最重要的线程,ConnectThread和ConnectedThread,第一个是用来建立连接的,第二个是已经连接了,处理的是连接中的事,主要是两点,一个是收发信息,一个是如果发生connectionLost怎么办。而第一个建立连接是通过createRfcommSocketToServiceRecord方法来实现的。但是我们前面说到了这里有三个线程,还有一个是AcceptThread,这是一个监听socket的线程,用来查看有没有连接请求,我对他的理解是,他要监听的是刚才连接时说到的那个方法的UUID,然后进行连接。然后返回的是一个socket。这里还有的就是UI的更新,这里用到的是state的设置,然后通过handler把这个state返回去,然后更新UI。
好吧,这就是我能理解的部分,还有就是把我的注释的给展示出来吧。至于以后用到蓝牙的部分,以后再更新吧。
这是这个月最后一更了,这个月本来这应该是最有价值的一篇文章,结果,水平太菜了,没办法,只能做到这里,五一回家玩玩吧,放松下。。。
DeviceListActivity.java
package com.example.bluetooth;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView;
public class DeviceListActivity extends Activity {
private BluetoothAdapter mBtAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
private ArrayAdapter<String> mNewDevicesArrayAdapter;
public static String EXTRA_DEVICE_ADDRESS = "device_address";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//这里设置窗体为不确定进度,因为有progressbar
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.device_list);
//setResult(Activity.RESULT_CANCELED);
Button scanButton = (Button) findViewById(R.id.button_scan);
scanButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.GONE);
}
});
mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
pairedListView.setAdapter(mPairedDevicesArrayAdapter);
pairedListView.setOnItemClickListener(mDeviceClickListener);
ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
newDevicesListView.setOnItemClickListener(mDeviceClickListener);
//注册两个过滤器,用来接收两个广播,一个是搜索到一个可用设备,一个是结束搜索
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
//获取本地蓝牙适配器,把本地已配对设备显示出来
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
for (BluetoothDevice device : pairedDevices) {
mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
} else {
String noDevices = getResources().getText(R.string.none_paired).toString();
mPairedDevicesArrayAdapter.add(noDevices);
}
}
//搜索
private void doDiscovery(){
//设置显示
setProgressBarIndeterminateVisibility(true);
setTitle(R.string.scanning);
findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
//如果正在搜索,取消正在搜索
if (mBtAdapter.isDiscovering()) {
mBtAdapter.cancelDiscovery();
}
//开始搜索
mBtAdapter.startDiscovery();
}
//监听器
private OnItemClickListener mDeviceClickListener = new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
mBtAdapter.cancelDiscovery();
//获取内容,然后把后面17位的MAC地址取出来,连接只需要MAC地址
String info = ((TextView) arg1).getText().toString();
String address = info.substring(info.length() - 17);
//把MAC地址传回到主activity,调用setResult在finish之前传回值
Intent intent = new Intent();
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
setResult(Activity.RESULT_OK, intent);
finish();
}};
//注册一个广播接收,两个不同的接收给出不同的动作
private final BroadcastReceiver mReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action))
{
//把新发现的设备显示出来
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
{
mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0)
{
String noDevices = getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}};
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mBtAdapter != null)
{
mBtAdapter.cancelDiscovery();
}
//广播要取消注册,防止内存泄漏
this.unregisterReceiver(mReceiver);
}
}
BluetoothChat.java
package com.example.bluetooth;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.ActionBar;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class BluetoothChat extends Activity {
//handler处理
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;
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothChatService mChatService = null;
private ArrayAdapter<String> mConversationArrayAdapter;
private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;
private StringBuffer mOutStringBuffer;
private String mConnectedDeviceName = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//本地如果没有蓝牙,提示没有蓝牙
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null)
{
Toast.makeText(this, "没有发现蓝牙设备", Toast.LENGTH_LONG).show();
finish();
return;
}
//蓝牙是否打开了,没有的话,让用户选择是否打开
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, RESULT_FIRST_USER);
} else {
if (mChatService == null) setupChat();
}
}
//蓝牙是否可以被检测
private void ensureDiscoverable() {
// TODO Auto-generated method stub
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
//信息显示
private void setupChat() {
// TODO Auto-generated method stub
mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
mConversationView = (ListView) findViewById(R.id.in);
mConversationView.setAdapter(mConversationArrayAdapter);
mOutEditText = (EditText) findViewById(R.id.edit_text_out);
mOutEditText.setOnEditorActionListener(mWriteListener);
mSendButton = (Button) findViewById(R.id.button_send);
mSendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Send a message using content of the edit text widget
TextView view = (TextView) findViewById(R.id.edit_text_out);
String message = view.getText().toString();
sendMessage(message);
}
});
}
//EditText+Button响应,软键盘设置
private TextView.OnEditorActionListener mWriteListener =
new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
String message = view.getText().toString();
sendMessage(message);
}
return true;
}
};
//开始聊天服务
@Override
protected synchronized void onResume() {
// TODO Auto-generated method stub
super.onResume();
if (mChatService != null)
{
if (mChatService.getState() == BluetoothChatService.STATE_NONE)
{
mChatService.start();
}
}
}
protected void sendMessage(String message) {
// TODO Auto-generated method stub
//是否已经连接,没有连接是不能发送信息的
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED)
{
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
//发送信息
if (message.length() > 0)
{
byte[] send = message.getBytes();
mChatService.write(send);
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
//停止服务
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mChatService != null) mChatService.stop();
}
//设置当前连接状态的显示
private final void setStatus(int resId) {
final ActionBar actionBar = getActionBar();
actionBar.setSubtitle(resId);
}
private final void setStatus(CharSequence subTitle) {
final ActionBar actionBar = getActionBar();
actionBar.setSubtitle(subTitle);
}
//从BluetoothChatService中读取message,更新UI显示
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
setStatus(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// 写信息到缓存
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " + writeMessage);
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// 从缓存中读信息
String readMessage = new String(readBuf, 0, msg.arg1);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
break;
case MESSAGE_DEVICE_NAME:
// 保存设备名称
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
//打印toast
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
//DeviceActivity的结果返回响应
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// 返回结果是要求一个连接
if (resultCode == Activity.RESULT_OK) {
connectDevice(data, true);
}
break;
case REQUEST_CONNECT_DEVICE_INSECURE:
//
if (resultCode == Activity.RESULT_OK) {
connectDevice(data, false);
}
break;
case REQUEST_ENABLE_BT:
// 返回结果是要求打开蓝牙
if (resultCode == Activity.RESULT_OK) {
setupChat();
} else {
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}
//连接设备
private void connectDevice(Intent data, boolean secure) {
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
mChatService.connect(device, secure);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Intent serverIntent = null;
switch (item.getItemId()) {
case R.id.secure_connect_scan:
// Launch the DeviceListActivity to see devices and do scan
serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
case R.id.insecure_connect_scan:
// Launch the DeviceListActivity to see devices and do scan
serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
return true;
case R.id.discoverable:
// Ensure this device is discoverable by others
ensureDiscoverable();
return true;
}
return false;
}
}
BluetoothChatService.java
package com.example.bluetooth;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class BluetoothChatService {
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
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");
//设置UI的状态
private int mState;
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
public BluetoothChatService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
//UI的动态显示,显示的是状态
mState = STATE_NONE;
//信息的处理线程
mHandler = handler;
}
public int getState() {
// TODO Auto-generated method stub
return mState;
}
//改变UI的状态显示
private void setState(int stateListen) {
// TODO Auto-generated method stub
mState = stateListen;
mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, stateListen, -1).sendToTarget();
}
//建立设备之间的连接
public void connect(BluetoothDevice device, boolean secure) {
// TODO Auto-generated method stub
if (mState == STATE_CONNECTING)
{
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
}
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
mConnectThread = new ConnectThread(device, secure);
mConnectThread.start();
setState(STATE_CONNECTING);
}
//连接失败的提示
private void connectionFailed() {
// 把连接失败显示在UI上
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
// 重新开始服务
BluetoothChatService.this.start();
}
//连接已建立,保持连接
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device, final String socketType) {
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
if (mSecureAcceptThread != null)
{
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
// 在UI上把当前连接的设备名显示出来
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
//连接中断
private void connectionLost() {
// 连接如果中断了,就在UI上提示
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
// 重新开始服务
BluetoothChatService.this.start();
}
//开始聊天服务
public void start() {
// TODO Auto-generated method stub
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
setState(STATE_LISTEN);
// 开始监听socket
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread(true);
mSecureAcceptThread.start();
}
}
//停止服务
public void stop() {
// TODO Auto-generated method stub
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null)
{
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
setState(STATE_NONE);
}
//监听连接请求线程
private class AcceptThread extends Thread{
//本地socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread(boolean secure){
BluetoothServerSocket tmp = null;
mSocketType = secure ? "Secure":"Insecure";
// 创建一个新的服务socket
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
}
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
//没有建立连接
while (mState != STATE_CONNECTED) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// 建立了连接
if (socket != null) {
synchronized (BluetoothChatService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
connected(socket, socket.getRemoteDevice(),
mSocketType);
break;
case STATE_NONE:
case STATE_CONNECTED:
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
}
}
}
//连接线程
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
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) {
}
mmSocket = tmp;
}
public void run() {
setName("ConnectThread" + mSocketType);
mAdapter.cancelDiscovery();
//连接到BluetoothSocket
try {
mmSocket.connect();
} catch (IOException e) {
try {
mmSocket.close();
} catch (IOException e2) {
}
connectionFailed();
return;
}
// 取消连接线程
synchronized (BluetoothChatService.this) {
mConnectThread = null;
}
// 开始连接线程
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
//已连接线程,通过这个线程发送和接收数据
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//初始化
public ConnectedThread(BluetoothSocket socket, String socketType){
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//得到输入输出数据流
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
//读
public void run(){
byte[] buffer = new byte[1024];
int bytes;
//长连接
while (true) {
try {
bytes = mmInStream.read(buffer);
// 把信息反馈给UI界面显示出来
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
connectionLost();
// 重新开始服务
BluetoothChatService.this.start();
break;
}
}
}
//写
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
//写接口
public void write(byte[] send) {
// TODO Auto-generated method stub
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
r.write(send);
}
}