文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android中怎么实现蓝牙通信

2023-05-30 20:02

关注

这期内容当中小编将会给大家带来有关Android中怎么实现蓝牙通信,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一:注意事项

      1:android6.0使用蓝牙时,需要开启gps定位权限,不然无法搜索其它蓝牙设备。

二:权限

      1:权限配置

<!--允许程序连接到已配对的蓝牙设备--><uses-permission android:name="android.permission.BLUETOOTH" /><!-- 允许程序发现和配对蓝牙设备 --><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!--android 6.0 涉及到的权限--><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><!-- 在SDCard中创建与删除文件的权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!-- 往SDCard写入数据的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    2:动态权限代码

    由于需要用到存储卡,定位等,android6.0以上需要代码动态设置。

   a)获取定位设置

if (Build.VERSION.SDK_INT >= 23) {  boolean isLocat = isLocationOpen(getApplicationContext());  Toast.makeText(mContext, "isLo:" + isLocat, Toast.LENGTH_LONG).show();   //开启位置服务,支持获取ble蓝牙扫描结果  if (!isLocat) {  Intent enableLocate = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);  startActivityForResult(enableLocate, 1);  }}  private static boolean isLocationOpen(final Context context) {  LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);  //gps定位  boolean isGpsProvider = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);  //网络定位  boolean isNetWorkProvider = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);  return isGpsProvider || isNetWorkProvider; }

b)存储卡权限设置

if (Build.VERSION.SDK_INT >= 23) {   int write = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);   int read = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);   //动态请求读写sd卡权限   if (write != PackageManager.PERMISSION_GRANTED || read != PackageManager.PERMISSION_GRANTED) {    requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, SD_CARD);   }}

然后通过onRequestPermissionsResult()方法获取动态权限的结果:

