一、申请位置权限

在Android6.0以后要扫描蓝牙设备,还需要请求位置权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

位置权限属于危险权限,因此需要动态获取:

//判断是否有权限
if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//请求权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);//判断是否需要 向用户解释,为什么要申请该权限if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_CONTACTS)) {Toast.makeText(this,"shouldShowRequestPermissionRationale",
Toast.LENGTH_SHORT).show();}
}
//权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

在实际开发的过程中你也可以设置只有支持蓝牙的设备才能运行该APP:

<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true" />

这里设置required为true就是只有在支持蓝牙的设备上才能运行,但是如果想让你的app提供给那些不支持BLE的设备,需要在manifest中包括上面代码并设置required="false",然后在运行时可以通过使用PackageManager.hasSystemFeature()确定BLE的可用性。

// 使用此检查确定BLE是否支持在设备上,然后你可以有选择性禁用BLE相关的功能
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();finish();
}

二、扫描方式

Android官方提供的蓝牙扫描方式有三种,分别是:

  1. BluetoothAdapter.startDiscovery()//可以扫描经典蓝牙和ble蓝牙两种
  2. BluetoothAdapter.startLeScan()//扫描低功耗蓝牙,在api21已经弃用,不过还是可以使用
  3. BluetoothLeScanner.startScan()//新的ble扫描方法

startDiscovery()方法在大多数手机上是可以同时发现经典蓝牙和低功耗蓝牙(BLE)的,但是startDiscovery()的回调无法返回BLE的广播,所以无法通过广播识别设备,而且startDiscovery()扫描BLE效率比startLeScan()低很多。因此需要根据具体的需求去做适配,才能更高效的搜寻蓝牙。PS: startLeScan()和startScan()有重载方法可以指定规则,参数去搜索。

市面上的蓝牙设备,现在一般都是低功耗的蓝牙设备,因此只需要用下面两种扫描方式就OK了

2.1.startLeScan方式

官方提供的事例代码正是使用了这种方式,startLeScan方法有两个:

public boolean startLeScan(LeScanCallback callback)
public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)

查看源码会发现一个参数的方法是调用了两个参数的方法,只是serviceuuid[]传入为null,也就是过滤条件为空。这里我使用的是没有过滤条件的方法:

// Stops scanning after 10 seconds.private static final long SCAN_PERIOD = 10000;...private void scanLeDevice(final boolean enable) {if (enable) {// Stops scanning after a pre-defined scan period.mHandler.postDelayed(new Runnable() {@Overridepublic void run() {mScanning = false;mBluetoothAdapter.stopLeScan(mLeScanCallback);}}, SCAN_PERIOD);mScanning = true;mBluetoothAdapter.startLeScan(mLeScanCallback);} else {mScanning = false;mBluetoothAdapter.stopLeScan(mLeScanCallback);}...}// Device scan callback.private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {//扫描到的设备信息,将字符数组转成16进制字符串String scanRecordStr = SysConvert.bytesToHex(scanRecord);//在这里可以做一下简单的操作,避免多操作造成性能问题}};

因为在扫描蓝牙是一个非常非常耗能的操作,因此一定要扫描一段时间就关闭,如果需要循环扫描,可以通过定时器实现扫描的开关操作

注意:打开和关闭所使用的回调必须是同一个,虽然关闭一个没有打开的回调没有错误返回。

2.2.startScan方式

我在项目中是使用startScan()扫描的,因为可以通过设置一些参数来灵活控制扫描的频率等。

同样的有三个重载方法:

public void startScan(final ScanCallback callback)

public void startScan(List<ScanFilter> filters, ScanSettings settings,final ScanCallback callback)

public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
        @NonNull PendingIntent callbackIntent)

这里我以第二种为例:

