android 蓝牙搜索、配对连接通信总结
蓝牙协议可以实现一个蓝牙设备和6到8个蓝牙设备进行通信。
1、蓝牙搜索的实现
利用蓝牙的发现和完成动作动态注册广播接受者获得蓝牙设备。
第一步,获得蓝牙适配器
BluetoothAdapter mBtAdapter= BluetoothAdapter.getDefaultAdapter();
<span style="white-space:pre"> </span>// 判断蓝牙是否打开
<span style="white-space:pre"> </span>if (!mAdapter.isEnabled()) {
<span style="white-space:pre"> </span>mAdapter.enable();
第二步动态注册蓝牙搜索广播接收者
// Register for broadcasts when a device is discoveredIntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);this.registerReceiver(mReceiver, filter);// Register for broadcasts when discovery has finishedfilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);this.registerReceiver(mReceiver, filter);
并且可以利用意图过滤器设置广播的优先级
filter.setPriority(Integer.MAX_VALUE);
对应的广播接收者:
// The BroadcastReceiver that listens for discovered devices and// changes the title when discovery is finishedprivate final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();// When discovery finds a deviceif (BluetoothDevice.ACTION_FOUND.equals(action)) {// Get the BluetoothDevice object from the IntentBluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);// If it's already paired, skip it, because it's been listed alreadyif (device.getBondState() != BluetoothDevice.BOND_BONDED) {mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());}// When discovery is finished, change the Activity title} 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);}}}};
或者利用发现和完成动作定义两个广播接受者,在完成的动作中注销广播接收者。
关键代码如下:
/*** 接收器 当搜索蓝牙设备完成时调用*/private BroadcastReceiver _foundReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);// 将结果添加到列表中_devices.add(device);DeviceInfo info = new DeviceInfo();info.setmDeviceName(device.getName());info.setmDeviceMacAddr(device.getAddress());infos.add(info);info = null;// 显示列表showDevices();}};private BroadcastReceiver _discoveryReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {// 卸载注册的接收器unregisterReceiver(_foundReceiver);unregisterReceiver(this);_discoveryFinished = true;}};
这样便完成蓝牙的搜索了。
2、蓝牙配对
蓝牙要想通信目前是必须要先配对才能连接的。
蓝牙配对的api是hide的。但是api19可以直接调用蓝牙设备的配对方法。
所以配对都是利用反射的方法。这里有一个强大的工具类可以直接拿来使用,如下:
public class ClsUtils {public ClsUtils() {// TODO Auto-generated constructor stub}/** * 与设备配对 参考源码:platform/packages/apps/Settings.git * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java */ static public boolean createBond(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice) throws Exception { Method createBondMethod = btClass.getMethod("createBond"); Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice); return returnValue.booleanValue(); } /** * 与设备解除配对 参考源码:platform/packages/apps/Settings.git * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java */ static public boolean removeBond(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice) throws Exception { Method removeBondMethod = btClass.getMethod("removeBond"); Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice); return returnValue.booleanValue(); } static public boolean setPin(Class btClass, BluetoothDevice btDevice, String str) throws Exception { try { Method removeBondMethod = btClass.getDeclaredMethod("setPin", new Class[] {byte[].class}); Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[] {str.getBytes()}); Log.e("returnValue设置密码", "" + returnValue.booleanValue()); return returnValue.booleanValue(); } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } // 取消用户输入 static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelPairingUserInput"); cancelBondProcess(btClass,device) ; Boolean returnValue = (Boolean) createBondMethod.invoke(device); Log.i("取消对话框","cancelPairingUserInput"+returnValue.booleanValue());return returnValue.booleanValue(); } // 取消配对 static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelBondProcess"); Boolean returnValue = (Boolean) createBondMethod.invoke(device); return returnValue.booleanValue(); } /** * * @param clsShow */ static public void printAllInform(Class<?> clsShow) { try { // 取得所有方法 Method[] hideMethod = clsShow.getMethods(); int i = 0; for (; i < hideMethod.length; i++) { Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i); } // 取得所有常量 Field[] allFields = clsShow.getFields(); for (i = 0; i < allFields.length; i++) { Log.e("Field name", allFields[i].getName()); } } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } static public boolean pair(String strAddr, String strPsw) { boolean result = false; BluetoothAdapter bluetoothAdapter = BluetoothAdapter .getDefaultAdapter(); bluetoothAdapter.cancelDiscovery(); if (!bluetoothAdapter.isEnabled()) { bluetoothAdapter.enable(); } BluetoothDevice device = bluetoothAdapter.getRemoteDevice(strAddr); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { try { Log.d("mylog", "NOT BOND_BONDED"); boolean flag1=ClsUtils.setPin(device.getClass(), device, strPsw); // 手机和蓝牙采集器配对 boolean flag2=ClsUtils.createBond(device.getClass(), device);
// remoteDevice = device; // 配对完毕就把这个设备对象传给全局的remoteDevice result = true; } catch (Exception e) { // TODO Auto-generated catch block Log.d("mylog", "setPiN failed!"); e.printStackTrace(); } // } else { Log.d("mylog", "HAS BOND_BONDED"); try { ClsUtils.removeBond(device.getClass(), device);//ClsUtils.createBond(device.getClass(), device); boolean flag1= ClsUtils.setPin(device.getClass(), device, strPsw); // 手机和蓝牙采集器配对 boolean flag2=ClsUtils.createBond(device.getClass(), device);
// remoteDevice = device; // 如果绑定成功,就直接把这个设备对象传给全局的remoteDevice result = true; } catch (Exception e) { // TODO Auto-generated catch block Log.d("mylog", "setPiN failed!"); e.printStackTrace(); } } return result; } }
蓝牙配对的关键代码:
flag3= ClsUtils.createBond(device.getClass(), device);
其中device是蓝牙设备。在配对的时候会有一个配对广播,可以自定义一个广播接受者获取配对广播,然后在这个广播接收者里设置pin值,取消确定对话框,实现自动配对。关键代码如下:
mReceiver=new ParingReceiver(device);IntentFilter filter=new IntentFilter();filter.addAction( BluetoothDevice.ACTION_PAIRING_REQUEST);filter.setPriority(Integer.MAX_VALUE);registerReceiver(mReceiver, filter);
private class ParingReceived extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {BluetoothDevice btDevice=mAdapter.getRemoteDevice("EC:89:F5:98:46:f9");try {setPin(btDevice.getClass(),btDevice,"000000");cancelPairingUserInput(btDevice.getClass(), btDevice);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
在我的4.2系统上是没有效果的。找了一个上午的资料;网上给出了两种解决方法:(1)修改setting 系统源码,(2)模拟点击事件。
蓝牙配对完成后就可以连接通信了。
3、蓝牙通信
蓝牙同时的本质是蓝牙套接字,一个主动发起连接的的设备做客户端,一个监听连接的设备做服务端,类似sokcet网络编程,利用多线程,读取数据流就可完成蓝牙通信。
如下是蓝牙串口通信的关键代码:
/*** 建立连接并通信* * @param btDev* @return*/private boolean connect(BluetoothDevice btDev) {boolean flag = false;try {/*if(btDev.fetchUuidsWithSdp()){btDev.getUuids();}*///建立连接mSocket = btDev .createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));mSocket.connect();mOutputStream = mSocket.getOutputStream();mInputStream = mSocket.getInputStream();mOutputStream.write("StartOnNet\n".getBytes());mOutputStream.flush();flag = true;} catch (Exception e) {}
如下蓝牙服务端关键代码:
private class ServerThread implements Runnable {private InputStream mInputStream;private OutputStream mOutputStream;public ServerThread() {}@Overridepublic void run() {try {while (true) {mBluetoothServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("btspp",UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));Log.i("服务端线程运行", "蓝牙服务端线程开始");Log.i("服务端线程运行", "蓝牙服务端线程阻塞中");mBluetoothSocket = mBluetoothServerSocket.accept();if (mBluetoothSocket != null) {break;}}Log.i("服务端线程运行", "蓝牙服务端线程<<<<<<<<<<<<<");mInputStream = mBluetoothSocket.getInputStream();mOutputStream = mBluetoothSocket.getOutputStream();byte[] data = getSocketResult(mInputStream);String tempString = new String(data);Log.i("蓝牙服务端监听str", tempString);// 向客户端发送数据if (tempString.equals("StartOnNet\n")) {mOutputStream.write("haha".getBytes());mOutputStream.flush();if(!isServiceRunning("com.yqq.endClient3.service.GpsInfoCollectionService",BluethoothServer.this)){// 开启GPS收集服务gpsService= new Intent(BluethoothServer.this,GpsInfoCollectionService.class);Log.i("蓝牙服务端监听<<<<<<<<<<<<<<<<<<<<<<", "<<<<<<<<<<<<<<<<<");startService(gpsService);}}} catch (Exception e) {// TODO: handle exception} finally {if (mInputStream != null) {try {mInputStream.close();mInputStream = null;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (mInputStream != null) {try {mOutputStream.close();mOutputStream = null;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (mBluetoothSocket != null) {try {mBluetoothSocket.close();mBluetoothSocket = null;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (mBluetoothServerSocket != null) {try {mBluetoothServerSocket.close();mBluetoothServerSocket = null;Looper.prepare();Message message = Message.obtain();message.what = 0x123456;mHandler.sendMessage(message);Looper.loop();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}
android 蓝牙搜索、配对连接通信总结相关推荐
- android蓝牙配对 自动联接,Android系统下蓝牙自动配对连接方法
Android系统下蓝牙自动配对连接方法 [专利摘要]本发明涉及一种Android系统下蓝牙自动配对连接方法,其包括如下步骤:步骤1.在Android设备端内存储上次进行蓝牙连接蓝牙外设的蓝牙地址,并 ...
- Android蓝牙搜索连接通信
蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙技术最初由电信巨头爱立 ...
- android 实现ble蓝牙自动配对连接
蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框. 本文章用来连接蓝牙设备ai-thinker,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值 ...
- android开发之蓝牙主动配对连接手机
上一篇介绍了手机配对连接的三种方式,这篇以完整的一个代码实例介绍如何搜索周围的蓝牙设备,以及主动配对,连接. 主要注释在代码中都有. package jason.com; import java.io ...
- 【转载】Android蓝牙自动配对Demo
注:新版本安卓需增加权限 <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION ...
- win10蓝牙已配对连接不上_Win10系统蓝牙配对手机连接不成功的解决方法
Win10系统蓝牙配对手机连接不成功的解决方法.很多的Win10用户都在使用蓝牙连接手机,一些网友在连接时出现win10系统蓝牙已配对但连接不成功,出现在这样的问题怎么解决呢?下面我们来看看Win10 ...
- Android 蓝牙hfp协议连接slc连接rfcomm连接源码分析(2)- HF侧发送和接受数据流程
android-蓝牙A2dp-avrcp-hfp-opp-配对流程-ble-rfcomm源码流程 Android 蓝牙hfp初始化.rfcomm连接.slc连接.sco连接源代码分析大全 - 点击下载 ...
- win10蓝牙已配对连接不上_图文解读win10系统显示蓝牙已配对但未连接的解决教程...
图文解读win10系统显示蓝牙已配对但未连接的解决教程 更新日期:2020-05-06 12:12:02 作者:win10蓝牙 来源:本站整理 我们在操作win10系统电脑的时候,常常会遇到win10 ...
- win10蓝牙已配对连接不上_win10系统蓝牙已配对但未连接的解决方法
很多小伙伴都遇到过win10系统蓝牙已配对但未连接的困惑吧,一些朋友看过网上零散的win10系统蓝牙已配对但未连接的处理方法,并没有完完全全明白win10系统蓝牙已配对但未连接是如何解决的,今天小编准 ...
最新文章
- linux mysql远程连接其他服务器_Linux服务器中MySQL远程连接的开启方法
- mkdir创建递归目录
- 【渝粤题库】陕西师范大学500001 理论力学 作业(专升本)
- mysql构建栋_【转载】这次拆库 应是微服务化的拆分方式
- WSS页面定制系列(1)--如何启用表单页面的编辑模式
- linux设备驱动之串口移植,Linux设备驱动之UART驱动结构
- python torch exp_学习Pytorch过程遇到的坑(持续更新中)
- HDU1175(dfs)
- 关于mysql性能优化_关键的十个MySQL性能优化技巧
- 有限元分析简单实例之平面矩形薄板(matlab)
- 冒险岛进去计算机丢失,找不到队伍怎么办?《冒险岛2》打杂攻略
- zemax验证高斯公式_Zemax中高斯光束设置的相关问题
- JavaScript数组方法(最全)
- Relative Ranks问题及解法
- spyder 5.0.0 提示依赖项spyder-kernels版本错误
- NoC(Network on Chip)基础 (3):网络拓扑结构 Butterfly、Torus、Mesh
- 让人春分日 哈工科教100272.关路灯
- 机器学习 (一) 基础概念
- 软件工程学习(十)常见的软件架构
- 【UE4】TimeLine(蓝图)
热门文章
- 麦咖啡阻挡正常打开Excel文件
- 腾讯阿里是否开始走向衰落,用新互联网大脑模型分析
- 微型计算机48MHz辐射超,造成EMC辐射超标原因有哪些(精彩案例分析)
- TypeError: can‘t convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory
- scala函数自我小结(待更新)
- ssm+jsp计算机毕业设计大媛小南美味佳肴网站8p0nh(程序+LW+源码+远程部署)
- rabbitmq网络框架剖析
- 微博数据解析 | 可口可乐 VS 元气森林
- 解决 Chrome浏览器网页上出现光标,无法通过键盘方向键实现页面滚动的问题
- 《算法图解》——第五章 散列表(服务器大姨妈来了?第四第五内容传不上去= =!)