Android 4.2 API

Nivel de API: 17

Android 4.2 (JELLY_BEAN_MR1) es una actualización del lanzamiento de Jelly Bean que ofrece nuevas funciones a los usuarios desarrolladores. Este documento proporciona una introducción a los conceptos más destacados APIs nuevas y útiles para desarrolladores.

Como desarrollador de aplicaciones, debes descargar la imagen del sistema Android 4.2 y la plataforma SDK desde SDK Manager lo antes posible. Si no tienes un dispositivo con Android 4.2 en el cual probar la app, usa el sistema Android 4.2 para probar la app en el emulador de Android. Luego, compila tus apps con la plataforma Android 4.2 para comenzar a usar las APIs más recientes.

Para optimizar mejor tu app para dispositivos con Android 4.2, haz lo siguiente: Debes configurar tu targetSdkVersion como "17", instálala en una imagen del sistema Android 4.2 probarlo y, luego, publicar una actualización con este cambio.

Tú puedes usar APIs en Android 4.2 y, al mismo tiempo, admitir versiones anteriores agregando condiciones a tu código que comprueben el nivel de API del sistema antes de la ejecución APIs no compatibles con tu minSdkVersion. Para obtener más información mantener la retrocompatibilidad, lee Cómo crear retrocompatibilidad más recientes.

Puedes encontrar más información sobre el funcionamiento de los niveles de API en Qué es la API nivel?

Importantes cambios en los comportamientos

Si publicaste anteriormente una app para Android, ten en cuenta lo siguiente: cambios que podrían afectar el comportamiento de tu app:

  • Los proveedores de contenido ya no se exportan de forma predeterminada. Es decir, el valor predeterminado del atributo android:exported ahora es “false". Si es importante que otras apps acceder a tu proveedor de contenido, ahora debes configurar android:exported="true" de forma explícita.

    Este cambio solo se aplica si estableces android:targetSdkVersion o android:minSdkVersion en 17 o un valor superior. De lo contrario, el valor predeterminado sigue siendo “true". incluso con Android 4.2 y versiones posteriores.

  • En comparación con versiones anteriores de Android, los resultados de la ubicación del usuario pueden ser menos precisos. si tu app solicita el permiso ACCESS_COARSE_LOCATION, pero no solicita el permiso ACCESS_FINE_LOCATION.

    Para cumplir con las expectativas de privacidad de los usuarios cuando la app solicita permiso para lo siguiente: ubicación aproximada (y no precisa), el sistema no proporcionará una estimación de la ubicación del usuario que es más preciso que una manzana.

  • Algunos parámetros de configuración del dispositivo definidos por Settings.System ahora son son de solo lectura. Si tu app intenta escribir cambios en la configuración definida en Settings.System que se movieron a Settings.Global, ocurrirá lo siguiente: La operación de escritura fallará silenciosamente cuando se ejecute en Android 4.2 y versiones posteriores.

    Incluso si el valor para android:targetSdkVersion y android:minSdkVersion es inferior a 17, la app no podrá modificar los parámetros Se trasladó a Settings.Global cuando se ejecuta en Android 4.2 y versiones posteriores.

  • Si tu app usa WebView, Android 4.2 agrega una capa adicional de para que puedas vincular JavaScript a tu Código de Android Si estableces targetSdkVersion a 17 o versiones posteriores, ahora debes agregar la anotación @JavascriptInterface a cualquier método que estén disponibles para tu JavaScript (el método también debe ser público). Si no proporcionas la anotación, no se puede acceder al método desde una página web en tu WebView cuando se ejecuta en Android 4.2 o versiones posteriores. Si estableces targetSdkVersion a 16 o menos, la anotación no es obligatoria, pero te recomendamos que actualices la versión de destino y agrega la anotación para mayor seguridad.

    Más información sobre la vinculación Código JavaScript a código de Android.

Daydream

