Android 蓝牙开发之数据通信
本文所述通信,是建立在已配对的基础上的。因为,个人认为,目前手机上的蓝牙配对功能已经很完善了,所以,我们完全可以先通过手机进行配对,然后直接在程序里面获取以配对的蓝牙设备进行开发即可,这样一来,我们把蓝牙开发里面的搜索和配对的工作就都给省略了。当然,这得根据个人想法以及功能需要来决断,因此不再多做赘述。下面简单描述下功能实现:
- 从手机中已经配对的蓝牙设备中,得到指定的某一个蓝牙设备,进行连接,然后进行数据的发送和接收。
一、首先,需要获得一个BluetoothAdapter,可以通过getDefaultAdapter()获得系统默认的蓝牙适配器,当然我们也可以自己指定,但这个真心没有必要,至少我是不需要的。然后我们检查手机的蓝牙是否打开,如果没有,通过startActivity()方法打开。
代码如下:
/**
* 获取已配对的蓝牙设备
*/
private void init(){
/* 取得默认的蓝牙适配器 */
BlueAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//adapter不等于null,说明本机有蓝牙设备
if(adapter != null){
//如果蓝牙设备未开启
if(!adapter.isEnabled()){
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//请求开启蓝牙设备
context.startActivity(intent);
}
//获得已配对的远程蓝牙设备的集合
Set<BluetoothDevice> devices = adapter.getBondedDevices();
if(devices.size()>0){
//(这里用到了Iterator,有不懂的可以网上搜索一下,也比较好理解)
for(Iterator<BluetoothDevice> it = devices.iterator();it.hasNext();){
BluetoothDevice device = it.next();
//获取远程蓝牙设备的名称
String bluetoothName = device.getName();
//如果蓝牙设备的名称跟我们的目标设备的名称一致,则记录下该设备(device)
if (bluetoothName.equals(lockName)) {
targetDevice = device;
Log.i("bluetooth", "连接设备的名称:" + device.getName());
break;
}
}
}else{
toast.setText("还没有已配对的远程蓝牙设备!");
}
}else{
toast.setText("本机没有蓝牙设备!");
}
}
二、搜索到该设备后,我们就要对该设备进行连接。下面是读取数据的代码:
/**
* 连接应该放在一个线程中进行,要让该线程与我们程序的主线程进行通信,我们需要使用Handle,
*/
public void connect() {
Thread thread = new Thread(new Runnable() {
public void run() {
//这里是调试遇到bug之后的解决方案,不明白的可以网上搜索下,
//也可以去掉这一句以及最后面的那一句,观察log提示
Looper.prepare();
BluetoothSocket tmp = null;
//这里需要重点说明下,本来连接设备之前是需要UUID的,所谓的UUID,就是用来进行配对的,
//全称是Universally Unique Identifier,是一个128位的字符串ID,用于进行唯一标识。
//因为我们是已经配对好的,所以这里直接通过下面的方法获得BluetoothSocket 即可。
Method method;
try {
method = targetDevice.getClass().getMethod("createRfcommSocket",
new Class[]{int.class});
tmp = (BluetoothSocket) method.invoke(targetDevice, 1);
} catch (Exception e) {
Log.i("bluetooth", e.toString());
}
socket = tmp;
try {
//连接设备之前还有一件事必须确保,取消扫描:
adapter.cancelDiscovery();
socket.connect();
toast.setText("连接成功,开始进行数据读取");
Log.i("bluetooth", "连接成功,开始进行数据读取");
// 连接成功之后进行读取
read();
} catch (Exception e) {
Log.i("bluetooth", "连接失败");
//如果连接失败,则继续连接
connect();
}
Looper.loop();
}
});
thread.start();
}
三、连接完成之后,我们就可以进行数据的发送和读取了
/**
* 读取目标蓝牙设备发送过来的数据
*/
private void read() {
Thread threadRead = new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
String result = "01100000";
/**
* 当然,这里只是将手机当做客户端,但是接收蓝牙模块发送过来的信息是没有必要特意
* 创建服务端的,我们只要一个不断监听并读取对方消息的循环就行。
*/
while (true) {
try {
int count = 4;
int realCount = 0; // 已经成功读取的字节的个数
创建一个长度为4的byte数组,每次读取4个字节
byte[] bytes = new byte[4];
//这里的这个循环,是为了保证每次都能够读取到4个字节。
//这里给大家一个连接,建议去体会
//(http://ouyangfei0426.iteye.com/blog/1024950)
while (realCount < count) {
realCount += inputStream.read(bytes, realCount, count - realCount);
}
//这里是将字节数组转换为十六进制字符串,后面会贴代码
String message = Utils.bytesToHexString(bytes);
//下面呢,则是我的一些数据处理的方式,这里大家就可以自由发挥了
result += message;
if (message.equals("3535376A")) {
int start = result.indexOf("A3200061");
int end = result.indexOf("3535376A");
result = result.substring(start + 6, end + 6);
Log.i("bluetooth", "最终接收数据结果:" + result);
}
Log.i("bluetooth", "读取的数据:" + message);
//这里是handler数据处理语句,具体代码不再贴了
Message msg = handler.obtainMessage();
msg.what = 0x00;
msg.obj = result;
handler.sendMessage(msg);
} catch (IOException e) {
Log.e("TAG", e.toString());
***//循环结束语句在这里哦***
break;
}
}
} catch (IOException e) {
Log.e("TAG", e.toString());
}
}
});
//千万别忘了开启线程(本人不才,犯过错误,,)
threadRead.start();
}
四、下面是发送数据的语句,也比较简单。代码如下:
/**
* 写数据
*/
public void write(final byte[] bytes) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
OutputStream out = socket.getOutputStream();
for (byte b : bytes) {
out.write(b);
Thread.sleep(10);
}
out.flush();
} catch (Exception e) {
Log.e("Write", e.toString());
}
}
});
thread.start();
}
五、OK!主体功能已经实现了,下面就是那个字节数据转十六进制字符串的方法了(比较惭愧,这个方法是借鉴的别人的)。
//二进制转十六进制字符串
public static String bytesToHexString(byte[] bytes) {
String result = "";
for (int i = 0; i < bytes.length; i++) {
String hexString = Integer.toHexString(bytes[i] & 0xFF);
if (hexString.length() == 1) {
hexString = '0' + hexString;
}
result += hexString.toUpperCase();
}
return result;
}
六、以上就是个人的一点关于蓝牙开发数据通信方面的小小的总结。有不当的地方欢迎大家提出来,我们一起探讨学习。