@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  switch (requestCode){   case SD_CARD:    if(grantResults.length>0&&grantResults[0] == PackageManager.PERMISSION_GRANTED){     //允许访问    }else{     Toast.makeText(mContext,"您拒绝了程序访问存储卡",Toast.LENGTH_LONG).show();    }    break;   case COARES_LOCATION:    break;  } }

 三:蓝牙搜索

android.bluetooth.BluetoothAdapter 是蓝牙开发用得比较多,并且比较重要的一个类,可以设备蓝牙名称,打开,关闭,搜索等常规操作。

  1 蓝牙打开,以及搜索

     蓝牙打开和关闭信息使用BluetoothAdapter.ACTION_STATE_CHANGED去接收广播

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();mBluetoothAdapter.setName("blueTestPhone"); //判断蓝牙是否打开boolean originalBluetooth = (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled());if (originalBluetooth) { mBluetoothAdapter.startDiscovery();} else if (originalBluetooth == false) { mBluetoothAdapter.enable();}

蓝牙打开后,我们可以获取设备的蓝牙信息

StringBuilder sb = new StringBuilder(); //获取本机蓝牙名称 String name = mBluetoothAdapter.getName();//获取本机蓝牙地址 String address = mBluetoothAdapter.getAddress();

搜索完成后,通过BluetoothDevice.ACTION_FOUND广播去接收结果,广播代码如下(注意:可能出现设备搜索不到的情况,设备需要开启允许周围设备搜索,或者通过程序来控制允许搜索的时间范围)

Android中怎么实现蓝牙通信

 Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//设置可见状态的持续时间为300秒,但是最多是300秒discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivityForResult(discoverableIntent, REQUEST_DISCOVERABLE_BLUETOOTH);private void initSearchBroadcast() {  IntentFilter intentFilter = new IntentFilter();  //发现设备  intentFilter.addAction(BluetoothDevice.ACTION_FOUND);  //设备配对状态改变  intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);  //蓝牙设备状态改变  intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);  //开始扫描  intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);  //结束扫描  intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);  //其它设备请求配对  intentFilter.addAction(ACTION_PAIRING_REQUEST);  //intentFilter.addAction(BluetoothAdapter.CONNECTION_STATE_CHANGED);  registerReceiver(bluetoothReceiver, intentFilter); }private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {  @Override  public void onReceive(Context context, Intent intent) {   String action = intent.getAction();   Logger.e(TAG + "mBluetoothReceiver action =" + action);   try {    if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {//开始扫描     setProgressBarIndeterminateVisibility(true);     log1.setText("正在扫描设备,请稍候...");    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {//结束扫描     Logger.e(TAG + "设备搜索完毕");     setProgressBarIndeterminateVisibility(false);     log1.setText("扫描完成");     bondAdapter.notifyDataSetChanged();     unbondAdapter.notifyDataSetChanged();     scanStatus = false;    } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {//发现设备     findDevice(intent);    } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {//蓝牙配对状态的广播     BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);     Logger.e(TAG + device.getName() + "蓝牙配对广播:" + device.getBondState());     switch (device.getBondState()) {      case BluetoothDevice.BOND_BONDING:       Logger.e(TAG + device.getName() + "蓝牙配对广播 正在配对......");       break;      case BluetoothDevice.BOND_BONDED:       Logger.e(TAG + device.getName() + "蓝牙配对广播 完成配对,本机自动配对");       bondDevices.add(device);       unbondDevices.remove(device);       bondAdapter.notifyDataSetChanged();       unbondAdapter.notifyDataSetChanged();        break;      case BluetoothDevice.BOND_NONE:       Logger.e(TAG + device.getName() + "蓝牙配对广播 取消配对");       unbondDevices.add(device);       bondDevices.remove(device);       unbondAdapter.notifyDataSetChanged();       bondAdapter.notifyDataSetChanged();      default:       break;     }    } else if (action.equals(ACTION_PAIRING_REQUEST)) {//其它设备蓝牙配对请求     BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);     int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); //当前的配对的状态     try {      String path = Environment.getExternalStorageDirectory() + "/blueTest/";      String deviceName = btDevice.getName();      Logger.e(TAG + "蓝牙 匹配信息:" + deviceName + "," + btDevice.getAddress() + ",state:" + state);      //1.确认配对,高版本无效,蓝牙配对不是zuk的问题,而是安卓6.0的bug,凡是遇到蓝牙适配问题的,请同时打开蓝牙和定位,再去配对,基本90%都没有问题了。      Object object = ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);      //2.终止有序广播,如果没有将广播终止,则会出现一个一闪而过的配对框。      abortBroadcast();      //3.调用setPin方法进行配对...      boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, PWD);     } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();      Toast.makeText(mContenxt, "error:" + btDevice + "," + state, Toast.LENGTH_LONG).show();     }    } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {//蓝牙开关状态     // BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);     int statue = mBluetoothAdapter.getState();     switch (statue) {      case BluetoothAdapter.STATE_OFF:       Logger.e("蓝牙状态:,蓝牙关闭");       ClsUtils.closeDiscoverableTimeout(mBluetoothAdapter);       break;      case BluetoothAdapter.STATE_ON:       Logger.e("蓝牙状态:,蓝牙打开");       ClsUtils.setDiscoverableTimeout(1000 * 60, mBluetoothAdapter);       scanBluetooth();       break;      case BluetoothAdapter.STATE_TURNING_OFF:       Logger.e("蓝牙状态:,蓝牙正在关闭");       mBluetoothAdapter.cancelDiscovery();       break;      case BluetoothAdapter.STATE_TURNING_ON:       Logger.e("蓝牙状态:,蓝牙正在打开");       break;     }    }   } catch (Exception e) {    e.printStackTrace();   }  } };//发现设备的代码如下 private void findDevice(Intent intent) throws Exception{ //获取到设备对象 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String str = device.getName() + "|" + device.getAddress(); Logger.e("扫描到设备:" + str); if (device.getBondState() == BluetoothDevice.BOND_BONDED) {//判断当前设备地址下的device是否已经配对  if (!bondDevices.contains(device)) {   bondDevices.add(device);  } } else {  if (!unbondDevices.contains(device)) {   unbondDevices.add(device);  }  if (device.getName().equals(TEST_DEVICE_NAME)) {   boolean bondStatus = ClsUtils.createBond(device.getClass(), device);   Logger.i(TAG + " bondStatus:" + bondStatus);  } } Log.e("error", "搜索完毕,准备刷新!"); bondAdapter.notifyDataSetChanged(); unbondAdapter.notifyDataSetChanged();}

四:蓝牙配对

   正常情况下,蓝牙匹配需要弹出一个匹配确认框,如下图,但我想实现的是,匹配其中一方,不能手动点击配对,因为发起蓝牙连接的设备是android设备,是不能触摸的,所以就要通过程序来解决这个问题,特别声明:(测试的android设备,版本为5.x,并且已经root,没有root的设备,或者不是android5.x不清楚能否实现自动匹配,因为我只有这个测试设备)。

Android中怎么实现蓝牙通信

1 当我们搜索到目标手机的蓝牙后,android设备主动发起连接请求,代码如下

 if (device.getName().equals(TEST_DEVICE_NAME)) {    boolean bondStatus = ClsUtils.createBond(device.getClass(), device);    Logger.i(TAG + " bondStatus:" + bondStatus); }//发起蓝牙匹配请求 public boolean createBond(Class btClass, BluetoothDevice btDevice)   throws Exception {  Method createBondMethod = btClass.getMethod("createBond");  Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);  return returnValue.booleanValue();}

2 当被匹配方点击配对后,系统会通过BluetoothDevice.ACTION_BOND_STATE_CHANGED广播告诉android设备,此时android设备就可以自动确认,通过这个流程来完成整个蓝牙的配对,具体代码如下

 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);     int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); //当前的配对的状态     try {      String path = Environment.getExternalStorageDirectory() + "/blueTest/";      String deviceName = btDevice.getName();      Logger.e(TAG + "蓝牙 匹配信息:" + deviceName + "," + btDevice.getAddress() + ",state:" + state);       if(deviceName.equals(TEST_DEVICE_NAME)){//TEST_DEVICE_NAME 为被匹配蓝牙设备的名称,自己手动定义       Object object = ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);       abortBroadcast();       boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, PWD);      }     } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();      Toast.makeText(mContenxt, "error:" + btDevice + "," + state, Toast.LENGTH_LONG).show();     }//确认配对public Object setPairingConfirmation(Class<?> btClass, BluetoothDevice device, boolean isConfirm) throws Exception {  Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation", boolean.class);  Object object = setPairingConfirmation.invoke(device, isConfirm);   return object; }//配对需要调用的方法public boolean setPin(Class<? extends BluetoothDevice> 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);  } 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 true; }

上述就是小编为大家分享的Android中怎么实现蓝牙通信了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