/*** 扫描设备*/public void scanDevices() {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {mProgressDialog.dismiss();if (mBluetoothLeScanner != null) {mBluetoothLeScanner.stopScan(scanCallback);}}},  1000);mBluetoothLeScanner.startScan(null, createScanSetting(), scanCallback);}
/*** 扫描广播数据设置** @return*/public ScanSettings createScanSetting() {ScanSettings.Builder builder = new ScanSettings.Builder();builder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);//builder.setReportDelay(100);//设置延迟返回时间if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);}return builder.build();}
/**
* 回调
*/
private ScanCallback scanCallback=new ScanCallback() {@Overridepublic void onScanResult(int callbackType, ScanResult result) {byte[] scanData=result.getScanRecord().getBytes();//把byte数组转成16进制字符串,方便查看}@Overridepublic void onBatchScanResults(List<ScanResult> results) {super.onBatchScanResults(results);}@Overridepublic void onScanFailed(int errorCode) {super.onScanFailed(errorCode);}};

ScanSettings :

setScanMode:有三种模式分别是

SCAN_MODE_LOW_POWER--------耗电最少,扫描时间间隔最短

SCAN_MODE_BALANCED---------平衡模式,耗电适中,扫描时间间隔一般,我使用这种模式来更新设备状态

SCAN_MODE_LOW_LATENCY---------最耗电,扫描延迟时间短,打开扫描需要立马返回结果可以使用

setReportDelay:设置扫描返回延迟时间,一般是大于零的毫秒值

如果设置了该属性,扫描结果会以list形式在onBatchScanResults方法返回,在onScanResult中没有返回,如果不设置则在onScanResult中返回,返回的信息包含在result中,可以通过getBytes返回每一个设备信息的字符数组,getDevice获取BluetoothDevice设备,在通过字符数组和蓝牙设备对象获取你想要的信息

本人也是一个蓝牙开发新手,如果上面有什么地方有问题,请指出,共同探讨,共同进步,不胜感激!

蓝牙开发(二)扫描设备相关推荐

  1. Android 蓝牙开发(扫描设备、绑定、解绑)Kotlin版

    Kotlin版 蓝牙开发 (扫描设备.绑定.解绑) 前言 运行效果图 正文 ① 配置项目 ② 布局和样式 ③ 编码 1. 通知栏样式修改 2. 蓝牙设备列表适配器编写 3. 权限请求 4. 初始化蓝牙 ...

  2. Android 蓝牙开发(扫描设备、绑定、解绑)

    Android 蓝牙开发(扫描设备.绑定.解绑) 前言 效果图 一.配置项目 二.布局和样式 三.编码 四.源码 前言 公司最近给我丢了一个蓝牙开发的项目,不了解怎么办呢,那当然是从最基础的开始了,所 ...

  3. Android 蓝牙开发(二) --手机与蓝牙音箱配对,并播放音频

    Android 蓝牙开发(一) – 传统蓝牙聊天室 Android 蓝牙开发(三) – 低功耗蓝牙开发 项目工程BluetoothDemo 上一章中,我们已经学习了传统蓝牙的开发,这一章,我们来学习如 ...

  4. Android Studio开发蓝牙应用(二)

    Android Studio开发蓝牙应用(二) 实现的功能 与蓝牙模块HC-06交换信息 过程 新建Empty Activity 创建布局 activity_btread_and_write.xml ...

  5. Android蓝牙开发教程(二)——连接蓝牙设备

    在上一篇中已经介绍如何搜索附近可连接的蓝牙设备,如果你还没阅读过,建议先看看上一篇文章Android蓝牙开发教程(一)--搜索蓝牙设备 获取到设备后就可以开始处理蓝牙设备之间的连接. 在上一篇教程中我 ...

  6. iOS 蓝牙开发 BabyBluetooth蓝牙库介绍

    BabyBluetooth 是一个最简单易用的蓝牙库,基于CoreBluetooth的封装,并兼容iOS和Mac OS X. 特色: 基于原生CoreBluetooth框架封装的轻量级的开源库,可以帮 ...

  7. Android蓝牙开发系列文章-蓝牙设备类型知多少?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...

  8. Android 蓝牙开发

    一.蓝牙版本介绍 蓝牙版本现在最新是蓝牙 5.在蓝牙4.0 提出了"低功耗蓝牙"."经典蓝牙"和"高速蓝牙"三种. 低功耗蓝牙和经典蓝牙 现 ...

  9. Android蓝牙开发记录

    本文主要记录下项目开发过程中的蓝牙功能 其中开发流程部分主要参考博文Android蓝牙开发-经典蓝牙详细开发流程 开发流程 开启蓝牙 扫描蓝牙 配对蓝牙 连接蓝牙 状态监听 通信 开启蓝牙 获取Blu ...

最新文章

  1. 零样本风格迁移:多模态CLIP文本驱动图像生成
  2. matlab降低视频帧数,如何更改视频的帧速率
  3. python在财务领域的应用-浅谈财务智能化在实际工作中的运用
  4. 统计学习:三大奇技(1)
  5. 机器学习——人工神经网络之多层神经网络(多层与三层)
  6. html 两个图片并排,HTML – 两个图像并排和响应
  7. SSH 登录失败:Host key verification failed 的处理方法
  8. 关于cknife与burpsuite对java的版本需求的冲突机器解决办法
  9. 【微信小程序】简洁好用的icon(94/100)
  10. SaaS行业的六大安全问题
  11. POJ 1625 Censored!(自动机DP+高精度)
  12. 史上最全Java学习路线
  13. 皮卡智能2022年功能升级汇总,打造智能工作新体验
  14. c++字符串转换为数字(stoi, stol, stoul, stoull, stof, stod, stold)
  15. 学习matlab(七)——符号计算
  16. HDMI 网线延长器
  17. R语言多层桑基图_绘制炫酷桑基图,R语言(networkD3包)能搞定?
  18. 用android开发一个识别人形的app,一键切换背景
  19. [前端笔记006]CSS布局之字体 -- font
  20. 关于旋转平移的理解与思考

热门文章

  1. VANCL•凡客诚品
  2. 详细讲解ABTest假设检验【实验设计结论分析】数据分析
  3. JavaScript实现输入数字,输出是几月份的代码
  4. 数字后仿,SDF文件
  5. GHOST 安装系统教程
  6. python到pandas_Python-Pandas
  7. NUMA与英特尔下一代Xeon处理器学习心得(2)
  8. docker 安装fileBrowser
  9. taro标签_渲染 HTML
  10. You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to ex