bluetoothPermissions.ts 2.77 KB
export interface BluetoothPermissionResult {
  ok: boolean
  message?: string
}

function normalizePermissionName (permission: string): string {
  return String(permission || '').split('.').pop() || String(permission || '')
}

function formatDeniedMessage (permissions: string[]): string {
  if (!permissions.length) return 'Bluetooth permission denied.'
  return 'Please allow Bluetooth permissions: ' + permissions.map(normalizePermissionName).join(', ')
}

function requestAndroidPermissions (permissions: string[]): Promise<BluetoothPermissionResult> {
  return new Promise((resolve) => {
    // #ifdef APP-PLUS
    try {
      if (typeof plus === 'undefined' || !plus.android || !permissions.length) {
        resolve({ ok: true })
        return
      }
      plus.android.requestPermissions(
        permissions,
        (resultObj: any) => {
          const deniedPresent = Array.isArray(resultObj?.deniedPresent) ? resultObj.deniedPresent : []
          const deniedAlways = Array.isArray(resultObj?.deniedAlways) ? resultObj.deniedAlways : []
          const denied = [...deniedPresent, ...deniedAlways]
          if (denied.length > 0) {
            resolve({
              ok: false,
              message: formatDeniedMessage(denied),
            })
            return
          }
          resolve({ ok: true })
        },
        () => {
          resolve({
            ok: false,
            message: 'Failed to request Bluetooth permissions.',
          })
        }
      )
      return
    } catch (e: any) {
      resolve({
        ok: false,
        message: e?.message || 'Failed to request Bluetooth permissions.',
      })
      return
    }
    // #endif
    resolve({ ok: true })
  })
}

export async function ensureBluetoothPermissions (options?: {
  scan?: boolean
  connect?: boolean
}): Promise<BluetoothPermissionResult> {
  const { scan = false, connect = false } = options || {}

  // #ifdef APP-PLUS
  try {
    if (typeof plus === 'undefined' || !plus.android) {
      return { ok: true }
    }
    const Build = plus.android.importClass('android.os.Build')
    const sdkInt = Number(Build.VERSION.SDK_INT || 0)

    const permissions = new Set<string>()
    if (sdkInt >= 31) {
      if (scan) permissions.add('android.permission.BLUETOOTH_SCAN')
      if (scan || connect) permissions.add('android.permission.BLUETOOTH_CONNECT')
      if (scan) permissions.add('android.permission.ACCESS_FINE_LOCATION')
    } else if (scan) {
      permissions.add('android.permission.ACCESS_FINE_LOCATION')
      permissions.add('android.permission.ACCESS_COARSE_LOCATION')
    }

    return await requestAndroidPermissions(Array.from(permissions))
  } catch (e: any) {
    return {
      ok: false,
      message: e?.message || 'Bluetooth permission check failed.',
    }
  }
  // #endif

  return { ok: true }
}