Permisos y solicitudes en tiempo de ejecución
Declare y solicite permisos peligrosos en tiempo de ejecución mediante ActivityResultContracts, muestre diálogos explicativos y gestione las denegaciones permanentes.
Permisos y solicitudes en tiempo de ejecución es una lección gratuita de Android Academy en CoddyKit. Esta es la lección 7 de 7. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Android Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Android Academy incluye 7 lecciones en total.
Descripción general de los permisos de Android
Las aplicaciones de Android deben declarar qué funciones del dispositivo necesitan. Los permisos protegen la privacidad del usuario:
- Permisos normales — riesgo bajo; se conceden automáticamente (INTERNET, VIBRATE)
- Permisos peligrosos — permiten acceder a datos sensibles y deben solicitarse en tiempo de ejecución (CAMERA, LOCATION, READ_CONTACTS)
- Permisos de firma — solo se aplican a aplicaciones firmadas con el mismo certificado
Declaración en el manifiesto
Todos los permisos deben declararse primero en AndroidManifest.xml:
<!-- AndroidManifest.xml -->
<manifest ...>
<!-- Normal: granted automatically -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- Dangerous: must request at runtime -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application ...>
...
</application>
</manifest>Comprobar si se ha concedido el permiso
Antes de usar una función peligrosa, compruebe siempre si ya se ha concedido el permiso:
import androidx.core.content.ContextCompat
import android.content.pm.PackageManager
fun isCameraPermissionGranted(): Boolean {
return ContextCompat.checkSelfPermission(
this, // Context
android.Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
}Solicitar permisos con ActivityResultLauncher
Use ActivityResultContracts.RequestPermission(), la forma moderna (sin el obsoleto onRequestPermissionsResult):
class CameraActivity : AppCompatActivity() {
private val requestCameraPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
openCamera()
} else {
showPermissionDeniedMessage()
}
}
fun onTakePhotoClick(view: View) {
if (isCameraPermissionGranted()) {
openCamera()
} else {
requestCameraPermission.launch(android.Manifest.permission.CAMERA)
}
}
}Varios permisos a la vez
Solicite varios permisos con RequestMultiplePermissions:
private val requestMultiple = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val cameraGranted = permissions[android.Manifest.permission.CAMERA] ?: false
val locationGranted = permissions[android.Manifest.permission.ACCESS_FINE_LOCATION] ?: false
if (cameraGranted && locationGranted) {
startFeature()
} else {
showWhichPermissionsDenied(cameraGranted, locationGranted)
}
}
fun requestPermissions() {
requestMultiple.launch(arrayOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.ACCESS_FINE_LOCATION
))
}Justificación: cuándo explicar el motivo
shouldShowRequestPermissionRationale() devuelve true cuando el usuario ha denegado anteriormente el permiso. Muestre una explicación antes de volver a solicitarlo:
fun requestCameraWithRationale() {
when {
isCameraPermissionGranted() -> {
openCamera()
}
shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA) -> {
// Explain why we need it, then request
AlertDialog.Builder(this)
.setTitle("Camera needed")
.setMessage("We use the camera to take profile photos.")
.setPositiveButton("OK") { _, _ ->
requestCameraPermission.launch(android.Manifest.permission.CAMERA)
}
.show()
}
else -> {
requestCameraPermission.launch(android.Manifest.permission.CAMERA)
}
}
}Denegado permanentemente: enviar a Ajustes
Si el usuario pulsa "No volver a preguntar", shouldShowRequestPermissionRationale devuelve false y no puede volver a solicitar el permiso. Diríjalo a los ajustes de la aplicación:
fun openAppSettings() {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}
startActivity(intent)
}Permiso de ubicación
La ubicación tiene dos niveles; elija el adecuado para su caso de uso:
ACCESS_COARSE_LOCATION— precisión a nivel de ciudad (WiFi/antenas de telefonía)ACCESS_FINE_LOCATION— precisión del GPSACCESS_BACKGROUND_LOCATION— necesario por separado en Android 10 y posteriores para acceder a la ubicación en segundo plano
Ejemplo completo del permiso de cámara
Flujo completo que combina comprobación → justificación → solicitud:
class PhotoActivity : AppCompatActivity() {
private val cameraLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (granted) openCamera() else showDenied()
}
private fun handleCameraClick() {
val permission = android.Manifest.permission.CAMERA
when {
ContextCompat.checkSelfPermission(this, permission) ==
PackageManager.PERMISSION_GRANTED -> openCamera()
shouldShowRequestPermissionRationale(permission) ->
showRationaleDialog()
else -> cameraLauncher.launch(permission)
}
}
private fun showDenied() {
Snackbar.make(binding.root, "Camera permission required", Snackbar.LENGTH_LONG)
.setAction("Settings") { openAppSettings() }.show()
}
}Buenas prácticas para los permisos
Reglas clave para ofrecer una experiencia fluida con los permisos:
- Solicite permisos solo cuando sean necesarios (no al iniciar la aplicación)
- Solicite únicamente los permisos mínimos requeridos
- Gestione siempre el caso de denegación correctamente
- No vuelva a preguntar repetidamente después de "No volver a preguntar"
- Explique el motivo antes del cuadro de diálogo del sistema, no después de la denegación
Permisos multimedia detallados en Android 13 y posteriores
Desde Android 13 (API 33), READ_EXTERNAL_STORAGE se divide en permisos específicos:
READ_MEDIA_IMAGESREAD_MEDIA_VIDEOREAD_MEDIA_AUDIO
Compruebe siempre Build.VERSION.SDK_INT y solicite el permiso adecuado para la versión del sistema operativo.
Comprobación rápida
¿Cuándo debe mostrar un cuadro de diálogo de justificación antes de solicitar un permiso peligroso?
Resumen: permisos
Permisos en tiempo de ejecución correctamente implementados:
- Declárelos en
AndroidManifest.xml - Compruébelos con
ContextCompat.checkSelfPermission() - Solicítelos mediante
registerForActivityResult(RequestPermission()) - Muestre una justificación cuando
shouldShowRequestPermissionRationale()sea true - En caso de denegación permanente, guíe a los usuarios a Ajustes
- No solicite nunca permisos antes de que el usuario los necesite
Siguiente: guardar datos localmente con DataStore.
Preguntas frecuentes
¿La lección «Permisos y solicitudes en tiempo de ejecución» es gratis?
Sí — el texto completo de «Permisos y solicitudes en tiempo de ejecución» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Android Academy, actualiza a CoddyKit PRO. El curso de Android Academy incluye 7 lecciones en total.
¿Qué aprenderé en «Permisos y solicitudes en tiempo de ejecución»?
Declare y solicite permisos peligrosos en tiempo de ejecución mediante ActivityResultContracts, muestre diálogos explicativos y gestione las denegaciones permanentes. Practicas Android Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Android Academy?
No se requiere experiencia previa. Android Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 7 de 7.
¿Cuánto tiempo toma la lección «Permisos y solicitudes en tiempo de ejecución»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Android Academy?
Sí. Cada lección de Android Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Estructura del proyecto y manifiesto
- Activities y ciclo de vida
- Layouts y vistas
- Gestión de la entrada del usuario
- Intents y navegación
- Fragments
- Permisos y solicitudes en tiempo de ejecución