当前位置: 首页 > news >正文

uniapp开发蓝牙搜索startBluetoothDevicesDiscovery:fail Location services are turned off

  1. 问题描述
    在使用uniapp开发安卓应用程序时,使用uni.startBluetoothDevicesDiscovery搜索蓝牙时,在部分设备上出现fail Location services are turned off报错(特别是无GPS硬件支持的设备),已确认开启位置信息,且给了权限
  2. 解决方法
    使用安卓原生蓝牙扫描+广播接收实现(借助AI),具体示例代码如下:
    <template> <view class="container"> <view class="status">状态: {{ isScanning ? '正在扫描...' : '停止扫描' }}</view> <button type="primary" @click="startScan" :disabled="isScanning">开始扫描</button> <button type="warn" @click="stopScan" :disabled="!isScanning">停止扫描</button> <view class="list-title">已发现设备:</view> <scroll-view scroll-y="true" class="device-list"> <view v-for="(item, index) in deviceList" :key="index" class="device-item"> <text class="name">{{ item.name || '未知设备' }}</text> <text class="address">{{ item.address }}</text> <text class="rssi">信号: {{ item.rssi }} dBm</text> </view> </scroll-view> </view> </template> <script> // 在这里声明变量,使其在整个组件内可用 let _BluetoothAdapter; let _BluetoothDevice; let _IntentFilter; let _mainActivity; export default { data() { return { isScanning: false, deviceList: [], receiver: null, nativeAdapter: null }; }, onLoad() { // 确保在 plus 环境下初始化 // #ifdef APP-PLUS this.initNativeClasses(); // #endif }, onUnload() { this.stopScan(); this.unregisterReceiver(); }, methods: { // 1. 导入原生类并获取适配器 initNativeClasses() { try { // 导入原生类并赋值给外部变量 _BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter"); _BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice"); _IntentFilter = plus.android.importClass("android.content.IntentFilter"); _mainActivity = plus.android.runtimeMainActivity(); this.nativeAdapter = _BluetoothAdapter.getDefaultAdapter(); if (!this.nativeAdapter) { uni.showToast({ title: "该设备不支持蓝牙", icon: "none" }); } } catch (e) { console.error("初始化原生类失败", e); } }, // 2. 注册广播接收器 registerReceiver() { if (this.receiver) return; const self = this; // 必须使用 plus.android.implements 实现 BroadcastReceiver 接口 this.receiver = plus.android.implements("io.dcloud.feature.internal.reflect.BroadcastReceiver", { onReceive: function(context, intent) { plus.android.importClass(intent); const action = intent.getAction(); if (action == _BluetoothDevice.ACTION_FOUND) { // 查找到设备 const device = intent.getParcelableExtra(_BluetoothDevice.EXTRA_DEVICE); const rssi = intent.getShortExtra(_BluetoothDevice.EXTRA_RSSI, -100); // 使用 plus.android.invoke 调用原生方法获取属性 const name = plus.android.invoke(device, "getName"); const address = plus.android.invoke(device, "getAddress"); const index = self.deviceList.findIndex(d => d.address === address); if (index === -1) { self.deviceList.push({ name, address, rssi }); } else { self.deviceList[index].rssi = rssi; } } else if (action == _BluetoothAdapter.ACTION_DISCOVERY_FINISHED) { self.isScanning = false; uni.hideLoading(); } } }); const filter = new _IntentFilter(); filter.addAction(_BluetoothDevice.ACTION_FOUND); filter.addAction(_BluetoothAdapter.ACTION_DISCOVERY_FINISHED); _mainActivity.registerReceiver(this.receiver, filter); }, // 3. 开始扫描 async startScan() { if (!this.nativeAdapter) return; // 权限检查 const hasPermission = await this.checkPermission(); if (!hasPermission) return; this.deviceList = []; this.registerReceiver(); // 如果正在扫描,先停止 if (this.nativeAdapter.isDiscovering()) { this.nativeAdapter.cancelDiscovery(); } // 启动原生扫描 const success = this.nativeAdapter.startDiscovery(); if (success) { this.isScanning = true; uni.showLoading({ title: "原生扫描中..." }); } else { uni.showToast({ title: "开启扫描失败", icon: "none" }); } }, // 4. 停止扫描 stopScan() { if (this.nativeAdapter && this.nativeAdapter.isDiscovering()) { this.nativeAdapter.cancelDiscovery(); } this.isScanning = false; uni.hideLoading(); }, unregisterReceiver() { if (this.receiver) { _mainActivity.unregisterReceiver(this.receiver); this.receiver = null; } }, // Android 高版本定位权限申请 checkPermission() { return new Promise((resolve) => { plus.android.requestPermissions( ["android.permission.ACCESS_FINE_LOCATION"], (result) => { if (result.granted.length > 0) resolve(true); else resolve(false); }, (err) => resolve(false) ); }); } } }; </script> <style scoped> .container { padding: 20px; } .status { color: #007AFF; margin-bottom: 10px; font-size: 14px; } .list-title { margin-top: 20px; font-weight: bold; border-bottom: 1px solid #eee; padding-bottom: 5px; } .device-list { height: 400px; } .device-item { padding: 10px 0; border-bottom: 1px solid #f9f9f9; } .name { display: block; font-size: 16px; } .address { font-size: 12px; color: #888; } .rssi { font-size: 12px; color: #007AFF; margin-left: 10px; } button { margin-top: 10px; } </style>
