需要说明的是,该通讯是安卓手机与蓝牙模块之间的通讯。
通讯的步骤如下
- 判断蓝牙是否打开,如果没有打开,则打开蓝牙。
- 扫描周围的蓝牙设备
- 得到周围的蓝牙设备对象BluetoothDevice
- 通过扫描到的蓝牙设备BluetoothDevice和UUID得到BluetoothSocket,这是双方进行通讯的socket,是通讯的核心。关于UUID后面会简单介绍。
通过得到的BluetoothSocket对象,进行数据的读写。
下面我就分别写下这几个步骤。
1,得到本地的蓝牙适配器并且打开蓝牙
1.1得到本地蓝牙适配器:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
1.2打开蓝牙
// 如果蓝牙没有打开,通过这个Activity打开
if (!adapter.isEnabled())
{
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
}
Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
// 300为可以被其他蓝牙设备搜索到的时间,单位为秒
enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(enable, DISCOVERY_REQUEST);
2,扫描周围的设备
通过BluetoothAdapter 的startDiscovery()进行扫描,找到一个设备,就会发出一条广播,所以找到的新设备要在广播接收器里面进行接收。
扫描的时间会比较长,一般会持续十多秒。
if (adapter!=null) {
adapter.startDiscovery();
}
3,通过广播接收器找到扫描到的新设备。
前面已经说了,如果adapter发现新的设备,就会发出广播。因此我们需要在广播接收器里面得到新设备。
BluetoothDevice对象就是发现的新设备,BluetoothDevice有好多方法,比如通过bluetoothdevice.getName()获取新设备名称。通过bluetoothdevice.getAddress()获取设备的硬件地址,比如“00:11:22:AA:BB:CC”。当然还有其他的方法,这里不再多说。
发现的新设备可以显示到一个列表里面。这里只是说明原理,列表显示在源码里面。
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}
}
};
当然,最后需要对广播接收器进行注册。
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
4,得到BluetoothSocket。
需要说明的是,这里手机是作为客户端来使用。如果是作为服务端,得到Socket的方法会有所不同。
无论手机是作为客户端还是服务端,在和其他设备连接过程中,都需要UUID,下面简单地介绍下UUID。
UUID
UUID 含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标
准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。
在蓝牙 3.0 及一下版本中,UUID 被用于唯一标识一个服务,比如文件传输服务,串口服务、打印机服务等,如下:
蓝牙串口服务
SerialPortServiceClass_UUID = ‘{00001101-0000-1000-8000-00805F9B34FB}’
LANAccessUsingPPPServiceClass_UUID = ‘{00001102-0000-1000-8000-00805F9B34FB}’
拨号网络服务
DialupNetworkingServiceClass_UUID = ‘{00001103-0000-1000-8000-00805F9B34FB}’
信息同步服务
IrMCSyncServiceClass_UUID = ‘{00001104-0000-1000-8000-00805F9B34FB}’
SDP_OBEXObjectPushServiceClass_UUID = ‘{00001105-0000-1000-8000-00805F9B34FB}’
文件传输服务
OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’
IrMCSyncCommandServiceClass_UUID = ‘{00001107-0000-1000-8000-00805F9B34FB}’
因为我们和蓝牙模块进行通讯,所以选择蓝牙串口服务的UUID。
通过UUID建立连接
private static String uuid = "00001101-0000-1000-8000-00805F9B34FB";
try{
//device为BluetoothDevice 对象,即扫描到的新设备对象
BluetoothSocket mmSocket=device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
}
catch(IOException e){
}
得到BluetoothSocket 之后,就可以在两台设备之间建立连接,在连接之前,我们最好取消上面开启的扫描功能功能。
//adapter是BluetoothAdapter 的对象。
adapter.cancelDiscovery();
进行连接:
try{
//这个方法是阻塞式的,所以最好开一个线程进行连接。在这里可以写一个回调,连接成功后,就可以通过该socket读写数据了,详细的代码见源码。
mmSocket.connect();
}catch(Exception e){
//连接过程中若抛出异常,则关闭socket。
try {
mmSocket.close();
} catch (Exception e1) {
Log.e("close", e1.toString());
}
}
5,通过BluetoothSocket 对象读写数据。
收到数据后,通过Handler 发送message来刷新界面。
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public String datas;
public Message message;
public Handler handler;
//输入输出流的初始化
public ConnectedThread(BluetoothSocket socket,Handler handlers) {
mmSocket = socket;
this.handler=handlers;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
/**
* 接收数据,线程
*/
public void run() {
byte[] buffer = new byte[2048];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
String str= new String(buffer,"ISO-8859-1");
str=str.substring(0,bytes);
datas=str;
message=new Message();
message.what=Constant.DATAS;
handler.sendMessage(message);
} catch (IOException e) {
break;
}
}
}
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
}
6,其他
关于将手机作为服务端我没有尝试过,下面是连接的代码:
private static String uuid = "00001101-0000-1000-8000-00805F9B34FB";
//adapter是BluetoothAdapter 的对象。
BluetoothServerSocket =adapter.listenUsingRfcommWithServiceRecord("blue",UUID.fromString(uuid));
//连接之前会一直等待,所以要开启一个线程
while (true) {
try {
BluetoothSocket socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
}
拿到BluetoothSocket之后,就可以进行通讯了,通讯的代码和作为客户端连接设备应该是一样的。我没有尝试过。