Android 9 (nivel 28 de API) presenta varios cambios en el sistema de Android. Los siguientes cambios de comportamiento se aplican a todas las apps cuando se ejecutan en la plataforma de Android 9, independientemente del nivel de API al que se orienten. Todos los desarrollares deben revisar estos cambios y modificar sus apps para admitirlos de manera correspondiente, cuando sea pertinente para estas.
Para los cambios que solo afecten a las apps orientadas a niveles de API a partir del 28, consulta Cambios en el comportamiento: Apps orientadas a niveles de API a partir del 28.
Administración de energía
Android 9 presenta características nuevas para mejorar la administración de energía de los dispositivos. Estos cambios, sumados a características que ya estaban disponibles antes de Android 9, garantizan que se proporcionen los recursos de sistema a las apps que más los necesiten.
Para obtener información detallada, consulta Administración de energía.
Cambios relacionados con la privacidad
Con el objetivo de mejorar la privacidad del usuario, Android 9 introduce varios cambios de comportamiento, como la limitación del acceso de las apps en segundo plano a sensores del dispositivo, la restricción de la información obtenida en análisis de Wi-Fi, y nuevas reglas de permisos y grupos de permisos relacionados con llamadas telefónicas, el estado del teléfono y análisis de Wi-Fi.
Estos cambios afectan a todas las apps que se ejecuten en Android 9, sin importar la versión de SDK a la que se orienten.
Acceso limitado a sensores en segundo plano
Android 9 limita la capacidad de las apps en segundo plano para acceder a entradas del usuario y datos de sensores. Si tu app se ejecuta en segundo plano en un dispositivo con Android 9, el sistema aplica a esta las siguientes restricciones:
- Tu app no puede acceder al micrófono ni a la cámara.
- Los sensores que usan el modo de generación de informes continua, como acelerómetros y giroscopios, no reciben eventos.
- Los sensores que usan los modos de generación de informes ante un cambio o de acción única no reciben eventos.
Si tu app debe detectar eventos de sensores en dispositivos con Android 9, usa un servicio en primer plano.
Acceso restringido a registros de llamadas
En Android 9, se introduce el grupo
de permisos
CALL_LOG
y se mueven a este los permisos
READ_CALL_LOG
,
WRITE_CALL_LOG
y
PROCESS_OUTGOING_CALLS
. En versiones anteriores de Android, estos permisos
se encontraban en el grupo de permisos PHONE
.
Este grupo de permisos CALL_LOG
brinda a los usuarios más control y visibilidad respecto de
apps que necesiten acceder a información confidencial sobre llamadas telefónicas;
la lectura de registros de llamadas telefónicas y la identificación de números telefónicos son algunos ejemplos.
Si tu app necesita acceder a registros de llamadas o necesita procesar llamadas salientes,
debes solicitar estos permisos de forma explícita desde el grupo
de permisos
CALL_LOG
. En caso contrario, se produce una
SecurityException
.
Nota: Debido a que estos permisos han cambiado de grupos y se otorgan en el tiempo de ejecución, el usuario puede denegar a tu app el acceso a la información de registros de llamadas. En este caso, tu app debería poder manejar correctamente la falta de acceso a la información.
Si tu app ya cumple con las prácticas recomendadas para permisos de tiempo de ejecución, puede manejar los cambios en el grupo de permisos.
Acceso restringido a números telefónicos
Las apps que se ejecutan en Android 9 no pueden leer números telefónicos ni estados de teléfonos sin
adquirir primero el permiso
READ_CALL_LOG
,
además de otros permisos que
se requieran según el caso de uso de tu app.
Los números telefónicos asociados con llamadas entrantes o salientes son visibles en la
transmisión
del estado del teléfono,
como en el caso de las llamadas entrantes y salientes, y puede accederse a ellos desde la clase
PhoneStateListener
.
Sin embargo, sin el permiso
READ_CALL_LOG
,
el campo del número telefónico que se proporciona en las transmisiones
PHONE_STATE_CHANGED
y a través de PhoneStateListener
se encuentra vacío.
Para leer los números telefónicos del estado del teléfono, actualiza tu app a fin de solicitar los permisos necesarios según tu caso de uso:
- Para leer números desde la acción
de intent
PHONE_STATE
, necesitas los permisosREAD_CALL_LOG
yREAD_PHONE_STATE
. - Para leer números desde
onCallStateChanged()
, solo necesitas el permisoREAD_CALL_LOG
. No necesitas el permisoREAD_PHONE_STATE
.
Acceso restringido a la información de conexión y ubicación de Wi-Fi
En Android 9, los requisitos de permisos para que una app realice análisis de Wi-Fi son más estrictos que en versiones anteriores. Para obtener información detallada, consulta la sección de restricciones para el análisis de Wi-Fi.
También se aplican restricciones similares al método
getConnectionInfo()
,
el cual muestra un objeto WifiInfo
que describe la conexión Wi-Fi actual. Solo puedes usar los métodos de estos
objetos para obtener valores de SSID y BSSID si la app que realiza la llamada tiene los siguientes
permisos:
- ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE
Para obtener el SSID o BSSID también es necesario que los servicios de ubicación estén habilitados en el dispositivo (dentro de Settings > Location).
Información quitada de métodos de servicios de Wi-Fi
En Android 9, los eventos y las transmisiones siguientes no reciben información sobre la ubicación del usuario ni datos que puedan identificarse personalmente:
- Los métodos
getScanResults()
ygetConnectionInfo()
deWifiManager
. - Los métodos
discoverServices()
yaddServiceRequest()
deWifiP2pManager
. - La transmisión
NETWORK_STATE_CHANGED_ACTION
.
La transmisión de sistema NETWORK_STATE_CHANGED_ACTION
de Wi-Fi ya no contiene SSID (anteriormente EXTRA_SSID),
BSSID (anteriormente EXTRA_BBSID) ni información de conexión (anteriormente
EXTRA_NETWORK_INFO). Si tu app necesita esta información, llama a
getConnectionInfo()
como alternativa.
La información de telefonía ahora depende de la configuración de ubicación del dispositivo
Si el usuario ha inhabilitado la ubicación del dispositivo en un dispositivo que ejecute Android 9, los siguientes métodos no proporcionan resultados:
Restricciones para el uso de interfaces que no pertenezcan al SDK
Para garantizar la estabilidad y compatibilidad con apps, la plataforma restringe el uso de algunos métodos y campos que no pertenecen al SDK; estas restricciones se aplican si intentas acceder a estos métodos y campos de manera directa mediante reflejo o a través de JNI. En Android 9, tu app puede seguir teniendo acceso a estas interfaces restringidas; la plataforma usa notificaciones y entradas de registro para llamar tu atención respecto de ellas. Si tu app muestra estas notificaciones, es importante que apliques una estrategia de implementación alternativa a la interfaz restringida. Si crees que no hay una estrategia alternativa viable, puedes notificar un error para solicitar la reconsideración de la restricción.
En Restricciones en interfaces que no pertenecen al SDK se ofrece más información importante. Te convendrá consultarla para asegurarte de que tu app siga funcionando correctamente.
Cambios de comportamiento vinculados a la seguridad
Cambios de seguridad para dispositivos
En Android 9 se introducen varias capacidades que mejoran la seguridad de tu app, sin importar la versión a la que esta se oriente.
Cambios en la implementación de TLS
La implementación de TLS del sistema se ha sometido a varias modificaciones en Android 9:
- Si una instancia de
SSLSocket
no puede establecer conexión mientras se crea, el sistema genera unaIOException
en lugar de unaNullPointerException
. - La clase
SSLEngine
controla de manera ordenada cualquier alertaclose_notify
que se produzca.
Para obtener más información sobre cómo realizar solicitudes web seguras en una app para Android, consulta Un ejemplo HTTPS.
Filtro de SECCOMP más estricto
En Android 9 se imponen más restricciones a las llamadas al sistema disponibles para las apps. Este comportamiento es una extensión del filtro de SECCOMP que incluye Android 8.0 (nivel de API 26).
Nota: Este cambio solo afecta a las apps que usan llamadas de sistema con privilegios.
Cambios criptográficos
En Android 9, se presentan varias modificaciones para la implementación y el manejo de los algoritmos criptográficos.
Implementaciones de parámetros y algoritmos de Conscrypt
En Android 9 se proporcionan implementaciones adicionales de parámetros de algoritmos en Conscrypt. Entre estos parámetros se incluyen AES, DESEDE, OAEP y EC. Las versiones Bouncy Castle de estos parámetros y muchos algoritmos han quedado obsoletos a partir de Android 9.
Nota: La implementación del parámetro EC en Conscrypt solo es compatible con curvas designadas.
Si tu app se orienta a Android 8.1 (nivel de API 27) o versiones anteriores, recibirás una advertencia
al solicitar la implementación de Bouncy Castle a uno de estos algoritmos
obsoletos. Sin embargo, si tienes como objetivo Android 9, estas solicitudes generan una
NoSuchAlgorithmException
.
Otros cambios
En Android 9, se introducen varios cambios adicionales relacionados con la criptografía:
- Cuando se usan claves PBE, si Bouncy Castle espera un vector de inicialización (IV) y tu app no proporciona uno, recibes una advertencia.
- La implementación de Conscrypt del cifrado ARC4 te permite especificar ARC4/ECB/NoPadding o ARC4/NONE/NoPadding.
- El proveedor Crypto Java Cryptography Architecture (JCA) se ha eliminado. Como
resultado, si tu app llama a
SecureRandom.getInstance("SHA1PRNG", "Crypto")
, se produce unaNoSuchProviderException
. - Si tu app analiza las claves RSA desde búferes que son más grandes que la estructura principal, dejará de producirse una excepción.
Para obtener más información sobre las capacidades criptográficas de Android, visita Criptografía.
Los archivos encriptados seguros ya nos son compatibles
En Android 9, se quita por completo la compatibilidad con los archivos encriptados seguros de Android (ASEC).
En Android 2.2 (nivel de API 8), Android introdujo los ASEC para admitir la funcionalidad de apps en tarjetas SD. En Android 6.0 (nivel de API 23), la plataforma introdujo una tecnología de dispositivos de almacenamiento adoptables que los desarrolladores pueden usar en lugar de los ASEC.
Actualización de las bibliotecas de ICU
Android 9 usa la versión 60 de la biblioteca de ICU. Android 8.0 (nivel de API 26) y Android 8.1 (nivel de API 27) usan ICU 58.
ICU se usa para proporcionar API públicas debajo del android.icu package
y se aplica internamente en la plataforma Android para admitir la internacionalización.
Por ejemplo, se usa para implementar clases de Android en java.util
, java.text
y android.text.format
.
La actualización a ICU 60 tiene varias modificaciones pequeñas pero útiles, como compatibilidad con datos de Emoji 5.0 y formatos mejorados de fecha y hora, tal como se documenta en las notas de la versión de ICU 59 e ICU 60.
Cambios destacados en esta actualización:
- Se ha modificado el modo en que la plataforma administra las zonas horarias.
- La plataforma maneja mejor las zonas GMT y UTC; UTC ya no es sinónimo de
GMT.
ICU proporciona nombres de zonas traducidos para GMT y UTC. Esta modificación afecta
android.icu
el comportamiento de formateo y análisis para zonas como “GMT”, “Etc/GMT”, “UTC”, “Etc/UTC” y “Zulu”. java.text.SimpleDateFormat
ahora usa ICU para proporcionar nombres de visualización para UTC y GMT. Esto implica lo siguiente:- El formateo de
zzzz
genera una string localizada extensa para muchas configuraciones regionales. Anteriormente, producía “UTC” para UTC y strings como “GMT+00:00” para GMT. - El análisis de
zzzz
reconoce strings como “hora universal coordinada” y “hora de Greenwich”. - Las apps pueden experimentar problemas de compatibilidad si prevén
que se muestra “UTC” o “GMT+00:00” para
zzzz
en todos los idiomas.
- El formateo de
- El comportamiento de
java.text.DateFormatSymbols.getZoneStrings()
ha cambiado:- Como en el caso de
SimpleDateFormat
, UTC y GMT ahora tienen nombres largos. Las variantes de los nombres de zonas horarias DST para la zona UTC, como “UTC”, "Etc/UTC" y “Zulu”, se convirtió en “GMT+00:00”, que es la alternativa de reserva estándar cuando no hay nombres disponibles, en lugar de la string codificada en forma rígidaUTC
. - Algunos ID de zonas se reconocen correctamente como sinónimos para otras
zonas, de modo que Android encuentre strings para
los ID de zonas arcaicas, como
Eire
, que antes no se podían resolver.
- Como en el caso de
- Asia/Hanoi ya no es una zona reconocida. Por esta razón
java.util.TimeZones.getAvailableIds()
no muestra este valor yjava.util.TimeZone.getTimeZone()
no lo reconoce. Este comportamiento responde al comportamiento existente deandroid.icu
.
- La plataforma maneja mejor las zonas GMT y UTC; UTC ya no es sinónimo de
GMT.
- El método
android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String)
puede mostrar unaParseException
incluso al analizar un texto de moneda legítima. Puedes evitar este problema usandoNumberFormat.parseCurrency
, disponible a partir de Android 7.0 (nivel de API 24), para texto de moneda de estiloPLURALCURRENCYSTYLE
.
Cambios de prueba de Android
Android 9 introduce varios cambios en la biblioteca del marco de trabajo de Android Test y en la estructura de clases. Estos cambios ayudan a los desarrolladores a usar API públicas compatibles con el marco de trabajo, pero también brindan mayor flexibilidad al compilar y ejecutar pruebas usando bibliotecas de terceros o lógica personalizada.
Bibliotecas eliminadas del marco de trabajo
Android 9 reorganiza las clases basadas en JUnit en tres bibliotecas:
android.test.base, android.test.runner y android.test.mock.
Este cambio te permite realizar pruebas con una versión de JUnit que funcione mejor
con las dependencias de tu proyecto. Esta versión de JUnit podría ser diferente de
la que android.jar
proporciona.
Para obtener más información sobre cómo se organizan las clases basadas en JUnit en estas bibliotecas, y sobre cómo preparar el proyecto de tu app para escribir y ejecutar pruebas, consulta Configurar un proyecto para Android Test.
Cambios de compilación en conjuntos de pruebas
El método addRequirements()
de la clase
TestSuiteBuilder
se eliminó y la clase TestSuiteBuilder
pasó a ser obsoleta.
El método addRequirements()
exigía a los desarrolladores proporcionar argumentos cuyos
tipos representaban API ocultas, con lo cual estas resultaban inválidas.
Decodificador UTF para Java
UTF-8 es el grupo de caracteres predeterminado en Android. Una secuencia de bytes UTF-8 se puede decodificar
con un constructor String
, como String(byte[] bytes)
.
El decodificador UTF-8 en Android 9 sigue los estándares Unicode de manera más estricta que en las versiones anteriores. Se incluyen los siguientes cambios:
- La forma no corta de UTF-8, como
<C0, AF>
, se trata como incorrecta. - La forma suplente de UTF-8, como
U+D800
..U+DFFF
, se trata como incorrecta. - La subsección máxima se reemplaza por una única
U+FFFD
. Por ejemplo, en la secuencia de bytes “41 C0 AF 41 F4 80 80 41
”, las subsecciones máximas son “C0
”, “AF
” y “F4 80 80
”. “F4 80 80
” puede ser la subsecuencia inicial de “F4 80 80 80
”, pero “C0
” no puede ser la subsecuencia inicial de cualquier secuencia de unidades de código bien formada. Por lo tanto, el resultado debe ser “A\ufffd\ufffdA\ufffdA
”. - Para decodificar una secuencia modificada UTF-8 o CESU-8 en Android 9 o versiones posteriores, usa el método
DataInputStream.readUTF()
o el método de JNINewStringUTF()
.
Verificación del nombre de host con un certificado
En la RFC 2818 se describen dos
métodos para hacer coincidir el nombre de un dominio con un certificado usando los nombres
disponibles dentro de la extensión subjectAltName
(SAN
) o, ante la ausencia de una extensión
SAN
, volviendo al commonName
(CN
).
Sin embargo, la reserva para el CN
dejó de estar disponible en RFC 2818. Por esto,
en Android ya no se usa el CN
. Para verificar un nombre de host, el servidor
debe presentar un certificado con un SAN
coincidente. Los certificados que no
contienen un SAN
que coincida con el nombre de host ya no se consideran confiables.
Las búsquedas de direcciones de red pueden generar violaciones de red
Las búsquedas de direcciones de red que requieren resolución de nombres pueden implicar entradas y salidas de red y, por lo tanto, se consideran como operaciones de bloqueo. Las operaciones de bloqueo en el subproceso principal pueden ocasionar pausas o bloqueos.
La clase StrictMode
es una herramienta de desarrollo que permite a los
desarrolladores detectar problemas en su código.
En Android 9 y versiones posteriores, StrictMode
detecta las violaciones
de red causadas por las búsquedas de direcciones de red que requieren resolución de nombres.
No deberías publicar tus apps con StrictMode
habilitado. De lo contrario,
estas pueden experimentar excepciones, como
NetworkOnMainThreadException
, al usar los métodos
detectNetwork()
o
detectAll()
para obtener una
política que detecte violaciones de red.
La resolución de una dirección IP numérica no se considera como una operación de bloqueo. La resolución de la dirección IP numérica funciona del mismo modo que en versiones anteriores a Android 9.
Etiquetado de socket
En las versiones de plataforma anteriores a Android 9, si un socket
se etiqueta con el método
setThreadStatsTag()
,
pierde la etiqueta cuando se envía a otro proceso mediante
IPC de enlace
con un contenedor ParcelFileDescriptor
.
En Android 9 y versiones posteriores, la etiqueta del socket se conserva cuando este se envía a otro
proceso mediante IPC de enlace. Este cambio puede afectar las estadísticas del tráfico de red, por
ejemplo, cuando se usa el método
queryDetailsForUidTag()
.
Si quieres conservar el comportamiento de las versiones anteriores, que quita la etiqueta de un
socket enviado a otro proceso, puedes llamar a
untagSocket()
antes de enviar el
socket.
Cantidad registrada de bytes disponibles en el socket
El método available()
muestra 0
cuando se lo llama
luego de invocar al método shutdownInput()
.
Informe más detallado de capacidades de red para VPN
En Android 8.1 (nivel de API 28) y versiones anteriores, la clase
NetworkCapabilities
solo proporcionaba un conjunto limitado de
información para VPN, como
TRANSPORT_VPN
, pero omitía
NET_CAPABILITY_NOT_VPN
. Esta información
limitada hacía que fuera más difícil determinar si usar una VPN supondría costos
para el usuario de la app. Por ejemplo, la comprobación de
NET_CAPABILITY_NOT_METERED
no
determinaba si las redes subyacentes eran medidas o no.
En Android 9 y versiones posteriores, cuando una VPN llama al método
setUnderlyingNetworks()
,
el sistema de Android combina los transportes y las capacidades de cualquier
red subyacente, y muestra el resultado como las capacidades
efectivas de red de la VPN.
En Android 9 y versiones posteriores, las apps que ya buscan
NET_CAPABILITY_NOT_METERED
reciben las capacidades de redes de la VPN y las
redes subyacentes.
Los archivos de la carpeta xt_qtaguid ya no están disponibles para las apps
A partir de Android 9, las apps no pueden tener acceso directo de
lectura a archivos de la carpeta /proc/net/xt_qtaguid
. Esto se aplica para
garantizar la uniformidad con algunos dispositivos que no cuenten con estos archivos.
Las API públicas que se basan en estos archivos, TrafficStats
y
NetworkStatsManager
, continúan funcionando de la forma prevista.
Sin embargo, es posible que las funciones
cutils
no compatibles, como
qtaguid_tagSocket()
,
no funcionen como se espera o que ni siquiera lo hagan en diferentes dispositivos.
Ahora se aplica el requisito FLAG_ACTIVITY_NEW_TASK
Con Android 9, no puedes iniciar una actividad desde un
contexto sin actividades a menos que pases el indicador de intent
FLAG_ACTIVITY_NEW_TASK
.
Si intentas iniciar una actividad sin pasar este indicador, esta
no se iniciará y el sistema mostrará un mensaje en el registro.
Nota: El requisito del indicador siempre fue el comportamiento deseado, y se implementaba de manera forzosa en versiones anteriores a Android 7.0 (nivel de API 24). Un error en Android 7.0 evitó que este requisito se implementara.
Cambios de rotación de pantallas
A partir de Android 9, se introdujeron cambios importantes en el modo de rotación de retrato. En Android 8.0 (nivel de API 26), los usuarios podían activar o desactivar los modos de rotación de giro automático y retrato usando una configuración de mosaicos o visualización Quicksettings. El nombre del modo de retrato se ha cambiado a bloqueo de rotación y permanece activo cuando la rotación automática se desactiva. No hay modificaciones en el modo de rotación automática.
Cuando el dispositivo se encuentra en el modo de bloqueo de rotación, los usuarios pueden bloquear su pantalla en cualquier
rotación compatible con la Activity visible en la parte superior. Una Activity no debe prever que
siempre se representará en el modo de retrato. Si la Activity de la parte superior se puede representar en
varias rotaciones en el modo de rotación automática, las mismas opciones deben estar disponibles en el
modo de bloqueo de rotación, con algunas excepciones según la configuración de la Activity
screenOrientation
(consulta la tabla que aparece a continuación).
Las Activity que solicitan una orientación específica (por ejemplo,
screenOrientation=landscape
) ignoran la preferencia de bloqueo del usuario y se comportan del mismo modo
que en Android 8.0.
La preferencia respecto de la orientación de la pantalla se puede fijar en el nivel de Activity del manifiesto de Android, o mediante programación con setRequestedOrientation().
El modo de bloqueo de rotación funciona fijando la preferencia de rotación del usuario que el WindowManager usa cuando maneja la rotación de la Activity. La preferencia de la rotación del usuario se puede cambiar en los siguientes casos. Ten en cuenta que hay una tendencia a volver a la rotación natural de los dispositivos, que normalmente es de retrato para los dispositivos con factor de forma de teléfono:
- Cuando el usuario acepta una sugerencia de rotación, la preferencia de rotación se modifica según la sugerencia.
- Cuando el usuario realiza un cambio a una app vertical forzada (se incluyen la pantalla bloqueada o el lanzador), la preferencia de rotación cambia al modo de retrato.
En la siguiente tabla se resume el comportamiento de rotación para las orientaciones comunes de pantalla:
Orientación de la pantalla | Comportamiento |
---|---|
unspecified, user | En la rotación automática y el bloqueo de rotación, la Activity se puede representar en sentido vertical u horizontal (y a la inversa). Se prevé compatibilidad con diseños verticales y horizontales. |
userLandscape | En la rotación automática y el bloqueo de rotación, la Activity se puede representar de manera horizontal u horizontal inversa. Se prevé asistencia solo para diseños horizontales. |
userPortrait | En la rotación automática y el bloqueo de rotación, la Activity se puede representar en el modo de retrato o de retrato inverso. Se prevé compatibilidad solo con diseños verticales. |
fullUser | En la rotación automática y el bloqueo de rotación, la Activity se puede representar en el modo de retrato u horizontal (e inverso). Se prevé compatibilidad con diseños verticales y horizontales. Los usuarios del bloqueo de rotación tendrán la opción de aplicar bloqueo en el modo de retrato inverso; a menudo, a 180º. |
sensor, fullSensor, sensorPortrait y sensorLandscape | La preferencia del modo de bloqueo de rotación se ignora y se trata como si el giro automático estuviese activo. Solo debe usarse en circunstancias excepcionales, con especial consideración de la experiencia del usuario. |
La interrupción del cliente de HTTP de Apache afecta las apps con ClassLoader no estándar
En Android 6.0,
eliminamos la compatibilidad con el cliente HTTP de Apache.
Este cambio afecta a la gran mayoría de apps que no tengan como destino
Android 9 o versiones posteriores. Sin embargo, el cambio puede afectar a ciertas apps que
usen una estructura ClassLoader
no estándar,
incluso si las apps no están orientadas a Android 9 o versiones posteriores.
Una app puede verse afectada si usa un ClassLoader
no estándar que
realiza delegaciones de manera explícita al ClassLoader
del sistema. En cambio, estas apps deben realizar la delegación al
ClassLoader
de la app cuando buscan clases en org.apache.http.*
. Si
realizan la delegación al ClassLoader
del sistema, las apps fallarán en Android 9 o versiones posteriores
con un NoClassDefFoundError
,
debido a que el ClassLoader
del sistema ya no conoce esas clases. Para
evitar problemas similares en el futuro, las apps en general deben cargar las clases
a través del ClassLoader
de la app en vez de acceder directamente al ClassLoader
del sistema.
Enumerar cámaras
Las apps que se ejecuten en dispositivos con Android 9 pueden descubrir todas las cámaras disponibles llamando a
getCameraIdList()
.
Una app no debe suponer que el dispositivo solo tiene una cámara trasera o
una delantera.
Por ejemplo, si tu app tiene un botón para alternar las cámaras delantera y trasera, puede haber más de una cámara delantera o trasera para elegir. Debes revisar la lista de cámaras, examinar las características de cada una de estas y decidir qué cámaras mostrar al usuario.