SDK_APP/PERMISSION_GUIDE.md

5.3 KiB
Raw Blame History

蓝牙权限申请指南

🔐 权限说明

在Android 12及以上版本使用蓝牙功能需要动态申请以下权限

必需权限

  1. BLUETOOTH_SCAN - 扫描蓝牙设备
  2. BLUETOOTH_CONNECT - 连接蓝牙设备
  3. ACCESS_FINE_LOCATION - 精确位置(蓝牙扫描需要)
  4. ACCESS_COARSE_LOCATION - 粗略位置(蓝牙扫描需要)

📱 权限申请流程

首次启动应用

  1. 应用启动时会显示当前权限状态
  2. 点击"连接蓝牙"按钮
  3. 系统弹出权限申请对话框
  4. 选择"允许"授予所有权限

权限状态显示

权限状态:
BLUETOOTH_SCAN: ✓
BLUETOOTH_CONNECT: ✓
ACCESS_FINE_LOCATION: ✓
ACCESS_COARSE_LOCATION: ✓

⚠️ 常见问题

1. 权限被拒绝

症状:按钮显示"权限被拒绝",无法使用蓝牙功能 解决

  • 进入系统设置 → 应用管理 → 本应用 → 权限
  • 手动开启蓝牙和位置权限
  • 重新启动应用

2. 部分权限缺失

症状:提示"缺少权限: BLUETOOTH_SCAN, ACCESS_FINE_LOCATION" 解决

  • 确保所有4个权限都已授予
  • 位置权限对于蓝牙扫描是必需的

3. 权限申请对话框不出现

症状:点击按钮无反应 解决

  • 检查应用是否被系统限制
  • 重启应用或设备
  • 检查系统版本是否支持

🔧 技术实现

权限检查代码

private fun checkAndRequestPermissions(): Boolean {
    val missingPermissions = mutableListOf<String>()
    
    for (permission in REQUIRED_PERMISSIONS) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            missingPermissions.add(permission)
        }
    }
    
    if (missingPermissions.isNotEmpty()) {
        updateStatus("需要蓝牙权限: ${missingPermissions.joinToString(", ")}")
        ActivityCompat.requestPermissions(
            this,
            missingPermissions.toTypedArray(),
            PERMISSION_REQUEST_CODE
        )
        return false
    }
    
    return true
}

权限结果处理

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
            
            if (allGranted) {
                updateStatus("蓝牙权限已授予,开始扫描...")
                startBluetoothScan()
            } else {
                updateStatus("蓝牙权限被拒绝,无法使用蓝牙功能")
                binding.bluetoothButton.text = "权限被拒绝"
                binding.bluetoothButton.setBackgroundColor(Color.parseColor("#9E9E9E"))
            }
        }
    }
}

📋 权限清单

AndroidManifest.xml

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- 蓝牙功能声明 -->
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

MainActivity.kt

companion object {
    private const val PERMISSION_REQUEST_CODE = 1001
    private val REQUIRED_PERMISSIONS = arrayOf(
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )
    
    // Used to load the 'cmake_project_test' library on application startup.
    init {
        System.loadLibrary("cmake_project_test")
    }
}

🎯 最佳实践

1. 权限申请时机

  • 在用户主动点击蓝牙功能时申请
  • 避免应用启动时强制申请
  • 提供清晰的权限用途说明

2. 用户体验

  • 显示当前权限状态
  • 提供权限被拒绝时的解决方案
  • 友好的错误提示

3. 兼容性

  • 支持Android 6.0+的动态权限
  • 兼容Android 12+的新蓝牙权限
  • 处理权限被拒绝的情况

🔍 调试技巧

检查权限状态

private fun checkPermissionStatus(): String {
    val status = mutableListOf<String>()
    
    for (permission in REQUIRED_PERMISSIONS) {
        val granted = ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
        status.add("${permission.split(".").last()}: ${if (granted) "✓" else "✗"}")
    }
    
    return status.joinToString("\n")
}

日志输出

  • 权限申请过程会记录详细日志
  • 可通过Logcat查看权限状态变化
  • 便于调试权限相关问题

📝 注意事项

  1. 位置权限必需:蓝牙扫描需要位置权限,这是系统要求
  2. 权限持久性:权限一旦授予,应用重启后仍然有效
  3. 系统限制:某些系统可能限制权限申请
  4. 版本兼容不同Android版本的权限要求可能不同