Daydream es un nuevo modo de protector de pantalla interactivo para dispositivos Android. Se activa automáticamente Cuando el dispositivo se inserta en un conector o cuando el dispositivo permanece inactivo mientras está conectado a una (en lugar de apagar la pantalla). Daydream muestra un sueño a la vez, lo que puede ser una pantalla puramente visual y pasiva que se descarta con el tacto o puede ser interactiva y responsiva al kit completo de eventos de entrada. Tus sueños se desarrollan en el proceso de tu app y tienen acceso completo a el kit de herramientas de IU de Android, que incluye vistas, diseños y animaciones, para que sean más flexibles y potentes que los fondos de pantalla animados o los widgets de apps.

Puedes crear un sueño para Daydream implementando una subclase de DreamService. Las APIs de DreamService son diseñados para ser similares a los de Activity. Para especificar la IU de tu pasar un ID de recurso de diseño o View a setContentView() en cualquier momento después de una ventana, como onAttachedToWindow() devolución de llamada.

La clase DreamService proporciona otra devolución de llamada importante del ciclo de vida. sobre las APIs de Service base, como onDreamingStarted(), onDreamingStopped() y onDetachedFromWindow(). No puedes iniciar una DreamService desde tu la aplicación, el sistema la inicia automáticamente.

Si tu sueño es interactivo, puedes iniciar una actividad desde el sueño para enviar al usuario la IU completa de tu app para obtener más detalles o control. Puedes usar finish() para finalizar el sueño, de modo que el usuario pueda ver el actividad nueva.

Para que tu daydream esté disponible para el sistema, declara tu DreamService con un elemento <service>. en tu archivo de manifiesto. Luego, debes incluir un filtro de intents con la acción "android.service.dreams.DreamService". Por ejemplo:

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

Existen otros métodos útiles en DreamService debes tener en cuenta:

  • setInteractive(boolean) controla si El sueño recibe eventos de entrada o sale inmediatamente después de la entrada del usuario. Si el sueño es interactivo, el usuario puede usar los botones Atrás o Inicio para salir del sueño o puedes llamar finish() para detener el sueño.
  • Si quieres una pantalla completamente envolvente, puedes llamar a setFullscreen() para ocultar la barra de estado.
  • Antes de que se inicie el protector de pantalla interactivo, la pantalla se atenúa para indicarle al usuario que el tiempo de espera de inactividad se acerca. Llamar a setScreenBright(true) te permite configurar la pantalla con el brillo habitual.

Para obtener más información, consulta la documentación de DreamService.

Pantallas secundarias

Android ahora permite que tu app muestre contenido único en pantallas adicionales que están conectadas al dispositivo del usuario a través de una conexión con cable o Wi-Fi. Si quieres crear contenido único para una pantalla secundaria, extiende Presentation e implementar la devolución de llamada onCreate(). En un radio de onCreate(), especifica la IU para la pantalla secundaria llamando a setContentView(). Como una extensión de la clase Dialog, la clase Presentation proporciona la región en la que tu app puede mostrar una IU única en la pantalla secundaria.

Para detectar pantallas secundarias en las que puedes mostrar tu Presentation, usa DisplayManager o MediaRouter. APIs Si bien las APIs de DisplayManager te permiten enumerar varias pantallas que pueden conectarse a la vez, por lo general, debes usar MediaRouter en su lugar para acceder rápidamente a la pantalla predeterminada del sistema para presentaciones.

Para obtener la pantalla predeterminada de tu presentación, llama a MediaRouter.getSelectedRoute() y pásala ROUTE_TYPE_LIVE_VIDEO Se mostrará un objeto MediaRouter.RouteInfo que describe la ruta seleccionada actualmente del sistema. para las presentaciones en video. Si MediaRouter.RouteInfo no es nulo, llama a getPresentationDisplay() para obtener el Display que representa la pantalla conectada.

Luego, puedes mostrar tu presentación pasando el objeto Display. a un constructor para la clase Presentation. Ahora, tu presentación en la pantalla secundaria.

Para detectar durante el tiempo de ejecución cuando se conecta una pantalla nueva, crea una instancia de MediaRouter.SimpleCallback en la que implementes el método de devolución de llamada onRoutePresentationDisplayChanged(), al que el sistema llamará cuando se cree una nueva la pantalla de presentación esté conectada. Luego, registra el MediaRouter.SimpleCallback pasándolo a MediaRouter.addCallback() junto con el tipo de ruta ROUTE_TYPE_LIVE_VIDEO. Cuando recibes una llamada a onRoutePresentationDisplayChanged(), simplemente llama a MediaRouter.getSelectedRoute() como se mencionó anteriormente.