http://www.zskr.cn/news/1475500.html

相关文章:

  • Simple Live:跨平台直播聚合应用的终极解决方案,一站式观看所有热门直播
  • 2026年光身压入式定位珠/压入定位珠/无牙碰珠厂家推荐:滚花定位珠、平台定位珠、台阶定位珠等精密五金定位珠品牌选择指南 - 品牌企业推荐师(官方)
  • 如何用Deep-Live-Cam实现实时人脸替换:3步打造专业级视频特效
  • 2026太原市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 跨网数据安全交换:从“遍地是门”到“一道安检门”
  • ESP8266内存不够用?巧用TFT_eSPI的Sprite类打造流畅动画和复杂UI界面
  • 株洲黄金回收认准湘奢汇(天元店),拒绝隐形套路省心高效变现(附靠谱机构排行) - 生活测评小能手
  • 3步诊断法:彻底解决novel-downloader小说下载失败问题
  • 倍硫磷农药残留检测卡快速检测果蔬中的倍硫磷农药残留
  • 技术大纲:DeepSeek一键导出word文档的办法
  • 小蜜蜂企微 RPA,把企业微信变成 24 小时不眠的销冠军团
  • 在Photoshop中无缝使用Stable Diffusion:Auto-Photoshop-StableDiffusion-Plugin完全指南
  • 快递柜系统设计(中):取件与取回
  • 2026年专业做工厂短视频获客的公司怎么选?行业标杆与避坑指南
  • 南宁购宠全攻略:湿热气候避坑指南 + 5 家靠谱门店精选 - 资讯速览
  • 浏览器视频编辑新纪元:OmniClip如何用Web技术重塑创作边界
  • Matter协议实战指南:构建可靠智能家居系统的完整配置手册
  • 腰肌劳损久拖不治,小心腰椎受损
  • 2026 南宁旧金回收深度实测,同城稳妥出手指南 - 奢侈品回收评测
  • 别再只看K线了!用Python自制‘筹码获利比例’指标,给你的量化策略加个‘透视挂’
  • 关于贪心算法【968.监控二叉树】的想法
  • 西安购宠全攻略:避坑指南 + 5 家靠谱门店精选 - 资讯速览
  • 同样是低代码,为什么织信搭建系统比别人快10倍?真相很简单
  • AI技术写作的真实性原则与事实核查方法论
  • 零基础也能上手:AI建站工具极速操作指南
  • 分享一个免费下载全行业报告的宝藏网站,职场人亲测好用
  • WeChatExporter:3步完成微信聊天记录备份,彻底告别数据丢失烦恼
  • 2026合肥黄金回收权威测评教程,新手高价变现 - 奢侈品回收评测
  • 实战指南:基于快马平台开发全栈式代码截图工具并部署上线
  • 2026 成都黄金回收 TOP 排行,优质连锁高价现付,雄厚实力登顶本地榜首 - 奢侈品回收评测