Android 权限(Permission)完整指南
发布: (2025年12月31日 GMT+8 12:22)
5 min read
原文: Dev.to
Source: Dev.to
权限类型
Protection Level
-
Normal: 安装时自动授予,无需用户批准
例如:INTERNET,VIBRATE,ACCESS_NETWORK_STATE -
Dangerous: 运行时需要用户批准
例如:CAMERA,READ_CONTACTS,ACCESS_FINE_LOCATION -
Signature: 仅限相同签名的应用使用
例如:BIND_ACCESSIBILITY_SERVICE
运行时权限
Android 6.0 (API 23)+ 以及 targetSdkVersion 23 以上时需要。
权限检查
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
// 권한 있음
openCamera()
} else {
// 권한 요청 필요
requestCameraPermission()
}
权限请求
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
openCamera()
} else {
showPermissionDeniedMessage()
}
}
private fun requestCameraPermission() {
when {
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// 권한 필요 이유 설명 후 요청
showPermissionRationale()
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
一次请求多个权限
private val requestMultiplePermissions = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
permissions.entries.forEach { (permission, isGranted) ->
when {
isGranted -> Log.d(TAG, "$permission granted")
shouldShowRequestPermissionRationale(permission) -> {
// 거부됨, 다시 설명 가능
}
else -> {
// 영구 거부됨
}
}
}
}
// 요청
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
)
权限流程
检查权限 -> 无 -> shouldShowRationale?
-> Yes: 显示说明 -> 请求权限
-> No: 请求权限
-> 允许: 使用功能
-> 拒绝:
-> shouldShowRationale = true: 可再次请求
-> shouldShowRationale = false: 永久拒绝
永久拒绝处理
private fun handlePermanentDenial() {
AlertDialog.Builder(this)
.setTitle("권한 필요")
.setMessage("이 기능을 사용하려면 설정에서 권한을 허용해주세요.")
.setPositiveButton("설정으로 이동") { _, _ ->
openAppSettings()
}
.setNegativeButton("취소", null)
.show()
}
private fun openAppSettings() {
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
startActivity(this)
}
}
权限组
如果允许同一组中的任意一个权限,组内的其他权限也会自动被允许。
注意:权限组可能会发生变化,请单独检查每个权限。
硬件功能
if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
// 카메라 기능 사용 가능
}
BroadcastReceiver 权限
仅接收具有特定权限的应用的广播:
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.SOME_ACTION"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ANOTHER_ACTION"/>
</intent-filter>
<meta-data
android:name="android.permission.SOME_PERMISSION"
android:value="true"/>
</receiver>
使用 ADB 测试权限
# 授予权限
adb shell pm grant com.example.app android.permission.CAMERA
# 撤销权限
adb shell pm revoke com.example.app android.permission.CAMERA
Permission Helper 类
class PermissionHelper(private val activity: ComponentActivity) {
private var callback: ((Boolean) -> Unit)? = null
private val launcher = activity.registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val allGranted = permissions.values.all { it }
callback?.invoke(allGranted)
}
fun requestPermissions(
permissions: Array<String>,
onResult: (Boolean) -> Unit
) {
callback = onResult
val notGranted = permissions.filter {
ContextCompat.checkSelfPermission(activity, it) !=
PackageManager.PERMISSION_GRANTED
}
if (notGranted.isEmpty()) {
onResult(true)
return
}
launcher.launch(notGranted.toTypedArray())
}
fun hasPermission(permission: String): Boolean {
return ContextCompat.checkSelfPermission(activity, permission) ==
PackageManager.PERMISSION_GRANTED
}
fun shouldShowRationale(permission: String): Boolean {
return activity.shouldShowRequestPermissionRationale(permission)
}
}
使用示例
class MainActivity : AppCompatActivity() {
private lateinit var permissionHelper: PermissionHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
permissionHelper = PermissionHelper(this)
// 示例:请求摄像头和音频权限
permissionHelper.requestPermissions(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
) { allGranted ->
if (allGranted) {
// 所有权限已授予
startRecording()
} else {
// 权限被拒绝
showPermissionDeniedMessage()
}
}
}
private fun startRecording() {
// 录音/拍摄逻辑
}
private fun showPermissionDeniedMessage() {
Toast.makeText(this, "需要权限。", Toast.LENGTH_SHORT).show()
}
}
代码示例
missionHelper = PermissionHelper(this)
}
private fun checkCameraPermission() {
permissionHelper.requestPermissions(
arrayOf(Manifest.permission.CAMERA)
) { granted ->
if (granted) {
openCamera()
} else {
handlePermissionDenied()
}
}
}
在没有 SMS 权限的情况下接收 OTP – 使用 SMS Retriever API
val client = SmsRetriever.getClient(this)
client.startSmsRetriever()
.addOnSuccessListener { /* 监听器已启动 */ }
.addOnFailureListener { /* 失败 */ }
注意事项
- 权限组可更改:对每个权限单独勾选
- 可在设置中解除:即使之前已允许,也需要重新勾选
- 拒绝权限时应用会重启:
onTerminate()不会被调用 - 授权后再拒绝:永久拒绝记录会被重置
结论
运行时权限对于保护用户隐私非常重要。请明确说明请求权限的原因,仅在必要时请求,并在被拒绝时提供替代流程。