Para optimizar aún más la IU en tu Presentation para pantallas secundarias, puedes aplicar un tema diferente especificando el atributo android:presentationTheme en el <style> que aplicarse a tu aplicación o actividad.

Ten en cuenta que las pantallas conectadas al dispositivo del usuario suelen tener un tamaño de pantalla más grande y probablemente una densidad de pantalla diferente. Debido a que las características de la pantalla pueden ser diferentes, debes proporcionan recursos optimizados específicamente para pantallas más grandes. Si necesitas Para solicitar recursos adicionales de tu Presentation, llama a getContext().getResources() para obtener el objeto Resources correspondiente a la pantalla. Esto proporciona para conocer los recursos adecuados de tu app la densidad y el tamaño de la pantalla secundaria.

Para obtener más información y algunas muestras de código, consulta el archivo Presentation. la documentación de la clase.

Widgets de pantalla de bloqueo

Android ahora permite a los usuarios agregar widgets de apps a la pantalla de bloqueo. Para que el widget de la app esté disponible en la pantalla de bloqueo, agrega el atributo android:widgetCategory a tu archivo en formato XML que especifica el AppWidgetProviderInfo. Este atributo admite dos valores: home_screen y keyguard. De forma predeterminada, el atributo se establece en home_screen para que los usuarios puedan agregar tu widget de la app en la pantalla principal. Si quieres que el widget de la app también esté disponible en la cerradura pantalla, agrega el valor keyguard:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

También debes especificar un diseño inicial para el widget de tu app en la pantalla de bloqueo con el atributo android:initialKeyguardLayout. Funciona de la misma manera que android:initialLayout, en el sentido de que proporciona un diseño que pueda aparecer de inmediato hasta que se inicialice el widget de tu app y pueda actualizar el .

Obtén más información sobre cómo crear widgets de apps para la pantalla de bloqueo, incluso para ajusta el tamaño del widget de tu app cuando está en la pantalla de bloqueo, consulta la guía Widgets de apps.

Varios usuarios

Android ahora permite múltiples espacios de usuario en dispositivos que se pueden compartir, como tablets. Cada usuario en un dispositivo cuenta con su propio conjunto de cuentas, aplicaciones, configuración del sistema, archivos y cualquier otro asociados con el usuario.

Como desarrollador, no necesitas hacer nada diferente para que tu app funcione correctamente con varios usuarios en un solo dispositivo. Independientemente de la cantidad de usuarios que puedan existir en un dispositivo, los datos que guarda tu app para un usuario determinado se mantienen separados de los datos que guarda tu app para otros usuarios. El sistema lleva un registro de qué datos del usuario pertenecen al proceso del usuario en el que que tu app se esté ejecutando y le proporcione acceso solo a los datos de ese usuario; no permite el acceso a los datos de otros usuarios.

Guarda datos en un entorno multiusuario

Siempre que tu app guarde las preferencias del usuario, cree una base de datos o escriba un archivo en la en un espacio de almacenamiento interno o externo, solo se podrá acceder a esos datos mientras se ejecuten como ese usuario.

Para asegurarte de que tu app se comporte correctamente en un entorno multiusuario, no consultes tu directorio interno de la app o ubicación de almacenamiento externo por medio de rutas hard-coded y, en su lugar, usar siempre las APIs adecuadas:

Independientemente de cuál de estas APIs uses para guardar datos de un usuario determinado, los datos no se y accesibles mientras se ejecuta como un usuario diferente. Desde el punto de vista de tu app, cada usuario ejecuta en un dispositivo completamente independiente.

Identifica usuarios en un entorno multiusuario

