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

Android 权限申请现代化指南

Android 权限申请现代化指南

一、核心概念:权限分类

Android 将权限分为三大类,申请方式各不相同:

  1. 普通权限 (Normal Permissions)
    · 范围:涉及应用沙盒外部但对用户隐私或设备操作风险极低的操作。
    · 示例:网络访问 (INTERNET)、振动 (VIBRATE)、设置壁纸 (SET_WALLPAPER)。
    · 授权方式:在 AndroidManifest.xml 中声明后,系统在安装时自动授予。
  2. 危险权限 (Dangerous Permissions)
    · 范围:涉及用户隐私或设备敏感数据的操作。
    · 示例:相机 (CAMERA)、精确位置 (ACCESS_FINE_LOCATION)、联系人 (READ_CONTACTS)、麦克风 (RECORD_AUDIO)。
    · 授权方式:必须在运行时明确向用户请求。这是本指南的重点。
  3. 特殊权限 (Special Permissions)
    · 范围:拥有系统级影响的极高特权权限。
    · 示例:在其他应用上方绘制 (SYSTEM_ALERT_WINDOW)、修改系统设置 (WRITE_SETTINGS)。
    · 授权方式:通常需要引导用户至系统特定页面进行授权,不通过标准 API 请求。

二、现代化实现方式

Google 推荐使用 Activity Result API 配合 ActivityResultContracts 来请求权限。这种方式取代了传统的重写 onRequestPermissionsResult() 的方法,具有以下优势:

· 生命周期安全:自动管理生命周期,避免内存泄漏。
· 代码清晰:请求逻辑和结果处理集中在一起,易于维护。
· 无需请求码:避免了手动管理 requestCode 的繁琐和错误。

  1. 声明权限

在 AndroidManifest.xml 中声明所有需要的权限,这是任何方式的前提。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><!-- 其他权限 --><application ...> ... </application>
</manifest>
  1. 请求单个权限(以相机权限为例)

在 Activity 或 Fragment 中:

class MainActivity : AppCompatActivity() {// 1. 注册权限请求启动器(Launcher)private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission() // 使用请求单个权限的合约) { isGranted: Boolean ->// 权限请求结果的回调handlePermissionResult(isGranted)}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val button = findViewById<Button>(R.id.btn_request)button.setOnClickListener {checkCameraPermission()}}private fun checkCameraPermission() {// 2. 检查权限是否已授予when {ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> {// 已有权限,执行操作openCamera()}// 3. 判断是否需要向用户解释原因shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {showPermissionRationaleDialog()}else -> {// 直接发起请求(首次或用户未选择"不再询问")requestPermissionLauncher.launch(Manifest.permission.CAMERA)}}}private fun handlePermissionResult(isGranted: Boolean) {if (isGranted) {openCamera()} else {// 处理拒绝逻辑,特别是“不再询问”的情况showGoToSettingsDialog()}}private fun openCamera() {Toast.makeText(this, "Camera opened!", Toast.LENGTH_SHORT).show()}private fun showPermissionRationaleDialog() {AlertDialog.Builder(this).setTitle("Need Permission").setMessage("This app needs camera access to take pictures.").setPositiveButton("OK") { _, _ ->// 用户理解后,再次发起请求requestPermissionLauncher.launch(Manifest.permission.CAMERA)}.setNegativeButton("Cancel", null).show()}private fun showGoToSettingsDialog() {AlertDialog.Builder(this).setTitle("Permission Denied").setMessage("You have permanently denied this permission. Please enable it in app settings.").setPositiveButton("Open Settings") { _, _ ->// 跳转到本应用的系统设置页val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {data = Uri.fromParts("package", packageName, null)}startActivity(intent)}.setNegativeButton("Cancel", null).show()}
}
  1. 请求多个权限(同时请求相机和麦克风)

使用 RequestMultiplePermissions Contract。

class MainActivity : AppCompatActivity() {// 1. 注册多权限请求启动器private val requestMultiplePermissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions: Map<String, Boolean> -> // 结果是一个映射表// 检查所有权限是否都被授予val allGranted = permissions.all { it.value }if (allGranted) {setupAppWithAllPermissions()} else {// 处理未全部授予的情况showSomePermissionsDenied()}}private fun requestMultiplePermissions() {// 2. 定义权限数组val permissionsToRequest = arrayOf(Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO)// 3. 发起请求requestMultiplePermissionsLauncher.launch(permissionsToRequest)}private fun setupAppWithAllPermissions() {Toast.makeText(this, "All permissions granted!", Toast.LENGTH_SHORT).show()}// ... 其他方法
}

三、最佳实践与关键提示

  1. 按需请求:在用户即将使用需要权限的功能时才请求权限,而不是一进入应用就请求所有权限。
  2. 善用解释 (shouldShowRequestPermissionRationale):
    · 此方法返回 true:用户之前拒绝过权限,你应该弹窗解释为什么需要它。
    · 返回 false:可能是第一次请求,或者用户已选择“不再询问”。
  3. 妥善处理“不再询问”:当用户勾选“不再询问”并拒绝后,再次调用 launch() 会直接拒绝。此时应引导用户前往系统设置手动开启权限。
  4. 测试所有路径:务必测试用户允许、拒绝、拒绝并不再询问等多种场景,确保应用行为正确。

通过遵循这套现代化方案,你的应用可以以一种用户友好、稳定且易于维护的方式处理Android运行时权限。

http://www.xdnf.cn/news/19327.html

相关文章:

  • MySQL 在 CentOS 上的安装与配置文件路径详解
  • 2025-08-18面试题(nginx,mysql,zabbix为主)
  • LeetCode 2540.最小公共值
  • 1.7 Rendering模块
  • 数据结构 03(线性:单链表)
  • web渗透之RCE漏洞
  • Java中使用JSONUtil处理JSON数据:从前端到后端的完美转换
  • [Mysql数据库] 知识点总结7
  • 06.《STP 基础原理与配置详解》
  • DFS 回溯 【各种题型+对应LeetCode习题练习】
  • 突发,支付宝发布公告
  • 一体化步进伺服电机在汽车线束焊接设备中的应用案例
  • LZ4 解压工具(WPF / .NET 8)说明书
  • 【金仓数据库产品体验官】KingbaseES-ORACLE兼容版快速体验
  • 深入理解drv_spi.c后,完全正向亲手移植rt-thread的drv_spi.c驱动 (基于stm32h750 artpi)
  • Java函数式编程之【流(Stream)性能优化】
  • WPF和WinFrom区别
  • 计算机毕设 java 阿歹果园养鸡场管理系统 基于 SSM 框架的果园养鸡场全流程管理系统设计与实现 Java+MySQL 的养殖生产与进销存一体化平台开发
  • 汽车专卖店管理系统的设计与实现(代码+数据库+LW)
  • Langflow核心技术学习笔记
  • 探索 XGBoost 与 LightGBM 的差异:哪个更适合你的项目?
  • 基于TCN-BiLSTM-SelfAttention神经网络的多输入单输出回归预测【MATLAB】
  • 力扣(LeetCode) ——645. 错误的集合(C语言)
  • 整体设计 的语言设计:通用模型语言的标准模板语言的规格模式语言(搜狗汪仔答问)
  • GooglePlay提审问题记录
  • 国家统计局数据分析01——机器学习
  • wpf之附加属性
  • Odoo与Django 的区别是什么?
  • ADFS 和 OAuth 的区别
  • 龙迅#LT7641GX适用于四路HDMI2.1/DP/TPYE-C转HDMI2.1混切应用,分辨率高达8K60HZ!