/** * Android / iOS 权限与能力检测 * Android 6+ 扫描 BLE 需要位置权限 + 位置服务开启 * Android 12+ 需要 BLUETOOTH_SCAN / BLUETOOTH_CONNECT * iOS 需要 NSBluetoothAlwaysUsageDescription (在 manifest.json 中配置) * * 仅在 APP-PLUS 环境下调用 plus API, H5 / 小程序环境跳过 */ export function getPlatform() { try { return uni.getSystemInfoSync().platform } catch (_) { return '' } } /** 是否 App 环境 (plus 存在) */ export function isAppPlus() { // #ifdef APP-PLUS return typeof plus !== 'undefined' // #endif // #ifndef APP-PLUS return false // #endif } /** 检查位置服务是否已开启 (Android) */ export function isLocationEnabled() { return new Promise(resolve => { if (!isAppPlus() || getPlatform() !== 'android') return resolve(true) // #ifdef APP-PLUS try { const main = plus.android.runtimeMainActivity() const LocationManager = plus.android.importClass('android.location.LocationManager') const context = plus.android.importClass('android.content.Context') const lm = main.getSystemService(context.LOCATION_SERVICE) const gps = lm.isProviderEnabled(LocationManager.GPS_PROVIDER) const net = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) resolve(gps || net) } catch (e) { resolve(true) } // #endif }) } /** 跳转到系统位置服务设置 */ export function openLocationSettings() { // #ifdef APP-PLUS if (!isAppPlus() || getPlatform() !== 'android') return try { const main = plus.android.runtimeMainActivity() const Intent = plus.android.importClass('android.content.Intent') const Settings = plus.android.importClass('android.provider.Settings') const intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) main.startActivity(intent) } catch (e) { console.error(e) } // #endif } /** 请求 Android 运行时权限(定位/蓝牙扫描/连接). 返回 true/false */ export function requestAndroidPermissions() { return new Promise(resolve => { if (!isAppPlus() || getPlatform() !== 'android') return resolve(true) // #ifdef APP-PLUS try { const main = plus.android.runtimeMainActivity() const Build = plus.android.importClass('android.os.Build') const sdkInt = Build.VERSION.SDK_INT const perms = ['android.permission.ACCESS_FINE_LOCATION'] if (sdkInt >= 31) { perms.push('android.permission.BLUETOOTH_SCAN') perms.push('android.permission.BLUETOOTH_CONNECT') } const PackageManager = plus.android.importClass('android.content.pm.PackageManager') const need = perms.filter(p => main.checkSelfPermission(p) !== PackageManager.PERMISSION_GRANTED) if (!need.length) return resolve(true) const ActivityCompat = plus.android.importClass('androidx.core.app.ActivityCompat') // 注册结果回调 const onReq = (activity, requestCode, permsArr, grantResults) => { plus.android.clearRequestPermissions && plus.android.clearRequestPermissions() const granted = grantResults && Array.from(grantResults).every(r => r === 0) resolve(!!granted) } if (plus.android.requestPermissions) { plus.android.requestPermissions(need, res => { resolve(res && res.granted && res.granted.length === need.length) }, () => resolve(false)) } else { ActivityCompat.requestPermissions(main, need, 1001) // 无结果回调能力时, 乐观等待 2s 后查询 setTimeout(() => { const still = need.filter(p => main.checkSelfPermission(p) !== PackageManager.PERMISSION_GRANTED) resolve(!still.length) }, 2000) } } catch (e) { console.error(e); resolve(false) } // #endif }) } /** 检查系统蓝牙是否已开启 (Android 使用原生 API,iOS 依赖 uni API) */ export function isBluetoothEnabled() { return new Promise(resolve => { const platform = getPlatform() if (!isAppPlus()) return resolve(true) // #ifdef APP-PLUS if (platform === 'android') { try { const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter') const adapter = BluetoothAdapter.getDefaultAdapter() resolve(adapter != null && adapter.isEnabled()) } catch (e) { // 无法检测时放行,让后续流程处理 resolve(true) } } else if (platform === 'ios') { // iOS 无法直接通过原生 API 检测,依赖 uni.openBluetoothAdapter 的结果 resolve(true) } else { resolve(true) } // #endif // #ifndef APP-PLUS resolve(true) // #endif }) } /** 跳转到系统蓝牙设置页面 */ export function openBluetoothSettings() { // #ifdef APP-PLUS const platform = getPlatform() if (platform === 'android') { try { const main = plus.android.runtimeMainActivity() const Intent = plus.android.importClass('android.content.Intent') const Settings = plus.android.importClass('android.provider.Settings') const intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS) main.startActivity(intent) } catch (e) { console.error('跳转蓝牙设置失败', e) } } else if (platform === 'ios') { plus.runtime.openURL('App-Prefs:root=Bluetooth') } // #endif } /** 一键: 申请权限 + 校验定位服务 + 检测蓝牙开启. 失败抛异常 */ export async function ensureBlePrerequisite() { const platform = getPlatform() if (platform === 'android') { const ok = await requestAndroidPermissions() if (!ok) throw new Error('BLE_PERMISSION_DENIED') const loc = await isLocationEnabled() if (!loc) throw new Error('BLE_LOCATION_OFF') } // 检测蓝牙是否开启(Android 原生检测,iOS 跳过此步) const bleOn = await isBluetoothEnabled() if (!bleOn) throw new Error('BLE_ADAPTER_OFF') return true }