蓝牙协议可以实现一个蓝牙设备和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 蓝牙搜索、配对连接通信总结相关推荐

  1. android蓝牙配对 自动联接,Android系统下蓝牙自动配对连接方法

    Android系统下蓝牙自动配对连接方法 [专利摘要]本发明涉及一种Android系统下蓝牙自动配对连接方法,其包括如下步骤:步骤1.在Android设备端内存储上次进行蓝牙连接蓝牙外设的蓝牙地址,并 ...

  2. Android蓝牙搜索连接通信

    蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙技术最初由电信巨头爱立 ...

  3. android 实现ble蓝牙自动配对连接

    蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框. 本文章用来连接蓝牙设备ai-thinker,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值 ...

  4. android开发之蓝牙主动配对连接手机

    上一篇介绍了手机配对连接的三种方式,这篇以完整的一个代码实例介绍如何搜索周围的蓝牙设备,以及主动配对,连接. 主要注释在代码中都有. package jason.com; import java.io ...

  5. 【转载】Android蓝牙自动配对Demo

    注:新版本安卓需增加权限 <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION ...

  6. win10蓝牙已配对连接不上_Win10系统蓝牙配对手机连接不成功的解决方法

    Win10系统蓝牙配对手机连接不成功的解决方法.很多的Win10用户都在使用蓝牙连接手机,一些网友在连接时出现win10系统蓝牙已配对但连接不成功,出现在这样的问题怎么解决呢?下面我们来看看Win10 ...

  7. Android 蓝牙hfp协议连接slc连接rfcomm连接源码分析(2)- HF侧发送和接受数据流程

    android-蓝牙A2dp-avrcp-hfp-opp-配对流程-ble-rfcomm源码流程 Android 蓝牙hfp初始化.rfcomm连接.slc连接.sco连接源代码分析大全 - 点击下载 ...

  8. win10蓝牙已配对连接不上_图文解读win10系统显示蓝牙已配对但未连接的解决教程...

    图文解读win10系统显示蓝牙已配对但未连接的解决教程 更新日期:2020-05-06 12:12:02 作者:win10蓝牙 来源:本站整理 我们在操作win10系统电脑的时候,常常会遇到win10 ...

  9. win10蓝牙已配对连接不上_win10系统蓝牙已配对但未连接的解决方法

    很多小伙伴都遇到过win10系统蓝牙已配对但未连接的困惑吧,一些朋友看过网上零散的win10系统蓝牙已配对但未连接的处理方法,并没有完完全全明白win10系统蓝牙已配对但未连接是如何解决的,今天小编准 ...

最新文章

  1. linux mysql远程连接其他服务器_Linux服务器中MySQL远程连接的开启方法
  2. mkdir创建递归目录
  3. 【渝粤题库】陕西师范大学500001 理论力学 作业(专升本)
  4. mysql构建栋_【转载】这次拆库 应是微服务化的拆分方式
  5. WSS页面定制系列(1)--如何启用表单页面的编辑模式
  6. linux设备驱动之串口移植,Linux设备驱动之UART驱动结构
  7. python torch exp_学习Pytorch过程遇到的坑(持续更新中)
  8. HDU1175(dfs)
  9. 关于mysql性能优化_关键的十个MySQL性能优化技巧
  10. 有限元分析简单实例之平面矩形薄板(matlab)
  11. 冒险岛进去计算机丢失,找不到队伍怎么办?《冒险岛2》打杂攻略
  12. zemax验证高斯公式_Zemax中高斯光束设置的相关问题
  13. JavaScript数组方法(最全)
  14. Relative Ranks问题及解法
  15. spyder 5.0.0 提示依赖项spyder-kernels版本错误
  16. NoC(Network on Chip)基础 (3):网络拓扑结构 Butterfly、Torus、Mesh
  17. 让人春分日 哈工科教100272.关路灯
  18. 机器学习 (一) 基础概念
  19. 软件工程学习(十)常见的软件架构
  20. 【UE4】TimeLine(蓝图)

热门文章

  1. 麦咖啡阻挡正常打开Excel文件
  2. 腾讯阿里是否开始走向衰落,用新互联网大脑模型分析
  3. 微型计算机48MHz辐射超,造成EMC辐射超标原因有哪些(精彩案例分析)
  4. TypeError: can‘t convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory
  5. scala函数自我小结(待更新)
  6. ssm+jsp计算机毕业设计大媛小南美味佳肴网站8p0nh(程序+LW+源码+远程部署)
  7. rabbitmq网络框架剖析
  8. 微博数据解析 | 可口可乐 VS 元气森林
  9. 解决 Chrome浏览器网页上出现光标,无法通过键盘方向键实现页面滚动的问题
  10. 《算法图解》——第五章 散列表(服务器大姨妈来了?第四第五内容传不上去= =!)