Además de nuevas funciones y capacidades, Android 6.0 (nivel de API 23) incluye diversos cambios en el sistema y cambios en los comportamientos de la API. En este documento, se destacan algunos de los cambios clave que debes comprender y tener en cuenta en tus apps.
Si publicaste anteriormente una app para Android, ten en cuenta que estos cambios en la plataforma afectan a tu app.
Permisos de tiempo de ejecución
En esta versión, se presenta un nuevo modelo de permisos en el que los usuarios ahora pueden administrar directamente los permisos de la app durante el tiempo de ejecución. Este modelo les brinda a los usuarios mayor visibilidad y control sobre los permisos, a la vez que simplifica los procesos de instalación y actualización automática para los desarrolladores de apps. Los usuarios pueden conceder o revocar permisos de forma individual para las apps instaladas.
En tus apps que se orientan a Android 6.0 (nivel de API 23) o versiones posteriores, asegúrate de verificar y solicitar los permisos durante el tiempo de ejecución. Para determinar si se le otorgó un permiso a tu app, llama al nuevo método checkSelfPermission()
. Para solicitar un permiso, llama al nuevo método requestPermissions()
. Incluso si tu app no tiene como objetivo Android 6.0 (nivel de API 23), debes probarla de acuerdo con el nuevo modelo de permisos.
Para obtener detalles sobre la compatibilidad del nuevo modelo de permisos en tu app, consulta Cómo trabajar con permisos del sistema. Para obtener sugerencias sobre cómo evaluar el impacto en tu app, consulta las Notas de uso de permisos.
Descanso y App Standby
En esta versión se presentan nuevas optimizaciones de ahorro de energía para apps y dispositivos inactivos. Estas funciones afectan a todas las apps, así que asegúrate de probarlas en estos nuevos modos.
- Descanso: Si un usuario desconecta un dispositivo y lo deja inactivo, con la pantalla apagada durante un período determinado, el dispositivo entra en el modo Descanso, en el que intenta mantener el sistema en estado de suspensión. En este modo, los dispositivos reanudan periódicamente el funcionamiento normal durante períodos breves, de modo que la app se pueda sincronizar y el sistema pueda realizar las operaciones pendientes.
- App Standby: Permite que el sistema determine que una app se encuentra inactiva cuando el usuario no la usa activamente. El sistema hace esta determinación cuando el usuario no toca la app durante un período determinado. Si el dispositivo está desconectado, el sistema inhabilita el acceso a la red y suspende las sincronizaciones y los trabajos para las apps que considere inactivas.
Para obtener más información sobre estos cambios en el ahorro de energía, consulta Cómo optimizar para Descanso y App Standby.
Eliminación del cliente HTTP de Apache
En la versión de Android 6.0 se elimina la compatibilidad con el cliente HTTP de Apache. Si tu app usa este cliente y se orienta a Android 2.3 (nivel de API 9) o versiones posteriores, usa la clase HttpURLConnection
en su lugar. Esta API es más eficiente porque reduce el uso de red a través de una compresión y un almacenamiento en caché de respuestas transparentes, y minimiza el consumo de energía. Para seguir usando las APIs de HTTP de Apache, primero debes declarar la siguiente dependencia de tiempo de compilación en tu archivo build.gradle
:
android { useLibrary 'org.apache.http.legacy' }
BoringSSL
Android está migrando de OpenSSL a la biblioteca BoringSSL. Si usas el NDK de Android en tu app, no vincules bibliotecas criptográficas que no formen parte de la API del NDK, como libcrypto.so
y libssl.so
. Estas bibliotecas no son APIs públicas y pueden cambiar o interrumpirse sin previo aviso en todas las versiones y dispositivos.
A su vez, puedes exponerte a vulnerabilidades de seguridad. En cambio, modifica tu código nativo para llamar a las APIs de criptografía de Java a través de JNI o vincular estáticamente con una biblioteca criptográfica de tu elección.
Acceso al identificador de hardware
Para brindar una mayor protección de datos a los usuarios, a partir de esta versión, Android quita el acceso programático al identificador de hardware local del dispositivo para las apps que utilizan las APIs de Wi-Fi y Bluetooth. Los métodos WifiInfo.getMacAddress()
y BluetoothAdapter.getAddress()
ahora muestran un valor constante de 02:00:00:00:00:00
.
Para acceder a los identificadores de hardware de dispositivos externos cercanos mediante los escaneos de Bluetooth y Wi-Fi, tu app ahora debe tener los permisos ACCESS_FINE_LOCATION
o ACCESS_COARSE_LOCATION
:
Nota: Cuando un dispositivo con Android 6.0 (nivel de API 23) inicia una búsqueda de Wi-Fi o Bluetooth en segundo plano, la operación es visible para dispositivos externos como si se origina en una dirección MAC aleatoria.
Notificaciones
En esta versión, se quita el método Notification.setLatestEventInfo()
. En su lugar, usa la clase Notification.Builder
para crear notificaciones. Para actualizar una notificación varias veces, vuelve a usar la instancia de Notification.Builder
. Llama al método build()
para obtener instancias Notification
actualizadas.
El comando adb shell dumpsys notification
ya no imprime el texto de la notificación.
Usa el comando adb shell dumpsys notification --noredact
en su lugar para imprimir el texto en un objeto de notificación.
Cambios en AudioManager
Ya no se admiten las funciones para configurar el volumen de forma directa ni silenciar transmisiones específicas mediante la clase AudioManager
. El método setStreamSolo()
dejó de estar disponible y, en su lugar, debes llamar al método requestAudioFocus()
. Del mismo modo, el método setStreamMute()
dejó de estar disponible. En su lugar, llama al método adjustStreamVolume()
y pasa el valor de dirección ADJUST_MUTE
o ADJUST_UNMUTE
.
Selección de texto
Cuando los usuarios seleccionan texto en tu app, ahora puedes mostrar acciones de selección de texto, como Cortar, Copiar y Pegar en una barra de herramientas flotante. La implementación de la interacción del usuario es similar a la de la barra de acciones contextuales, como se describe en Cómo habilitar el modo de acción contextual para vistas individuales.
Si deseas implementar una barra de herramientas flotante para la selección de texto, realiza los siguientes cambios en tus apps existentes:
- En el objeto
View
oActivity
, cambia las llamadas aActionMode
destartActionMode(Callback)
astartActionMode(Callback, ActionMode.TYPE_FLOATING)
. - Toma tu implementación existente de
ActionMode.Callback
y, en su lugar, haz que extiendaActionMode.Callback2
. - Anula el método
onGetContentRect()
para proporcionar las coordenadas del objetoRect
de contenido (como un rectángulo de selección de texto) en la vista. - Si el posicionamiento del rectángulo ya no es válido y este es el único elemento que se invalidará, llama al método
invalidateContentRect()
.
Si utilizas la revisión 22.2 de la
biblioteca de compatibilidad de Android, ten en cuenta que las barras de herramientas flotantes no son retrocompatibles y que appcompat toma el control de los objetos ActionMode
de forma predeterminada. Esto impide que se muestren las barras de herramientas flotantes. Para habilitar la compatibilidad con ActionMode
en un AppCompatActivity
, llama a getDelegate()
, luego llama a setHandleNativeActionModesEnabled()
en el objeto AppCompatDelegate
que se muestra y establece el parámetro de entrada en false
. Esta llamada muestra el control de los objetos ActionMode
al framework. En los dispositivos que ejecutan Android 6.0 (nivel de API 23), eso permite que el framework admita los modos ActionBar
o de la barra de herramientas flotante, mientras que en dispositivos que ejecutan Android 5.1 (nivel de API 22) o versiones anteriores, solo se admiten los modos ActionBar
.
Cambios en marcadores de navegadores
Esta versión elimina la compatibilidad con marcadores globales. Se quitaron los métodos android.provider.Browser.getAllBookmarks()
y android.provider.Browser.saveBookmark()
. Del mismo modo, se quitan los permisos READ_HISTORY_BOOKMARKS
y WRITE_HISTORY_BOOKMARKS
. Si tu app se orienta a Android 6.0 (nivel de API 23) o versiones posteriores, no accedas a los favoritos desde el proveedor global ni uses los permisos de favoritos. En cambio, tu app debería almacenar datos de favoritos internamente.
Cambios en Android Keystore
Con esta versión, el proveedor de Android Keystore ya no admite DSA. ECDSA aún es compatible.
Las claves que no requieran encriptación de datos estáticos ya no se borrarán cuando se inhabilite o restablezca la pantalla de bloqueo segura (por ejemplo, cuando lo haga el usuario o el administrador del dispositivo). Las claves que requieren encriptación en reposo se borrarán durante estos eventos.
Cambios en las funciones de red y Wi-Fi
En esta versión se presentan los siguientes cambios de comportamiento en las API de redes y Wi-Fi.
- Ahora tus apps pueden cambiar el estado de los objetos
WifiConfiguration
solo si tú los creaste. No puedes modificar ni borrar objetosWifiConfiguration
creados por el usuario o por otras apps. -
Anteriormente, si una app forzaba al dispositivo a conectarse a una red Wi-Fi específica mediante
enableNetwork()
con la configuracióndisableAllOthers=true
, el dispositivo se desconectaba de otras redes, como los datos móviles. En esta versión, el dispositivo ya no se desconecta de otras redes como estas. Si latargetSdkVersion
de tu app es“20”
o inferior, se fijará a la red Wi-Fi seleccionada. Si latargetSdkVersion
de tu app es“21”
o superior, usa las APIs de redes múltiples (comoopenConnection()
,bindSocket()
y el nuevo métodobindProcessToNetwork()
) para asegurarte de que el tráfico de red se envíe en la red seleccionada.
Cambios en el servicio de cámara
En esta versión, el modelo para acceder a los recursos compartidos en el servicio de cámara se cambió del modelo de acceso anterior “por orden de llegada” a un modelo de acceso en el que se favorecen los procesos de prioridad alta. Entre los cambios en el comportamiento del servicio se incluyen los siguientes:
- El acceso a los recursos del subsistema de la cámara, lo que incluye abrir y configurar un dispositivo de cámara, se otorga según la "prioridad" del proceso de la aplicación cliente. Por lo general, los procesos de la aplicación con actividades en primer plano o visibles para el usuario reciben una prioridad más alta, lo que hace que el uso y la adquisición de recursos de la cámara sean más dependientes.
- Los clientes con cámara activa para apps de menor prioridad pueden ser “expulsados” cuando una aplicación de mayor prioridad intenta usar la cámara. En la API de
Camera
obsoleta, esto hace que se llame aonError()
para el cliente expulsado. En la API deCamera2
, esto hace que se llame aonDisconnected()
para el cliente expulsado. - En los dispositivos con el hardware de cámara adecuado, distintos procesos de la aplicación pueden abrir y usar de forma independiente dispositivos de cámara separados al mismo tiempo. Sin embargo, el servicio de cámara ahora detecta y no permite los casos de uso de procesos múltiples, en los que el acceso simultáneo genera una degradación significativa del rendimiento o las capacidades de cualquiera de los dispositivos de cámara abiertos. Este cambio puede generar “expulsiones” de clientes de menor prioridad, incluso cuando ninguna otra app esté intentando acceder directamente al mismo dispositivo de cámara.
- Cambiar el usuario actual provoca que se expulsen los clientes con cámara activa en las apps que pertenecen a la cuenta de usuario anterior. El acceso a la cámara se limita a perfiles de usuario que pertenezcan al usuario actual del dispositivo. En la práctica, esto significa que una cuenta de "invitado", por ejemplo, no podrá salir de procesos en ejecución que usen el subsistema de la cámara cuando el usuario haya cambiado a una cuenta diferente.
Tiempo de ejecución
El entorno de ejecución de ART ahora implementa correctamente reglas de acceso para el método newInstance()
. Este cambio soluciona un problema por el que Dalvik comprobaba las reglas de acceso de forma incorrecta en versiones anteriores.
Si tu app usa el método newInstance()
y deseas anular las verificaciones de acceso, llama al método setAccessible()
con el parámetro de entrada configurado en true
. Si tu app usa la biblioteca appcompat v7 o la biblioteca recyclerview v7, debes actualizarla para usar las versiones más recientes de estas bibliotecas. De lo contrario, asegúrate de que las clases personalizadas a las que se haga referencia desde el XML estén actualizadas para que se pueda acceder a sus constructores de clases.
En esta versión se actualiza el comportamiento del vinculador dinámico. El vinculador dinámico ahora entiende la diferencia entre soname
de una biblioteca y su ruta de acceso (
error público 6670), y ahora se implementa la búsqueda por soname
. Las apps que anteriormente funcionaban y que tenían entradas DT_NEEDED
incorrectas (por lo general, rutas de acceso absolutas en el sistema de archivos de la máquina de compilación) pueden fallar cuando se cargan.
Se implementó correctamente la marca dlopen(3) RTLD_LOCAL
. Ten en cuenta que RTLD_LOCAL
es el valor predeterminado, por lo que se verán afectadas las llamadas a dlopen(3)
que no usaron RTLD_LOCAL
de forma explícita (a menos que tu app use RTLD_GLOBAL
de manera explícita). Con RTLD_LOCAL
, los símbolos no estarán disponibles para las bibliotecas cargadas por llamadas posteriores a dlopen(3)
(a diferencia de lo que sucede con las entradas DT_NEEDED
).
En versiones anteriores de Android, si tu app solicitaba al sistema que cargara una biblioteca compartida con reubicaciones de texto, el sistema mostraba una advertencia, pero permitía que se cargara la biblioteca.
A partir de esta versión, el sistema rechaza esta biblioteca si la versión del SDK de destino de tu app es la 23 o una posterior. Para ayudarte a detectar si una biblioteca no se pudo cargar, tu app debe registrar el error de dlopen(3)
e incluir el texto de descripción del problema que muestra la llamada dlerror(3)
. Si deseas obtener más información sobre cómo controlar las reubicaciones de texto, consulta esta guía.
Validación de APK
Ahora la plataforma realiza validaciones más estrictas de APK. Un APK se considera dañado si se declara un archivo en el manifiesto, pero no está presente en el APK en sí. Si se quita contenido, se debe volver a firmar el APK.
Conexión USB
Las conexiones del dispositivo a través del puerto USB ahora están configuradas de manera predeterminada para el modo de solo carga. Para acceder al dispositivo y a su contenido por conexión USB, los usuarios deben otorgar permiso explícitamente para tales interacciones. Si tu app admite interacciones del usuario con el dispositivo a través de un puerto USB, ten en cuenta que la interacción debe habilitarse de manera explícita.
Cambios en Android for Work
En esta versión se incluyen los siguientes cambios en los comportamientos para Android for Work:
- Contactos de trabajo en contextos personales El registro de llamadas de Google Dialer ahora muestra los contactos de trabajo cuando el usuario ve las llamadas anteriores.
Si estableces
setCrossProfileCallerIdDisabled()
comotrue
, se ocultarán los contactos del perfil de trabajo en el registro de llamadas de Google Dialer. Los contactos de trabajo se pueden mostrar junto con los contactos personales en los dispositivos a través de Bluetooth solo si configurassetBluetoothContactSharingDisabled()
comofalse
. De forma predeterminada, se establece entrue
. - Eliminación de la configuración de Wi-Fi: Las configuraciones de Wi-Fi agregadas por un propietario de perfil (por ejemplo, mediante llamadas al método
addNetwork()
) ahora se quitan si se borra ese perfil de trabajo. - Bloqueo de configuración de Wi-Fi: El usuario ya no puede modificar ni borrar la configuración de Wi-Fi creada por un propietario activo del dispositivo si
WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN
no es cero. El usuario aún puede crear y modificar sus propias configuraciones de Wi-Fi. Los propietarios activos del dispositivo tienen el privilegio de editar o quitar configuraciones de Wi-Fi, incluidas las que no hayan creado. - Adición del controlador de política del dispositivo mediante la incorporación de la Cuenta de Google: Cuando se agrega una Cuenta de Google que requiere administración a través de la app de un controlador de política de dispositivo (DPC) a un dispositivo fuera de un contexto administrado, el flujo de incorporación de cuentas ahora le solicita al usuario que instale el WPC correspondiente. Este comportamiento también se aplica a las cuentas agregadas mediante Configuración > Cuentas y en el asistente de configuración inicial del dispositivo.
- Cambios en comportamientos específicos de la API de
DevicePolicyManager
:- Llamar al método
setCameraDisabled()
afecta solo a la cámara del usuario que lo llama. Llamarlo desde el perfil administrado no afecta a las apps de cámara que se ejecutan en el usuario principal. - Además, el método
setKeyguardDisabledFeatures()
ahora está disponible para los propietarios de perfiles y de dispositivos. - Un propietario de perfil puede configurar estas restricciones de protección de seguridad:
KEYGUARD_DISABLE_TRUST_AGENTS
yKEYGUARD_DISABLE_FINGERPRINT
, que afectan la configuración de protección de seguridad del usuario superior del perfil.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS
, que solo afecta las notificaciones que generan las aplicaciones en el perfil administrado.
- Los métodos
DevicePolicyManager.createAndInitializeUser()
yDevicePolicyManager.createUser()
dejaron de estar disponibles. - El método
setScreenCaptureDisabled()
ahora también bloquea la estructura de asistencia cuando una app del usuario determinado se ejecuta en primer plano. EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
ahora se establece de forma predeterminada en SHA-256. SHA-1 es todavía compatible con versiones anteriores, pero se quitará en el futuro.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM
ahora solo acepta SHA-256.- Las API de inicializador de dispositivo que existían en Android 6.0 (nivel de API 23) ahora se han quitado.
- Se quitó
EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS
, por lo que el aprovisionamiento de transmisión de NFC no puede desbloquear de manera programática un dispositivo protegido con restablecimiento de la configuración de fábrica. - Ahora puedes usar el extra
EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE
para pasar datos a la app del propietario del dispositivo durante el aprovisionamiento de NFC del dispositivo administrado. - Las API de Android for Work están optimizadas para los permisos de tiempo de ejecución de M, lo que incluye los perfiles de trabajo, la capa de asistencia y otros. Las nuevas APIs de permisos
DevicePolicyManager
no afectan a las apps anteriores a M. - Cuando los usuarios cancelan la parte síncrona del flujo de configuración que se inició a través de un intent
ACTION_PROVISION_MANAGED_PROFILE
oACTION_PROVISION_MANAGED_DEVICE
, el sistema ahora muestra un código de resultadoRESULT_CANCELED
.
- Llamar al método
- Cambios en otras APIs:
- Uso de datos: Se cambió el nombre de la clase
android.app.usage.NetworkUsageStats
aNetworkStats
.
- Uso de datos: Se cambió el nombre de la clase
- Cambios en la configuración global:
- Esta configuración ya no se puede establecer mediante
setGlobalSettings()
:BLUETOOTH_ON
DEVELOPMENT_SETTINGS_ENABLED
MODE_RINGER
NETWORK_PREFERENCE
WIFI_ON
- Esta configuración global ahora se puede establecer con
setGlobalSettings()
:
- Esta configuración ya no se puede establecer mediante