1. Bienvenida
Introducción
Los permisos de la app se usan para brindar acceso a los datos y las funcionalidades que proporciona la zona de pruebas de la app. Para mejorar la funcionalidad de tu app, debes permitir el acceso a Internet, a la ubicación del dispositivo, a la cámara, y mucho más.
A fin de usar estas capacidades, deberás solicitarle permisos al usuario. En este codelab, te guiaremos por los pasos necesarios para agregar permisos de tiempo de ejecución y verificar si se otorgaron o no.
Requisitos
- La versión más reciente de Android Studio
Conocimientos que ya deberías tener
- Kotlin, como se explica en la Capacitación de Kotlin
- Habilidades básicas de desarrollo de Android, como se explica en Cómo desarrollar apps para Android con Kotlin
Qué aprenderás
- Cómo agregar permisos al manifiesto de Android
- Cómo solicitar permisos
- Cómo controlar cuándo se aceptan y se rechazan permisos
- Cómo verificar si se otorgó un permiso
Qué compilarás
Crearás una app que solicite un permiso para acceder a la cámara. Implementarás la parte del permiso de la app, pero no la parte de la cámara.
2. Cómo crear un proyecto de Android Studio
- Inicia un proyecto nuevo de Android Studio.
- Selecciona Empty Activity.
- Asígnale el nombre Permissions Codelab al proyecto y establece el lenguaje en Kotlin.
3. Cómo configurar el código
- Agrega las últimas versiones de las siguientes dependencias al archivo
build.gradle
del nivel de app. Estas versiones te permiten usar la bibliotecaActivity
que se tratará más adelante en el codelab.
implementation "androidx.activity:activity-ktx:1.2.2"
implementation "androidx.fragment:fragment-ktx:1.3.2"
- Establece la opción de compilación
viewBinding
como verdadera en el bloque de Android para habilitar ViewBinding.
android {
...
buildFeatures {
viewBinding true
}
}
- Luego, presiona el botón de martillo verde para compilar. Esto generará una clase de vinculación llamada
ActivityMainBinding
que usarás más adelante paraViewBinding
.
- Navega al archivo
activity_main.xml
y reemplaza el código por este.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Request Permissions"
android:onClick="onClickRequestPermission"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Agrega estas strings al archivo
strings.xml
.
<string name="app_name">Permissions Codelab</string>
<string name="permission_required">Camera access is required to display the camera preview.</string>
<string name="ok">OK</string>
<string name="permission_granted">Permission is granted. You can use the camera now.</string>
- En
MainActivity.kt
, arriba del métodoonCreate()
, define las variables para el diseño y el elementoViewBinding
.
private lateinit var layout: View
private lateinit var binding: ActivityMainBinding
- Reemplaza el código del método
onCreate()
con el siguiente código. Este código inicializa la vinculación, crea un elementoval
para representar la vista y lo establece en la raíz de la vinculación, y establece el diseño en el elementomainLayout
de la vinculación.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
layout = binding.mainLayout
setContentView(view)
}
- En la parte inferior del archivo, debajo de la clase
MainActivity
, agrega una función de extensión para mostrar las barras de notificaciones en todo el codelab.
fun View.showSnackbar(
view: View,
msg: String,
length: Int,
actionMessage: CharSequence?,
action: (View) -> Unit
) {
val snackbar = Snackbar.make(view, msg, length)
if (actionMessage != null) {
snackbar.setAction(actionMessage) {
action(this)
}.show()
} else {
snackbar.show()
}
}
4. Cómo agregar un permiso al manifiesto
Lo primero que debes hacer es declarar que se usará tu permiso en Android manifest
con la etiqueta <uses-permission>
.
Con frecuencia, el permiso que solicitas también tendrá otros requisitos. En este caso, no puedes usar una app de cámara, a menos que el dispositivo tenga una cámara. Por este motivo, también agregarás la etiqueta <uses-feature>
al manifiesto.
- En el archivo
AndroidManifest.xml
, agrega el permiso para acceder a la cámara arriba de la etiqueta<application>
.
<uses-permission android:name="android.permission.CAMERA" />
5. Cómo crear un selector de permisos
En MainActivity.kt
, crea un val
con el nombre requestPermissionLauncher
y copia el código en este. En las siguientes viñetas, se explicará lo que incluye este código.
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
Log.i("Permission: ", "Granted")
} else {
Log.i("Permission: ", "Denied")
}
}
- Haz que
requestPermissionLauncher
sea igual aregisterForActivityResult
y pasaActivityResultContracts.RequestPermission()
.
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission())
- Agrega una devolución de llamada para controlar el caso en el que se otorga o no. En este caso, registramos el resultado.
{ isGranted: Boolean ->
if (isGranted) {
Log.i("Permission: ", "Granted")
} else {
Log.i("Permission: ", "Denied")
}
}
6. Cómo solicitar un permiso
- Crea una función con el nombre
onClickRequestPermission(view: View)
y copia el código en esta. En las siguientes viñetas, explicaremos lo que sucede dentro del código.
fun onClickRequestPermission(view: View) {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
layout.showSnackbar(
view,
getString(R.string.permission_granted),
Snackbar.LENGTH_INDEFINITE,
null
) {}
}
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
layout.showSnackbar(
view,
getString(R.string.permission_required),
Snackbar.LENGTH_INDEFINITE,
getString(R.string.ok)
) {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
- Configura una sentencia
when
para cubrir tres casos: si ya se otorgó el permiso, si la app considera que debería mostrar la lógica del permiso de solicitud y si todavía no se solicitó.
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
}
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
}
else -> {
}
}
- En el caso en que se haya otorgado el permiso, muestra una barra de notificaciones que lo anuncie.
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
layout.showSnackbar(
view,
getString(R.string.permission_granted),
Snackbar.LENGTH_INDEFINITE,
null
) {}
}
- Si
shouldShowRequestPermissionRationale()
muestra un valor verdadero, se ofrece una IU que describa, con más detalles, el motivo por el que la función necesita ese permiso particular y que también le brinde al usuario una manera de aceptar o rechazar el permiso de la IU.
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
layout.showSnackbar(
view,
getString(R.string.permission_required),
Snackbar.LENGTH_INDEFINITE,
getString(R.string.ok)
) {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
- De lo contrario, solicita el permiso.
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
7. Resumen
¡Eso es todo! En este codelab, te mostramos la manera de agregar permisos de tiempo de ejecución, y se puede usar para permisos relacionados con la ubicación, la red, el contenido multimedia y mucho más.
Puedes consultar el código final y leer más en la documentación.