uniApp开发微信小程序-连接蓝牙连接打印机上岸!

历经波折三次成功上岸!

三次经历简单絮叨一下:使用uniApp+vue开发的微信小程序,使用蓝牙连接打印机,蓝牙所有的接口都是插件中封装的,用的插件市场中的这个: dothan-lpapi-ble ;所以,开发中,主要是看插件文档中使用的API。

首次上线

情况说明: 首次上线微信小程序:直接初始化实例,调用的插件API,测试环境成功连接打印,就上线了。

结果

客户手机一直搜索不到打印机,根据经验发现没执行实例的代码;
想到授权蓝牙也没自动弹框提示,小程序设置中也没有蓝牙开启设置;

问题定位:

那就问 deepseeek 开干呗!
1. 可能是用户手机 鸿蒙系统 问题:在系统设置中找到应用管理,找到微信,然后打开微信的权限管理,查看 附近设备的权限 - 开启(反复开关)。

插件市场遇到的特殊情况
2. 显示授权:必要的权限声明
3. 检查manifest.json配置
4. 微信小程序发版后台 - 设置 - 基本设置 - 服务内容声明 - 用户隐私保护指引 - 添加(蓝牙、微信信息收集)

二次上线

情况说明: 二次上线微信小程序:提交审核是其他同事在做,正常提交

结果

客户手机一直搜索不到打印机,根据经验发现没执行实例的代码;
线上环境用户还是没有触发授权蓝牙、位置信息提示;
审核没通过

问题定位:

1. 提交审核时勾选了:未采集用户隐私
2. 亲自提审、加图片、视频辅佐

三次上线

情况说明:审核通过

结果

线上成功授权、成功搜索打印机!

成功版本代码

manifest.json配置