Si tu app quiere identificar usuarios únicos, por ejemplo, para recopilar estadísticas o crear otra cuenta asociaciones, debes seguir las prácticas recomendadas para identificar instalaciones únicas. Si creas un nuevo elemento UUID cuando se inicie tu app para la primera vez, se asegurará de obtener un ID único para realizar el seguimiento de cada usuario, independientemente de la usuarios instalan tu app en un solo dispositivo. También puedes guardar un token local recuperado de tu servidor o usa el ID de registro que proporciona Google Cloud Messaging.

Ten en cuenta que si tu app solicita uno de los identificadores de dispositivos de hardware (como el identificador de MAC de Wi-Fi dirección IP o el número de SERIAL), proporcionarán el mismo valor para cada usuario porque estos identificadores están vinculados al hardware y no al usuario. Sin mencionar el otro los problemas que introducen estos identificadores, como se explica en el artículo Cómo identificar Entrada de blog sobre instalaciones de aplicaciones

Nueva configuración global

Se actualizó la configuración del sistema para admitir varios usuarios, además de Settings.Global. Este conjunto de parámetros de configuración es similar a los de Settings.Secure porque son de solo lectura, pero se aplican globalmente en a todos los espacios de usuario del dispositivo.

Varios parámetros de configuración existentes se trasladaron aquí, ya sea de Settings.System o Settings.Secure. Si tu app es se están realizando cambios en la configuración definida anteriormente en Settings.System (como AIRPLANE_MODE_ON), debes esperar que ya no funcionará en un dispositivo con Android 4.2 o superior si esos parámetros se movió a Settings.Global. Puedes seguir leyendo la configuración que se encuentra en Settings.Global, pero debido a que la configuración ya no se considera segura para que las apps cambien, intentar hacerlo fallará silenciosamente y el sistema escribirá una advertencia a el registro del sistema cuando ejecutas tu app en Android 4.2 o versiones posteriores.

Compatibilidad con el diseño RTL

Android ahora ofrece varias APIs que te permiten compilar interfaces de usuario que Transformar la orientación del diseño para admitir idiomas que utilizan IU de derecha a izquierda (RTL) y lectura específica, como el árabe y el hebreo.

Para comenzar a admitir diseños de derecha a izquierda en tu app, establece el atributo android:supportsRtl en el elemento <application> del archivo de manifiesto y configúrala como “true". Cuando habilites esto, el sistema habilitará varias APIs de RTL para mostrará tu app con diseños RTL. Por ejemplo, la barra de acciones mostrará el ícono y el título. a la derecha y los botones de acción a la izquierda, y cualquier diseño que hayas creado con el También se revertirán las clases View proporcionadas por el framework.

Si necesitas optimizar aún más la apariencia de tu app cuando se muestra con un diseño RTL, existen dos niveles básicos de optimización:

  1. Convierte las propiedades de diseño orientadas a la izquierda y la derecha en un diseño orientado al inicio y al final propiedades.

    Por ejemplo, usa android:layout_marginStart. en lugar de android:layout_marginLeft y android:layout_marginEnd en lugar de android:layout_marginRight.

    La clase RelativeLayout también proporciona el diseño correspondiente. atributos para reemplazar las posiciones izquierda y derecha, como android:layout_alignParentStart para reemplazar android:layout_alignParentLeft y android:layout_toStartOf en lugar de android:layout_toLeftOf

  2. O bien, para proporcionar una optimización completa para los diseños RTL, puedes proporcionar instrucciones completamente separadas archivos de diseño que usan el calificador de recursos ldrtl (ldrtl significa diseño-dirección-de-derecha a izquierda}). Por ejemplo, puedes guardar los archivos de diseño predeterminados en res/layout/ y tus diseños optimizados con RTL en res/layout-ldrtl/.

    El calificador ldrtl es excelente para recursos de elementos de diseño, de modo que puedes gráficos que se orientan en la dirección correspondiente a la dirección de lectura.

Hay varias otras APIs disponibles en el framework para admitir diseños RTL, como en la clase View, de modo que puedas implementar los comportamientos adecuados para los eventos y en Configuration para consultar la dirección del diseño actual.

Nota: Si usas SQlite y los nombres de las tablas o columnas son "solo números", de ten cuidado: usar String.format(String, Object...) puede generar errores en los que los números se hayan convertido a sus equivalentes árabes si el dispositivo está configurado en la configuración regional árabe. Debes usar String.format(Locale,String,Object...) para asegurarte de que los números estén se conserva como ASCII. También debes usar String.format("%d", int) en lugar de String.valueOf(int) para dar formato a los números.

