Una de las decisiones que más impacto tiene en la primera impresión de una app, y que sin embargo se toma casi sin pensar en muchos proyectos, es cuándo y cómo pedir permisos. He visto apps que, nada más abrirse por primera vez, lanzan tres o cuatro diálogos de permiso seguidos: cámara, ubicación, notificaciones, contactos. El resultado casi siempre es el mismo: el usuario rechaza varios sin pensarlo, porque no ha visto todavía ningún motivo para concederlos. En el desarrollo de Caladero he intentado hacer justo lo contrario, y quiero explicar el razonamiento.

El problema de pedir permisos por adelantado

Cuando un permiso se pide antes de que el usuario entienda para qué sirve, la decisión de conceder o denegar se toma sin contexto. Un usuario que abre una app de pesca por primera vez y ve inmediatamente un diálogo pidiendo acceso a la ubicación no tiene forma de saber si ese permiso es imprescindible para el funcionamiento básico o es algo secundario. La reacción más común, y la más razonable desde el punto de vista del usuario, es denegar por precaución.

Esto tiene una consecuencia práctica además de la de confianza: en Android, si un usuario deniega un permiso dos veces, el sistema deja de mostrar el diálogo estándar y obliga a que el usuario active el permiso manualmente desde los ajustes del sistema, un flujo mucho más largo y con más fricción. Pedir mal un permiso no solo genera desconfianza, también reduce las probabilidades de conseguirlo más adelante aunque el usuario cambie de opinión.

El principio que sigo: pedir en el contexto de uso

La regla que aplico en Caladero es simple de enunciar aunque no siempre trivial de implementar: un permiso se pide en el momento exacto en que el usuario intenta usar la funcionalidad que lo necesita, nunca antes. Si el usuario abre la app y solo consulta el mapa general sin marcar ningún punto, no se le pide ningún permiso de ubicación. El permiso de ubicación se solicita en el instante en que el usuario pulsa el botón de "guardar mi posición actual como punto", que es el momento en que el motivo de la petición es evidente por sí mismo.

En código, esto se traduce en comprobar el estado del permiso justo antes de ejecutar la acción que lo requiere, no en el arranque de la aplicación:

fun onGuardarPosicionActualClick() {
    when {
        ContextCompat.checkSelfPermission(
            context, Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED -> {
            guardarPosicionActual()
        }
        else -> {
            solicitarPermisoUbicacion()
        }
    }
}

La diferencia con pedir el permiso en el onCreate de la actividad principal es sutil en el código pero grande en la experiencia: el usuario ve el diálogo justo después de haber pulsado un botón cuyo propósito entendía, no como un obstáculo antes de haber visto nada de la app.

Explicar el motivo antes de pedir, cuando hace falta

Android permite comprobar si el sistema considera razonable mostrar una explicación adicional antes del diálogo de permiso (shouldShowRequestPermissionRationale), típicamente porque el usuario ya denegó el permiso una vez. En Caladero uso ese momento para mostrar una explicación breve y concreta, del tipo "Necesitamos tu ubicación para guardar este punto en el mapa. No se comparte con nadie salvo que tú decidas exportarlo", en vez de repetir el diálogo del sistema sin más contexto.

Esto no es solo cortesía: la documentación oficial de Android recomienda explícitamente este patrón para mejorar la tasa de aceptación de permisos, precisamente porque un usuario que entiende el motivo tiene muchas más probabilidades de conceder el permiso la segunda vez. Más detalles sobre las prácticas recomendadas están en la documentación oficial de developer.android.com sobre permisos.

Pedir el permiso mínimo, no el máximo disponible

Otro error frecuente es pedir un permiso más amplio del que realmente hace falta. Un ejemplo claro es la ubicación: Android distingue entre ubicación aproximada (ACCESS_COARSE_LOCATION) y ubicación precisa (ACCESS_FINE_LOCATION). Si una funcionalidad concreta solo necesita saber en qué zona general está el usuario, pedir precisión exacta es pedir más de lo necesario, y eso también afecta a cómo lo percibe el usuario al leer qué permisos solicita la app. Dedico un artículo aparte a cómo tomo esa decisión en detalle, en ubicación aproximada o precisa en Android.

Lo mismo aplica a acceso a archivos multimedia: pedir acceso a toda la galería cuando solo se necesita que el usuario elija una foto puntual es innecesario desde que existe el selector de fotos del sistema, algo que trato con más detalle en el artículo sobre Android Photo Picker sin permiso de galería.

Un ejemplo de decisión concreta en Caladero

Cuando diseñé la función de compartir una foto asociada a un punto de pesca, la primera versión que escribí pedía el permiso de acceso a todas las imágenes del dispositivo, porque era la forma más directa de implementarlo. Al revisar esa decisión, y siguiendo el principio de pedir lo mínimo, cambié la implementación para usar el selector de fotos del sistema, que no requiere ningún permiso de Android en absoluto porque el propio sistema operativo gestiona la selección de forma aislada de la app. El resultado es una funcionalidad equivalente desde el punto de vista del usuario, pero con muchísima menos superficie de permisos declarados.

Errores y límites a tener en cuenta

Un límite real de la estrategia de "pedir en el momento de uso" es que puede generar más interrupciones puntuales si una pantalla necesita varios permisos distintos en sucesión rápida, lo que también resulta molesto si no se agrupan bien. La solución no es volver a pedir todo de golpe al principio, sino diseñar el flujo de la pantalla para que cada permiso se pida justo antes de la acción concreta que lo necesita, aunque eso implique una interacción más.

Otro error que cometí al principio fue no comprobar qué pasa cuando el usuario deniega un permiso de forma permanente ("no volver a preguntar"). Sin gestionar ese caso, la app simplemente no hacía nada visible al pulsar el botón, lo cual es confuso. Ahora, cuando detecto ese estado, muestro un mensaje claro explicando que el permiso está bloqueado y ofrezco un enlace directo a los ajustes de la app para que el usuario pueda activarlo manualmente si cambia de opinión.

Conclusión

Pedir permisos bien no es solo una cuestión de cumplir normativas o evitar rechazos en las tiendas de aplicaciones. Es, sobre todo, una forma de respetar al usuario: darle la información necesaria en el momento en que la necesita, y no pedirle más acceso del que la funcionalidad concreta requiere. En mi experiencia, esto no solo mejora la confianza percibida, también reduce el número de rechazos reales, porque el usuario entiende exactamente por qué se le está pidiendo cada permiso en cada momento.