安卓经典蓝牙:从设备扫描到数据接收
2018-03-07 15:48
639 查看
看了半年的蓝牙,真的是快半年了,刚开始学安卓就是直接看蓝牙模块真的是难为自己了。今天终于实现了蓝牙的数据接收并显示在了手机上,所以需要稍微记录一下。
分为以下步骤:
a. 获取本机蓝牙BA =BluetoothAdapter.getDefaultAdapter();
b. 打开蓝牙Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
turnOn.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 10);
mContext.startActivity(turnOn);c. 获取已经匹配蓝牙pairedDevices = BA.getBondedDevices();
//得到的pairedDevices应该是一个数组类型
for(BluetoothDevice device : pairedDevices) {
list1.add("已配对:" + device.getName() + "/" + device.getAddress());
mainList1.add(device);
adapter1.notifyDataSetChanged(); 其中mainList1为ArrayList类型,泛型为BluetoothDevice为了在点击ListView时获取
d. 扫描未匹配蓝牙
1. 添加广播过滤器,打开广播IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND); //搜索到蓝牙设备
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mContext.registerReceiver(mReceiver, filter);同时需要在广播响应中设置:class Receiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(!mainList1.contains(device)){
list1.add("未配对:" + device.getName() + "/" + device.getAddress());
mainList1.add(device);
adapter1.notifyDataSetChanged();
}
}
}
}
2. 开始扫描BA.startDiscovery();其中:
a. 广播中获取动作String action = intent.getAction();b. 获取扫描到的蓝牙设备BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);e. 点击设备lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d("检测:","mainList1:"+mainList1.get(i));
BA.cancelDiscovery();
connectDevice(mainList1.get(i));
String deviceName=mainList1.get(i).getAddress().toString();
StoreData.put(MainActivity.this,"address",deviceName);
new Thread(){
@Override
public void run(){
String deviceName=StoreData.
get(MainActivity.this,"address","").toString();
BluetoothDevice device=BA.getRemoteDevice(deviceName);
communicate(device);
DataTransport();
}
}.start();
String address=mainList1.get(i).toString();
Log.d("检测:","getRemoteAddress:"+BA.getRemoteDevice(address).getBondState());
}
});
f. 配对设备
1. 判断状态mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE2. Method creMethod(连接蓝牙)Method creMethod = BluetoothDevice.class
.getMethod("createBond");
Log.e("TAG", "开始配对");
creMethod.invoke(mBluetoothDevice);g. 存储蓝牙设备Mac地址String deviceName=mainList1.get(i).getAddress().toString();
StoreData.put(MainActivity.this,"address",deviceName);其中StoreData.put()为自定义函数,继承的
SharedPreferences类
h. 通过Mac地址找回设备对象(getRemoteDevice(String str))String deviceName=StoreData.
get(MainActivity.this,"address","").toString(); BluetoothDevice device=BA.getRemoteDevice(deviceName);
i. 判断状态(同f.1)
j. 新建线程并完成以下步骤new Thread(){
@Override
public void run(){
String deviceName=StoreData.
get(MainActivity.this,"address","").toString();
BluetoothDevice device=BA.getRemoteDevice(deviceName);
communicate(device);
DataTransport();
}
}.start();
k. 获取本机uuidUUID uuid= UUID.fromString(SPP_UUID);l. 新建BluetoothSocketbtSocket=device.createRfcommSocketToServiceRecord(uuid);m. 连接BluetoothSocketbtSocket.connect();n. 获取BluetooSocket的输入输出流inputStream=btSocket.getInputStream();
outputStream=btSocket.getOutputStream();
对于imn三步骤,涉及到输入输出数据传输,因此需要在try/catch结构中实现
o. 将输入输出流读取成可处理格式length = inputStream.read(recvBuffer);p. 其中length为int型,recvBuffer是byte[]型
q. 将输入输出流转化为二进制,即对recvBuffer进行处理public class functions {
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public static String BytesToString(byte[] inHex, int nOff, int nLen) {
int i;
StringBuilder strResult = new StringBuilder();
strResult.append("");
for (i = 0; i < nLen; i++) {
strResult.append(String
.valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff + i]) >>> 4]));
strResult.append(String
.valueOf(DIGITS_UPPER[inHex[nOff + i] & 0x0F]));
}
return strResult.toString();
}
}r. 通过handler发送出带有二进制信息的MessageMessage message = new Message();
message.obj =functions.BytesToString(recvBuffer, 0, length);
//将输入二进制数转化为十六进制数
handler.sendMessage(message);s. 回到handleMessage处理接收到的MessageHandlerhandler=new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
String str3 = (String) msg.obj;
StoreData sdata = new StoreData();
sdata.setContent(str3);
EventBus.getDefault().post(sdata);
return false;
}
});1. 通过EventBus将数据发送至显示层String str3 = (String) msg.obj;
StoreData sdata = new StoreData();
sdata.setContent(str3);
EventBus.getDefault().post(sdata);
2. 在显示层通过onEventMainThread()函数接收、读取并显示public void onEventMainThread(StoreData sdata) {
tv1.setText(sdata.mMsg);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}大工告成,当然还有环境配置之类的。目前虽然遇到过这些问题,但是也还没系统性搞明白怎么处理。以后再说了。
分为以下步骤:
a. 获取本机蓝牙BA =BluetoothAdapter.getDefaultAdapter();
b. 打开蓝牙Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
turnOn.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 10);
mContext.startActivity(turnOn);c. 获取已经匹配蓝牙pairedDevices = BA.getBondedDevices();
//得到的pairedDevices应该是一个数组类型
for(BluetoothDevice device : pairedDevices) {
list1.add("已配对:" + device.getName() + "/" + device.getAddress());
mainList1.add(device);
adapter1.notifyDataSetChanged(); 其中mainList1为ArrayList类型,泛型为BluetoothDevice为了在点击ListView时获取
d. 扫描未匹配蓝牙
1. 添加广播过滤器,打开广播IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND); //搜索到蓝牙设备
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mContext.registerReceiver(mReceiver, filter);同时需要在广播响应中设置:class Receiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(!mainList1.contains(device)){
list1.add("未配对:" + device.getName() + "/" + device.getAddress());
mainList1.add(device);
adapter1.notifyDataSetChanged();
}
}
}
}
2. 开始扫描BA.startDiscovery();其中:
a. 广播中获取动作String action = intent.getAction();b. 获取扫描到的蓝牙设备BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);e. 点击设备lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.d("检测:","mainList1:"+mainList1.get(i));
BA.cancelDiscovery();
connectDevice(mainList1.get(i));
String deviceName=mainList1.get(i).getAddress().toString();
StoreData.put(MainActivity.this,"address",deviceName);
new Thread(){
@Override
public void run(){
String deviceName=StoreData.
get(MainActivity.this,"address","").toString();
BluetoothDevice device=BA.getRemoteDevice(deviceName);
communicate(device);
DataTransport();
}
}.start();
String address=mainList1.get(i).toString();
Log.d("检测:","getRemoteAddress:"+BA.getRemoteDevice(address).getBondState());
}
});
f. 配对设备
1. 判断状态mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE2. Method creMethod(连接蓝牙)Method creMethod = BluetoothDevice.class
.getMethod("createBond");
Log.e("TAG", "开始配对");
creMethod.invoke(mBluetoothDevice);g. 存储蓝牙设备Mac地址String deviceName=mainList1.get(i).getAddress().toString();
StoreData.put(MainActivity.this,"address",deviceName);其中StoreData.put()为自定义函数,继承的
SharedPreferences类
h. 通过Mac地址找回设备对象(getRemoteDevice(String str))String deviceName=StoreData.
get(MainActivity.this,"address","").toString(); BluetoothDevice device=BA.getRemoteDevice(deviceName);
i. 判断状态(同f.1)
j. 新建线程并完成以下步骤new Thread(){
@Override
public void run(){
String deviceName=StoreData.
get(MainActivity.this,"address","").toString();
BluetoothDevice device=BA.getRemoteDevice(deviceName);
communicate(device);
DataTransport();
}
}.start();
k. 获取本机uuidUUID uuid= UUID.fromString(SPP_UUID);l. 新建BluetoothSocketbtSocket=device.createRfcommSocketToServiceRecord(uuid);m. 连接BluetoothSocketbtSocket.connect();n. 获取BluetooSocket的输入输出流inputStream=btSocket.getInputStream();
outputStream=btSocket.getOutputStream();
其中:
对于imn三步骤,涉及到输入输出数据传输,因此需要在try/catch结构中实现
o. 将输入输出流读取成可处理格式length = inputStream.read(recvBuffer);p. 其中length为int型,recvBuffer是byte[]型
q. 将输入输出流转化为二进制,即对recvBuffer进行处理public class functions {
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public static String BytesToString(byte[] inHex, int nOff, int nLen) {
int i;
StringBuilder strResult = new StringBuilder();
strResult.append("");
for (i = 0; i < nLen; i++) {
strResult.append(String
.valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff + i]) >>> 4]));
strResult.append(String
.valueOf(DIGITS_UPPER[inHex[nOff + i] & 0x0F]));
}
return strResult.toString();
}
}r. 通过handler发送出带有二进制信息的MessageMessage message = new Message();
message.obj =functions.BytesToString(recvBuffer, 0, length);
//将输入二进制数转化为十六进制数
handler.sendMessage(message);s. 回到handleMessage处理接收到的MessageHandlerhandler=new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
String str3 = (String) msg.obj;
StoreData sdata = new StoreData();
sdata.setContent(str3);
EventBus.getDefault().post(sdata);
return false;
}
});1. 通过EventBus将数据发送至显示层String str3 = (String) msg.obj;
StoreData sdata = new StoreData();
sdata.setContent(str3);
EventBus.getDefault().post(sdata);
2. 在显示层通过onEventMainThread()函数接收、读取并显示public void onEventMainThread(StoreData sdata) {
tv1.setText(sdata.mMsg);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}大工告成,当然还有环境配置之类的。目前虽然遇到过这些问题,但是也还没系统性搞明白怎么处理。以后再说了。
相关文章推荐
- 安卓蓝牙4.0以上连接多台设备并接收蓝牙设备数据
- Android安卓蓝牙BLE 扫描连接接收数据 封装好的类
- Android 低功耗蓝牙的多设备连接与数据接收,简单实现
- RxBluetooth一个很好的开源蓝牙操作类(扫描、状态监听、连接、发送、接收数据)
- Android蓝牙搜索设备,向其发送数据并接收-刘宇
- Android蓝牙搜索设备,向其发送数据并接收
- uuid正确却接收不到蓝牙设备返回的数据
- 安卓蓝牙设备连接仪器的数据交互
- iBeacon在iPhone锁屏下有几率扫描不到蓝牙设备以及折中解决方案
- 如何优雅的抓取低功耗蓝牙ble的数据(未经测试,需要花钱买ble设备,类似网卡)
- android 蓝牙编程重点---如何发送和接收16进制数据
- [解决方法]安卓与蓝牙模块HM05,HM06数据接收不完全的一种解决方法
- C++ Builder XE8 安卓开发之使用TidTCPClient控件获取接收数据长度的方法
- Android 蓝牙自动打开并扫描设备,以及获取对方蓝牙设备的种类
- android之蓝牙通信(一)(检测蓝牙、开启蓝牙、扫描附近蓝牙设备)
- Android开发之蓝牙(Bluetooth)操作(一)--扫描已经配对的蓝牙设备
- Android蓝牙扫描设备过程
- Android 扫描附近的蓝牙设备并连接蓝牙音响的示例
- Linux I2C驱动分析(二)----I2C板级设备扫描和数据传输
- MFC实现ffmpeg流媒体数据推送与接收(1.获取设备)