"mp-weixin": {"appid": "...",//  添加..."permission": {"scope.bluetooth": {"desc": "用于连接蓝牙设备"},"scope.userLocation": {"desc": "你的位置信息将用于蓝牙设备连接"}},"requiredPrivateInfos": ["getLocation"]},

授权提示 - deepseek友情提供

// 使用-获取蓝牙权限
await this.bringBluetoothRight();// 方法 methods: 
bringBluetoothRight() {let _this = this;return new Promise((resolve, reject) => {uni.getSetting({success: async (res) => {try {console.log(res, 'res')// 1. 同时检查蓝牙和位置权限const needBluetooth = !res.authSetting['scope.bluetooth'];const needLocation = !res.authSetting['scope.userLocation'];if (!needBluetooth && !needLocation) {// 已有全部权限return resolve(await _this.wechatBluetoothAuthUtils());}// 2. 显示预授权提示(合并说明)await _this.showPreAuthorizeModal('需要蓝牙和位置权限','连接打印机需要以下权限:\n\n1. 蓝牙权限 - 用于设备配对\n2. 位置权限 - 用于搜索设备');// 3. 按顺序请求权限if (needBluetooth) {await _this.requestPermission('scope.bluetooth', '蓝牙');}if (needLocation) {await _this.requestPermission('scope.userLocation', '位置');}// 4. 验证权限获取结果const currentSettings = await _this.getSettingWithRetry();console.log(currentSettings, 'currentSettings')if ((!needBluetooth || currentSettings['scope.bluetooth']) &&(!needLocation || currentSettings['scope.userLocation'])) {console.log('.......')resolve(await _this.wechatBluetoothAuthUtils());} else {console.log('1111111')// 5. 有权限未被授予,引导去设置页await _this.showGoSettingModal();const finalSettings = await _this.getSettingWithRetry();if ((!needBluetooth || finalSettings['scope.bluetooth']) &&(!needLocation || finalSettings['scope.userLocation'])) {resolve(await _this.wechatBluetoothAuthUtils());} else {reject(new Error('权限未完全授予'));}}} catch (error) {reject(error);}},fail: reject});});
},
// 新增:带重试的获取设置
getSettingWithRetry(retry = 2) {return new Promise((resolve, reject) => {const tryGet = (attempt) => {uni.getSetting({success: resolve,fail: attempt > 0 ?() => setTimeout(() => tryGet(attempt - 1), 500) : reject});};tryGet(retry);});
},// 改进:通用权限请求方法
requestPermission(scope, permissionName) {let _this = this;// 添加最大重试次数控制const MAX_RETRY = 1; // 最多重试1次(即总共2次机会)return new Promise((resolve, reject) => {const tryAuthorize = (retryCount = 0) => {uni.authorize({scope,success: resolve,fail: async () => {// 第一次拒绝时显示提示,后续直接引导去设置页if (retryCount < MAX_RETRY) {const confirmed = await _this.showPreAuthorizeModal(`${permissionName}权限被拒绝`,`需要${permissionName}权限才能连接打印机,是否重新授权?`,'重新授权','取消');if (confirmed) {tryAuthorize(retryCount + 1); // 增加重试计数return;}}// 达到最大重试或用户取消,引导去设置页const goSetting = await _this.showPreAuthorizeModal('权限不足',`需要${permissionName}权限才能使用打印机功能,是否去设置页开启?`,'去设置','暂不开启');if (goSetting) {uni.openSetting({success: (res) => {res.authSetting[scope] ? resolve() :reject(new Error(`用户未授权${permissionName}权限`));},fail: () => reject(new Error('打开设置页失败'))});} else {reject(new Error(`用户取消${permissionName}权限授权`));}}});};tryAuthorize(); // 开始首次授权尝试});
},
// 改进:预授权弹窗(返回Promise<boolean>)
showPreAuthorizeModal(title, content) {return new Promise((resolve) => {uni.showModal({title,content,confirmText: '继续',cancelText: '取消',success: (res) => {resolve(!!res.confirm);},fail: () => resolve(false)});});
},// 改进:去设置页弹窗
showGoSettingModal() {return this.showPreAuthorizeModal('需要权限','需要前往设置页手动开启权限,是否现在去设置?').then((confirm) => {if (confirm) {return new Promise((resolve) => {uni.openSetting({success: resolve,fail: resolve});});}return Promise.reject(new Error('用户取消设置'));});
},wechatBluetoothAuthUtils() {let _this = this;const {bluetoothEnabled,platform} = uni.getSystemInfoSync();console.log(bluetoothEnabled,platform)// 设备为IOS时,微信蓝牙是否开启if (platform === 'ios') {return new Promise((resolve, reject) => {// 初始化蓝牙模块(用openBluetoothAdapter 方法解决部分ios设备,授权蓝牙失败的问题)uni.openBluetoothAdapter({success: () => {// 开启蓝牙功能 =》 初始化拾果sdkresolve(true);},fail: (openBlueFail) => {if (openBlueFail.state === 3) {// 说明微信应用蓝牙未授权uni.showModal({content: '检测到您未允许微信访问手机蓝牙权限,是否打开系统设置?',showCancel: false,confirmText: '前往设置',success: () => {// 跳转微信应用权限uni.openAppAuthorizeSetting();},});} else if (openBlueFail.state === 4) {// 说明系统蓝牙未开启uni.showModal({content: '蓝牙设置 - 小程序需要通过蓝牙搜索和连接设备,请确认手机蓝牙功能是否已开启?',showCancel: false,confirmText: '我已开启',success: async () => {const {bluetoothEnabled,platform} = uni.getSystemInfoSync();if (bluetoothEnabled) {// 开启蓝牙功能resolve(true);} else {uni.showToast({icon: 'none',title: '手机蓝牙未开启'})}},});}},});});} else {return new Promise(function(resolve, reject) {// andriodif (!bluetoothEnabled) {// 说明系统蓝牙未开启uni.showModal({content: '蓝牙设置 - 小程序需要通过蓝牙搜索和连接设备,请确认手机蓝牙功能是否已开启?',showCancel: false,confirmText: '我已开启',success: async () => {const {bluetoothEnabled,platform} = uni.getSystemInfoSync();if (bluetoothEnabled) {// 开启蓝牙功能resolve(true);} else {toast({title: '手机蓝牙未开启'});}},});} else {// 开启蓝牙功能resolve(true);}});}
},

额外关闭提示:

<button class="search-btn" type="default" @click="toggleLocationTracking">{{ isTrackingLocation ? '关闭位置追踪' : '开启位置追踪' }}</button>// data
isTrackingLocation:false// methods
toggleLocationTracking() {if (this.isTrackingLocation) {this.stopLocationTracking();} else {this.startLocationTracking();}},
startLocationTracking() {uni.authorize({scope: 'scope.userLocation',success: () => {this.isTrackingLocation = true;uni.showToast({title: '已开启位置服务',icon: 'success'});},fail: () => {uni.showModal({title: '提示',content: '需要位置权限才能搜索蓝牙设备',confirmText: '去设置',success: (res) => {if (res.confirm) uni.openSetting();}});}});},
stopLocationTracking() {uni.getSetting({success: (res) => {if (res.authSetting['scope.userLocation']) {uni.showModal({title: '确认',content: '确定要关闭位置服务吗?关闭后将无法搜索新设备',success: (res) => {if (res.confirm) {// 实际微信小程序无法直接关闭权限,引导用户去设置页uni.openSetting({success: () => {this.isTrackingLocation = false;}});}}});}}});},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件系统安全设计方案,信息化安全建设方案(Word原件)

1.1 总体设计 1.1.1 设计原则 1.2 物理层安全 1.2.1 机房建设安全 1.2.2 电气安全特性 1.2.3 设备安全 1.2.4 介质安全措施 1.3 网络层安全 1.3.1 网络结构安全 1.3.2 划分子网络 1.3.3 异常流量管理 1.3.4 网络安全审计 1.3.5 网络访问控制 1.3.6 完…

wsl2+ubuntu22.04安装blenderproc教程

本章教程,介绍如何在windows操作系统上通过wsl2+Ubuntu22.04上安装blenderproc。 一、pipi安装方式 推荐使用minconda3安装Python环境。 pip install Blenderproc二、源码安装 1、下载源码 git clone https://github.com/DLR-RM/BlenderProc2、安装依赖 cd BlenderProc &am…

Blender 转 STL 文件全攻略:从基础到进阶

在 3D 建模与打印领域&#xff0c;Blender 凭借其强大的功能和开源特性&#xff0c;深受创作者喜爱。而 STL 文件格式&#xff0c;作为 3D 打印行业的通用标准&#xff0c;能被绝大多数 3D 打印软件和设备所识别。因此&#xff0c;将 Blender 模型转换为 STL 文件&#xff0c;是…

Ansys Electronics 变压器 ACT

你好&#xff0c; 在本博客中&#xff0c;我将讨论如何使用 Ansys 电子变压器 ACT 自动快速地设计电力电子电感器或变压器。我将逐步介绍设计和创建电力电子变压器示例的步骤&#xff0c;该变压器为同心组件&#xff0c;双绕组&#xff0c;采用正弦电压激励&#xff0c;并应用…

nacos配置达梦数据库驱动源代码步骤

1.在父工程pom.xml添加依赖&#xff1a; <dependency><groupId>com.dameng</groupId><artifactId>DmJdbcDriver18</artifactId><version>8.1.1.193</version> </dependency> 2.在nacos-config模块pom.xml添加依赖&#xff1…

4.9-4.10学习总结 Stream流练习+方法引用+异常

Stream流练习&#xff1a; 1.打印数组内的偶数。 import java.util.*; import java.util.function.BiConsumer; public class test {public static void main(String[] args) {ArrayList<Integer> listnew ArrayList<>();Collections.addAll(list,1,2,3,4,5,6,7,…

FPGA系统开发板调试过程不同芯片的移植步骤介绍

目录 1.我目前使用的开发板 2.不同开发板的移植 步骤一&#xff1a;芯片型号设置 步骤二&#xff1a;约束修改 步骤三、IP核更新 关于FPGA系统开发板调试过程中不同芯片的移植。我需要先理清楚FPGA开发中移植到不同芯片的一般流程。首先&#xff0c;移植通常涉及到更换FPG…

复现QGIS-MCP教程

由于Claude国内下载不了尝试使用Cursor 下载安装Cursor Cursor - The AI Code Editor 本示例安装的是0.46版本 UV安装 简介 安装 安装成功 配置环境变量 验证 下载代码 git clone gitgithub.com:jjsantos01/qgis_mcp.git QGIS插件安装 文件拷贝 您需要将 qgis_mcp_plu…

java笔记03

基本数据类型 数据值是存储在自己的空间中。 特点&#xff1a;赋值给其他变量&#xff0c;也是赋的真实的值。 引用数据类型 数据值是存储在其他空间中&#xff0c;自己空间中存储的是地址值。 特点&#xff1a;赋值给其他变量&#xff0c;赋的地址值。 综合练习 使用 ctrl…

【开发工具】快速自定义图标元素的颜色

如果你想要一个轻量级、简单易用 的小工具来快速自定义图标元素的颜色&#xff08;比如调整 SVG/PNG 图标的颜色&#xff0c;或者生成多色图标&#xff09;&#xff0c;可以试试以下工具&#xff1a; 1. 在线工具&#xff08;无需安装&#xff09; SVG/PNG 图标改色 - Recol…

【CompletableFuture】异步编程

CompletableFuture异步编程 CompletableFuture介绍与传统 Future 的对比使用方法1. 使用 supplyAsync&#xff08;有返回值&#xff09;使用 runAsync&#xff08;无返回值&#xff09;指定自定义线程池 处理异步结果1. thenApply&#xff1a;转换结果2.thenAccept&#xff1a;…

【TS学习】(23)理解类的双重角色

在 TypeScript 中&#xff0c;类&#xff08;class&#xff09;不仅是一个运行时的值&#xff08;即可以实例化对象的构造函数&#xff09;&#xff0c;同时也是一个类型声明。具体来说&#xff0c;类在 TypeScript 中既声明了值&#xff0c;也声明了类型&#xff0c;并且它的类…

IAP Firmware Upload Tools.exe IAP 网络固件升级教程

IAP是In Application Programming的简写&#xff0c;IAP升级可以被视为固件升级的一种形式,它是一种在应用程序运行过程中对固件进行更新的技术手段。允许MCU在运行过程中对MCU User Flash的部分区域进行烧写,目的是为了代替编程器对MCU烧录的依赖。 主程序UI 软件按钮说明&a…

Uniapp当中的async/await的作用

一、原始代码的行为&#xff08;使用 async/await&#xff09; const getUserMessagePlan async () > {// 等待两个异步操作完成const tabsList await message.getTagesList(); // 等待获取标签列表const tagsStateList await message.getTagsStateList(); // 等…

设计模式 Day 5:夯实观察者模式(Boost 实战精讲)

今天我们继续深入观察者模式的学习&#xff0c;不再局限于手写的抽象结构&#xff0c;而是聚焦于真实项目中如何使用成熟框架&#xff08;如 Boost.Signals2&#xff09;高效落地观察者模式。 本篇采用**“理论解析 问答讲解 实战用例”**结构&#xff0c;帮助你从设计思想到…

设计模式 Day 3:抽象工厂模式(Abstract Factory Pattern)详解

经过前两天的学习&#xff0c;我们已经掌握了单例模式与工厂方法模式&#xff0c;理解了如何控制实例个数与如何通过子类封装对象的创建逻辑。 今天&#xff0c;我们将进一步深入“工厂”体系&#xff0c;学习抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&a…

MySQL:事务的理解

一、CURD不加控制&#xff0c;会有什么问题 &#xff08;1&#xff09;因为&#xff0c;MySQL里面存的是数据&#xff0c;所以很有可能会被多个客户访问&#xff0c;所以mysqld可能一次会接受到多个关于CURD的请求。&#xff08;2&#xff09;且mysql内部是采用多线程来完成数…

蓝桥杯刷题--宝石组合

在一个神秘的森林里&#xff0c;住着一个小精灵名叫小蓝。有一天&#xff0c;他偶然发现了一个隐藏在树洞里的宝藏&#xff0c;里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状&#xff0c;但最引人注目的是它们各自独特的 “闪亮度” 属性。每颗宝石都有一个…

DAY06:【pytorch】图像增强

1、基本概念 数据增强&#xff0c;又称数据增广、数据扩增&#xff0c;是对训练集进行变换&#xff0c;使训练集更丰富&#xff0c;从而让模型更具泛化能力 2、裁剪 — — Crop 2.1 transforms.CenterCrop 功能&#xff1a;从图像中心裁剪图片 size&#xff1a;所需裁剪图…

mysql 禁止 读 某个 表

mysql 禁止 读 某个 表 mysql禁用某张表,禁用MySQL表的操作 https://shuyeidc.com/wp/89479.html MySQL严格禁止读取表如何避免数据泄露 https://www.kdun.cn/ask/394700.html select host,user from mysql.user; FLUSH PRIVILEGES; 1. MySQL严格禁止读取表如何避免数据泄露…