Fragmentos anidados

Ahora puedes incorporar fragmentos dentro de fragmentos. Esto es útil para varias situaciones en en la que colocar componentes de la IU dinámicos y reutilizables en un componente de IU que sea dinámicos y reutilizables. Por ejemplo, si usas ViewPager para crear fragmentos que se puedan deslizar hacia la izquierda y la derecha, y ocupen la mayor parte del espacio de la pantalla, puedes ahora insertar fragmentos en cada página de fragmento.

Para anidar un fragmento, simplemente llama a getChildFragmentManager() en el Fragment en el que quieres agregar un fragmento. Se mostrará un FragmentManager que puedes usar como lo haces normalmente desde la actividad de nivel superior. para crear transacciones de fragmentos. Por ejemplo, aquí tienes código que agrega un fragmento desde adentro una clase Fragment existente:

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

Desde dentro de un fragmento anidado, puedes obtener una referencia al fragmento superior llamando getParentFragment()

La biblioteca de compatibilidad de Android ahora también admite fragmentos anidados, por lo que puedes implementar de fragmentos en Android 1.6 y versiones posteriores.

Nota: No puedes aumentar un diseño en un fragmento cuando ese diseño incluye un <fragment>. Los fragmentos anidados solo se admiten cuando se agregan a un fragmentos de manera dinámica.

RenderScript

Se mejoró la funcionalidad de procesamiento de Renderscript con las siguientes características:

Funciones intrínsecas de secuencias de comandos

Puedes usar las funciones intrínsecas de secuencias de comandos integradas de Renderscript para implementar operaciones comunes para ti, como las siguientes:

Para usar una secuencia de comandos intrínseca, llama al método estático create() de cada elemento intrínseco. para crear una instancia de la secuencia de comandos. Luego, llamarás al set() disponible de cada secuencia de comandos intrínseca para configurar las entradas y opciones necesarias. Por último, llama a forEach(). para ejecutar la secuencia de comandos.

Grupos de secuencias de comandos

Los elementos ScriptGroup te permiten encadenar los RenderScript relacionados. de comandos de shell y ejecutarlas con una llamada.

Usa un ScriptGroup.Builder para agregar todas las secuencias de comandos al grupo. llamando a addKernel(). Una vez que agregar todas las secuencias de comandos, crear las conexiones entre de comandos llamando a addConnection(). Cuando termines de agregar las conexiones, llama a create() para crear el grupo de secuencias de comandos. Antes de ejecutar el grupo de secuencias de comandos, especifica la entrada Allocation y la secuencia de comandos inicial que se ejecutarán con el setInput(Script.KernelID, Allocation) y proporcionará el resultado Allocation donde se escribirá el resultado y la secuencia de comandos final para se ejecuta con setOutput(). Por último, llama execute() para ejecutar el grupo de secuencias de comandos.

Filterscript

Filterscript define restricciones en las APIs de Renderscript existentes que permiten que se ejecute el código resultante. en una variedad más amplia de procesadores (CPU, GPU y DSP). Para crear archivos de Filterscript, crea .fs. en lugar de archivos .rs, y especifica #pragma rs_fp_relaxed como Indícale al entorno de ejecución de Renderscript que tus secuencias de comandos no requieren una precisión estricta de punto flotante IEEE 754-2008. Esta precisión permite el vaciado a cero para denormales y el redondeo a cero. Además, tu elemento Filterscript Las secuencias de comandos no deben usar tipos integrados de 32 bits y deben especificar una función raíz personalizada usando el atributo __attribute__((kernel)) porque Filterscript no admite punteros, lo cual la firma predeterminada de la función root() define.

Nota: Si bien la compatibilidad de Filterscript está en la plataforma, el desarrollador asistencia estará disponible en la versión 21.0.1 de las herramientas del SDK.

Para obtener una vista detallada de todos los cambios de API en Android 4.2, consulta la Informe de diferencias de las APIs.