docs: Removing Android dev docs from Gerrit

Android developer docs are now maintained in Piper, go/dac-source

Removing all files from Gerrit, since these files can cause build
errors if they refer to classes that are later removed (whence
bug b/35849713 ).

Gerrit already has readme files in these directories telling people
docs are not maintained here; these readmes will be a lot easier to
spot now.

Ran a doc build with these files deleted, and it seems to work fine,
so submitting this CL *shouldn't* break anything.

Merged to master to resolve conflict.
Merged-In: Ic74c3f97f9620daf23543930a8b7ed1386f4d172

Bug: 35849713
Change-Id: I5331cdc968be817ff70ba32dd03fce76493a6ab8
This commit is contained in:
Andrew Solovay
2017-03-08 17:38:01 -08:00
parent 89d2b46a4a
commit ecf817682a
8079 changed files with 0 additions and 2051118 deletions

View File

@@ -1,635 +0,0 @@
page.title=API de Android 5.0
excludeFromSuggestions=true
sdk.platform.version=5.0
sdk.platform.apiLevel=21
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>En este documento <a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle"> <span class="more">mostrar más</span> <span class="less" style="display:none">mostrar menos</span></a></h2>
<ol id="toc44" class="hide-nested">
<li><a href="#ApiLevel">Actualiza el nivel de la API de destino</a></li>
<li><a href="#Behaviors">Cambios importantes de comportamiento</a>
<ol>
<li><a href="#ART">Si no probaste la aplicación con el nuevo Android Runtime (ART)…</a></li>
<li><a href="#BehaviorNotifications">Si la aplicación implementa notificaciones…</a></li>
<li><a href="#BehaviorMediaControl">Si la aplicación usa RemoteControlClient…</a></li>
<li><a href="#BehaviorGetRecentTasks">Si la aplicación usa getRecentTasks()…</a></li>
<li><a href="#64BitSupport">Si usas el kit de desarrollo nativo (NDK) de Android…</a></li>
<li><a href="#BindService">Si la aplicación se vincula a un servicio…</a></li>
<li><a href="#BehaviorWebView">Si la aplicación usa WebView…</a></li>
</ol>
</li>
<li><a href="#UI">Interfaz de usuario</a>
<ol>
<li><a href="#MaterialDesign">Compatibilidad con diseño de materiales</a></li>
<li><a href="#Recents">Documentos y actividades concurrentes en la pantalla de actividades y tareas recientes</a></li>
<li><a href="#WebView">Actualizaciones de WebView</a></li>
<li><a href="#ScreenCapture">Captura y uso compartido de pantalla</a></li>
</ol>
</li>
<li><a href="#Notifications">Notificaciones</a>
<ol>
<li><a href="#LockscreenNotifications">Notificaciones de pantalla bloqueada</a></li>
<li><a href="#NotificationsMetadata">Metadatos de notificaciones</a></li>
</ol>
</li>
<li><a href="#Graphics">Gráficos</a>
<ol>
<li><a href="#OpenGLES-3-1">Compatibilidad con OpenGL ES 3.1</a></li>
<li><a href="#AndroidExtensionPack">Android Extension Pack</a></li>
</ol>
</li>
<li><a href="#Media">Medios</a>
<ol>
<li><a href="#Camera-v2">API de cámara para capacidades avanzadas de la cámara</a></li>
<li><a href="#AudioPlayback">Reproducción de audio</a></li>
<li><a href="#MediaPlaybackControl">Control de reproducción de medios</a></li>
<li><a href="#MediaBrowsing">Exploración de medios</a></li>
</ol>
</li>
<li><a href="#Storage">Almacenamiento</a>
<ol>
<li><a href="#DirectorySelection">Selección de directorio</a></li>
</ol>
</li>
<li><a href="#Wireless">Redes inalámbricas y conectividad</a>
<ol>
<li><a href="#Multinetwork">Múltiples conexiones de red</a></li>
<li><a href="#BluetoothBroadcasting">Emisión de Bluetooth</a></li>
<li><a href="#NFCEnhancements">Mejoras de NFC</a></li>
</ol>
</li>
<li><a href="#Power">Proyecto Volta</a>
<ol>
<li><a href="#JobScheduler">Programación de trabajos</a></li>
<li><a href="#PowerMeasurementTools">Herramientas de programadores para el uso de la batería</a>
</ol>
</li>
<li><a href="#Enterprise">Android en el entorno de trabajo y en el entorno educativo</a>
<ol>
<li><a href="#ManagedProvisioning">Aprovisionamiento administrado</a></li>
<li><a href="#DeviceOwner">Propietario de dispositivo</a></li>
<li><a href="#ScreenPinning">Fijación de pantalla</a></li>
</ol>
</li>
<li><a href="#System">Sistema</a>
<ol>
<li><a href="#AppUsageStatistics">Estadísticas de uso de aplicaciones</a></li>
</ol>
</li>
<li><a href="#Printing">Marco de impresión</a>
<ol>
<li><a href="#PDFRender">Representación de PDF como mapa de bits</a></li>
</ol>
</li>
<li><a href="#TestingA11y">Pruebas y accesibilidad</a>
<ol>
<li><a href="#TestingA11yImprovements">Mejoras de pruebas y accesibilidad</a></li>
</ol>
</li>
<li><a href="#IME">IME</a>
<ol>
<li><a href="#Switching">Cambio más sencillo de idiomas de entrada</a></li>
</ol>
</li>
<li><a href="#Manifest">Declaraciones de manifiesto</a>
<ol>
<li><a href="#ManifestFeatures">Características requeridas declarables</a></li>
<li><a href="#Permissions">Permisos de usuario</a></li>
</ol>
</li>
</ol>
<h2>API Differences</h2>
<ol>
<li><a href="{@docRoot}sdk/api_diff/21/changes.html">API level 20 to 21 &raquo;</a> </li>
<li><a href="{@docRoot}sdk/api_diff/preview-21/changes.html">L Developer Preview to 21 &raquo;</a> </li>
</ol>
<h2>See Also</h2>
<ol>
<li><a href="{@docRoot}about/versions/android-5.0-changes.html">Android 5.0 Behavior Changes</a> </li>
<li><a href="{@docRoot}about/versions/lollipop.html">Android Lollipop Highlights</a> </li>
</ol>
</div>
</div>
<p>Nivel de API: {@sdkPlatformApiLevel}</p>
<p>Android 5.0 (<a href="{@docRoot}reference/android/os/Build.VERSION_CODES.html#LOLLIPOP">LOLLIPOP</a>) ofrece nuevas funciones para los usuarios y los programadores de aplicaciones. En este documento, se proporciona una introducción a las API nuevas más destacadas.</p>
<p>Para conocer con más detalle las nuevas funciones de la plataforma, consulta los <a href="{@docRoot}about/versions/lollipop.html">Aspectos destacados de Android Lollipop</a>.</p>
<h3 id="Start">Empieza a programar</h3>
<p>Si deseas empezar a crear aplicaciones para Android 5.0, primero debes <a href="{@docRoot}sdk/index.html">obtener el SDK de Android</a>. Luego, usa el <a href="{@docRoot}tools/help/sdk-manager.html">Administrador de SDK</a> para descargar las imágenes del sistema y la plataforma de SDK de Android 5.0.</p>
<h3 id="ApiLevel">Actualiza el nivel de la API de destino</h3>
<p>Si deseas optimizar de una mejor manera la aplicación para dispositivos que tienen Android {@sdkPlatformVersion}, establece <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> en <code>"{@sdkPlatformApiLevel}"</code>, instala la aplicación en una imagen del sistema de Android {@sdkPlatformVersion}, pruébala y luego publica la aplicación actualizada con este cambio.</p>
<p>Puedes usar API de Android {@sdkPlatformVersion}, además de admitir versiones anteriores, agregando condiciones al código que comprueban el nivel de la API del sistema antes de ejecutar API no admitidas por <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a>. Para obtener más información sobre el mantenimiento de la compatibilidad con versiones anteriores, consulta <a href="{@docRoot}training/basics/supporting-devices/platforms.html">Compatibilidad con versiones de plataforma diferentes</a>.</p>
<p>Para obtener más información sobre el funcionamiento de los niveles de API, consulta <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">¿Qué es un nivel de API?</a></p>
<h2 id="Behaviors">Cambios importantes de comportamiento</h2>
<p>Si publicaste previamente una aplicación para Android, ten en cuenta que la aplicación podría verse afectada por los cambios en Android 5.0.</p>
<h3 id="ART">Si no probaste la aplicación con el nuevo Android Runtime (ART)…</h3>
<p>La versión 4.4 introdujo un nuevo tiempo de ejecución experimental de Android, ART. En la versión 4.4, ART era opcional, y el tiempo de ejecución predeterminado seguía siendo Dalvik. Con Android 5.0, ART ahora es el tiempo de ejecución predeterminado.</p>
<p>Para obtener una descripción general de las nuevas funciones de ART, consulta <a href="https://source.android.com/devices/tech/dalvik/art.html">Introducción a ART</a>. Algunas de las principales funciones nuevas son las siguientes:</p>
<ul>
<li>compilación por adelantado (AOT);</li>
<li>recolección de basura (GC) mejorada;</li>
<li>compatibilidad con depuración mejorada.</li>
</ul>
<p>La mayoría de las aplicaciones de Android deberían funcionar sin ningún tipo de cambio en ART. Sin embargo, algunas de las técnicas que funcionan en Dalvik no funcionan en ART. Para obtener información sobre los problemas más significativos, consulta <a href="{@docRoot}guide/practices/verifying-apps-art.html">Verificación de comportamiento de aplicaciones en Android Runtime (ART)</a>. Presta especial atención en los siguientes casos:</p>
<ul>
<li>La aplicación usa Java Native Interface (JNI) para ejecutar el código C/C++.</li>
<li>Usas herramientas de programación que generan código no estándar (por ejemplo, algunos ofuscadores).</li>
<li>Usas técnicas que son incompatibles con la compactación de la recolección de basura. ART no implementa actualmente la compactación GC, pero esta función está en programación en el proyecto de código abierto de Android.</li>
</ul>
<h3 id="BehaviorNotifications">Si la aplicación implementa notificaciones…</h3>
<p>Asegúrate de que las notificaciones tengan en cuenta estos cambios de Android 5.0. Para obtener más información sobre el diseño de las notificaciones para Android 5.0 o versiones posteriores, consulta la <a href="{@docRoot}design/patterns/notifications.html">guía de diseño de notificaciones</a>.
</p>
<h4 id="NotificationsMaterialDesignStyle">Estilo de diseño de materiales</h4>
<p>Las notificaciones se crean con texto oscuro sobre fondo blanco (o muy claro) para que coincidan con los nuevos widgets de diseño de materiales. Asegúrate de que todas las notificaciones se vean bien con el nuevo esquema de colores. Si las notificaciones se ven mal, corrígelas:</p>
<ul>
<li>Usa {@link android.app.Notification.Builder#setColor(int) setColor()} para establecer un color de énfasis en un círculo detrás de la imagen del ícono. </li>
<li>Actualiza o elimina recursos que involucran color. El sistema ignora todos los canales no alfa en los íconos de acción y en el ícono de notificación principal. Debes asumir que estos íconos solo serán alfa. El sistema dibuja íconos de notificación en blanco e íconos de acción en gris oscuro.</li>
</ul>
<h4 id="NotificationsSoundVibration">Sonido y vibración</h4>
<p>Si actualmente estás agregando sonidos y vibraciones a las notificaciones mediante el uso de las clases {@link android.media.Ringtone}, {@link android.media.MediaPlayer} o {@link android.os.Vibrator}, elimina este código para que el sistema pueda presentar notificaciones de forma correcta en modo de <em>prioridad</em>. En su lugar, usa los métodos {@link android.app.Notification.Builder} para agregar sonidos y vibraciones.</p>
<p>Configurar el dispositivo en {@link android.media.AudioManager#RINGER_MODE_SILENT RINGER_MODE_SILENT} hace que el dispositivo pase al nuevo modo de prioridad. El dispositivo sale del modo de prioridad si lo estableces en {@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_NORMAL} o {@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_VIBRATE}.</p>
<p>Anteriormente, Android usaba {@link android.media.AudioManager#STREAM_MUSIC STREAM_MUSIC} como la secuencia maestra para controlar el volumen de las tablets. En Android 5.0, la secuencia maestra de volumen tanto para teléfonos como para tablets ahora está unificada y controlada por {@link android.media.AudioManager#STREAM_RING STREAM_RING} o {@link android.media.AudioManager#STREAM_NOTIFICATION STREAM_NOTIFICATION}.</p>
<h4 id="NotificationsLockscreenVisibility">Visibilidad de la pantalla bloqueada</h4>
<p>De forma predeterminada, las notificaciones ahora aparecen en la pantalla bloqueada del usuario en Android 5.0. Los usuarios pueden elegir proteger la información confidencial de dicha exposición, en cuyo caso el sistema redacta automáticamente el texto que aparece en la notificación. Para personalizar esta notificación redactada, usa {@link android.app.Notification.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}.</p>
<p>Si la notificación no contiene información personal o si deseas permitir el control de la reproducción de medios en la notificación, llama al método {@link android.app.Notification.Builder#setVisibility(int) setVisibility()} y establece el nivel de visibilidad de la notificación en {@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}.
</p>
<h4 id="NotificationsMediaPlayback">Reproducción de los medios</h4>
<p>Si implementas notificaciones que presentan controles de transporte o estado de reproducción de medios, considera el uso de la nueva plantilla {@link android.app.Notification.MediaStyle}, en lugar de un objeto {@link android.widget.RemoteViews.RemoteView} personalizado. Cualquiera sea el enfoque que elijas, asegúrate de establecer la visibilidad de la notificación en {@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC} a fin de que los controles estén accesibles desde la pantalla bloqueada. Ten en cuenta que, a partir de Android 5.0, el sistema ya no muestra objetos {@link android.media.RemoteControlClient} en la pantalla bloqueada. Para obtener más información, consulta <a href="#BehaviorMediaControl">Si la aplicación usa RemoteControlClient</a>.</p>
<h4 id="NotificationsHeadsup">Notificación de aviso</h4>
<p>Las notificaciones ahora pueden aparecer en una pequeña ventana flotante (también denominada notificación de aviso) cuando el dispositivo está activo (es decir, el dispositivo está desbloqueado y su pantalla está encendida). Estas notificaciones son similares a la forma compacta de tu notificación, salvo que la notificación de aviso también muestra los botones de acción. Los usuarios pueden actuar sobre una notificación de aviso o descartarla sin salir de la aplicación actual.</p>
<p>Algunos ejemplos de condiciones que pueden desencadenar notificaciones de aviso incluyen:</p>
<ul>
<li>La actividad del usuario está en modo de pantalla completa (la aplicación usa {@link android.app.Notification#fullScreenIntent}).</li>
<li>La notificación tiene alta prioridad y utiliza tonos o vibraciones.</li>
</ul>
<p>Si la aplicación implementa notificaciones en cualquiera de esos escenarios, asegúrate de que las notificaciones de aviso se presenten correctamente.</p>
<h3 id="BehaviorMediaControl">Si la aplicación usa RemoteControlClient…</h3>
<p>La clase {@link android.media.RemoteControlClient} ahora está obsoleta. Cambia a la nueva API {@link android.media.session.MediaSession} tan pronto como sea posible.</p>
<p>Las pantallas bloqueadas en Android 5.0 no muestran controles de transporte para {@link android.media.session.MediaSession} ni {@link android.media.RemoteControlClient}. En cambio, la aplicación puede proporcionar un control de la reproducción de los medios desde la pantalla bloqueada a través de una notificación. De este modo, la aplicación tiene un mayor control sobre la presentación de los botones de medios, al mismo tiempo que proporciona una experiencia uniforme para los usuarios a través de los dispositivos bloqueados y desbloqueados.</p>
<p>Android 5.0 introduce una nueva plantilla {@link android.app.Notification.MediaStyle} para este fin. {@link android.app.Notification.MediaStyle} convierte acciones de notificación que agregas con {@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence, android.app.PendingIntent) Notification.Builder.addAction()} en botones compactos integrados en las notificaciones de reproducción de medios de la aplicación. Pasa el token de sesión al método {@link android.app.Notification.MediaStyle#setMediaSession(android.media.session.MediaSession.Token) setSession()} para informar al sistema que esta notificación controla una sesión de medios en curso.</p>
<p>Asegúrate de establecer la visibilidad de la notificación en {@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC} para marcar la notificación como segura y mostrarla en cualquier pantalla bloqueada (segura o de otra manera). Para obtener más información, consulta <a href="#LockscreenNotifications">Notificaciones de pantalla bloqueada</a>.</p>
<p>Para mostrar los controles de reproducción de medios si la aplicación se está ejecutando en la plataforma de Android <a href="{@docRoot}tv/index.html">TV</a> o Android <a href="{@docRoot}wear/index.html">Wear</a>, implementa la clase {@link android.media.session.MediaSession}. También debes implementar {@link android.media.session.MediaSession} si la aplicación necesita recibir eventos de botones de medios en dispositivos Android.</p>
<h3 id="BehaviorGetRecentTasks">Si la aplicación usa getRecentTasks()…</h3>
<p>Con la introducción de la nueva función de <em>tareas de documentos y actividades concurrentes</em> en Android 5.0 (consulta <a href="#Recents">Documentos y actividades concurrentes en la pantalla de actividades y tareas recientes</a> a continuación), el método {@link android.app.ActivityManager#getRecentTasks ActivityManager.getRecentTasks()} ahora está obsoleto para mejorar la privacidad del usuario. En el caso de la compatibilidad con versiones anteriores, este método sigue devolviendo un pequeño subconjunto de sus datos, que incluye algunas tareas propias de la aplicación que llama y, posiblemente, algunas otras tareas no confidenciales (como Página principal). Si la aplicación usa este método para recuperar sus propias tareas, usa {@link android.app.ActivityManager#getAppTasks() getAppTasks()} en su lugar para recuperar esa información.</p>
<h3 id="64BitSupport">Si usas el kit de desarrollo nativo (NDK) de Android…</h3>
<p>Android 5.0 introduce compatibilidad con sistemas de 64 bits. La mejora de 64 bits aumenta el espacio de direcciones y mejora el rendimiento, al mismo tiempo que mantiene la compatibilidad absoluta con las aplicaciones de 32 bits existentes. La compatibilidad con 64 bits también mejora el rendimiento de OpenSSL para la criptografía. Además, esta versión introduce nuevas API de NDK de medios nativas, así como compatibilidad nativa con la OpenGL ES (GLES) 3.1.</p>
<p>Para usar la compatibilidad con 64 bits proporcionada en Android 5.0, descarga e instala la revisión 10c de NDK desde la <a href="{@docRoot}tools/sdk/ndk/index.html">página de NDK de Android</a>. Consulta las <a href="{@docRoot}tools/sdk/ndk/index.html#Revisions">notas de la versión</a> de la revisión 10c para obtener más información acerca de los cambios y las correcciones de errores importantes en el NDK.</p>
<h3 id="BindService">Si la aplicación se vincula a un servicio…</h3>
<p>El método {@link android.content.Context#bindService(android.content.Intent, android.content.ServiceConnection, int) Context.bindService()} ahora requiere un {@link android.content.Intent} explícito y genera una excepción si se realiza un intento implícito. Para asegurarte de que la aplicación sea segura, usa un intento explícito al iniciar o vincular tu {@link android.app.Service}, y no declares filtros de intención para el servicio.</p>
<h3 id="BehaviorWebView">Si la aplicación usa WebView…</h3>
<p>Android 5.0 cambia el comportamiento predeterminado de la aplicación.</p>
<ul>
<li><strong>Si la aplicación está destinada para el nivel de API 21 o un nivel posterior:</strong>
<ul>
<li>El sistema bloquea <a href="https://developer.mozilla.org/en-US/docs/Security/MixedContent" class="external-link">contenido mixto</a> y cookies de terceros de forma predeterminada. Para permitir contenido mixto y cookies de terceros, usa los métodos {@link android.webkit.WebSettings#setMixedContentMode(int) setMixedContentMode()} y {@link android.webkit.CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView, boolean) setAcceptThirdPartyCookies()}, respectivamente.</li>
<li>El sistema ahora elige inteligentemente partes del documento HTML para dibujar. Este nuevo comportamiento predeterminado ayuda a reducir la superficie de memoria y a aumentar el rendimiento. Si quieres representar todo el documento a la vez, inhabilita esta optimización llamando a {@link android.webkit.WebView#enableSlowWholeDocumentDraw()}.</li>
</ul>
</li>
<li><strong>Si la aplicación está destinada para los niveles de API anteriores a 21:</strong> El sistema permite contenido mixto y cookies de terceros, y siempre representa todo el documento a la vez.</li>
</ul>
<h2 id="UI">Interfaz de usuario</h2>
<h3 id="MaterialDesign">Compatibilidad con diseño de materiales</h3>
<p>La próxima versión agrega compatibilidad con el nuevo estilo de <em>diseño de materiales</em> de Android. Puedes crear aplicaciones con diseño de materiales que sean visualmente dinámicas y tengan transiciones de elementos de interfaz de usuario que parezcan reales para los usuarios. Esta compatibilidad incluye lo siguiente:</p>
<ul>
<li>tema de material;</li>
<li>sombras de vista;</li>
<li>widget {@link android.support.v7.widget.RecyclerView};</li>
<li>animación dibujable y efectos de estilo;</li>
<li>animación de diseño de materiales y efectos de transición de actividad;</li>
<li>animadores para propiedades de vista en función del estado de la vista;</li>
<li>widgets de interfaz de usuario personalizables y barras de aplicaciones con paletas de colores que se pueden controlar;</li>
<li>dibujables animados y no animados en función de gráficos con vectores XML.</li>
</ul>
<p>Para obtener más información sobre la adición de la funcionalidad de diseño de materiales a la aplicación, consulta <a href="{@docRoot}training/material/index.html">Diseño de materiales</a>.</p>
<h3 id="Recents">Documentos y actividades concurrentes en la pantalla de actividades y tareas recientes</h3>
<p>En versiones anteriores, la <a href="{@docRoot}guide/components/recents.html">pantalla de actividades y tareas recientes</a> solo podía mostrar una tarea para cada aplicación con la que el usuario había interaccionado recientemente. Si es necesario, ahora la aplicación puede abrir más tareas para actividades y documentos concurrentes adicionales. Esta función facilita la multitarea, ya que permite a los usuarios cambiar rápidamente entre las actividades y los documentos individuales de la pantalla de actividades y tareas recientes, y brinda una experiencia de cambio uniforme entre todas las aplicaciones. Algunos ejemplos de este tipo de tareas concurrentes pueden incluir pestañas abiertas en una aplicación de navegador web, documentos en una aplicación de productividad, partidos concurrentes en un juego o chats en una aplicación de mensajería. La aplicación puede administrar sus tareas a través de la clase {@link android.app.ActivityManager.AppTask}.</p>
<p>Para insertar un salto lógico a fin de que el sistema trate la actividad como una nueva tarea, usa {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} al iniciar la actividad con {@link android.app.Activity#startActivity(android.content.Intent) startActivity()}. También puedes obtener este comportamiento estableciendo el atributo {@code documentLaunchMode} del elemento de <a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;actividad&gt;</a> en {@code "intoExisting"} o {@code "always"} en tu manifiesto.</p>
<p>Para evitar la saturación de la pantalla de actividades y tareas recientes, puedes establecer la cantidad máxima de tareas de la aplicación que pueden aparecer en esa pantalla. Para hacerlo, establece el atributo {@link android.R.attr#maxRecents android:maxRecents} de la <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;aplicación&gt;</a>. La cantidad máxima actual que se puede especificar es de 50 tareas por usuario (25 para dispositivos con baja memoria RAM).</a></p>
<p>Las tareas en la pantalla de actividades y tareas recientes se pueden configurar para que se mantengan tras los reinicios. Para controlar el comportamiento de persistencia, usa el atributo <a href="{@docRoot}reference/android/R.attr.html#persistableMode">android:persistableMode</a>. También puedes cambiar las propiedades visuales de una actividad en la pantalla de actividades y tareas recientes, como el color, la etiqueta y el ícono de la actividad, llamando al método {@link android.app.Activity#setTaskDescription(android.app.ActivityManager.TaskDescription) setTaskDescription()}.</p>
<h3 id="WebView">Actualizaciones de WebView</h3>
<p>Android 5.0 actualiza la implementación de {@link android.webkit.WebView} a Chromium M37, que incorpora mejoras de seguridad y estabilidad, así como correcciones de errores. Se actualizó la cadena de usuario-agente predeterminada de una {@link android.webkit.WebView} que se ejecuta en Android 5.0 para incorporar 37.0.0.0 como el número de versión.</p>
<p>Esta versión introduce la clase {@link android.webkit.PermissionRequest}, que permite a la aplicación conceder el permiso {@link android.webkit.WebView} para acceder a los recursos protegidos, como la cámara y el micrófono, a través de las API web, como <a href="https://developer.mozilla.org/en-US/docs/NavigatorUserMedia.getUserMedia" class="external-link">getUserMedia()</a>. La aplicación debe tener los permisos apropiados de Android para estos recursos con el fin de otorgar los permisos a {@link android.webkit.WebView}.</p>
<p>Con el nuevo método <code><a href="{@docRoot}reference/android/webkit/WebChromeClient.html#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams)">onShowFileChooser()</a></code>, ahora puedes usar un campo de formulario de entrada en {@link android.webkit.WebView} y abrir un selector de archivos para seleccionar imágenes y archivos desde el dispositivo Android.</p>
<p>Además, esta versión admite los estándares abiertos <a href="http://webaudio.github.io/web-audio-api/" class="external-link">WebAudio</a>, <a href="https://www.khronos.org/webgl/" class="external-link">WebGL</a> y <a href="http://www.webrtc.org/" class="external-link">WebRTC</a>. Para obtener más información sobre las nuevas funciones incluidas en esta versión, consulta <a href="https://developer.chrome.com/multidevice/webview/overview" class="external-link">WebView para Android</a>.</p>
<h3 id="ScreenCapture">Captura y uso compartido de pantalla</h3>
<p>Android 5.0 permite agregar capacidades de captura y uso compartido de pantalla a la aplicación con las nuevas API {@link android.media.projection}. Esta funcionalidad es útil, por ejemplo, si quieres habilitar el uso compartido de la pantalla en una aplicación de videoconferencia.</p>
<p>El nuevo método {@link android.media.projection.MediaProjection#createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler) createVirtualDisplay()} permite que la aplicación capture el contenido de la pantalla principal (la pantalla predeterminada) en un objeto {@link android.view.Surface}, que luego la aplicación puede enviar a través de la red. La API solo permite capturar contenido de pantalla no seguro, y no audio del sistema. Para comenzar la captura de pantalla, la aplicación primero debe solicitar el permiso del usuario abriendo un cuadro de diálogo de captura de pantalla con un {@link android.content.Intent} obtenido a través del método {@link android.media.projection.MediaProjectionManager#createScreenCaptureIntent()}.</p>
<p>Para ver un ejemplo de cómo utilizar las nuevas API, consulta la clase {@code MediaProjectionDemo} en el proyecto de ejemplo.</p>
<h2 id="Notifications">Notificaciones</h2>
<h3 id="LockscreenNotifications">Notificaciones de pantalla bloqueada</h3>
<p>Las pantallas bloqueadas en Android 5.0 tienen la capacidad de presentar notificaciones. Los usuarios pueden elegir mediante la <em>configuración</em> si desean permitir que el contenido de notificación confidencial se muestre a través de una pantalla bloqueada segura.</p>
<p>La aplicación puede controlar el nivel de detalle visible cuando las notificaciones se muestran a través de la pantalla bloqueada segura. Para controlar el nivel de visibilidad, llama a {@link android.app.Notification.Builder#setVisibility(int) setVisibility()} y especifica uno de estos valores:</p>
<ul>
<li>{@link android.app.Notification#VISIBILITY_PRIVATE VISIBILITY_PRIVATE}: Muestra información básica, como el ícono de la notificación, pero oculta el contenido completo de la notificación.</li>
<li>{@link android.app.Notification#VISIBILITY_PUBLIC VISIBILITY_PUBLIC}: Muestra el contenido completo de la notificación.</li>
<li>{@link android.app.Notification#VISIBILITY_SECRET VISIBILITY_SECRET}: No muestra nada y excluye incluso el ícono de la notificación.</li>
</ul>
<p>Cuando el nivel de visibilidad es {@link android.app.Notification#VISIBILITY_PRIVATE VISIBILITY_PRIVATE}, también puedes proporcionar una versión redactada del contenido de la notificación que oculta datos personales. Por ejemplo, una aplicación de SMS podría mostrar una notificación que te indique que tienes tres nuevos mensajes de texto, pero oculta el contenido y los remitentes del mensaje. Para proporcionar esta notificación alternativa, primero crea la notificación de reemplazo utilizando {@link android.app.Notification.Builder}. Cuando crees el objeto de notificación privado, adjúntale la notificación de reemplazo a través del método {@link android.app.Notification.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}.</p>
<h3 id="NotificationsMetadata">Metadatos de notificaciones</h3>
<p>Android 5.0 utiliza metadatos asociados con notificaciones de la aplicación para ordenar las notificaciones de forma más inteligente. Para definir los metadatos, llama a los siguientes métodos en {@link android.app.Notification.Builder} cuando creas la notificación:</p>
<ul>
<li>{@link android.app.Notification.Builder#setCategory(java.lang.String) setCategory()}: Indica al sistema cómo manejar las notificaciones de la aplicación cuando el dispositivo está en modo de <em>prioridad</em> (por ejemplo, si una notificación representa una llamada entrante, un mensaje instantáneo o una alarma).
<li>{@link android.app.Notification.Builder#setPriority(int) setPriority()}: Marca la notificación como más o menos importante que las notificaciones habituales. Las notificaciones con el campo de prioridad establecido en {@link android.app.Notification#PRIORITY_MAX PRIORITY_MAX} o {@link android.app.Notification#PRIORITY_HIGH PRIORITY_HIGH} aparecen en una pequeña ventana flotante si la notificación también tiene sonido o vibración.</li>
<li>{@link android.app.Notification.Builder#addPerson(java.lang.String) addPerson()}: Permite agregar una o más personas que son relevantes para una notificación. La aplicación puede usar esta opción para indicar al sistema que debería agrupar las notificaciones de las personas especificadas o clasificar las notificaciones de estas personas como más importantes.</li>
</ul>
<h2 id="Graphics">Gráficos</h2>
<h3 id="OpenGLES-3-1">Compatibilidad con OpenGL ES 3.1</h3>
<p>Android 5.0 agrega interfaces Java y compatibilidad nativa para OpenGL ES 3.1. La nueva funcionalidad clave proporcionada en OpenGL ES 3.1 incluye lo siguiente:</p>
<ul>
<li>sombreadores de cálculo;
<li>objetos de sombreadores independientes;
<li>comandos de dibujo indirectos;
<li>texturas de símbolos y multimuestra;
<li>mejoras del lenguaje de sombreado;
<li>extensiones para depuración y modos de fusión avanzados;
<li>compatibilidad de versiones anteriores con OpenGL ES 2.0 y 3.0.
</ul>
<p>La interfaz Java para OpenGL ES 3.1 en Android se proporciona con {@link android.opengl.GLES31}. Al usar OpenGL ES 3.1, asegúrate de declararlo en el archivo de manifiesto con la etiqueta <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a> y el atributo {@code android:glEsVersion}. Por ejemplo:</p>
<pre>
&lt;manifest&gt;
&lt;uses-feature android:glEsVersion="0x00030001" /&gt;
...
&lt;/manifest&gt;
</pre>
<p>Para obtener más información sobre el uso de OpenGL ES, incluso cómo comprobar la versión de OpenGL ES compatible del dispositivo en el tiempo de ejecución, consulta la <a href="{@docRoot}guide/topics/graphics/opengl.html">guía de la API OpenGL ES</a>.</p>
<h3 id="AndroidExtensionPack">Android Extension Pack</h3>
<p>Además de OpenGL ES 3.1, esta versión ofrece un paquete de extensiones con interfaces Java y compatibilidad nativa para la funcionalidad de gráficos avanzada. Estas extensiones se tratan como un solo paquete en Android. (Si la extensión {@code ANDROID_extension_pack_es31a} está presente, la aplicación puede asumir que todas las extensiones en el paquete están presentes y habilitar las funciones del lenguaje de sombreado con una sola instrucción {@code #extension}).</p>
<p>El paquete de extensiones admite lo siguiente:</p>
<ul>
<li>compatibilidad con sombreador de fragmento garantizada para búferes de almacenamiento de sombreador, imágenes y operaciones atómicas (la compatibilidad con el sombreador de fragmento es opcional en OpenGL ES 3.1);</li>
<li>sombreadores de geometría y teselación;</li>
<li>formato de compresión de texturas ASTC (LDR);</li>
<li>interpolación y sombreado por muestra;</li>
<li>diferentes modos de fusión para cada archivo adjunto de color en un búfer de fotogramas.</li>
</ul>
<p>La interfaz Java para el paquete de extensiones se proporciona con {@link android.opengl.GLES31Ext}. En el manifiesto de la aplicación, puedes declarar que la aplicación debe instalarse solo en dispositivos compatibles con el paquete de extensiones. Por ejemplo:</p>
<pre>
&lt;manifest&gt;
&lt;uses-feature android:name=“android.hardware.opengles.aep”
android:required="true" /&gt;
...
&lt;/manifest&gt;
</pre>
<h2 id="Media">Medios</h2>
<h3 id="Camera-v2">API de cámara para capacidades avanzadas de la cámara</h3>
<p>Android 5.0 introduce la nueva API <a href="{@docRoot}reference/android/hardware/camera2/package-summary.html">android.hardware.camera2</a> para facilitar la captura y el procesamiento de imágenes de grano fino. Ahora puedes acceder mediante programación a los dispositivos de cámara disponibles para el sistema con {@link android.hardware.camera2.CameraManager#getCameraIdList() getCameraIdList()} y conectarte a un dispositivo específico con {@link android.hardware.camera2.CameraManager#openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) openCamera()}. Para iniciar la captura de imágenes, crea una {@link android.hardware.camera2.CameraCaptureSession} y especifica los objetos {@link android.view.Surface} para enviar las imágenes capturadas. La {@link android.hardware.camera2.CameraCaptureSession} puede configurarse para tomar fotos individuales o múltiples imágenes al instante.</p>
<p>Para recibir una notificación cuando se capturan imágenes nuevas, implementa el agente de escucha {@link android.hardware.camera2.CameraCaptureSession.CaptureCallback} y establécelo en la solicitud de captura. Cuando el sistema completa la solicitud de captura de imágenes, el agente de escucha {@link android.hardware.camera2.CameraCaptureSession.CaptureCallback} recibe una llamada en {@link android.hardware.camera2.CameraCaptureSession.CaptureCallback#onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult) onCaptureCompleted()} y proporciona los metadatos de captura de imágenes en un {@link android.hardware.camera2.CaptureResult}.</p>
<p>La clase {@link android.hardware.camera2.CameraCharacteristics} permite que la aplicación detecte las funciones de la cámara que están disponibles en un dispositivo. La propiedad {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL INFO_SUPPORTED_HARDWARE_LEVEL} del objeto representa el nivel de funcionalidad de la cámara.</p>
<ul>
<li>Todos los dispositivos admiten al menos el nivel de hardware {@link android.hardware.camera2.CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY}, que tiene capacidades similares a las de la API {@link android.hardware.Camera} obsoleta.</li>
<li>Los dispositivos que admiten el nivel de hardware {@link android.hardware.camera2.CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL INFO_SUPPORTED_HARDWARE_LEVEL_FULL} permiten el control manual de la captura y el procesamiento posterior, así como la captura de imágenes de alta resolución a altas velocidades de fotogramas.</li>
</ul>
<p>Para ver cómo utilizar la API de la <a href="{@docRoot}reference/android/hardware/camera2/package-summary.html">cámara</a> actualizada, consulta las muestras de implementación de {@code Camera2Basic} y {@code Camera2Video} en esta versión.</p>
<h3 id="AudioPlayback">Reproducción de audio</h3>
<p>En esta versión, se incluyen los cambios a {@link android.media.AudioTrack} que se indican a continuación:</p>
<ul>
<li>La aplicación ahora puede suministrar datos de audio en formato de punto flotante ({@link android.media.AudioFormat#ENCODING_PCM_FLOAT ENCODING_PCM_FLOAT}). Esta función permite obtener un rango dinámico mayor, una precisión más coherente y una capacidad de aumento mayor. La aritmética de punto flotante es especialmente útil durante los cálculos intermedios. Los puntos finales de reproducción usan un formato de enteros para datos de audio con una profundidad en bits inferior. (En Android 5.0, las partes de la canalización interna todavía no son puntos flotantes).
<li>La aplicación ahora puede suministrar datos de audio como un {@link java.nio.ByteBuffer} en el mismo formato que proporciona {@link android.media.MediaCodec}.
<li>La opción {@link android.media.AudioTrack#WRITE_NON_BLOCKING WRITE_NON_BLOCKING} puede simplificar el almacenamiento en búfer y los subprocesos para algunas aplicaciones.
</ul>
<h3 id="MediaPlaybackControl">Control de reproducción de medios</h3>
<p>Usa las nuevas API de notificación y medios para asegurarte de que la interfaz de usuario del sistema sepa cuando reproduces medios y pueda extraer y mostrar la carátula del álbum. El control de la reproducción de medios en una interfaz de usuario y un servicio es ahora más fácil con las nuevas clases {@link android.media.session.MediaSession} y {@link android.media.session.MediaController}.</p>
<p>La nueva clase {@link android.media.session.MediaSession} reemplaza la clase {@link android.media.RemoteControlClient} obsoleta y proporciona un único conjunto de métodos de devolución de llamada para el manejo de los controles de transporte y los botones de los medios. Si la aplicación permite reproducir medios y se ejecuta en la plataforma Android <a href="{@docRoot}tv/index.html">TV</a> o Android <a href="{@docRoot}wear/index.html">Wear</a>, usa la clase {@link android.media.session.MediaSession} para manejar los controles de transporte con los mismos métodos de devolución de llamada.</p>
<p>Ahora puedes crear tu propia aplicación de controlador de medios con la nueva clase {@link android.media.session.MediaController}. Esta clase ofrece una manera segura para subprocesos de supervisar y controlar la reproducción de medios desde el proceso de la interfaz de usuario de la aplicación. Al crear un controlador, especifica un objeto {@link android.media.session.MediaSession.Token} para que la aplicación pueda interaccionar con la {@link android.media.session.MediaSession} dada. Mediante el uso de los métodos {@link android.media.session.MediaController.TransportControls}, puedes enviar comandos, como {@link android.media.session.MediaController.TransportControls#play() play()}, {@link android.media.session.MediaController.TransportControls#stop() stop()}, {@link android.media.session.MediaController.TransportControls#skipToNext() skipToNext()} y {@link android.media.session.MediaController.TransportControls#setRating(android.media.Rating) setRating()}, para controlar la reproducción de medios en esa sesión. Con el controlador, también puedes registrar un objeto {@link android.media.session.MediaController.Callback} para escuchar metadatos y cambios de estado en la sesión.</p>
<p>Además, puedes crear notificaciones enriquecidas que permiten el control de la reproducción vinculado a una sesión de medios con la nueva clase {@link android.app.Notification.MediaStyle}.</p>
<h3 id="MediaBrowsing">Exploración de medios</h3>
<p>Android 5.0 introduce la capacidad para las aplicaciones de explorar la biblioteca de contenidos de medios de otra aplicación a través de la nueva API <a href="{@docRoot}reference/android/media/browse/package-summary.html">android.media.browse</a>. Para exponer el contenido de los medios en la aplicación, amplía la clase {@link android.service.media.MediaBrowserService}. La implementación de {@link android.service.media.MediaBrowserService} debe proporcionar acceso a {@link android.media.session.MediaSession.Token} para que las aplicaciones puedan reproducir contenido de medios proporcionado a través de tu servicio.</p>
<p>Para interaccionar con un servicio de explorador de medios, usa la clase {@link android.media.browse.MediaBrowser}. Especifica el nombre del componente para una {@link android.media.session.MediaSession} cuando creas una instancia {@link android.media.browse.MediaBrowser}. El uso de esa instancia de explorador hará que la aplicación pueda conectarse al servicio asociado y obtener un objeto {@link android.media.session.MediaSession.Token} para reproducir contenido expuesto a través de ese servicio.</p>
<h2 id="Storage">Almacenamiento</h2>
<h3 id="DirectorySelection">Selección de directorio</h3>
<p>Android 5.0 amplía el <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage Access Framework</a> para permitir a los usuarios seleccionar un subárbol entero del directorio y proporcionar a las aplicaciones acceso de lectura o escritura a todos los documentos incluidos sin requerir la confirmación del usuario para cada elemento.</p>
<p>Para seleccionar un subárbol del directorio, crea y envía un intento {@link android.content.Intent#ACTION_OPEN_DOCUMENT_TREE OPEN_DOCUMENT_TREE}. El sistema muestra todas las instancias {@link android.provider.DocumentsProvider} que admiten la selección de subárbol y permite que el usuario explore y seleccione un directorio. El URI devuelto representa el acceso al subárbol seleccionado. A continuación, puedes usar {@link android.provider.DocumentsContract#buildChildDocumentsUriUsingTree(android.net.Uri, java.lang.String) buildChildDocumentsUriUsingTree()} y {@link android.provider.DocumentsContract#buildDocumentUriUsingTree(android.net.Uri, java.lang.String) buildDocumentUriUsingTree()} junto con {@link android.content.ContentResolver#query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) query()} para explorar el subárbol.</p>
<p>El nuevo método {@link android.provider.DocumentsContract#createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String) createDocument()} permite crear nuevos documentos o directorios en cualquier lugar del subárbol. Para administrar los documentos existentes, usa {@link android.provider.DocumentsContract#renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String) renameDocument()} y {@link android.provider.DocumentsProvider#deleteDocument(java.lang.String) deleteDocument()}. Comprueba {@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS} para verificar si el proveedor admite estas llamadas antes de su emisión.</p>
<p>Si implementas un {@link android.provider.DocumentsProvider} y quieres admitir la selección de subárbol, implementa {@link android.provider.DocumentsProvider#isChildDocument(java.lang.String, java.lang.String) isChildDocument()} e incluye {@link android.provider.DocumentsContract.Root#FLAG_SUPPORTS_IS_CHILD FLAG_SUPPORTS_IS_CHILD} en tu {@link android.provider.DocumentsContract.Root#COLUMN_FLAGS COLUMN_FLAGS}.</p>
<p>Android 5.0 también introduce nuevos directorios específicos de paquetes en almacenamiento compartido, donde la aplicación puede colocar archivos de medios para que sean incluidos en {@link android.provider.MediaStore}. El nuevo {@link android.content.Context#getExternalMediaDirs()} devuelve rutas a estos directorios en todos los dispositivos de almacenamiento compartido. De forma similar a {@link android.content.Context#getExternalFilesDir(java.lang.String) getExternalFilesDir()}, la aplicación no necesita permisos adicionales para acceder a las rutas devueltas. La plataforma busca periódicamente nuevos medios en estos directorios, pero tú también puedes utilizar {@link android.media.MediaScannerConnection} para buscar contenido nuevo de forma explícita.</p>
<h2 id="Wireless">Redes inalámbricas y conectividad</h2>
<h3 id="Multinetwork">Múltiples conexiones de red</h3>
<p>Android 5.0 ofrece nuevas API de múltiples redes que permiten que la aplicación busque las redes disponibles con capacidades específicas dinámicamente y que establezca una conexión con ellas. Esta funcionalidad es útil cuando la aplicación requiere una red especializada, como una red de facturación del operador de telefonía celular, SUPL o MMS, o si quieres enviar datos con un determinado tipo de protocolo de transporte.</p>
<p>Para seleccionar una red y conectarte a ella de forma dinámica desde la aplicación, sigue estos pasos:</p>
<ol>
<li>Crea un {@link android.net.ConnectivityManager}.</li>
<li>Usa la clase {@link android.net.NetworkRequest.Builder} para crear un objeto {@link android.net.NetworkRequest} y especifica las características de la red y el tipo de transporte que requiere la aplicación.</li>
<li>Para buscar las redes adecuadas, llama a {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) requestNetwork()} o {@link android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()}, y envía el objeto {@link android.net.NetworkRequest} y una implementación de {@link android.net.ConnectivityManager.NetworkCallback}. Usa el método {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) requestNetwork()} si deseas cambiar de forma activa a una red adecuada una vez que se detecta; para recibir solamente notificaciones de redes analizadas sin tener que cambiar de forma activa de red, usa el método {@link android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} en su lugar.</li>
</ol>
<p>Cuando el sistema detecta una red adecuada, se conecta a la red e invoca la devolución de llamada {@link android.net.ConnectivityManager.NetworkCallback#onAvailable(android.net.Network) onAvailable()}. Puedes usar el objeto {@link android.net.Network} de la devolución de llamada para obtener información adicional acerca de la red o para indicar que el tráfico use la red seleccionada.</p>
<h3 id="BluetoothBroadcasting">Bluetooth de baja energía</h3>
<p>Android 4.3 introdujo compatibilidad de plataforma para <a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">Bluetooth de baja energía</a> (<em>Bluetooth LE</em>) en el rol central. En Android 5.0, un dispositivo Android ahora puede actuar como un <em>dispositivo periférico</em> Bluetooth LE. Las aplicaciones pueden utilizar esta capacidad para que otros dispositivos cercanos detecten su presencia. Por ejemplo, puedes crear aplicaciones que permiten que un dispositivo funcione como un podómetro o un monitor de estado, y comunique sus datos a otro dispositivo Bluetooth LE.</p>
<p>Las nuevas API {@link android.bluetooth.le} permiten a sus aplicaciones transmitir anuncios, buscar respuestas y establecer conexiones con dispositivos Bluetooth LE cercanos. Para utilizar las nuevas funciones de anuncio y búsqueda, agrega el permiso {@link android.Manifest.permission#BLUETOOTH_ADMIN BLUETOOTH_ADMIN} en el manifiesto. Cuando los usuarios actualizan o descargan tu aplicación desde Play Store, se les pide que concedan el siguiente permiso a tu aplicación: "Información de conexión Bluetooth: Permite que la aplicación controle Bluetooth, incluida la transmisión de información a dispositivos Bluetooth cercanos o la obtención de información sobre ellos".</p>
<p>Para comenzar el anuncio de Bluetooth LE a fin de que otros dispositivos puedan detectar tu aplicación, llama a {@link android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback) startAdvertising()} y envía una implementación de la clase {@link android.bluetooth.le.AdvertiseCallback}. El objeto de devolución de llamada recibe un informe del éxito o fracaso de la operación de anuncio.</p>
<p> Android 5.0 introduce la clase {@link android.bluetooth.le.ScanFilter} para que tu aplicación pueda buscar solo tipos específicos de dispositivos que le interesan. Para empezar a buscar dispositivos Bluetooth LE, llama a {@link android.bluetooth.le.BluetoothLeScanner#startScan(android.bluetooth.le.ScanCallback) startScan()} y envía una lista de filtros. En la llamada del método, también debes proporcionar una implementación de {@link android.bluetooth.le.ScanCallback} para infomar cuando se encuentra un anuncio de Bluetooth LE. </p>
<h3 id="NFCEnhancements">Mejoras de NFC</h3>
<p>Android 5.0 agrega estas mejoras para permitir un uso más amplio y más flexible de la NFC:</p>
<ul>
<li>Android Beam ahora está disponible en el menú de <em>uso compartido</em>.</li>
<li>La aplicación puede invocar Android Beam en el dispositivo del usuario para compartir datos llamando a {@link android.nfc.NfcAdapter#invokeBeam(android.app.Activity) invokeBeam()}. Esto evita que el usuario tenga que apoyar manualmente el dispositivo contra otro dispositivo NFC para completar la transferencia de datos.</li>
<li>Puedes utilizar el nuevo método {@link android.nfc.NdefRecord#createTextRecord(java.lang.String, java.lang.String) createTextRecord()} para crear un registro NDEF que contenga datos de texto UTF-8.</li>
<li>Si programas una aplicación de pago, ahora tienes la capacidad de registrar un ID de aplicación NFC (AID) dinámicamente llamando a <code><a href="{@docRoot}reference/android/nfc/cardemulation/CardEmulation.html#registerAidsForService(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>)">registerAidsForService()</a></code>. También puedes usar {@link android.nfc.cardemulation.CardEmulation#setPreferredService(android.app.Activity, android.content.ComponentName) setPreferredService()} para establecer el servicio de emulación de tarjeta preferido que se debe utilizar cuando una actividad específica está en primer plano.</li>
</ul>
<h2 id="Power">Proyecto Volta</h2>
<p>Además de las nuevas funciones, Android 5.0 hace hincapié en las mejoras de la duración de la batería. Usa las nuevas API y la herramienta para entender y optimizar el consumo de energía de la aplicación.</p>
<h3 id="JobScheduler">Programación de trabajos</h3>
<p>Android 5.0 proporciona una nueva API {@link android.app.job.JobScheduler} que permite optimizar la duración de la batería mediante la definición de trabajos que el sistema ejecutará de forma asíncrona (en otro momento) o en condiciones específicas (por ejemplo, cuando el dispositivo se está cargando). La programación de trabajos es útil en situaciones como las siguientes:</p>
<ul>
<li>La aplicación tiene trabajos en segundo plano que puedes posponer.</li>
<li>La aplicación tiene trabajos que prefieres hacer cuando la unidad está enchufada.</li>
<li>La aplicación tiene una tarea que requiere acceso a la red o una conexión Wi-Fi.</li>
<li>La aplicación tiene una serie de tareas que deseas que se ejecuten como un lote en un horario regular.</li>
</ul>
<p>Una unidad de trabajo está encapsulada por un objeto {@link android.app.job.JobInfo}. Este objeto especifica los criterios de programación.</p>
<p>Usa la clase {@link android.app.job.JobInfo.Builder} para configurar cómo se debe ejecutar la tarea programada. Puedes programar la tarea para que se ejecute en condiciones específicas, como las siguientes:</p>
<ul>
<li>Debe empezar cuando el dispositivo se está cargando.</li>
<li>Debe empezar cuando el dispositivo está conectado a una red no medida.</li>
<li>Debe empezar cuando el dispositivo está inactivo.</li>
<li>Debe terminar antes de que transcurra un determinado plazo o con una demora mínima.</li>
</ul>
<p>Por ejemplo, puedes agregar un código como este para ejecutar la tarea en una red no medida:</p>
<pre>
JobInfo uploadTask = new JobInfo.Builder(mJobId,
mServiceComponent /* JobService component */)
.setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
.build();
JobScheduler jobScheduler =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(uploadTask);
</pre>
<p>Si el dispositivo tiene energía estable (es decir, el dispositivo estuvo enchufado durante más de dos minutos, y la batería está en un <a href="{@docRoot}reference/android/content/Intent.html#ACTION_BATTERY_OKAY">nivel aceptable</a>), el sistema ejecutará cualquier trabajo programado que esté listo, incluso si la fecha límite del trabajo no pasó.</p>
<p>Para ver un ejemplo de cómo utilizar la API {@link android.app.job.JobScheduler}, consulta la muestra de implementación de {@code JobSchedulerSample} en esta versión.</p>
<h3 id="PowerMeasurementTools">Herramientas de programadores para el uso de la batería</h3>
<p>El nuevo comando {@code dumpsys batterystats} genera información estadística interesante sobre el uso de la batería en un dispositivo, organizada por ID de usuario único (UID). Las estadísticas incluyen:</p>
<ul>
<li>historial de eventos relacionados con la batería;
<li>estadísticas globales para el dispositivo;
<li>uso de energía aproximado por UID y componente de sistema;
<li>ms por paquete de dispositivos móviles por aplicación;
<li>estadísticas globales de UID de sistema;
<li>estadísticas globales de UID de aplicación.
</ul>
<p>Usa la opción {@code --help} para conocer acerca de las diversas opciones que tienes para adaptar la salida. Por ejemplo, para imprimir las estadísticas de uso de la batería de un paquete de aplicaciones dado desde que el dispositivo se cargó por última vez, ejecuta este comando:
<pre>
$ adb shell dumpsys batterystats --charged &lt;package-name&gt;
</pre>
<p>Puedes utilizar la herramienta <a href="https://github.com/google/battery-historian" class="external-link">Battery Historian</a> en la salida del comando {@code dumpsys} para generar una visualización HTML de eventos relacionados con la energía a partir de los registros. Esta información facilita la comprensión y el diagnóstico de cualquier problema relacionado con la batería.</p>
<h2 id="Enterprise">Android en el entorno de trabajo y en el entorno educativo</h2>
<h3 id="ManagedProvisioning">Aprovisionamiento administrado</h3>
<p>Android 5.0 ofrece nuevas funcionalidades para ejecutar aplicaciones en un entorno empresarial. Un <a href="{@docRoot}guide/topics/admin/device-admin.html">administrador de dispositivos</a> puede iniciar un proceso de aprovisionamiento administrado para agregar un <em>perfil administrado</em> copresente, pero separado, a un dispositivo si el usuario tiene una cuenta personal existente. Las aplicaciones que se asocian con perfiles administrados aparecen junto con las aplicaciones no administradas en el Launcher del usuario, la pantalla de actividades y tareas recientes, y las notificaciones.</p>
<p>Para iniciar el proceso de aprovisionamiento administrado, envía {@link android.app.admin.DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE ACTION_PROVISION_MANAGED_PROFILE} en un {@link android.content.Intent}. Si la llamada se realiza correctamente, el sistema activa la devolución de llamada {@link android.app.admin.DeviceAdminReceiver#onProfileProvisioningComplete(android.content.Context, android.content.Intent) onProfileProvisioningComplete()}. A continuación, puedes llamar a {@link android.app.admin.DevicePolicyManager#setProfileEnabled(android.content.ComponentName) setProfileEnabled()} para habilitar este perfil administrado.</p>
<p>De forma predeterminada, solo un pequeño subconjunto de aplicaciones están habilitadas en el perfil administrado. Puedes instalar aplicaciones adicionales en el perfil administrado llamando a {@link android.app.admin.DevicePolicyManager#enableSystemApp(android.content.ComponentName, android.content.Intent) enableSystemApp()}.</p>
<p>Si programas una aplicación Launcher, puedes utilizar la nueva clase {@link android.content.pm.LauncherApps} para obtener una lista de las actividades que se pueden iniciar para el usuario actual y los perfiles administrados asociados. El Launcher puede hacer que las aplicaciones administradas sean visualmente prominentes agregando una insignia de trabajo al ícono dibujable. Para recuperar el ícono con insignia, llama a {@link android.content.pm.PackageManager#getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle) getUserBadgedIcon()}.</p>
<p>Para ver cómo utilizar la nueva funcionalidad, consulta la muestra de implementación de {@code BasicManagedProfile} en esta versión.</p>
<h3 id="DeviceOwner">Propietario de dispositivo</h3>
<p>Android 5.0 introduce la capacidad de implementar una aplicación de propietario de dispositivo. Un <em>propietario de dispositivo</em> es un tipo especializado de <a href="{@docRoot}guide/topics/admin/device-admin.html">administrador de dispositivos</a> que tiene la capacidad adicional de crear y eliminar usuarios secundarios, y configurar opciones globales en el dispositivo. La aplicación de propietario de dispositivo puede utilizar los métodos de la clase {@link android.app.admin.DevicePolicyManager} para tomar un control específico de la configuración, la seguridad y las aplicaciones en los dispositivos administrados. Un dispositivo puede tener solamente un propietario de dispositivo activo a la vez.</p>
<p>Para implementar y activar un propietario de dispositivo, debes realizar una transferencia de datos NFC desde una aplicación de programación hasta el dispositivo mientras el dispositivo está en estado no aprovisionado. Esta transferencia de datos envía la misma información que la que se envía en el intento de aprovisionamiento descrito en <a href="#ManagedProvisioning">Aprovisionamiento administrado</a>.</p>
<h3 id="ScreenPinning">Fijación de pantalla</h3>
<p>Android 5.0 introduce una nueva API para fijar la pantalla que te permite impedir temporalmente que los usuarios salgan de tu tarea o sean interrumpidos por notificaciones. Podría usarse, por ejemplo, si estás programando una aplicación de educación para cumplir con requisitos de evaluación de gran importancia en Android o una aplicación de único propósito o kiosco. Una vez que la aplicación activa la fijación de pantalla, los usuarios no pueden ver las notificaciones, acceder a otras aplicaciones ni volver a la pantalla principal hasta que la aplicación sale del modo.</p>
<p>Hay dos formas de activar la fijación de pantalla:</p>
<ul>
<li><strong>Manualmente:</strong> Los usuarios pueden habilitar la fijación de pantalla desde <em>Configuración &gt; Seguridad&gt; Fijar pantalla</em> y seleccionar las tareas que desean fijar tocando el ícono para fijar de color verde en la pantalla de actividades y tareas recientes.</li> <li><strong>Mediante programación</strong>: Para activar la fijación de pantalla mediante programación, llama a {@link android.app.Activity#startLockTask() startLockTask()} desde la aplicación. Si la aplicación que realiza la solicitud no es un propietario de dispositivo, se solicita confirmación al usuario. Una aplicación de propietario de dispositivo puede llamar al método {@link android.app.admin.DevicePolicyManager#setLockTaskPackages(android.content.ComponentName, java.lang.String[]) setLockTaskPackages()} para permitir que las aplicaciones se puedan fijar sin tener que pasar por el paso de confirmación del usuario.</li>
</ul>
<p>Cuando el bloqueo de tarea está activo, ocurre lo siguiente:</p>
<ul>
<li>La barra de estado está en blanco, y las notificaciones de los usuarios y la información de estado están ocultas.</li>
<li>Los botones de pantalla principal y aplicaciones recientes están ocultos.</li>
<li>Otras aplicaciones no pueden iniciar actividades nuevas.</li>
<li>La aplicación actual puede iniciar actividades nuevas, siempre y cuando no cree nuevas tareas.</li>
<li>Cuando la fijación de pantalla es invocada por un propietario de dispositivo, el usuario no puede acceder a tu aplicación hasta que la aplicación llama a {@link android.app.Activity#stopLockTask() stopLockTask()}.</li>
<li>Si la fijación de pantalla es una actividad realizada por otra aplicación que no es un propietario de dispositivo o por el usuario directamente, el usuario puede salir de ella manteniendo presionados los botones de retroceso y aplicaciones recientes.</li>
</ul>
<h2 id="Printing">Marco de impresión</h2>
<h3 id="PDFRender">Representación de PDF como mapa de bits</h3>
<p>Ahora puedes representar páginas de documentos PDF en imágenes de mapa de bits para imprimir mediante el uso de la nueva clase {@link android.graphics.pdf.PdfRenderer}. Debes especificar un {@link android.os.ParcelFileDescriptor} que admita búsquedas (es decir, que se pueda acceder al contenido de forma aleatoria) y en el que el sistema pueda escribir el contenido imprimible. La aplicación puede obtener una página para representar con {@link android.graphics.pdf.PdfRenderer#openPage(int) openPage()} y luego llamar a {@link android.graphics.pdf.PdfRenderer.Page#render(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Matrix, int) render()} para convertir la {@link android.graphics.pdf.PdfRenderer.Page} abierta en un mapa de bits. También puedes configurar parámetros adicionales si solo deseas convertir una parte del documento en una imagen de mapa de bits (por ejemplo, para implementar la <a href="http://en.wikipedia.org/wiki/Tiled_rendering" class="external-link">representación en mosaicos</a> a fin de hacer zoom en el documento).</p>
<p>Para ver un ejemplo de cómo utilizar las nuevas API, consulta la muestra {@code PdfRendererBasic}.</p>
<h2 id="System">Sistema</h2>
<h3 id="AppUsageStatistics">Estadísticas de uso de aplicaciones</h3>
<p>Ahora puedes acceder al historial de uso de las aplicaciones desde un dispositivo Android con la nueva API {@link android.app.usage}. Esta API proporciona información de uso más detallada que el método {@link android.app.ActivityManager#getRecentTasks(int, int) getRecentTasks()} obsoleto. Para utilizar esta API, primero debes declarar el permiso {@code "android.permission.PACKAGE_USAGE_STATS"} en el manifiesto. El usuario también debe permitir el acceso a esta aplicación a través de <em>Configuración &gt; Seguridad&gt; Aplicaciones</em> con acceso de uso.</p>
<p>El sistema recopila los datos de uso por aplicación y agrega los datos en intervalos diarios, semanales, mensuales y anuales. El tiempo máximo que el sistema conserva estos datos es el siguiente:</p>
<ul>
<li>datos diarios: siete días;</li>
<li>datos semanales: cuatro semanas;</li>
<li>datos mensuales: seis meses;</li>
<li>datos anuales: dos años.</li>
</ul>
<p>Para cada aplicación, el sistema registra los siguientes datos:</p>
<ul>
<li>la última vez que se utilizó la aplicación;</li>
<li>la cantidad total de tiempo que la aplicación estuvo en primer plano durante ese intervalo (por día, semana, mes o año);</li>
<li>captura de marca de tiempo del momento en que un componente (identificado por un nombre de actividad y paquete) se trasladó a primer plano o segundo plano durante un día;</li>
<li>captura de marca de tiempo del momento en que se modificó la configuración de un dispositivo (por ejemplo, cuando la orientación del dispositivo cambió debido a la rotación).</li>
</ul>
<h2 id="TestingA11y">Pruebas y accesibilidad </h2>
<h3 id="TestingA11yImprovements">Mejoras de pruebas y accesibilidad</h3>
<p>Android 5.0 incorpora la siguiente compatibilidad para pruebas y accesibilidad:</p>
<ul>
<li>Los nuevos métodos {@link android.app.UiAutomation#getWindowAnimationFrameStats() getWindowAnimationFrameStats()} y {@link android.app.UiAutomation#getWindowContentFrameStats(int) getWindowContentFrameStats()} capturan estadísticas de fotogramas para animaciones de ventanas y contenido. Estos métodos permiten escribir pruebas de instrumentación para evaluar si una aplicación está representando fotogramas a una frecuencia de actualización suficiente que brinde a los usuarios una experiencia perfecta.</li>
<li>El nuevo método {@link android.app.UiAutomation#executeShellCommand(java.lang.String) executeShellCommand()} permite ejecutar comandos shell desde la prueba de instrumentación. La ejecución de comandos es similar a la ejecución de {@code adb shell} desde un host conectado al dispositivo, lo que permite utilizar herramientas basadas en shell, como {@code dumpsys}, {@code am}, {@code content} y {@code pm}.</li>
<li>Los servicios de accesibilidad y las herramientas de prueba que utilizan las API de accesibilidad (como <a href="{@docRoot}tools/help/uiautomator/index.html">{@code UiAutomator}</a>) ahora pueden recuperar datos precisos acerca de las propiedades de las ventanas en pantalla con las que pueden interaccionar los usuarios videntes. Para recuperar una lista de objetos {@link android.view.accessibility.AccessibilityWindowInfo}, llama al nuevo método {@link android.accessibilityservice.AccessibilityService#getWindows() getWindows()}.</li>
<li>La nueva clase {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction} permite definir acciones estándares o personalizadas para realizar en un {@link android.view.accessibility.AccessibilityNodeInfo}. La nueva clase {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction} reemplaza las API relacionadas con acciones que se encontraban previamente en {@link android.view.accessibility.AccessibilityNodeInfo}.</li>
<li>Android 5.0 ofrece un control más preciso sobre la síntesis de texto a voz en la aplicación. La nueva clase {@link android.speech.tts.Voice} permite que la aplicación use perfiles de voz asociados con configuraciones regionales específicas, calificaciones de calidad y latencia, y parámetros específicos del motor de conversión de texto a voz.</li>
</ul>
<h2 id="IME">IME</h2>
<h3 id="Switching">Cambio más sencillo de idiomas de entrada</h3>
<p>A partir de Android 5.0, los usuarios pueden cambiar más fácilmente entre todos los <a href="{@docRoot}guide/topics/text/creating-input-method.html">editores de métodos de entrada (IME)</a> admitidos por la plataforma. La ejecución de la acción de cambio designada (normalmente tocar un ícono del mundo en el teclado en pantalla) te lleva por todos estos IME. Este cambio de comportamiento es implementado por el método {@link android.view.inputmethod.InputMethodManager#shouldOfferSwitchingToNextInputMethod(android.os.IBinder) shouldOfferSwitchingToNextInputMethod()}.</p>
<p>Además, el marco ahora comprueba si el siguiente IME incluye un mecanismo de cambio (y, por lo tanto, si ese IME admite el cambio al IME después de él). Un IME con un mecanismo de cambio no pasará a otro IME que no lo tenga. Este cambio de comportamiento es implementado por el método {@link android.view.inputmethod.InputMethodManager#switchToNextInputMethod(android.os.IBinder, boolean) switchToNextInputMethod()}.
<p>Para ver un ejemplo de cómo utilizar las API de cambio de IME actualizadas, consulta la muestra de implementación de teclado en pantalla actualizada en esta versión. Para obtener más información acerca de cómo implementar el cambio entre los IME, consulta <a href="{@docRoot}guide/topics/text/creating-input-method.html">Creación de un método de entrada</a>.
</p>
<h2 id="Manifest">Declaraciones de manifiesto</h2>
<h3 id="ManifestFeatures">Características requeridas declarables</h3>
<p>Los siguientes valores ahora son compatibles con el elemento <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a>, por lo que puedes asegurarte de que la aplicación solo se instale en dispositivos que proporcionen las características que necesita.</p>
<ul>
<li>{@link android.content.pm.PackageManager#FEATURE_AUDIO_OUTPUT}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_CAMERA_CAPABILITY_RAW}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_CAMERA_LEVEL_FULL}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_GAMEPAD}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_LIVE_TV}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_MANAGED_USERS}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_LEANBACK}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_OPENGLES_EXTENSION_PACK}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_SECURELY_REMOVES_USERS}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_SENSOR_AMBIENT_TEMPERATURE}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_SENSOR_HEART_RATE_ECG}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_SENSOR_RELATIVE_HUMIDITY}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_VERIFIED_BOOT}</li>
<li>{@link android.content.pm.PackageManager#FEATURE_WEBVIEW}</li>
</ul>
<h3 id="Permissions">Permisos de usuario</h3>
<p>El siguiente permiso ahora es compatible con el elemento <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code <uses-permission>}</a> para declarar los permisos que requiere la aplicación para acceder a determinadas API.</p>
<ul>
<li>{@link android.Manifest.permission#BIND_DREAM_SERVICE}: Cuando se busca un nivel de API 21 o posterior, este permiso es requerido por un servicio de <a href="{@docRoot}about/versions/android-4.2.html#Daydream">Protector de pantalla interactivo</a> para garantizar que solo el sistema pueda vincularse a él.</li>
</ul>

View File

@@ -1,242 +0,0 @@
page.title=Android Lollipop
@jd:body
<div style="float:right;">
<img src="{@docRoot}images/home/l-hero_2x.png" srcset="/images/home/l-hero.png 1x, /images/home/l-hero_2x.png 2x">
</div>
<p>Te damos la bienvenida a Android 5.0 Lollipop, la versión de Android más extensa y ambiciosa hasta el momento.</p>
<p>Esta versión está repleta de funciones nuevas para usuarios y miles de API nuevas para programadores. Android se sigue expandiendo; desde teléfonos, tablets y wearables hasta televisores y autos.</p>
<p>Si quieres conocer las API para programadores más en detalle, consulta la <a href="{@docRoot}about/versions/android-5.0.html">Descripción general de las API de Android 5.0</a>. También puedes obtener más información sobre Android 5.0 para consumidores en <a href="http://www.android.com/versions/lollipop-5-0/">www.android.com</a>.</p>
<div id="qv-wrapper">
<div id="qv">
<h2>Funciones clave para programadores</h2>
<ol>
<ul style="list-style-type:none;">
<li><a href="#Material">Material design</a></li>
<li><a href="#Perf">Enfoque en el rendimiento</a></li>
<li><a href="#Notifications">Notificaciones</a></li>
<li><a href="#TV">Tus aplicaciones en la pantalla grande</a></li>
<li><a href="#Documents">Aplicaciones centradas en el documento</a></li>
<li><a href="#Connectivity">Conectividad avanzada</a></li>
<li><a href="#Graphics">Gráficos de alto rendimiento</a></li>
<li><a href="#Audio">Audio más potente</a></li>
<li><a href="#Camera">Cámara y video mejorados</a></li>
<li><a href="#Work">Android en el lugar de trabajo</a></li>
<li><a href="#ScreenCapture">Captura y uso compartido de pantalla</a></li>
<li><a href="#Sensors">Nuevos tipos de sensores</a></li>
<li><a href="#WebView">WebView de Chromium</a></li>
<li><a href="#Accessibility">Accesibilidad y entrada</a></li>
<li><a href="#Battery">Herramientas para aplicaciones con uso eficiente de batería</a></li>
</ol>
</div>
</div>
<h2 id="Material">Material design</h2>
<p>Android 5.0 incluye <a href="http://www.google.com/design/spec">Material design</a> y te ofrece un kit de herramientas expandido para la interfaz de usuario. Con este kit, podrás integrar los nuevos patrones de diseño a las aplicaciones fácilmente. </p>
<p>Las nuevas <strong>vistas 3D</strong> te permiten establecer un eje z y superponer los elementos en la jerarquía con <strong>sombras en tiempo real</strong>, incluso mientras se mueven.</p>
<p>Las <strong>transiciones de actividad</strong> integradas trasladan al usuario de un estado al otro de forma fluida y con un movimiento estético y animado. El tema del material agrega transiciones a las actividades, incluida la capacidad de usar <strong>elementos visuales compartidos</strong> a través de las actividades.</p>
<div style="width:290px;margin-right:35px;float:left">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay="">
<source src="/design/material/videos/ContactsAnim.mp4">
<source src="/design/videos/ContactsAnim.webm">
<source src="/design/videos/ContactsAnim.ogv">
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<em>Para volver a reproducir el video, haz clic en la pantalla del dispositivo.</em>
</div>
</div>
<p>Las animaciones con efecto de propagación están disponibles para botones, casillas de verificación y otros controles táctiles de tu aplicación.
<p>También puedes definir elementos de diseño vectoriales en XML y animarlos de distintas formas. Los elementos de diseño vectoriales escalan sin perder definición, por lo que son ideales para los íconos de un solo color integrados en aplicaciones.</p>
<p>Un nuevo grupo de subprocesos de procesamiento administrado por el sistema, llamado <strong>RenderThread</strong>, mantiene las animaciones fluidas incluso cuando hay demoras en el proceso de interfaz de usuario principal. </p>
<h2 id="Perf">Enfoque en el rendimiento</h2>
<p>Android 5.0 ofrece una experiencia informática más veloz, más fluida y más potente.</p>
<p>Android ahora se ejecuta exclusivamente en el nuevo <strong>tiempo de ejecución ART</strong>, creado desde cero para ofrecer compatibilidad con una mezcla de ahead-of-time (AOT), just-in-time (JIT) y código interpretado. Admite las arquitecturas ARM, x86 y MIPS, y además es totalmente compatible con la arquitectura de 64 bits.</p>
<p>El tiempo de ejecución ART mejora el rendimiento y la capacidad de respuesta de las aplicaciones. El recolector de basura eficiente reduce la cantidad y la duración de pausas para los eventos de recolección de basura, que encajan sin inconvenientes en la ventana con sincronización vertical para que la aplicación no omita fotogramas. Además, ART traslada memoria de forma dinámica para optimizar el rendimiento durante el uso de elementos en primer plano. </p>
<p>Android 5.0 incluye compatibilidad de plataforma para las <strong>arquitecturas de 64 bits</strong> que usa la placa NVIDIA Tegra K1 de la Nexus 9. Las optimizaciones ofrecen espacios de direcciones más amplios y un rendimiento mejorado para las cargas de trabajo de ciertos procesos. Las aplicaciones que están en lenguaje de Java se ejecutan automáticamente como aplicaciones de 64 bits; no es necesario realizar modificaciones. Si tu aplicación usa código nativo, extendimos el NDK para que sea compatible con las nuevas ABI para ARM v8, x86-64 y MIPS 64.</p>
<p>Continuando con el enfoque en el rendimiento más parejo, Android 5.0 ofrece sincronización A/V mejorada. Los procesos gráficos y de audio se instrumentaron para lograr marcas de tiempo más precisas, lo que permite que las aplicaciones de video y de juegos muestren contenido sincronizado y parejo.</p>
<h2 id="Notifications">Notificaciones</h2>
<p>Las notificaciones en Android 5.0 son más visibles, accesibles y configurables. </p>
<img src="{@docRoot}images/versions/notification-headsup.png" style="float:right; margin:0 0 40px 60px" width="300" height="224" />
<p>Pueden aparecer detalles de notificaciones distintos <strong>en la pantalla bloqueada</strong> si el usuario lo desea. Los usuarios pueden elegir si permiten que, en la pantalla bloqueada segura, aparezca todo el contenido las notificaciones, que aparezca parte del contenido o que no aparezca nada. </p>
<p>Las alertas de notificaciones clave, como una llamada entrante, aparecen en una <strong>notificación emergente</strong>, es decir, una ventana flotante pequeña que permite al usuario responder o ignorar la notificación sin abandonar la aplicación que está utilizando.</p>
<p>Ahora puedes agregar <strong>metadatos nuevos</strong> a las notificaciones para recopilar contactos asociados (para la clasificación), categoría y prioridad.</p>
<p>Una nueva plantilla de notificación de contenido multimedia ofrece controles multimedia para las notificaciones con hasta seis botones de acción, incluidos controles personalizados, como "Me gusta". Ya no necesitarás usar RemoteViews.</p>
<h2 id="TV">Tus aplicaciones en la pantalla grande</h2>
<p><a href="http://developer.android.com/tv/index.html">Android TV</a> te ofrece una plataforma de televisión completa para la experiencia de tu aplicación en la pantalla grande. Android TV se centra en una experiencia simplificada de pantalla principal que permite a los usuarios descubrir contenido fácilmente gracias a las recomendaciones personalizadas y la búsqueda por voz.</p>
<p>Con Android TV, ahora puedes <strong>crear una gran experiencia llena de creatividad</strong> para el contenido de tu aplicación o juego, además de ofrecer compatibilidad para que interaccione con controladores de juegos y otros dispositivos de entrada. Con el fin de ayudarte a crear una interfaz de usuario cinemática, de tres metros para televisión, Android ofrece un <strong>marco de trabajo de la interfaz de usuario Leanback</strong> en la <a href="{@docRoot}tools/support-library/features.html#v17-leanback">versión 17 de la biblioteca de soporte</a>.</p>
<p>El <strong>marco de trabajo de entrada de televisión de Android</strong> (TIF) permite que las aplicaciones de televisión manejen las transmisiones de video desde distintas fuentes, como entradas HDMI, sintonizadores de televisión y receptores IPTV. También permite la búsqueda y las recomendaciones de televisión en vivo a través de metadatos publicados por la entrada de televisión e incluye el Servicio de control HDMI-CEC para manejar múltiples dispositivos con un solo control remoto. </p>
<p>El marco de trabajo de entrada de televisión ofrece acceso a una amplia variedad de fuentes entrada de televisión en vivo. Además, las reúne en una sola interfaz de usuario para que estos puedan explorar, ver y disfrutar el contenido. Crear un servicio de entrada de televisión para tu contenido puede ayudar a que sea más accesible en los dispositivos de televisión.</p>
<img src="{@docRoot}images/versions/recents_screen_2x.png" srcset="{@docRoot}images/versions/recents_screen.png 1x, {@docRoot}images/versions/recents_screen_2x.png 2x" style="float:right; margin:0 0 40px 60px" width="300" height="521" />
<h2 id="Documents">Aplicaciones centradas en el documento</h2>
<p>Android 5.0 presenta un espacio rediseñado de la sección Recientes; mucho más versátil y útil para tareas múltiples.</p>
<p>Las nuevas API permiten mostrar actividades separadas en tu aplicación como documentos individuales junto a otras pantallas recientes.</p>
<p>Puedes aprovechar los documentos concurrentes para darles a los usuarios la posibilidad de acceder al instante a más contenidos o servicios tuyos. Por ejemplo, podrías usar los documentos concurrentes para representar archivos en una aplicación de productividad, partidos de un jugador en un juego o chats en una aplicación de mensajería. </p>
<h2 id="Connectivity">Conectividad avanzada</h2>
<p>Android 5.0 agrega nuevas API que permiten que las aplicaciones realicen operaciones concurrentes con <strong>Bluetooth de baja energía</strong> (BLE), lo que permite la detección (modo central) y la publicidad (modo periférico).</p>
<p>Las nuevas funciones de <strong>redes múltiples</strong> permiten que las aplicaciones realicen consultas a las redes disponibles sobre las funciones disponibles, por ejemplo, si son redes Wi-Fi, móviles o de uso medido, o si ofrecen ciertas funciones de red. Luego, la aplicación puede solicitar una conexión y responder a la pérdida de conectividad o a otros cambios en la red.</p>
<p>Las API de <strong>NFC</strong> ahora permiten que las aplicaciones registren un ID de aplicación NFC (AID) de forma dinámica. También pueden establecer el servicio de emulación de tarjeta preferido por servicio activo y crear un registro NDEF que contenga datos de texto UTF-8.</p>
<h2 id="Graphics">Gráficos de alto rendimiento</h2>
<p>La compatibilidad con <strong><a href="http://www.khronos.org/opengles/3_X/">OpenGL ES 3.1 de Khronos</a></strong> ahora permite que los juegos y las aplicaciones cuenten con la capacidad gráfica en 2D y 3D de más alto rendimiento en dispositivos admitidos. </p>
<p>OpenGL ES 3.1 incluye sombreadores de cálculo, texturas de símbolos, efectos visuales con aceleración, compresión de texturas ETC2/EAC de alta calidad, procesamiento de texturas avanzado, formatos renderbuffer y tamaño de textura estandarizados, y muchas cosas más.</p>
<div class="figure" style="width:350px; margin:0 0 0 60px">
<img src="{@docRoot}images/versions/rivalknights.png" style="float:right;" width="350" height="525" />
<p class="img-caption">Rival Knights de Gameloft usa compresión de texturas ASTC (Adaptive Scalable Texture Compression) de AEP y sombreadores de cálculo de ES 3.1 para brindar efectos bloom/HDR y gráficos más detallados.</p>
</div>
<p>Android 5.0 también presenta el <strong>paquete de extensiones de Android</strong> (AEP), un conjunto de extensiones de OpenGL ES que permiten acceder a funciones como sombreadores de teselación y geometría, compresión de texturas ASTC, interpolación y sombreado por muestra y otras capacidades avanzadas de procesamiento. Con AEP, puedes ofrecer gráficos de alto rendimiento a través de una gran variedad de GPU.</p>
<h2 id="Audio">Audio más potente</h2>
<p>Un nuevo diseño de captura de audio ofrece <strong>entrada de audio de baja latencia</strong>. El nuevo diseño incluye: un subproceso de captura rápida que nunca se bloquea, excepto durante una lectura; clientes de captura rápida a una tasa nativa de muestra, recuento de canales y profundidad de bits. Los clientes normales de captura ofrecen remuestreo y la opción de aumentar o disminuir la mezcla de canales o la profundidad de bit.</p>
<p>La <strong>mezcla de transmisión de audio</strong> de canales múltiples permite que las aplicaciones de audio profesionales mezclen hasta ocho canales, incluidos los canales 5.1 y 7.1.</p>
<p>Las aplicaciones pueden exponer su contenido multimedia y <strong>explorar el contenido multimedia</strong> de otras aplicaciones y luego solicitar reproducción. El contenido se expone a través de una interfaz consultable y no necesita residir en el dispositivo.</p>
<p>Las aplicaciones tienen un control más preciso de la <strong>síntesis de texto a voz</strong> mediante perfiles de voz asociados con idiomas específicos, calidad y tasa de latencia. Las nuevas API también mejoran compatibilidad con la comprobación de errores de síntesis, la síntesis de la red, la detección de idiomas y la reserva de red.</p>
<p>Android ahora incluye compatibilidad con los periféricos de <strong>audio USB</strong> estándar, lo que permite a los usuarios conectar auriculares USB, altavoces, micrófonos u otros periféricos digitales de alto rendimiento. Android 5.0 también agrega compatibilidad con códecs de audio <strong>Opus</strong>.</p>
<p>Gracias a las nuevas API <strong>{@link android.media.session.MediaSession}</strong> para controlar la reproducción de contenido multimedia, ahora es más sencillo brindar controles multimedia consistentes en todas las pantallas y en otros controladores.</p>
<h2 id="Camera">Cámara y video mejorados</h2>
<p>Android 5.0 presenta <strong>API de la cámara totalmente nuevas</strong> que te permiten capturar formatos sin procesar, como YUV y Bayer RAW, y controlar distintos parámetros, como el tiempo de exposición, la sensibilidad ISO y la duración de una toma cuadro por cuadro. Los nuevos procesos totalmente sincronizados de la cámara te permiten capturar imágenes YUV sin comprimir y en su resolución original a 30&nbsp;FPS en dispositivos compatibles.</p>
<p>Además de las imágenes, también puedes capturar metadatos de la cámara, como modelos de ruido e información óptica.</p>
<p>Las aplicaciones que envían transmisiones de video por redes ahora pueden aprovechar el estándar H.265 <strong>High Efficiency Video Coding (HEVC)</strong> para lograr la codificación y decodificación optimizadas de los datos de video. </p>
<p>Android 5.0 también agrega compatibilidad con la <strong>tunelización de contenido multimedia</strong> para ofrecer la mejor experiencia de contenido con ultraalta definición (4K) y la posibilidad de reproducir datos de audio y video comprimidos al mismo tiempo. </p>
<div class="figure" style="width:320px; margin:1em 0 0 20px;padding-left:2em;">
<img style="float:right; margin:0 1em 1em 2em" src="{@docRoot}images/android-5.0/managed_apps_launcher@2x.png" srcset="{@docRoot}images/android-5.0/managed_apps_launcher@2x.png 2x" alt="" width="300" />
<p class="img-caption">Los usuarios tienen una visión unificada de sus aplicaciones personales y laborales, las cuales tienen una insignia para identificarlas fácilmente.</p>
</div>
<h2 id="Work">Android en el lugar de trabajo</h2>
<p>Para habilitar la política de traer tu propio dispositivo en entornos empresariales, un <a href="{@docRoot}about/versions/android-5.0.html#Enterprise">proceso de aprovisionamiento administrado</a> se encarga de crear un perfil seguro de trabajo en el dispositivo. En el Launcher, las aplicaciones aparecen con una insignia de Work para indicar que un administrador de TI administra la aplicación y sus datos dentro del perfil de trabajo.</p>
<p>Notificaciones tanto del perfil personal y como del laboral son visibles en una vista unificada. Los datos de cada perfil se mantienen siempre seguros y separados entre sí, incluso cuando ambos perfiles usan la misma aplicación.</p>
<p>En el caso de dispositivos que son propiedad de la empresa, los administradores de TI pueden comenzar con un nuevo dispositivo y configurarlo con un <a href="{@docRoot}about/versions/android-5.0.html#DeviceOwner">propietario de dispositivo</a>. Los empleadores pueden entregar estos dispositivos con una aplicación de propietario de dispositivo ya instalada que pueda ajustar la configuración general del dispositivo.</p>
<h2 id="ScreenCapture">Captura y uso compartido de pantalla</h2>
<p>Android 5.0 te permite agregar capacidades de captura y uso compartido de pantalla a tu aplicación. </p>
<p>Con el permiso del usuario, puedes capturar video no seguro de la pantalla y distribuirlo en la red si lo deseas.</p>
<h2 id="Sensors">Nuevos tipos de sensores</h2>
<p>En Android 5.0, un nuevo sensor <strong>detector de inclinación</strong> ayuda a mejorar el reconocimiento de la actividad en los dispositivos compatibles, y un <strong>sensor de frecuencia cardíaca</strong> informa del ritmo cardíaco de la persona que toca el dispositivo. </p>
<p>Los nuevos <strong>sensores compuestos de interacción</strong> ahora están disponibles para detectar interacciones especiales, por ejemplo, cuando el usuario hace un gesto para <em>activar</em> el dispositivo, <em>levantarlo</em> o <em>mirarlo</em>.</p>
<h2 id="WebView">WebView de Chromium</h2>
<div style="float:right;margin:1em 2em 1em 2em;">
<img src="/images/kk-chromium-icon.png" alt="" height="160" style="margin-bottom:0em;">
</div>
<p>La versión inicial de Android 5.0 incluye una versión de Chromium para {@link android.webkit.WebView} basada en la versión M37 de Chromium, y con ella se agrega compatibilidad con <strong>WebRTC</strong>, <strong>WebAudio</strong> y <strong>WebGL</strong>. </p>
<p>Chromium M37 también incluye compatibilidad nativa para todas las especificaciones de los <strong>Web Components</strong>: Custom Elements, Shadow DOM, HTML Imports y Templates. Esto significa que puedes usar <a href="http://polymer-project.org/">Polymer</a> y sus <a href="https://www.polymer-project.org/docs/elements/material.html">elementos de diseño material</a> en una WebView sin polyfills.</p>
<p>A pesar de que WebView se basó en Chromium desde Android 4.4, ahora se puede actualizar la capa de Chromium desde Google Play.</p>
<p>A medida que haya más versiones disponibles de Chromium, los usuarios podrán actualizar la suya desde Google Play para asegurarse de que tienen las mejoras y correcciones de errores más recientes para WebView, además de encontrar las últimas API web y correcciones de errores para las aplicaciones que usen WebView en Android 5.0 y versiones posteriores.</p>
<h2 id="Accessibility">Accesibilidad y entrada</h2>
<p>Las nuevas API de accesibilidad pueden recuperar información detallada sobre las propiedades de las ventanas en la pantalla con la que los usuarios videntes pueden interactuar y definir acciones de entrada estándar o personalizadas para distintos elementos de la interfaz de usuario.</p>
<p>La nueva API de editor de método de entrada (IME) permite cambiar en menos tiempo a otros editores directamente desde el método de entrada.</p>
<h2 id="Battery">Herramientas para crear aplicaciones con uso eficiente de batería</h2>
<p>Las nuevas API de <strong>programación de tareas</strong> te permiten optimizar la duración de la batería gracias a la opción para postergar tareas que el sistema ejecutará más tarde o bajo condiciones específicas, por ejemplo, cuando el dispositivo se está cargando o conectado a Wi-Fi.</p>
<p>Un nuevo comando <code>dumpsys batterystats</code> genera <strong>estadísticas de uso de batería</strong> que puedes utilizar para comprender el uso de la batería en todo el sistema y el impacto de tu aplicación en la batería del dispositivo. Puedes consultar un historial de eventos de energía, el uso aproximado de energía por en una historia de eventos de energía, el uso de energía aproximado por identificador único de usuario (UID) y componente del sistema, y muchas opciones más.</p>
<img src="{@docRoot}images/versions/battery_historian.png" srcset="{@docRoot}images/versions/battery_historian@2x.png 2x" alt="" width="760" height="462" />
<p class="img-caption">Battery Historian es una nueva herramienta para convertir las estadísticas de <code>dumpsys batterystats</code> en una visualización de la depuración relacionada con la batería. Encuentra esta herramienta en <a href="https://github.com/google/battery-historian">https://github.com/google/battery-historian</a>.</p>

View File

@@ -1,190 +0,0 @@
page.title=Guía de prueba
page.image=images/cards/card-n-guide_2x.png
meta.tags="preview", "testing"
page.tags="preview", "developer preview"
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#runtime-permissions">Prueba de los permisos</a></li>
<li><a href="#doze-standby">Prueba de los modos Descanso y App Standby</a></li>
<li><a href="#ids">Copia de seguridad automática e identificadores de dispositivos</a></li>
</ol>
</div>
</div>
<p>
Android N te brinda la oportunidad de garantizar que tus aplicaciones funcionen con la próxima versión de la plataforma.
Esta versión preliminar incluye diversas API y cambios en los comportamientos que pueden
tener impactos en tu aplicación, como se describe en las secciones <a href="{@docRoot}preview/api-overview.html">Información general de la API</a> y <a href="{@docRoot}preview/behavior-changes.html">Cambios en los comportamientos</a>.
Al probar tu aplicación con la versión preliminar, te debes centrar en algunos cambios específicos del sistema para garantizar que los usuarios disfruten de una buena experiencia.
</p>
<p>
En esta guía, se describen qué y cómo probar las características preliminares con tu aplicación. Debes priorizar la prueba de estas características específicas preliminares, puesto que podrían tener un alto impacto en el comportamiento de tu aplicación:
</p>
<ul>
<li><a href="#runtime-permissions">Permisos</a>
</li>
<li><a href="#doze-standby">Modos Descanso y App Standby</a>
</li>
<li><a href="#ids">Copia de seguridad automática e identificadores de dispositivos</a></li>
</ul>
<p>
Para obtener más información sobre cómo configurar dispositivos o dispositivos virtuales con una imagen
del sistema de la versión preliminar para realizar pruebas, consulta la sección <a href="{@docRoot}preview/setup-sdk.html">Configurar el SDK de Android N</a>.
</p>
<h2 id="runtime-permissions">Prueba de los permisos</h2>
<p>
El nuevo modelo de <a href="{@docRoot}preview/features/runtime-permissions.html">permisos</a> cambia el modo en que el usuario asigna permisos a tu aplicación.
En lugar de conceder todos los permisos durante el procedimiento de instalación, tu aplicación debe solicitar al usuario los permisos individuales en el tiempo de ejecución.
Para los usuarios, este comportamiento ofrece más control granular sobre las actividades de cada aplicación, así como un mejor contexto para comprender por qué la aplicación está solicitando un permiso específico.
Los usuarios pueden conceder o revocar los permisos concedidos a una aplicación de forma individual en cualquier momento.
Es muy probable que esta característica de la versión preliminar tenga un impacto en el comportamiento de tu aplicación y puede hacer que algunas características de tu aplicación no funcionen o funcionen en un estado degradado.
</p>
<p class="caution">
Este cambio afecta a todas las aplicaciones que se ejecutan en la nueva plataforma, incluso a aquellas que no tienen como destino la nueva versión de la plataforma.
La plataforma ofrece un comportamiento de compatibilidad limitada para las aplicaciones heredadas, pero debes comenzar a planificar ahora la migración de tu aplicación al nuevo modelo de permisos, con el objetivo de publicar una versión actualizada de tu aplicación cuando se lance la plataforma oficial.
</p>
<h3 id="permission-test-tips">Tips para pruebas</h3>
<p>
Usa los siguientes tips para pruebas como ayuda para planificar y ejecutar las pruebas de tu aplicación con el nuevo comportamiento de permisos.
</p>
<ul>
<li>Identifica los permisos actuales de tu aplicación y las rutas de códigos relacionadas.</li>
<li>Prueba los flujos del usuario en los datos y servicios protegidos por permisos.</li>
<li>Realiza pruebas con varias combinaciones de permisos concedidos/revocados.</li>
<li>Usa la herramienta {@code adb} para administrar permisos desde la línea de comando:
<ul>
<li>Enumera los permisos y estados por grupo:
<pre>adb shell pm list permissions -d -g</pre>
</li>
<li>Concede o revoca un permiso o más permisos utilizando la siguiente sintaxis:<br>
<pre>adb shell pm [grant|revoke] &lt;permission.name&gt; ...</pre>
</li>
</ul>
</li>
<li>Analiza tu aplicación para detectar servicios que utilizan permisos.</li>
</ul>
<h3 id="permission-test-strategy">Estrategia de prueba</h3>
<p>
El cambio en los permisos afecta la estructura y el diseño de tu aplicación, además de la experiencia del usuario y los flujos que proporcionas a los usuarios.
Debes evaluar el uso de los permisos actuales de tu aplicación y comenzar a planificar los nuevos flujos que deseas ofrecer.
La versión oficial de la plataforma proporciona un comportamiento de compatibilidad, pero debes prever la actualización de tu aplicación y no depender de estos comportamientos.
</p>
<p>
Identifica los permisos que tu aplicación verdaderamente necesita y utiliza, y luego busca las diversas rutas de códigos que utilizan los servicios protegidos por permisos.
Puedes realizar esto mediante una combinación de pruebas en la plataforma nueva y análisis de códigos.
Al realizar las pruebas, debes centrarte en
incluir permisos de tiempo de ejecución cambiando {@code targetSdkVersion} de la aplicación a la versión preliminar. Para
obtener más información, consulta la sección <a href="{@docRoot}preview/setup-sdk.html#">Configurar el SDK de Android N</a>.
</p>
<p>
Realiza pruebas con diversas combinaciones de permisos revocados y agregados, a fin de destacar los flujos del usuario que dependen de permisos.
Cuando una dependencia no sea obvia ni lógica, debes considerar la opción de refactorizar o compartimentar ese flujo para eliminar la dependencia o aclarar por qué se necesita el permiso.
</p>
<p>
Para obtener más información sobre el comportamiento de los permisos de tiempo de ejecución, las pruebas y las mejores prácticas, consulta la página <a href="{@docRoot}preview/features/runtime-permissions.html">Permisos</a> de la versión preliminar para desarrolladores.
</p>
<h2 id="doze-standby">Prueba de los modos Descanso y App Standby</h2>
<p>
Las características de ahorro de energía de los modos Descanso y App Standby limitan la cantidad de procesamiento en segundo plano que puede realizar tu aplicación cuando un dispositivo se encuentra en estado inactivo o mientras tu aplicación no está en foco.
Entre las restricciones que el sistema puede imponer en las aplicaciones se incluyen el acceso limitado a la red o denegación de acceso, suspensión de las tareas en segundo plano, suspensión de notificaciones, y alarmas y solicitudes de reactivación ignoradas.
Para garantizar que tu aplicación tenga un comportamiento correcto con estas optimizaciones de ahorro de energía, debes probar tu aplicación simulando estos estados de bajo consumo.
</p>
<h4 id="doze">Cómo probar la aplicación en modo Descanso</h4>
<p>Para probar el modo Descanso con tu aplicación, realiza lo siguiente:</p>
<ol>
<li>Configura un dispositivo de hardware o un dispositivo virtual con una imagen del sistema Android N.</li>
<li>Conecta el dispositivo a tu equipo de desarrollo e instala tu aplicación.</li>
<li>Ejecuta tu aplicación y déjala activa.</li>
<li>Simula la activación del modo Descanso en el dispositivo ejecutando los siguientes comandos:
<pre>
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
$ adb shell dumpsys deviceidle -h
</pre>
</li>
<li>Observa el comportamiento de tu aplicación cuando se reactive el dispositivo. Asegúrate de que se recupere correctamente cuando el dispositivo salga del modo Descanso.
</li>
</ol>
<h4 id="standby">Cómo probar aplicaciones en modo App Standby</h4>
<p>Para probar el modo App Standby con tu aplicación, realiza lo siguiente:</p>
<ol>
<li>Configura un dispositivo de hardware o un dispositivo virtual con una imagen del sistema Android N.</li>
<li>Conecta el dispositivo a tu equipo de desarrollo e instala tu aplicación.</li>
<li>Ejecuta tu aplicación y déjala activa.</li>
<li>Simula la activación del modo App Standby en la aplicación ejecutando los siguientes comandos:
<pre>
$ adb shell am broadcast -a android.os.action.DISCHARGING
$ adb shell am set-idle &lt;packageName&gt; true
</pre>
</li>
<li>Simula la activación de tu aplicación con el siguiente comando:
<pre>$ adb shell am set-idle &lt;packageName&gt; false</pre>
</li>
<li>Observa el comportamiento de tu aplicación al reactivarse. Asegúrate de que se recupere correctamente del modo App Standby.
En particular, debes comprobar si los trabajos en segundo plano y las notificaciones de tu aplicación continúan funcionando de la manera esperada.
</li>
</ol>
<h2 id="ids">Copia de seguridad automática para aplicaciones e identificadores específicos del dispositivo</h2>
<p>Si tu aplicación continúa teniendo algún identificador específico del dispositivo, como la Id. de registro de Google Cloud Messaging, en el almacenamiento interno, asegúrate de seguir las mejores prácticas para excluir la ubicación de almacenamiento de la copia de seguridad automática, como se describe en la sección <a href="{@docRoot}preview/backup/index.html">Copia de seguridad automática para aplicaciones</a>.
</p>

View File

@@ -1,610 +0,0 @@
page.title=Cambios en los comportamientos
page.keywords=versión preliminar,sdk,compatibilidad
meta.tags="preview", "compatibility"
page.tags="preview", "developer preview"
page.image=images/cards/card-n-changes_2x.png
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#perf">Mejoras de rendimiento</a>
<ol>
<li><a href="#doze">Descanso</a></li>
<li><a href="#bg-opt">Optimizaciones en segundo plano</a></li>
</ol>
</li>
<li><a href="#perm">Cambios en los permisos</a>
</li>
<li><a href="#sharing-files">Intercambio de archivos entre aplicaciones</a></li>
<li><a href="#accessibility">Mejoras de accesibilidad</a>
<ol>
<li><a href="#screen-zoom">Zoom de la pantalla</a></li>
<li><a href="#vision-settings">Vision Settings en el asistente de configuración</a></li>
</ol>
</li>
<li><a href="#ndk">Aplicaciones del NDK con vínculos a bibliotecas de plataformas</a></li>
<li><a href="#afw">Android for Work</a></li>
<li><a href="#annotations">Retención de anotaciones</a></li>
<li><a href="#other">Otros aspectos importantes</a></li>
</ol>
<h2>Consulta también</h2>
<ol>
<li><a href="{@docRoot}preview/api-overview.html">
Información general sobre la API de Android N</a></li>
</ol>
</div>
</div>
<p>
Además de nuevas características y capacidades, Android N
incluye diversos cambios en el sistema y en los comportamientos de la API. En este documento,
se destacan algunos de los cambios principales que debes comprender y justificar
en tus aplicaciones.
</p>
<p>
Si publicaste anteriormente una aplicación para Android, ten en cuenta que tu aplicación
podría verse afectada por estos cambios en la plataforma.
</p>
<h2 id="perf">Batería y memoria</h2>
<p>
Android N incluye cambios en los comportamientos del sistema para mejorar la duración de la batería
de los dispositivos y reducir el uso de la memoria RAM. Estos cambios pueden afectar el acceso de tu aplicación a
recursos del sistema, además de la manera en que tu aplicación interactúa con otras aplicaciones mediante
determinadas intents implícitas.
</p>
<h3 id="doze">Descanso</h3>
<p>
Descanso, presentado en Android 6.0 (nivel de API 23), prolonga la duración de la batería
aplazando actividades de CPU y red cuando un usuario deja un dispositivo desenchufado,
quieto y con la pantalla apagada. En Android N se ofrecen más
mejoras para Descanso a través de la aplicación de un subconjunto de restricciones de CPU y red
mientras el dispositivo se encuentra desenchufado y con la pantalla apagada, aunque no necesariamente
quieto; por ejemplo, al ir dentro del bolsillo de un usuario en movimiento.
</p>
<img src="{@docRoot}images/android-7.0/doze-diagram-1.png" alt="" height="251px" id="figure1" />
<p class="img-caption">
<strong>Figura 1:</strong> Ilustración del modo en que Descanso aplica un primer nivel de
restricciones de actividad del sistema para prolongar la duración de la batería.
</p>
<p>
Cuando un dispositivo funciona con la batería y la pantalla permanece apagada durante un tiempo
determinado, se activa en este el modo Descanso y se aplica el primer subconjunto de restricciones: se
desactiva el acceso de las aplicaciones a la red y se aplazan tareas y sincronizaciones. Si el dispositivo
permanece quieto durante un tiempo determinado tras activarse el modo Descanso, el sistema aplica el
resto de las restricciones del modo a {@link android.os.PowerManager.WakeLock},
alarmas de {@link android.app.AlarmManager}, GPS y análisis de Wi-Fi. Independientemente de que
se apliquen algunas o todas las restricciones del modo Descanso, el sistema activa el
dispositivo durante plazos de mantenimiento breves en los cuales las aplicaciones tienen
acceso a la red y pueden ejecutar sincronizaciones o procesos aplazados.
</p>
<img src="{@docRoot}images/android-7.0/doze-diagram-2.png" alt="" id="figure2" />
<p class="img-caption">
<strong>Figura 2:</strong> Ilustración del modo en que Descanso aplica un segundo nivel de
restricciones de actividad del sistema después de que el dispositivo permanece quieto durante un tiempo determinado.
</p>
<p>
Ten en cuenta que, cuando se activa la pantalla o se enchufa el dispositivo, se desactiva el modo Descanso y
se retiran estas restricciones de procesamiento. El comportamiento adicional no
tiene efecto sobre las recomendaciones ni las prácticas recomendadas para adaptar tu aplicación a la versión
anterior de Descanso, presentada en Android 6.0 (nivel de API 23), según lo descrito en
<a href="{@docRoot}training/monitoring-device-state/doze-standby.html">
Optimización para Descanso y App Standby</a>. De todos modos, debes
seguir las recomendaciones; por ejemplo, la de usar Google Cloud Messaging (GCM) para
enviar y recibir mensajes, y la de planificar actualizaciones para adaptar
el comportamiento adicional de Descanso.
</p>
<h3 id="bg-opt">Project Svelte: Optimizaciones en segundo plano</h3>
<p>
En Android N, se eliminan tres transmisiones implícitas para ayudar a optimizar el uso de la
memoria y el consumo de energía. Este cambio es necesario porque las transmisiones
implícitas a menudo inician aplicaciones que se registran para realizar un seguimiento de ellas en
segundo plano. La eliminación de estas transmisiones puede mejorar sustancialmente el rendimiento del dispositivo
y la experiencia del usuario.
</p>
<p>
Los dispositivos móviles están sujetos a cambios de conectividad frecuentes
entre los modos de datos Wi-Fi y móviles. Actualmente, las aplicaciones pueden realizar controles en busca de cambios en la
conectividad registrando un receptor para la transmisión implícita {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} en su
manifiesto. Debido a que muchas aplicaciones se registran para recibir esta transmisión, un cambio de
red puede hacer que todas se activen y procesen la transmisión a la
vez.
</p>
<p>
Asimismo, en versiones anteriores de Android, las aplicaciones podían registrarse para recibir las transmisiones implícitas {@link
android.hardware.Camera#ACTION_NEW_PICTURE} y {@link
android.hardware.Camera#ACTION_NEW_VIDEO} de otras aplicaciones, como la
cámara. Cuando un usuario toma una foto con la aplicación de la cámara, estas aplicaciones se activan
para procesar la transmisión.
</p>
<p>
Para corregir estos problemas, en Android N se aplican las siguientes
optimizaciones:
</p>
<ul>
<li>Las aplicaciones orientadas a Android N no reciben transmisiones {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION}, aun cuando contengan
entradas de manifiesto que les permitan solicitar notificaciones de estos eventos. Las aplicaciones que
se ejecutan aún pueden escuchar {@code CONNECTIVITY_CHANGE} en su subproceso principal
si solicitan una notificación con un {@link android.content.BroadcastReceiver}.
</li>
<li>Las aplicaciones no pueden enviar ni recibir transmisiones {@link
android.hardware.Camera#ACTION_NEW_PICTURE} ni {@link
android.hardware.Camera#ACTION_NEW_VIDEO}. Esta optimización
afecta a todas las aplicaciones, no solo a aquellas orientadas a Android N.
</li>
</ul>
<p>Si la aplicación utiliza cualquiera de estas intents, debes quitar las dependencias
en ellas lo antes posible a fin de poder orientar los dispositivos con Android N correctamente.
El framework de Android ofrece varias soluciones para mitigar la necesidad de
estas transmisiones implícitas. Por ejemplo, la API {@link
android.app.job.JobScheduler} proporciona un mecanismo sólido para programar
operaciones de red cuando se cumplen las condiciones especificadas, como una conexión a una
red de uso no medido. Puedes usar {@link
android.app.job.JobScheduler} para responder a cambios en proveedores de contenido.
</p>
<p>
Para obtener más información sobre optimizaciones en segundo plano en Android N y la manera de adaptar tu aplicación,
consulta <a href="{@docRoot}preview/features/background-optimization.html">Optimizaciones
en segundo plano</a>.
</p>
<h2 id="perm">Cambios en los permisos</h2>
<p>
En Android N, se incorporan cambios en permisos que pueden afectar tu aplicación.
</p>
<h3 id="permfilesys">Cambios en los permisos del sistema de archivos</h3>
<p>
Para mejorar la seguridad de los archivos privados, el directorio privado de
las aplicaciones orientadas a Android N o versiones posteriores tiene acceso restringido. (<code>0700</code>).
Esta configuración evita la fuga de metadatos de archivos privados, como su tamaño
o existencia. Este cambio en los permisos tiene varios efectos secundarios:
</p>
<ul>
<li>
Los propietarios ya no pueden reducir los permisos de archivo de los archivos privados,
y un intento de hacerlo utilizando
{@link android.content.Context#MODE_WORLD_READABLE} o
{@link android.content.Context#MODE_WORLD_WRITEABLE} activará una
{@link java.lang.SecurityException}.
<p class="note">
<strong>Nota:</strong> Desde ahora, esta restricción no se aplica planamente.
Las aplicaciones pueden seguir modificando los permisos para sus directorios privados con
las API nativas o la API {@link java.io.File File}. Sin embargo, desaconsejamos
reducir los permisos para el directorio privado.
</p>
</li>
<li>
Pasar URI <code>file://</code> fuera del dominio del paquete puede dar al
receptor una ruta de acceso inaccesible. Por lo tanto, los intentos de pasar un
URI <code>file://</code> activan una
<code>FileUriExposedException</code>. La manera recomendada para compartir el
contenido de un archivo privado consiste en utilizar el {@link
android.support.v4.content.FileProvider}.
</li>
<li>
El {@link android.app.DownloadManager} ya no puede compartir archivos
almacenados de manera privada por nombre de archivo. Las aplicaciones heredadas pueden terminar con una
ruta de acceso inaccesible cuando acceden a {@link
android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. Las aplicaciones orientadas a
Android N o versiones posteriores activan una {@link java.lang.SecurityException} cuando
intentan acceder a
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}.
Las aplicaciones heredadas que establecen la ubicación de descarga en una ubicación pública
usando
{@link
android.app.DownloadManager.Request#setDestinationInExternalFilesDir
DownloadManager.Request.setDestinationInExternalFilesDir()} o
{@link
android.app.DownloadManager.Request#setDestinationInExternalPublicDir
DownloadManager.Request.setDestinationInExternalPublicDir()}
siguen teniendo acceso a la ruta de acceso en
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}; sin embargo, se desaconseja
seguir este método. El método preferido para acceder a un archivo
expuesto por el{@link android.app.DownloadManager} consiste en utilizar
{@link android.content.ContentResolver#openFileDescriptor
ContentResolver.openFileDescriptor()}.
</li>
</ul>
<h2 id="sharing-files">Intercambio de archivos entre aplicaciones</h2>
<p>
En las aplicaciones orientadas a Android N, el framework de Android aplica
la política de la API {@link android.os.StrictMode} que prohíbe exponer URI {@code file://}
fuera de la aplicación. Si una intent con un URI de archivo sale de tu aplicación, la aplicación falla
con una excepción {@code FileUriExposedException}.
</p>
<p>
Para compartir archivos entre aplicaciones, debes enviar un URI {@code content://}
y otorgar un permiso de acceso temporal en el URI. La forma más sencilla de otorgar este permiso es
utilizando la clase {@link android.support.v4.content.FileProvider}. Para obtener más información
sobre permisos e intercambio de archivos,
consulta <a href="{@docRoot}training/secure-file-sharing/index.html">Intercambio de archivos</a>.
</p>
<h2 id="accessibility">Mejoras de accesibilidad</h2>
<p>
En Android N, se incluyen cambios destinados a mejorar la usabilidad de la
plataforma para usuarios con defectos o discapacidades visuales. Estos cambios
generalmente no deben exigir modificaciones en el código de tu aplicación. Sin embargo, debes revisar
estas funciones y probarlas con tu aplicación para avaluar el posible impacto en la experiencia
del usuario.
</p>
<h3 id="screen-zoom">Zoom de la pantalla</h3>
<p>
Android N permite a los usuarios configurar <strong>Display size</strong>, el ajuste que expande
o contrae todos los elementos de la pantalla, lo cual mejora la accesibilidad al dispositivo
para usuarios con poca visión. Estos no podrán superar el valor de zoom
mínimo de <a href="http://developer.android.com/guide/topics/resources/providing-resources.html">
sw320dp</a> para el ancho de pantalla, que es el ancho de un Nexus 4, un teléfono común de tamaño intermedio.
</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}images/android-7.0/screen-zoom-1.png" alt="" height="XXX" id="figure1" />
</div>
<div class="col-6">
<img src="{@docRoot}images/android-7.0/screen-zoom-2.png" alt="" height="XXX" id="figure1" />
</div>
</div> <!-- end cols -->
<p class="img-caption">
<strong>Figura 3:</strong> En la pantalla de la derecha se muestra el efecto que tiene
aumentar Display size para un dispositivo con una imagen de sistema de Android N.
</p>
<p>
Al cambiar la densidad del dispositivo, el sistema notifica a las aplicaciones de las
siguientes maneras:
</p>
<ul>
<li>Si una aplicación se orienta hacia el nivel de API 23 o uno inferior, el sistema automáticamente finaliza
todos los procesos en segundo plano. Esto significa que, si un usuario hace a un lado
dicha aplicación para abrir la pantalla <em>Settings</em> y cambiar la configuración de
<strong>Display size</strong>, el sistema finalizará la aplicación tal
como lo haría en una situación de bajos recursos de memoria. Si en la aplicación hay procesos en
primer plano, el sistema notifica a estos procesos el cambio en la configuración como se
indica en <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Manejo de cambios
en tiempo de ejecución</a>, así como lo haría si cambiara la orientación del dispositivo.
</li>
<li>Si una aplicación se orienta hacia Android N, se notifica a todos los procesos
(en primer y segundo plano) el cambio en la configuración, como se
indica en <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Manejo de cambios
en tiempo de ejecución</a>.
</li>
</ul>
<p>
En la mayoría de las aplicaciones, no se necesitan cambios para admitir esta función, si
en ellas se siguen las prácticas recomendadas de Android. Verificaciones específicas que deben realizarse:
</p>
<ul>
<li>Prueba tu aplicación en un dispositivo con ancho de pantalla <code><a href=
"{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code>
y asegúrate de que funcione bien.
</li>
<li>Cuando se modifique la configuración del dispositivo, actualiza la información almacenada en caché que
dependa de la densidad, como los mapas de bits o recursos almacenados en caché que se carguen desde la
red. Busca de cambios en la configuración cuando se reanude la actividad de la aplicación, después de la
pausa.
<p class="note">
<strong>Nota:</strong> Si almacenaste en caché datos que dependen de la configuración, te
convendrá incluir metadatos relacionados, como el tamaño de pantalla
correspondiente o la densidad de píxeles para dichos datos. Guardar estos metadatos te permite
decidir si necesitas actualizar los datos almacenados en caché después de un cambio en la
configuración.
</p>
</li>
<li>Evita especificar dimensiones con unidades px, ya que no responden a la
densidad de pantalla. En lugar de ello, recurre a unidades de <a href="{@docRoot}guide/practices/screens_support.html">píxeles
(<code>dp</code>) independientes de la densidad</a>.
</li>
</ul>
<h3 id="vision-settings">Vision Settings en el asistente de configuración</h3>
<p>
Vision Settings se incluye en la pantalla de Bienvenida de Android N, en la cual los usuarios pueden
configurar los siguientes ajustes de accesibilidad para un nuevo dispositivo:
<strong>Magnification gesture</strong>, <strong>Font size</strong>,
<strong>Display size</strong> y <strong>TalkBack</strong>. Este cambio
aumenta la visibilidad de errores relacionados con diferentes ajustes de pantalla. Para
evaluar el impacto de esta función, debes probar tus aplicaciones con estos
ajustes habilitados. Puedes encontrarlos en <strong>Settings &gt;
Accessibility</strong>.
</p>
<h2 id="ndk">Aplicaciones del NDK con vínculos a bibliotecas de plataformas</h2>
<p>
En Android N, se incluyen cambios en el espacio de nombres a fin de evitar la carga de API no públicas.
Si usas el NDK, solo debes emplear API públicas de la plataforma de
Android. El uso de API no públicas en la próxima versión oficial de Android
puede hacer que tu aplicación se bloquee.
</p>
<p>
Con el propósito de alertarte sobre el uso de API no públicas, las aplicaciones que funcionen en un dispositivo con
Android N producirán un error de salida de logcat cuando una de ellas llame a una API no pública.
Este error también aparecerá en la pantalla del dispositivo como un mensaje para ayudar a
generar conciencia respecto de la situación. Debes revisar el código de tu aplicación para
quitar el uso de API de plataformas no públicas y probar por completo tus aplicaciones con
un dispositivo de prueba o emulador.
</p>
<p>
Si tu aplicación depende de bibliotecas de plataformas, consulta la documentación sobre el NDK a fin de hallar
soluciones típicas para el reemplazo de API privadas comunes por API públicas equivalentes.
También es posible que establezcas vínculos con bibliotecas de plataformas sin notarlo,
en especial si tu aplicación usa una biblioteca que forma parte de la plataforma (como
<code>libpng</code>), pero no del NDK. En ese caso, asegúrate de que
tu APK contenga todos los archivos .so con los cuales intentaste establecer vínculos.
</p>
<p class="caution">
<strong>Advertencia:</strong> Algunas bibliotecas de terceros pueden establecer vínculos con API
no públicas. Si tu aplicación usa estas bibliotecas, es probable que se bloquee al ejecutarse
en la próxima versión oficial de Android.
</p>
<p>
Las aplicaciones no deben depender de bibliotecas nativas no incluidas en el NDK
ni usarlas, ya que pueden modificarse o eliminarse en la transición de una versión de Android a
otra. El cambio de OpenSSL a BoringSSL es un ejemplo de modificaciones como esta.
A su vez, los diferentes dispositivos pueden ofrecer distintos niveles de compatibilidad, debido a que
no existen requisitos de compatibilidad para bibliotecas de plataformas no incluidas
en el NDK. Si debes acceder a bibliotecas no relacionadas con el NDK en dispositivos anteriores, haz que la
carga dependa del nivel de la API de Android.
</p>
<p>
Para ayudarte a diagnosticar estos tipos de problemas, a continuación, se ofrecen ejemplos de errores de Java y
del NDK que podrías hallar al intentar compilar tu aplicación con Android N:
</p>
<p>Ejemplo de error de Java:</p>
<pre class="no-pretty-print">
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
is not accessible for the namespace "classloader-namespace"
</pre>
<p>Ejemplo de error de NDK:</p>
<pre class="no-pretty-print">
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
</pre>
<p>
Aquí se ofrecen soluciones típicas para aplicaciones en las que se produzcan estos tipos de errores:
</p>
<ul>
<li>getJavaVM y getJNIEnv de libandroid_runtime.so pueden reemplazarse
por funciones estándares de JNI:
<pre class="no-pretty-print">
AndroidRuntime::getJavaVM -&gt; GetJavaVM from &lt;jni.h&gt;
AndroidRuntime::getJNIEnv -&gt; JavaVM::GetEnv or
JavaVM::AttachCurrentThread from &lt;jni.h&gt;.
</pre>
</li>
<li>El símbolo {@code property_get} de {@code libcutils.so} puede
reemplazarse por la API pública {@code alternative __system_property_get}.
Para hacerlo, usa {@code __system_property_get} con el siguiente elemento include:
<pre>
#include &lt;sys/system_properties.h&gt;
</pre>
</li>
<li>El símbolo {@code SSL_ctrl} de {@code libcrypto.so} debe
reemplazarse por una versión local de la aplicación. Por ejemplo, debes establecer un vínculo estático de
{@code libcyrpto.a} en tu archivo {@code .so} o incluir un vínculo dinámico propio de
{@code libcrypto.so} de BoringSSL u OpenSSL en tu aplicación.
</li>
</ul>
<h2 id="afw">Android for Work</h2>
<p>
Android N contiene cambios para aplicaciones orientadas a Android for Work, entre los que se incluyen
modificaciones en la instalación de certificados, el restablecimiento de contraseñas, la gestión de usuarios
secundarios y el acceso a identificadores de dispositivos. Si creas aplicaciones para entornos de
Android for Work, debes estudiar estos cambios y modificar
tu aplicación según corresponda.
</p>
<ul>
<li>Debes usar un instalador de certificados delegados para que el controlador de políticas de dispositivos (DPC) pueda
configurarlo. Para aplicaciones de propietarios de perfiles y de dispositivos orientadas al SDK de Android N, debes
usar el instalador de certificados delegados para que el
DPC llame a
<code>DevicePolicyManager.setCertInstallerPackage()</code>. Si el instalador
no está instalado de antemano, el sistema emite una
<code>IllegalArgumentException</code>.
</li>
<li>Las restricciones de restablecimiento de contraseñas para administradores de dispositivos ahora se aplican a los propietarios de
perfiles. Los administradores de dispositivos ya no pueden usar
{@code DevicePolicyManager.resetPassword()} para borrar contraseñas ni modificar
las que ya están establecidas. No obstante, pueden establecer una contraseña, aunque solo
cuando el dispositivo no tiene contraseña, PIN ni patrón.
</li>
<li>Los propietarios de dispositivos y perfiles pueden administrar cuentas aun cuando haya
restricciones. Tienen la posibilidad de llamar a las API de administración de cuentas
incluso al haber restricciones <code>DISALLOW_MODIFY_ACCOUNTS</code> para el usuario.
</li>
<li>Los propietarios de dispositivos pueden administrar usuarios secundarios de manera más sencilla. Cuando un dispositivo
funciona en el modo de propietario de dispositivo, automáticamente se establece la restricción <code>DISALLOW_ADD_USER</code>
. Esto evita que los usuarios creen usuarios secundarios no
administrados. A su vez, los métodos <code>CreateUser()</code> y
<code>createAndInitializeUser()</code> han sido dados de baja; los reemplaza el nuevo método
<code>DevicePolicyManager.createAndManageUser()</code>.
</li>
<li>Los propietarios de dispositivos pueden acceder a identificadores de dispositivos. Tienen la posibilidad de acceder a la
dirección MAC de Wi-Fi de un dispositivo a través de
<code>DevicePolicyManagewr.getWifiMacAddress()</code>. Si nunca se habilitó la función Wi-Fi
en el dispositivo, este método devuelve un valor {@code null}.
</li>
<li>La configuración Work Mode controla el acceso a las aplicaciones de trabajo. Cuando este ajuste está desactivado, el
launcher del sistema indica que las aplicaciones de trabajo no están disponibles atenuándolas. Para volver
a restaurar el comportamiento normal, habilita el modo de trabajo nuevamente.
</ul>
<p>
Para obtener más información sobre los cambios de Android for Work en Android N, consulta
<a href="{@docRoot}preview/features/afw.html">Actualizaciones de Android for Work</a>.
</p>
<h2 id="annotations">Retención de anotaciones</h2>
<p>
Android N soluciona un error por el cual la visibilidad de las anotaciones se había ignorado.
Este problema permitió que el tiempo de ejecución accediera a anotaciones a las que no debía
tener acceso. Entre estas anotaciones se incluyen las siguientes:
</p>
<ul>
<li>{@code VISIBILITY_BUILD}: destinada a ser visible solo en el momento de compilación.</li>
<li>{@code VISIBILITY_SYSTEM}: destinada a ser visible en el tiempo de ejecución, pero únicamente al
sistema subyacente.</li>
</ul>
<p>
Si tu aplicación se basa en este comportamiento, agrega una política de retención para las anotaciones que deben
estar disponibles en el tiempo de ejecución. Para ello, usa {@code @Retention(RetentionPolicy.RUNTIME)}.
</p>
<h2 id="other">Otros aspectos importantes</h2>
<ul>
<li>Cuando una aplicación funcione en Android N, pero esté orientada a un nivel de API inferior,
y el usuario modifique el tamaño de pantalla, el proceso de la aplicación finalizará. La aplicación
debe tener capacidad para manejar correctamente esta situación. De lo contrario, se bloqueará
cuando el usuario la restaure desde Recents.
<p>
Debes probar tu aplicación para controlar que no tenga lugar
este comportamiento.
Puedes hacerlo produciendo un error idéntico
al finalizarla manualmente a través del panel DDMS.
</p>
<p>
Las aplicaciones orientadas a Android N y versiones posteriores no finalizarán automáticamente por cambios en la densidad;
sin embargo, es posible que respondan en forma deficiente a los cambios en la configuración.
</p>
</li>
<li>
En Android N, las aplicaciones deben tener capacidad para manejar correctamente los cambios de configuración
y no deben bloquearse durante inicios posteriores. Puedes verificar el comportamiento de las aplicaciones
modificando el tamaño de la fuente (<strong>Setting</strong> &gt;
<strong>Display</strong> &gt; <strong>Font size</strong>) y restaurándolas
desde Recents.
</li>
<li>
Debido a un error en versiones anteriores de Android, el sistema no indicaba la escritura
a un socket del TCP en el subproceso principal como una violación del modo strict. En Android N, se corrige este error.
Las aplicaciones que tienen este comportamiento, ahora emiten una {@code android.os.NetworkOnMainThreadException}.
Generalmente, realizar operaciones de red en el subproceso principal no es una buena idea porque estas operaciones
suelen tener una latencia alta de cola que genera mensajes que indican que la aplicación no responde y bloqueos.
</li>
<li>
De manea predeterminada, la familia de métodos {@code Debug.startMethodTracing()} ahora
almacena los resultados en el directorio específico del paquete en el almacenamiento compartido,
en lugar de hacerlo en el nivel superior
de la tarjeta SD. Esto significa que las aplicaciones ya no tienen que solicitar el permiso {@code WRITE_EXTERNAL_STORAGE} para usar estas API.
</li>
<li>
Muchas API de la plataforma han comenzado a controlar en busca del envío de cargas grandes
a través de transacciones {@link android.os.Binder}. Además, el
sistema ahora vuelve a emitir {@code TransactionTooLargeExceptions}
como {@code RuntimeExceptions}, en lugar de registrarlas o suprimirlas silenciosamente. Un
ejemplo común es almacenar demasiados datos en
{@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()},
lo que hace que {@code ActivityThread.StopInfo} emita una
{@code RuntimeException} cuando la aplicación se orienta a Android N.
</li>
<li>
Si una aplicación publica tareas {@link java.lang.Runnable} en una {@link android.view.View}, y
la {@link android.view.View}
no está anexada a una ventana, el sistema
pone en cola la tarea {@link java.lang.Runnable} con la {@link android.view.View}.
La tarea {@link java.lang.Runnable} no se ejecuta hasta que la
{@link android.view.View} esté anexada
a una ventana. Este comportamiento soluciona los siguientes errores:
<ul>
<li>Si una aplicación publicaba una {@link android.view.View} desde un subproceso que no fuera el subproceso de la IU
de la ventana prevista, la tarea {@link java.lang.Runnable} podía ejecutarse en el subproceso incorrecto.
</li>
<li>Si la tarea {@link java.lang.Runnable} se publicaba desde un subproceso que no fuera
un subproceso de looper, la aplicación podía exponer la terea {@link java.lang.Runnable}.</li>
</ul>
</li>
<li>
Si una aplicación en Android N con el permiso
{@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES}
intentaba borrar un paquete instalado por otra aplicación,
el sistema solicitaba la confirmación del usuario. En este escenario, las aplicaciones debían esperar recibir el estado
{@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION}
al invocar
{@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}.
</li>
</ul>

View File

@@ -1,85 +0,0 @@
page.title=Ejemplos
page.tags="preview", "samples", "android"
page.image=images/cards/card-n-samples_2x.png
@jd:body
<p>
Los siguientes ejemplos de código se proporcionan para Android N. Para
descargarlos en Android Studio, selecciona la opción de menú <b>File &gt; Import
Samples</b>.
</p>
<p class="note">
<strong>Nota:</strong> Estos proyectos que se pueden descargar están diseñados
para su uso con Gradle y Android Studio.
</p>
<h3 id="mw">“Área de juegos” de ventanas múltiples</h3>
<img src="{@docRoot}images/android-7.0/sample-multiwindow.png" style="float: left; padding-right: 0.5em" height="250" width="156" />
<p>
En este ejemplo se muestra la manera de aprovechar interfaces de usuario
de ventanas múltiples con tu aplicación.
</p>
<p>
<a href="https://github.com/googlesamples/android-MultiWindowPlayground">
Obtener en GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="an">Notificaciones activas</h3>
<img src="{@docRoot}images/android-7.0/sample-activenotifications.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
Este es un ejemplo preexistente en el cual se muestra un servicio simple que envía
notificaciones con NotificationCompat. Cada conversación no leída
se envía como una notificación diferente.
</p>
<p>
Este ejemplo se actualizó para aprovechar nuevas funciones de notificación
disponibles en Android N.
</p>
<p>
<a href="https://github.com/googlesamples/android-ActiveNotifications">
Obtener en GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="ms">Servicio de mensajería</h3>
<img src="{@docRoot}images/android-7.0/sample-messagingservice.png" style="float: left; padding-right: 0.5em" height="250" width="150" />
<p>
Este es un ejemplo preexistente en el que se demuestra la manera de usar
NotificationManager para indicar la cantidad de notificaciones que se aparecen actualmente en una
aplicación.
</p>
<p>
Este ejemplo se actualizó para aprovechar nuevas funciones de notificación
disponibles en Android N.
</p>
<p>
<a href="https://github.com/googlesamples/android-MessagingService">
Obtener en GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="fbe">Inicio directo</h3>
<img src="{@docRoot}images/android-7.0/sample-directboot.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
En este ejemplo se demuestra la manera de almacenar datos, y de acceder a ellos, en un medio de almacenamiento encriptado por
dispositivo que esté siempre disponible mientras el dispositivo se haya iniciado.
</p>
<p>
<a href="https://github.com/googlesamples/android-DirectBoot">
Obtener en GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="sda">Acceso a directorios determinados</h3>
<img src="{@docRoot}images/android-7.0/sample-scopeddirectoryaccess.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
En este ejemplo se demuestra la manera de leer y escribir datos de
directorios específicos y, al mismo tiempo, evitar más permisos.
</p>
<p>
<a href="https://github.com/googlesamples/android-ScopedDirectoryAccess">
Obtener en GitHub</a>
</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +0,0 @@
page.title=Android 7.0 Nougat
page.tags="androidn","versions"
meta.tags="android n", "nougat", "android 7.0"
fullpage=true
forcelocalnav=true
header.hide=1
footer.hide=1
@jd:body
<section class="dac-expand dac-hero dac-light">
<div class="wrap" style="max-width:1100px;margin-top:0">
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
<div class="cols dac-hero-content" style="padding-bottom:1em;">
<div class="col-7of16 col-push-8of16" style="padding-left:2em">
<h1 class="dac-hero-title">Android 7.0 Nougat</h1>
<p class="dac-hero-description">
¡Prepárate para Android Nougat!
<strong>Prueba tus aplicaciones</strong> en Nexus y en otros dispositivos. Admite comportamientos del sistema
nuevo para <strong>ahorrar energía y memoria</strong>.
Amplía la funcionalidad de tus aplicaciones gracias a una <strong>IU con ventanas múltiples</strong>,
<strong>notificaciones de respuestas directas</strong> y más.
</p>
<a class="dac-hero-cta" href="{@docRoot}about/versions/nougat/android-7.0.html">
<span class="dac-sprite dac-auto-chevron"></span>
Comencemos
</a>
</div>
<div class="col-7of16 col-pull-6of16 dac-hero-figure" style="margin-top:1.5em;padding-right:1.5em;">
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
<img class="dac-hero-image" src="{@docRoot}images/home/n-preview-hero.png"
srcset="{@docRoot}images/home/n-preview-hero.png 1x,
{@docRoot}images/home/n-preview-hero_2x.png 2x" />
</a>
</div>
</div></a>
<div class="dac-section dac-small">
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/resources"
data-cardSizes="6x2"
data-maxResults="3"></div>
</div>
</div>
</section>
<div class="dac-section dac-slim dac-gray dac-expand">
<div class="wrap dac-offset-parent">
<a class="dac-fab dac-scroll-button" data-scroll-button href="#latest">
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
<ul class="dac-actions">
<li class="dac-action">
<a class="dac-action-link" href="https://source.android.com/source/report-bugs.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Informa un problema
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}preview/dev-community">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Únete a la comunidad de desarrolladores
</a>
</li>
</ul>
</div><!-- end .wrap -->
</div><!-- end .dac-actions -->
<section class="dac-section dac-light dac-small" id="latest"><div class="wrap">
<h2 class="norule">Lo último</h2>
<div class="resource-widget resource-flow-layout col-16"
data-query="type:blog+tag:androidn+tag:featured, type:youtube+tag:androidn+tag:featured"
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="3"></div>
</div></section>
<section class="dac-section dac-gray" id="videos"><div class="wrap">
<h1 class="dac-section-title">Videos</h1>
<div class="dac-section-subtitle">
New Android capabilities and the right way to use them in your apps.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/videos/first,type:youtube+tag:androidn"
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="3">
</div>
</div></section>
<section class="dac-section dac-light" id="resources"><div class="wrap">
<h1 class="dac-section-title">Recursos</h1>
<div class="dac-section-subtitle">
Información esencial para ayudarte a preparar tus aplicaciones para Android Nougat.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/more"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="6"></div>
</div>
</section>

View File

@@ -1,307 +0,0 @@
page.title=Principios de diseño para Android
@jd:body
<p>Estos principios de diseño fueron creados por el
equipo de experiencia del usuario de Android para su propio uso, con el fin de tener siempre en cuenta lo mejor para los usuarios.
En cuanto a los desarrolladores y diseñadores de Android, continúan
utilizando las pautas de diseño más detalladas para los diferentes
tipos de dispositivos.</p>
<p>
Tenga en cuenta estos principios cuando ponga en práctica su propia
creatividad e ideas de diseño. Desvíese de lo tradicional con un propósito.
</p>
<h2 id="enchant-me">Cautívame</h2>
<div class="cols">
<div class="col-7">
<h4 id="delight-me">Deléitame de formas sorprendentes</h4>
<p>Una superficie atractiva, una animación colocada en el lugar correcto o un efecto de sonido bien sincronizado suelen ser experiencias
placenteras. Los efectos sutiles contribuyen a crear un sentimiento de facilidad y la sensación de que se cuenta con una fuerza
poderosa.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="real-objects-more-fun">Los objetos reales son más divertidos que los botones y los menús</h4>
<p>Permite que los usuarios toquen y manipulen directamente los objetos de tu aplicación. Esto reduce el esfuerzo cognitivo
que se necesita para llevar a cabo una tarea que resulte satisfactoria a nivel emocional.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-it-mine">Permíteme darle un toque personal</h4>
<p>A los usuarios les gusta agregar toques personales, ya que esto los ayuda a sentirse cómodos y a sentir que tienen el control. Ofrece
opciones predeterminadas prácticas y atractivas, pero también ten en cuenta personalizaciones opcionales y divertidas que no entorpezcan las
tareas principales.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="get-to-know-me">Conóceme</h4>
<p>Con el paso del tiempo, conoce las preferencias de los usuarios. En lugar de pedirles a los usuarios que elijan las mismas cosas una y otra
vez, permita que puedan acceder fácilmente a las opciones que ya eligieron antes.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
</div>
</div>
<h2 id="simplify-my-life">Simplifica mi vida</h2>
<div class="cols">
<div class="col-7">
<h4 id="keep-it-brief">Sé breve</h4>
<p>Utilice frases cortas con palabras simples. Las personas tienden a omitir las oraciones largas.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="pictures-faster-than-words">Las imágenes son más prácticas que las palabras</h4>
<p>Considera la idea de utilizar imágenes para explicar las ideas. Las imágenes atraen la atención de las personas y pueden ser mucho más eficientes
que las palabras.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="decide-for-me">Decide por mí, pero permíteme tener la última palabra</h4>
<p>Sigue su instinto y actúa sin preguntar primero. Tener que elegir demasiadas veces y tomar muchas decisiones hace que las personas
se sientan molestas. Permite que los usuarios puedan deshacer sus elecciones en caso de que no sean lo que ellos desean.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="only-show-when-i-need-it">Solo muéstrame lo que necesito, cuando lo necesito</h4>
<p>Los usuarios se sienten abrumados cuando se les presenta demasiada información al mismo tiempo. Divide las tareas y la información en fragmentos pequeños
y fáciles de digerir. Oculta las opciones que no son fundamentales en el momento y capacita a los usuarios sobre la marcha.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="always-know-where-i-am">Siempre debo saber dónde me encuentro</h4>
<p>Haz que los usuarios sientan que conocen el camino de regreso. Para ello, diseña las distintas partes de su aplicación de modo tal que se vean diferentes y
utiliza transiciones para mostrar la relación entre las pantallas. Proporciona comentarios sobre las tareas que están en curso.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="never-lose-my-stuff">Nunca pierdas lo que es mío</h4>
<p>Guarda aquellas cosas que los usuarios crearon y permíteles acceder a ellas desde cualquier lugar. Recuerda las configuraciones,
los toques personales y las creaciones en todos los teléfonos, las tablets y las computadoras. Esta es la forma de hacer que las actualizaciones
sean lo más simple del mundo.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="looks-same-should-act-same">Si se ve igual, debe funcionar de la misma manera</h4>
<p>Ayuda a los usuarios a distinguir las diferencias funcionales al lograr que se vean diferentes en lugar de sutiles.
Evite los modos, que son sitios que lucen similar pero actúan diferente ante la misma entrada.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="interrupt-only-if-important">Solo interrúmpeme si es importante</h4>
<p>Al igual que un buen asistente personal, evite a los usuarios los pormenores poco importantes. Las personas desean estar
concentradas y, a menos que sea fundamental y esté sujeta a un plazo de tiempo, una interrupción puede resultar agobiante y frustrante.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
</div>
</div>
<h2 id="make-me-amazing">Permíteme ser asombroso</h2>
<div class="cols">
<div class="col-7">
<h4 id="give-me-tricks">Ofrézame trucos que funcionen en todos lados</h4>
<p>Las personas se sienten muy bien cuando descubren cosas por sí mismos. Logra que su aplicación sea más simple de utilizar al
aprovechar los patrones visuales y la memoria muscular de otras aplicaciones de Android. Por ejemplo, el gesto de deslizar rápidamente
puede ser un buen acceso directo de navegación.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="its-not-my-fault">No es mi culpa</h4>
<p>Sé sutil cuando solicites a los usuarios que realicen correcciones. Ellos desean sentirse inteligentes cuando usan la
aplicación que creaste. Si hacen algo mal, bríndales instrucciones claras de recuperación, pero evita darles detalles técnicos.
Sería incluso mejor que tú lo soluciones en segundo plano.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="sprinkle-encouragement">Fomenta lo simple</h4>
<p>Desglosa las tareas complejas en pasos más pequeños que se puedan cumplir fácilmente. Ofrece comentarios sobre las acciones,
incluso si es simplemente un halago sutil.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="do-heavy-lifting-for-me">Haz el trabajo pesado por mí</h4>
<p>Haz que los principiantes se sientan como expertos al permitirles hacer cosas que pensaron que nunca podrían hacer. Por
ejemplo, a través de los accesos directos en los que se combinan múltiples efectos de fotografías, puedes lograr que las fotografías de principiantes se vean maravillosas
en solo algunos pasos.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-important-things-fast">Haz que lo importante sea rápido</h4>
<p>No todas las acciones son iguales. Decide qué es lo más importante en tu aplicación y haz
que los usuarios lo puedan encontrar fácilmente y utilizar de forma rápida, como el obturador de una cámara o el botón de pausa de un reproductor de música.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">
</div>
</div>

View File

@@ -1,186 +0,0 @@
page.title=Material Design para Android
page.tags=Material,design
page.type=design
page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
<!-- developer docs box -->
<a class="notice-developers right" href="{@docRoot}training/material/index.html">
<div>
<h3>Documentos para desarrolladores</h3>
<p>Creación de aplicaciones con Material Design</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=p4gmvHyuZzw">
<div>
<h3>Video</h3>
<p>Introducción a Material Design</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
<div>
<h3>Video</h3>
<p>Papel y tinta: los materiales más importantes</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=XOcCOBe8PTc">
<div>
<h3>Video</h3>
<p>Material Design en la aplicación Google I/O</p>
</div>
</a>
<p itemprop="description">Material Design es una guía integral para el diseño visual, de movimientos y
de interacción en distintas plataformas y dispositivos. Android ahora es compatible con las aplicaciones de
Material Design. Para usar Material Design en tus aplicaciones de Android, sigue las pautas descritas
en la <a href="http://www.google.com/design/spec">especificación de Material Design</a> y usa los
nuevos componentes y funcionalidades disponibles en Android 5.0 (nivel de API 21) y versiones posteriores.</p>
<p>En Android, se proporcionan los siguientes elementos que te permitirán crear aplicaciones en Material Design:</p>
<ul>
<li>un tema nuevo;</li>
<li>nuevos widgets para vistas complejas;</li>
<li>nuevas API (interfaces de programación de aplicaciones) para sombras y animaciones personalizadas.</li>
</ul>
<p>Para obtener más información sobre la implementación de Material Design en Android, consulta
<a href="{@docRoot}training/material/index.html">Creación de aplicaciones con Material Design</a>.</p>
<h3>Tema Material</h3>
<p>El tema Material te ofrece un nuevo estilo para tu aplicación, widgets del sistema que te permiten configurar
la paleta de colores y animaciones predeterminadas para información táctil y transiciones de actividades.</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema Dark Material</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema Light Material</p>
</div>
</div>
<br style="clear:left"/>
</div>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/theme.html">Uso del tema
Material</a>.</p>
<h3>Listas y tarjetas</h3>
<p>Android proporciona dos widgets nuevos para mostrar listas y tarjetas con estilos y
animaciones de Material Design:</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
<p>El nuevo widget <code>RecyclerView</code> es una versión más acoplable de <code>ListView</code>
que admite diferentes tipos de diseños y proporciona mejoras en el rendimiento.</p>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
<p>El nuevo widget <code>CardView</code> te permite mostrar extractos de información importante dentro de
tarjetas que tienen apariencia y estilo coherentes.</p>
</div>
<br style="clear:left"/>
</div>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/lists-cards.html">Creación de listas
y tarjetas</a>.</p>
<h3>Visualización de sombras</h3>
<p>Además de las propiedades X e Y, las vistas de Android ahora poseen una
propiedad Z. Esta propiedad nueva representa la elevación de una vista, que determina lo siguiente:</p>
<ul>
<li>El tamaño de la sombra: las vistas con valores Z más elevados proyectan sombras más grandes.</li>
<li>El orden del dibujo: las vistas con valores Z más elevados aparecen sobre las otras vistas.</li>
</ul>
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay>
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4"/>
<source src="{@docRoot}design/videos/ContactsAnim.webm"/>
<source src="{@docRoot}design/videos/ContactsAnim.ogv"/>
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<em>Para volver a reproducir la película, haz clic en la pantalla del dispositivo.</em>
</div>
</div>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/shadows-clipping.html">Definición
de vistas de recorte y sombras</a>.</p>
<h3>Animaciones</h3>
<p>Las nuevas API de animaciones te permiten crear animaciones personalizadas para la información táctil en los controles de IU,
además de realizar cambios en el estado de las vistas y transiciones entre actividades.</p>
<p>Estas API te permiten hacer lo siguiente:</p>
<ul>
<li style="margin-bottom:15px">
responder a los eventos táctiles de tus vistas mediante animaciones de <strong>información táctil</strong>;
</li>
<li style="margin-bottom:15px">
ocultar y mostrar vistas con animaciones con <strong>efecto circular</strong>;
</li>
<li style="margin-bottom:15px">
alternar entre actividades con animaciones personalizadas de <strong>transición de actividades</strong>;
</li>
<li style="margin-bottom:15px">
crear animaciones más naturales con <strong>movimiento curvo</strong>;
</li>
<li style="margin-bottom:15px">
animar los cambios en una o más propiedades de las vistas con las animaciones de <strong>cambio de estado de la vista</strong>;
</li>
<li style="margin-bottom:15px">
mostrar animaciones en los <strong>elementos de diseño de la lista de estados</strong> entre los cambios de estado de las vistas.
</li>
</ul>
<p>Las animaciones de la información táctil se concentran en diferentes vistas estándar, como los botones. Las nuevas API
te permiten personalizar estas animaciones y agregarlas a tus vistas personalizadas.</p>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/animations.html">Definición de animaciones
personalizadas</a>.</p>
<h3>Elementos de diseño</h3>
<p>Estas nuevas capacidades para los elementos de diseño te permiten implementar aplicaciones de Material Design:</p>
<ul>
<li>Los <strong>dibujables en vector</strong> se pueden escalar sin perder definición y son perfectos
para los iconos de las aplicaciones de un solo color.</li>
<li>El <strong>teñido de los dibujables</strong> te permite definir mapas de bits como máscaras alfa y pintarlos con
un color durante el tiempo de ejecución.</li>
<li>La <strong>extracción de color</strong> te permite extraer automáticamente colores prominentes de una
imagen del mapa de bits.</li>
</ul>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/drawables.html">Trabajo con
elementos de diseño</a>.</p>

View File

@@ -1,70 +0,0 @@
page.title=Compatibilidad con versiones anteriores
page.tags="support"
page.metaDescription=Notas sobre cómo Android 4.x adapta la IU diseñada para versiones de hardware y de SO anteriores.
@jd:body
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
<div>
<h3>Documentos para desarrolladores</h3>
<p>Compatible con diferentes dispositivos</p>
</div>
</a>
<p>Estos son algunos de los cambios importantes en Android 3.0:</p>
<ul>
<li>Se dejan de usar las teclas físicas de menú (Atrás, Menú, Búsqueda, Inicio) en favor de la navegación
mediante controles virtuales (Back, Home, Recents).</li>
<li>Patrón sólido para el uso de menús en las barras de acción.</li>
</ul>
<p>Android 4.0 incorpora estos cambios para tablets en la plataforma del teléfono.</p>
<h2 id="older-hardware">Adaptar Android 4.0 a hardware y aplicaciones anteriores</h2>
<div class="cols">
<div class="col-6">
<h4>Teléfonos con controles de navegación virtuales</h4>
<p>Las aplicaciones de Android escritas para Android 3.0 y versiones posteriores muestran acciones en la barra de acciones. Las acciones que no
caben en la barra de acciones o que no son lo suficientemente importantes para que se las muestre en el nivel superior aparecen en la
ampliación de acciones (action overflow).</p>
<p>Los usuarios acceden a la ampliación de acciones (action overflow) tocando la barra de acciones.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Teléfonos con teclas de navegación físicas</h4>
<p>Los teléfonos con Android que tienen teclas físicas de navegación no muestran la barra de navegación virtual en
la parte inferior de la pantalla. En cambio, la ampliación de acciones (action overflow) está disponible desde la tecla física de menú. La
ventana emergente con acciones que se muestra tiene el mismo estilo que la del ejemplo anterior, pero aparece en la parte inferior de la pantalla.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Aplicaciones heredadas en teléfonos con controles de navegación virtuales</h4>
<p>Cuando se ejecuta una aplicación que fue generada para Android 2.3 o versiones anteriores en un teléfono con controles de
navegación virtuales, aparece un control de ampliación de acciones (action overflow) a la derecha de la barra de navegación virtual. Se
puede tocar el control para ver las acciones de la aplicación con el estilo del menú tradicional de Android.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
</div>
</div>

View File

@@ -1,70 +0,0 @@
page.title=Confirmación y reconocimiento
page.tags=dialog,toast,notification
@jd:body
<p>En algunos casos, cuando un usuario invoca una acción desde tu aplicación, se recomienda <em>confirmar</em> o proporcionar un <em>reconocimiento</em> de dicha acción a través del texto.</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>Confirmación</strong> es solicitarle al usuario que verifique que realmente desea proceder con una acción que acaba de invocar. En algunos casos, la confirmación se presenta junto con una advertencia o mensaje con información importante relacionada con la acción que el usuario debe aprobar.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p>El <strong>reconocimiento</strong> hace referencia al hecho de mostrar un determinado texto para informarle al usuario que la acción que acaba de invocar ya se completó. De este modo, se elimina la incertidumbre sobre las operaciones implícitas que lleva a cabo el sistema. En algunos casos, el reconocimiento se presenta junto con una opción para deshacer la acción.</p>
</div>
</div>
<p>Comunicarse con los usuarios de este modo permite reducir la incertidumbre respecto de acciones pasadas o futuras. Mediante la confirmación o el reconocimiento también se puede evitar que los usuarios cometan errores de los que podrían arrepentirse.</p>
<h2>Cuándo se debe solicitar una confirmación o proporcionar un reconocimiento de las acciones de los usuarios</h2>
<p>No es necesario que se solicite una confirmación o se proporcione un reconocimiento para todas las acciones. Utiliza este diagrama de flujo cuando tengas que tomar decisiones relacionadas con el diseño.</p>
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>Confirmación</h2>
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Google Play Books</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>En este ejemplo, el usuario solicitó eliminar un libro de su biblioteca de Google Play. Aparecerá una <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">alerta</a> para confirmar esta acción porque es importante que el usuario comprenda que el libro ya no estará disponible desde ningún dispositivo.</p>
<p>Cuando diseñes un cuadro de diálogo de confirmación, asegúrate de que el título sea significativo y que incluya la acción solicitada.</p>
</div>
<div class="col-7">
<h4>Ejemplo: Android Beam</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>No es necesario que las confirmaciones se presenten en todas las alertas con dos botones. Luego de iniciar Android Beam, se le solicita al usuario que seleccione el contenido que desea compartir (en este ejemplo, se trata de una fotografía). Si el usuario decide no continuar, simplemente se descartará el teléfono de la lista.</p>
</div>
</div>
<h2>Reconocimiento</h2>
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Borrador de Gmail abandonado y guardado</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>En este ejemplo, si el usuario navega con los botones Back o Up desde la pantalla de redacción de Gmail, posiblemente ocurrirá algo inesperado: el borrador actual se guardará automáticamente. Esto se mostrará a través de un reconocimiento en forma de aviso. Dicho aviso desaparece luego de algunos segundos.</p>
<p>En este caso, no se puede incluir la opción de deshacer porque el almacenamiento fue iniciado por la aplicación, no por el usuario. Gracias a esto, se puede continuar redactando el mensaje de forma rápida y fácil con solo navegar hasta la lista de borradores.</p>
</div>
<div class="col-6">
<h4>Ejemplo: Conversación de Gmail eliminada</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>Después de que el usuario elimina una conversación de la lista de Gmail, aparece un mensaje de reconocimiento con la opción de deshacer la acción. Dicho reconocimiento seguirá en pantalla hasta que el usuario lleve a cabo una acción no relacionada, como desplazarse por la lista.</p>
</div>
</div>
<h2>Sin confirmación ni reconocimiento</h2>
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Hacer +1</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>No se necesita confirmación</strong>. Si el usuario eligió +1 sin querer, esto no es un problema. Simplemente, puede tocar el botón de nuevo para deshacer la acción.</p>
<p><strong>No se necesita un reconocimiento</strong>. El usuario verá que el botón +1 parpadea y cambia a color rojo. Esa es una señal muy clara.</p>
</div>
<div class="col-7">
<h4>Ejemplo: Eliminación de una aplicación de la pantalla de inicio</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>No se necesita confirmación</strong>. Esta es una acción intencionada: el usuario debe arrastrar y colocar un elemento en un destino relativamente grande y aislado. Por lo tanto, es poco probable que se cometan errores. No obstante, si el usuario se arrepiente de la decisión que tomó, solo demorará algunos segundos en recuperar lo eliminado.</p>
<p><strong>No se necesita un reconocimiento</strong>. El usuario sabrá que la aplicación ya no aparecerá en la Pantalla de inicio porque él mismo la hizo desaparecer al arrastrarla.</p>
</div>
</div>

View File

@@ -1,213 +0,0 @@
page.title=Navegación con los botones Back y Up
page.tags="navigation","activity","task","up navigation","back navigation"
page.image=/design/media/navigation_between_siblings_gmail.png
@jd:body
<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
<div>
<h3>Documentos para desarrolladores</h3>
<p>Implementación de la navegación eficiente</p>
</div>
</a>
<p itemprop="description">La navegación coherente es un componente fundamental de la experiencia general del usuario. Pocas situaciones frustran más a los
usuarios que la navegación básica que se comporta de forma irregular e inesperada. En Android 3.0,
se introdujeron cambios significativos en el comportamiento global de la navegación. Si sigues detalladamente
las pautas de navegación con los botones Back y Up, la navegación en tu aplicación será predecible y confiable para los usuarios.</p>
<p>En Android 2.3 y versiones anteriores, se confió en el botón <em>Back</em> del sistema para respaldar la navegación dentro de una
aplicación. Con la introducción de las barras de acción en Android 3.0, apareció un segundo mecanismo de navegación:
el botón <em>Up</em>, que consiste en el icono de la aplicación y una pequeña flecha a la izquierda.</p>
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
<h2 id="up-vs-back">Up en comparación con Back</h2>
<p>El botón Up se utiliza para navegar dentro de una aplicación sobre la base de las relaciones jerárquicas
entre pantallas. Por ejemplo, si en la pantalla A se muestra una lista de elementos y, si se selecciona un elemento, se conduce al usuario a la
pantalla B (en la que se presenta ese elemento de forma más detallada), entonces en la pantalla B se debe mostrar el botón Up para regresar
a la pantalla A.</p>
<p>Si una pantalla aparece en la parte superior de una aplicación (es decir, en el inicio de la aplicación), no debes incluir el botón Up
.</p>
<p>El botón Back del sistema se utiliza para navegar, en orden cronológico inverso, por el historial
de pantallas en las que recientemente trabajó el usuario. Generalmente, se basa en las relaciones temporales
entre pantallas, y no en la jerarquía de la aplicación.</p>
<p>Cuando la pantalla que se visitó anteriormente es también el componente jerárquico primario de la pantalla actual, si se presiona el botón
Back, se obtendrá el mismo resultado que si se presiona el botón Up, y esto es algo que sucede a
menudo. Sin embargo, a diferencia del botón Up, mediante el cual se garantiza que el usuario permanezca en la aplicación, el botón Back
le permite al usuario regresar a la pantalla de inicio o, incluso, a otra aplicación.</p>
<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
<p>El botón Back también permite diferentes comportamientos que no están vinculados directamente con la navegación entre pantallas:
</p>
<ul>
<li>descartar las ventanas flotantes (cuadros de diálogo o emergentes);</li>
<li>descartar las barras de acción contextuales y eliminar el resaltado de los elementos seleccionados;</li>
<li>ocultar el teclado en la pantalla (IME [Editores de métodos de entrada]).</li>
</ul>
<h2 id="within-app">Navegación dentro de tu aplicación</h2>
<h4>Navegación hacia pantallas con múltiples puntos de entrada</h4>
<p>En algunos casos, las pantallas no tienen una posición fija dentro de la jerarquía de la aplicación, y se puede acceder a ellas
desde múltiples puntos de entrada (como la pantalla de configuración, a la que se puede acceder desde cualquier otra pantalla
de la aplicación). En este caso, el botón Up debe permitir regresar a la pantalla remitente, por lo que se comportaría
de forma idéntica al botón Back.</p>
<h4>Cambio de vista dentro de una pantalla</h4>
<p>Cambiar las opciones de vista de una pantalla no modifica el comportamiento de los botones Up o Back: la pantalla sigue estando
en el mismo lugar dentro de la jerarquía de la aplicación y no se crea ningún historial de navegación nuevo.</p>
<p>Entre los ejemplos de cambios en las vistas, se encuentran los siguientes:</p>
<ul>
<li>cambio de vistas mediante las pestañas o los deslizamientos de izquierda a derecha;</li>
<li>cambio de vistas mediante un menú desplegable (también conocido como pestañas colapsadas);</li>
<li>filtrado de listas;</li>
<li>clasificación de listas;</li>
<li>modificación de las características de la pantalla (como el zoom).</li>
</ul>
<h4>Navegación entre pantallas relacionadas</h4>
<p>Si tu aplicación es compatible con la navegación desde una lista de elementos hacia una vista de detalles de alguno de esos elementos, generalmente,
es preferible respaldar la navegación de dirección desde ese elemento a otro anterior
o siguiente en la lista. Por ejemplo, en Gmail, es fácil deslizarse hacia la izquierda o la derecha desde una conversación
para ver una conversación anterior o más nueva en la misma bandeja de entrada. Al igual que cuando se cambia la vista dentro de una pantalla, en este tipo de
navegación no se cambia el comportamiento de los botones Up o Back.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
<p>Sin embargo, una excepción importante a este caso se presenta cuando se explora entre vistas de detalles relacionadas que no están vinculadas
mediante la lista que se está utilizando; por ejemplo, cuando se explora en Play Store entre diferentes aplicaciones
del mismo desarrollador o entre álbumes del mismo artista. En estos casos, si se sigue cada vínculo, esto queda registrado en el
historial, por lo que, a través del botón Back, se regresa a cada pantalla que se visitó anteriormente. El botón Up debe seguir omitiendo
estas pantallas relacionadas y navegar hacia la pantalla del contenedor visitada más recientemente.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
<p>Puedes lograr que el comportamiento del botón Up sea incluso más inteligente teniendo en cuenta tus conocimientos de la vista
detallada. Si extendemos el ejemplo de Play Store mencionado antes, imaginemos que el usuario navegó desde el último
libro visto hacia los detalles de la adaptación de la película. En ese caso, mediante el botón Up podrás regresar a un contenedor
(Películas) por el que el usuario no navegó anteriormente.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
<h2 id="into-your-app">Navegación dentro de la aplicación a través de los widgets y las notificaciones de la pantalla de inicio</h2>
<p>Podrás utilizar los widgets y las notificaciones de la pantalla de inicio para ayudar a los usuarios a navegar directamente hacia las pantallas
que se encuentran en posiciones más profundas dentro de la jerarquía de tu aplicación. Por ejemplo, tanto el widget de la bandeja de entrada de Gmail como las notificaciones de los mensajes nuevos
pueden omitir la pantalla Bandeja de entrada y llevar al usuario directamente hacia una vista de conversación.</p>
<p>En ambos casos, el botón Up se debe utilizar de la siguiente manera:</p>
<ul>
<li><em>Si a la pantalla de destino generalmente se llega desde una determinada pantalla dentro de su
aplicación</em>, el botón Up debe permitir la navegación hacia esa pantalla.</li>
<li><em>De lo contrario, </em>el botón Up debe permitir la navegación hacia la pantalla que está en el nivel superior ("Inicio") de tu aplicación.</li>
</ul>
<p>En el caso del botón Back, la navegación debe ser más predecible. Para ello, coloca en la
pila de retroceso de la tarea la ruta completa de la navegación ascendente hacia la pantalla que se encuentra en el nivel superior de la aplicación. De este modo, los usuarios que
no recuerdan cómo ingresaron a tu aplicación podrán navegar hacia la pantalla del nivel superior de la aplicación antes de
salir.</p>
<p>A modo de ejemplo, el widget de la pantalla Inicio de Gmail posee un botón para llevar al usuario directamente a la pantalla de
redacción. Mediante los botones Up o Back de la pantalla de redacción el usuario debería poder dirigirse hacia la Bandeja de entrada y, a partir de allí, continuar hacia la pantalla Inicio
por medio del botón Back.</p>
<img src="{@docRoot}design/media/navigation_from_outside_back.png">
<h4>Notificaciones indirectas</h4>
<p>Cuando tu aplicación necesita presentar información sobre múltiples eventos de forma simultánea, puede utilizar una
sola notificación que dirija al usuario a una pantalla intersticial. En esta pantalla, se resumen dichos
eventos y se proporcionan rutas para que el usuario navegue más profundamente por la aplicación. Las notificaciones de este estilo se
denominan <em>notificaciones indirectas</em>.</p>
<p>A diferencia de las notificaciones estándar (directas), si se presiona Back desde una pantalla intersticial de una
notificación indirecta, el usuario será dirigido hacia el punto en el que se desencadenó la notificación. No se incluyen
pantallas adicionales en la pila de retroceso. Una vez que el usuario se dirige hacia la aplicación desde la
pantalla intersticial, los botones Up y Back se comportan del mismo modo que lo hacen en las notificaciones estándar, como se describió antes:
navegan dentro de la aplicación en lugar de regresar a la pantalla intersticial.</p>
<p>Por ejemplo, supongamos que un usuario de Gmail recibe una notificación indirecta del calendario. Si se toca
esta notificación, se abrirá la pantalla intersticial, en la que se mostrarán recordatorios de varios
eventos diferentes. Si se toca Back desde la pantalla intersticial, el usuario volverá a Gmail. Si se toca un evento
en particular, el usuario saldrá de la pantalla intersticial e ingresará en la aplicación Calendario, donde se mostrarán detalles del
evento. En la pantalla de detalles del evento, es posible navegar con los botones Up y Back hacia la visomunmenteta superior del calendario.</p>
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
<h4>Notificaciones emergentes</h4>
<p><em>Las notificaciones emergentes</em> omiten el panel lateral de notificaciones y aparecen directamente
frente al usuario. Estas casi nunca se utilizan, y se <strong>deben reservar para ocasiones en las que es necesario proporcionar una
respuesta oportuna y es necesario realizar una interrupción en el contexto del usuario</strong>. Por ejemplo,
en Talk se utiliza este estilo para alertar al usuario sobre una invitación de un amigo para participar en una videocharla, ya que esta
invitación caducará automáticamente luego de algunos segundos.</p>
<p>En términos de comportamiento de la navegación, las notificaciones emergentes siguen, en gran medida, el comportamiento de la pantalla intersticial
de una notificación indirecta. El botón Back le permite al usuario descartar la notificación emergente. Si el usuario navega
desde la ventana emergente hacia la aplicación que genera las notificaciones, los botones Up y Back seguirán las reglas para las notificaciones estándar
mientras se navega por la aplicación.</p>
<img src="{@docRoot}design/media/navigation_popup_notification.png">
<h2 id="between-apps">Navegación entre aplicaciones</h2>
<p>Una de las principales ventajas del sistema Android es la capacidad de las aplicaciones de activarse
mutuamente, por lo que el usuario puede navegar directamente desde una aplicación hacia otra. Por ejemplo, una
aplicación que debe tomar una fotografía puede area appactivar la aplicación de la cámara, la cual mostrará la fotografía
en la aplicación que la activó. Esto representa una gran ventaja tanto para el desarrollador, quien puede aprovechar fácilmente el
código de otras aplicaciones, como para el usuario, quien disfruta de una experiencia coherente para acciones
que se realizan comúnmente.</p>
<p>Para comprender la navegación entre aplicaciones, es importante que se entienda el comportamiento del framework de Android,
que se explica a continuación.</p>
<h4>Actividades, tareas e intentos</h4>
<p>En Android, una <strong>actividad</strong> es un componente de la aplicación que define una pantalla de
información y todas las acciones relacionadas que el usuario puede llevar a cabo. Tu aplicación es un conjunto de
actividades formado por las actividades que creas y aquellas que reutilizas de otras aplicaciones.</p>
<p>Una <strong>tarea</strong> es la secuencia de actividades que un usuario realiza para lograr un objetivo. En
una sola tarea, se pueden utilizar actividades de una sola aplicación o se pueden utilizar actividades de varias
aplicaciones diferentes.</p>
<p>Un <strong>intento</strong> es un mecanismo mediante el cual una aplicación indica que necesita la ayuda de
otra aplicación para realizar una acción. Las actividades de una aplicación pueden indicar los intentos
a los que pueden dar respuesta. En el caso de los intentos comunes, como "Compartir", es posible que el usuario tenga instaladas varias aplicaciones
que pueden cumplir con esta solicitud.</p>
<h4>Ejemplo: navegación entre aplicaciones para respaldar el uso compartido</h4>
<p>Para comprender cómo las actividades, las tareas y los intentos (intents) funcionan en conjunto, considera cómo una aplicación les permite a los usuarios
compartir contenido a través de otra aplicación. Por ejemplo, si se ejecuta la aplicación Play Store desde la pantalla de inicio, se iniciará
una nueva tarea A (consulta la imagen a continuación). Después de navegar por Play Store y de tocar un libro promocionado
para ver su información detallada, el usuario permanece en la misma tarea y la extiende al agregar actividades. Si se desencadena la acción
Compartir, se le mostrará al usuario un cuadro de diálogo con una lista de todas las actividades (provenientes de diferentes aplicaciones)
que se registraron para concretar el intento de compartir.</p>
<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
<p>Si el usuario decide compartir el contenido a través de Gmail, la actividad de redacción de Gmail se agrega como una continuación de la
tarea A; no se crea una tarea nueva. Si Gmail estaba ejecutando su propia tarea en segundo plano, esta
no debería verse afectada.</p>
<p>Desde la actividad de redacción, si se envía el mensaje o se toca el botón Back, se dirigirá nuevamente al usuario hacia
la actividad de detalles del libro. Si se sigue tocando el botón Back, el usuario seguirá navegando por Play
Store y, finalmente, llegará a la pantalla de inicio.</p>
<img src="{@docRoot}design/media/navigation_between_apps_back.png">
<p>Sin embargo, si el usuario toca el botón Up desde la actividad de redacción, estará indicando su deseo de permanecer dentro de
Gmail. Por consiguiente, aparecerá la actividad de la lista de conversaciones de Gmail y se creará una nueva tarea B para esto. La ruta raíz de las nuevas tareas siempre conduce
a la pantalla Inicio, por lo que, si se toca el botón Back desde la lista de conversaciones, se regresará a dicha pantalla.</p>
<img src="{@docRoot}design/media/navigation_between_apps_up.png">
<p>La tarea A permanece en segundo plano, y el usuario podrá regresar a ella después (por ejemplo, a través de la pantalla
Recientes). Si Gmail ya estaba ejecutando su propia tarea en segundo plano, esta se reemplazará con la
tarea B, y el contexto anterior se abandonará para darle preferencia al nuevo objetivo del usuario.</p>
<p>Cuando tu aplicación se registre para manipular los intentos de una actividad que se encuentra en un nivel profundo dentro de la jerarquía de la aplicación,
consulta <a href="#into-your-app">Navegación dentro de la aplicación a través de los widgets y
las notificaciones de la pantalla de inicio</a> para obtener información sobre cómo especificar la navegación del botón Up.</p>

View File

@@ -1,367 +0,0 @@
page.title=La oportunidad de Google Play
meta.tags="visibility, growth, distributing"
page.tags="play, apps, distributing, publishing"
page.metaDescription=Miles de millones de descargas por mes y en aumento. Exhibe tus aplicaciones a los usuarios en la escala de Google.
page.image=/distribute/images/about-play.jpg
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Acerca de Google Play</h2>
<ol style="list-style-type:none;">
<li><a href="#reach">Alcance mundial, crecimiento rápido</a></li>
<li><a href="#ratings-reviews">Calificaciones y reseñas de usuarios</a></li>
<li><a href="#category-browsing">Exploración por categoría</a></li>
<li><a href="#search">Búsqueda</a></li>
<li><a href="#top-charts-and-lists">Cuadros y listas principales</a></li>
<li><a href="#featured-staff-picks">Aplicaciones destacadas, seleccionadas por el equipo, colecciones e insignias</a></li>
<li><a href="#product-detail-pages">Páginas de directorio de la tienda</a></li>
<li><a href="#related-resources">Recursos relacionados</a></li>
</ol>
</div>
</div>
<p>
Google Play es la tienda más importante de distribución de aplicaciones para Android. Cuando
publicas en Google Play, exhibes tus aplicaciones a una enorme base de clientes activos
de Android en más de 190 países y territorios de todo el
mundo.
</p>
<div>
<img src="{@docRoot}images/gp-about-0.jpg" alt="Google Play on an Android Tablet" style="width:480px;position:relative" />
</div>
<p>
Google Play es una parte central de la experiencia Android. Los nuevos usuarios
personalizan su contenido con aplicaciones, juegos y otros contenidos de Google Play.
Los usuarios existentes regresan con frecuencia para ver qué hay de nuevo y las últimas tendencias. Descargar
nuevas aplicaciones es extremadamente cómodo y rápido; Google Play envía aplicaciones a los
dispositivos del usuario instantáneamente de forma inalámbrica.
</p>
<p>
Google Play es también el destino principal de los usuarios web. Cualquier persona que tenga un explorador
puede explorar Google Play en la Web. Los usuarios de Android incluso pueden comprar e instalar
las aplicaciones que deseen y Google Play las inserta automáticamente en sus dispositivos
sin la necesidad de utilizar cables.
</p>
<p>
La accesibilidad y conveniencia del sitio web de Google Play te ofrece nuevas
formas de dirigir tráfico a tus productos desde diferentes orígenes, como anuncios en línea,
búsquedas en la Web e interconexión. Google Play fue diseñado para conectar a los usuarios con
aplicaciones y juegos increíbles. Proporciona canales clave para que tu aplicación se destaque y
gane terreno en el mercado.
</p>
<div class="headerLine">
<h2 id="ratings-reviews">
Calificaciones y reseñas de usuarios
</h2>
</div>
<p>
Los usuarios potenciales toman en cuenta las calificaciones y las reseñas como indicadores clave de la calidad de una
aplicación. Mediante la calificación de aplicaciones en una escala de una a cinco estrellas y la publicación de reseñas, los usuarios de
Android muestran su agradecimiento por las aplicaciones que descargaron.
</p>
<p>
<strong>La calificación de tu aplicación es uno de los factores más importantes que influyen en
su clasificación</strong> en las listas de Google Play y en los resultados de búsqueda. También es
una de las métricas clave en las que se pone su atención el personal editorial para seleccionar aplicaciones
y juegos con el objetivo de promocionarlos en la tienda.
</p>
<div class="img" style="padding: 1em auto;width:96%;">
<img src="{@docRoot}images/gp-rating-web.png" style="border:1px solid #ddd;">
</div>
<div class="headerLine">
<h2 id="category-browsing">
Exploración por categoría
</h2>
</div>
<p>
Cuando publicas una aplicación en Google Play, seleccionas la categoría en la que quieres que los
usuarios encuentren tu aplicación. Hay más de 30 categorías disponibles. Dentro de cada
categoría, las aplicaciones se clasifican según una combinación de calificaciones, reseñas,
descargas, país y otros factores.
</p>
<div class="headerLine">
<h2 id="search">
Búsqueda
</h2>
</div>
<p>
La búsqueda en Google Play permite a los usuarios encontrar una aplicación o un juego rápidamente. La búsqueda utiliza
una heurística potente para sugerir términos a medida que el usuario escribe, y ofrece vínculos
directos a aplicaciones en forma de sugerencias. En los resultados, los usuarios encuentran en primer lugar las aplicaciones
más relevantes y populares.
</p>
<div class="headerLine">
<h2 id="top-charts-and-lists">
Cuadros y listas principales
</h2>
</div>
<div class="figure">
<img src="{@docRoot}images/gp-about-top.jpg">
</div>
<p>
Los cuadros de las aplicaciones principales mantienen a los usuarios en contacto con lo que es popular y con las tendencias entre los usuarios de
Android, directamente desde las páginas de inicio de aplicaciones y juegos. Los cuadros se actualizan
varias veces por día en función de la actividad de descarga reciente. A medida que
aumentan las calificaciones y la actividad de descarga de una aplicación, esa aplicación puede ascender de posición en los cuadros.
</p>
<p>
Para lograr que los cuadros sean lo más relevantes posible para los usuarios alrededor del mundo, en los
países donde Google Play es más popular también hay cuadros específicos para el país. A medida que tus
aplicaciones van ganando terreno y generan un impulso en las descargas y las calificaciones, ascienden en
uno o más de los cuadros de las aplicaciones principales, e incluso adquieren mayor exposición.
</p>
<table style="width:50%;">
<tr>
<td>
Principales gratis
</td>
<td>
Listas de aplicaciones y juegos gratuitos
</td>
</tr>
<tr>
<td>
Principales pagas
</td>
<td>
Listas de aplicaciones y juegos pagos
</td>
</tr>
<tr>
<td>
Principales en ingresos
</td>
<td>
Ingresos brutos, gratis o pagas
</td>
</tr>
<tr>
<td>
Principales nuevas gratis
</td>
<td>
Menos de 30 días de antigüedad
</td>
</tr>
<tr>
<td>
Principales nuevas pagas
</td>
<td>
Menos de 30 días de antigüedad
</td>
</tr>
<tr>
<td>
Tendencia
</td>
<td>
Recién llegadas con gran cantidad de instalaciones
</td>
</tr>
</table>
<div class="headerLine">
<h2 id="featured-staff-picks">
Destacadas, seleccionadas por el equipo, colecciones e insignias
</h2>
</div>
<p>
El equipo editorial de Google Play se dedica a captar la atención de los usuarios
con las mejores aplicaciones y marcar la pauta para la calidad de las aplicaciones en toda la tienda.
Evalúan constantemente aplicaciones en todo Google Play para encontrar no solo las
mejores aplicaciones y juegos, sino también "diamantes en bruto" que
desean que más personas vean. El equipo promociona aplicaciones excelentes en las colecciones
<em>Destacadas</em>, <em>Seleccionadas por el equipo</em>, y otras.
</p>
<p>
Tú no puedes nominar tu aplicación para que aparezca entre las destacadas, pero el equipo supervisa constantemente
Google Play para detectar aplicaciones de excelencia. Si creas una aplicación que los usuarios encuentren genial y que
se vea increíble en los dispositivos Android, el equipo editorial lo notará.
</p>
<h3 id="featured-staff-picks2">
Destacadas y seleccionadas por el equipo
</h3>
<p>
Cada semana, el personal editorial de Google Play selecciona un nuevo grupo de aplicaciones para
promocionar en sus colecciones populares <em>Destacadas</em> y <em>Seleccionadas por el equipo</em>
.
</p>
<p>
Las colecciones <em>Destacadas</em> resaltan los títulos de aplicaciones y juegos más nuevos e increíbles
disponibles para Android. La lista también incluye las mejores aplicaciones y las
más populares en las principales categorías. <em>Seleccionadas por el equipo</em>
incluye todas las aplicaciones y los juegos recientemente destacados en Google Play. A fin de incluir a los
usuarios de tablets, una colección especial de <em>Seleccionadas por el equipo</em> destaca las mejores
aplicaciones para tablets Android.
</p>
<table style="text-align:center;margin:1.5em 0;">
<tr>
<td style="border:none;">
<img src="{@docRoot}images/gp-about-picks1.jpg">
<p>
Destacadas
</p>
</td>
<td style="border:none;">
<img src="{@docRoot}images/gp-about-picks2.jpg">
<p>
Colección
</p>
</td>
<td style="border:none;">
<img src="{@docRoot}images/gp-about-picks3.jpg">
<p>
Selección de los editores
</p>
</td>
</tr>
</table>
<h3 id="collections">
Colecciones de aplicaciones
</h3>
<p>
De vez en cuando, el personal editorial reúne una colección de aplicaciones y
juegos en función de un tema o evento de temporada. Los usuarios, atraídos por la exactitud de la colección,
con frecuencia usan esas listas para seleccionar aplicaciones.
</p>
<p>
El personal editorial selecciona aplicaciones para la promoción de colecciones;
se trata de aplicaciones de alta calidad que exhiben lo mejor de Android en teléfonos y tablets. El
personal también busca aplicaciones que puedan realizar una contribución interesante o única
a la colección en su totalidad.
</p>
<h3 id="editors-choice">
<img style="margin-right:.25em;margin-bottom:.5em;" src="{@docRoot}images/editorschoice_ann.png"> Selección de los editores
</h3>
<p>
<em>Selección de los editores</em> es una colección exclusiva de aplicaciones que destaca algunas
de las mejores aplicaciones disponibles en Android. Los editores seleccionan las aplicaciones por su
calidad y excelente interfaz de usuario, gran popularidad y uso innovador de las
funciones de Android.
</p>
<p>
Las aplicaciones escogidas para <em>Selección de los editores</em> también reciben una insignia que se
exhibe cada vez que se visualiza el nombre de la aplicación en Google Play.
</p>
<h3 id="top-developer">
<img style="margin-right:.25em;margin-bottom:.5em;" src="{@docRoot}images/topdev_ann.png"> Desarrollador principal
</h3>
<p>
Desarrollador principal es una insignia que reconoce a los desarrolladores establecidos y respetados por su
compromiso con el lanzamiento de aplicaciones innovadoras y de alta calidad en Android.
El personal editorial de Google Play otorga la insignia de Desarrollador principal
periódicamente en función del historial de trabajo del desarrollador.
</p>
<p>
La insignia de Desarrollador principal aparece junto al nombre del desarrollador dondequiera que
se exhiba en Google Play. La insignia denota el reconocimiento continuo de todas las
aplicaciones del desarrollador. Implica un nivel adicional de confianza y seguridad
por parte de los usuarios en los productos de un desarrollador.
</p>
<div class="headerLine">
<h2 id="product-detail-pages">
Páginas de directorio de la tienda
</h2>
</div>
<div class="figure">
<img src="{@docRoot}images/gp-about-listing.jpg">
</div>
<p>
La vidriera de tu aplicación en Google Play es su <em>página de directorio de la tienda</em>: una página
colorida y llena de contenido que te permite promocionar tu aplicación, que destaca sus calificaciones y
reseñas y muestra lo que tu aplicación puede hacer.
</p>
<p>
El directorio de tu tienda es a donde acuden tus usuarios para averiguar todo sobre la
aplicación. Cuando ven tu aplicación en los resultados de búsqueda, en los cuadros de las principales, en las listas
de categorías y en las colecciones, un solo toque los lleva directamente al directorio de la tienda.
</p>
<p>
Administra tu página de detalles del producto en la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores de Google Play</a>
desde cualquier explorador. Inicia sesión para cargar o actualizar tus recursos de marca e
ingresa los detalles de tu producto en los idiomas de los mercados donde distribuyes.
</p>
<p>
Cuando realizas una publicación, Google Play agrega la calificación y las reseñas de tu aplicación, así como vínculos a tus
otros productos y más. También se asegura de que la página de directorio de tu tienda se vea
genial en teléfonos, tablets y en un explorador web.
</p>
<p>
Puedes vincular usuarios web directamente a tu página de detalles del producto desde fuera de
Google Play; por ejemplo, desde tu sitio web, y agregar campañas, reseñas, publicaciones en
redes sociales y más. Consulta <a href="{@docRoot}distribute/tools/promote/linking.html">Cómo vincular tus
productos</a> para averiguar cómo hacerlo.
</p>
<p style="clear:both">
</p>
<div class="headerLine">
<h2>Recursos relacionados</h2>
</div>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/googleplay"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="4"></div>
</div>

View File

@@ -1,230 +0,0 @@
page.title=Distribución para Android Auto
page.image=/design/auto/images/auto-overview.png
meta.tags="auto", "publish", "quality"
page.tags="auto", "publish", "googleplay"
page.metaDescription=Distribuye tus aplicaciones y contenido para Android Auto.
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Cómo participar</h2>
<ol>
<li><a href="#understand_guidelines">Comprende las pautas</a></li>
<li><a href="#develop_app">Desarrolla una aplicación excelente para Auto</a></li>
<li><a href="#test_app">Prueba la calidad de tu aplicación para Auto</a></li>
<li><a href="#opt_in">Acepta los términos</a></li>
<li><a href="#track_review">Realiza un seguimiento de tu revisión</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a></li>
</ol>
</div></div>
<p>
Si desarrollaste una aplicación excelente, Android Auto y Google Play pueden ayudarte a
llevarla directo a los vehículos de los usuarios. Puedes
ampliar tus aplicaciones nuevas o existentes para que sean compatibles con Auto y luego publicarlas en Google Play usando
herramientas y procesos ya conocidos.
</p>
<p>
Para comenzar, repasa las secciones de este documento para aprender a
distribuir a los usuarios tus aplicaciones para Auto a través de Google Play. Asegúrate de leer
<a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a>
para obtener información sobre las pautas de utilidad, calidad y seguridad que tu aplicación debe
cumplir. Cuando tu aplicación esté lista, puedes aceptar los términos en la Consola para desarrolladores y cargar tu
APK para someterlo a revisión.
</p>
<h2 id="how_to_participate">
Cómo participar
</h2>
<p>
Google Play te permite distribuir aplicaciones para utilizar en vehículos. Puedes desarrollar y publicar mediante el uso de tu
cuenta existente en la Consola para desarrolladores y tu configuración actual para distribución y fijación de precios. Participar
es fácil; las siguientes secciones describen el proceso.
</p>
<div style="float:right;margin:1em 0 1.5em 2em;">
<img src="{@docRoot}images/gp-auto-process.png">
</div>
<h3 id="understand_guidelines">
1. Comprende las pautas y los requisitos
</h3>
<p>
Si quieres prepararte para un lanzamiento exitoso en Android Auto, comienza por revisar las
pautas para crear experiencias excelentes en Auto. Consulta las <a href="{@docRoot}design/auto/index.html">Pautas de diseño para Android Auto</a> para obtener ideas acerca de
cómo ampliar tu aplicación para que sea compatible con Auto y detalles sobre diseño y utilidad.
</p>
<p>
Cuando comiences a diseñar tu experiencia para Auto, asegúrate de leer y
comprender los criterios de calidad de las aplicaciones para Auto. Únicamente las aplicaciones compatibles con Auto
se designarán como aplicaciones para Auto en Google Play; tus aplicaciones pueden participar
si cumplen con un conjunto de criterios de calidad básicos. Consulta
<a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad
de las aplicaciones para Auto</a> para obtener información detallada.
</p>
<h3 id="develop_app">2. Desarrolla una aplicación excelente para Auto</h3>
<p>
Una aplicación excelente para Auto es aquella que se diseña para utilizar en vehículos y aprovecha las
capacidades de Android Auto. La aplicación ofrece una experiencia de alta calidad mientras el usuario está conduciendo;
por ejemplo, permite reproducir contenido de audio o acceder a mensajes.
</p>
<p>
Mientras consideras la posibilidad de desarrollar una aplicación para Auto, lee la <a href="{@docRoot}training/auto/start/index.html">documentación para desarrolladores</a> y las
pautas de utilidad, y considera aplicarlas en la mayor medida
posible. Asegúrate de diseñar una gran experiencia y cumplir nuestras pautas para evitar la
distracción del conductor.
</p>
<p>
Debes ofrecer tu experiencia para Auto como parte de tu aplicación actual para teléfonos, tablets y otros
dispositivos, con el mismo nombre de paquete y el mismo directorio de la tienda.
</p>
<h3 id="test_app">3. Prueba la calidad de tu aplicación para Auto</h3>
<p>
Tus aplicaciones para Auto deben estar diseñadas para que funcionen bien, se vean increíbles en el vehículo
y ofrezcan la mejor experiencia de usuario posible. Google Play exhibirá aplicaciones para Auto seleccionadas de
alta calidad a fin de que los usuarios puedan encontrarlas fácilmente en Google Play. Aquí te mostramos
cómo puedes participar y ofrecer una aplicación para Android Auto que los usuarios disfrutarán:
</p>
<ul>
<li>Cumple con las pautas de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las
aplicaciones para Auto</a>.
<ul>
<li>Sigue nuestras mejores prácticas en el <a href="{@docRoot}training/auto/index.html">
Desarrollo de aplicaciones para Auto</a>.</li>
<li>Asegúrate de que tu aplicación cumpla con los criterios de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a>.</li>
</ul>
</li>
</ul>
<h3 id="opt_in">4. Acepta los términos de Android Auto y publica</h3>
<p>
Antes de que puedas cargar tu APK y publicar la aplicación para someterla a revisión, el propietario de la cuenta de desarrollador
debe aceptar los términos de
<a href="https://play.google.com/about/auto/developer-distribution-agreement-addendum.html">Android
Auto</a> en la sección <strong>Fijación de precios y distribución</strong> de la
Consola para desarrolladores. Aceptar los términos significa que quieres que tu aplicación esté disponible
para los usuarios de Android Auto a través de Google Play, y que
tu aplicación cumple las pautas de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad
de las aplicaciones para Auto</a>.
</p>
<p>
Solo podrás cargar tu aplicación para Auto después de haber aceptado los términos. A continuación se indica
qué aplicaciones están destinadas a ser aplicaciones para Auto:
</p>
<ul>
<li>El manifiesto de tu aplicación debe declarar la entrada de metadatos <code>com.google.android.gms.car.application</code>
con las capacidades de Auto que usa la aplicación. Para obtener más información
acerca de cómo configurar tu aplicación para utilizar con Android Auto, consulta
<a href="{@docRoot}training/auto/start/index.html#auto-metadata">Primeros pasos con Auto</a>.
</li>
</ul>
<p>
Una vez que hayas creado tu APK, esté listo para el lanzamiento y lo hayas probado para asegurarte de que cumple
todas las pautas de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las
aplicaciones para Auto</a>, carga la aplicación a la Consola para desarrolladores. Actualiza el directorio de tu
tienda con información adicional sobre la funcionalidad Auto y establece opciones de distribución según
sea necesario. Si no sabes cómo prepararte para el lanzamiento en Google Play,
consulta la <a href="{@docRoot}distribute/googleplay/publish/preparing.html">Lista de comprobación
para el lanzamiento.</a>
</p>
<p>
Después de aceptar los términos y guardar los cambios, puedes cargar y publicar tu aplicación como lo haces habitualmente.
Antes de que tu aplicación esté disponible para los usuarios de Android Auto, Google Play envía
tu aplicación para revisión conforme a los criterios de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a>
y te notifica el resultado. Si se aprueba tu aplicación, Google Play la exhibe
a los usuarios de Android Auto. Consulta la siguiente sección para obtener información detallada acerca de cómo realizar un seguimiento del estado
de aprobación de tu aplicación.
</p>
<p>
Ten en cuenta que la revisión afecta la disponibilidad de tu aplicación para otros dispositivos en la
Play Store de Google; por ejemplo, para teléfonos y tablets.
Si tienes una aplicación actual que incluya actualizaciones para el componente de teléfono/tablet,
el componente de Android Auto debe pasar la revisión antes de que la aplicación actualizada
esté disponible en la Play Store de Google.
</p>
<p>
Aquí te mostramos los pasos que debes seguir para aceptar los términos de Android Auto en la Consola para desarrolladores:
</p>
<ol>
<li>Asegúrate de que tu aplicación cumpla con los criterios de <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a>.
</li>
<li>En la página <strong>Todas las aplicaciones</strong>, haz clic en la aplicación que quieres publicar.
</li>
<li>En <strong>Fijación de precios y distribución</strong>, desplázate hacia abajo hasta que encuentres <em>Android Auto</em> y el
vínculo a los términos.
</li>
<li>Haz clic en el vínculo <em>términos</em>.
</li>
<li>Lee los términos y haz clic en <em>Acepto</em>.
</li>
</ol>
<div style="padding-top:1em">
<img style="border:2px solid #ddd;" src="{@docRoot}images/gp-auto-opt-in.png">
<p class="caption">
<strong>Acepta los términos para Auto:</strong> Incluye tu aplicación en Android Auto; para ello, debes aceptar los
términos en la Consola para desarrolladores.
</p>
</div>
<h3 id="track_review">5. Realiza un seguimiento de tu revisión</h3>
<p>
Tu aplicación se someterá a revisión para determinar si cumple con las pautas de distracción del conductor y con los
criterios técnicos y de calidad que se describen más arriba. Este proceso de revisión detallada puede demorar
más tiempo que el que se demora habitualmente cuando envías aplicaciones para teléfono/tablet.
Hasta que se apruebe la aplicación, no podrás publicar en la Play Store de Google la aplicación ni actualizaciones para la aplicación.
Después de una revisión exitosa, se publicará tu aplicación y estará disponible en la Play
Store de Google.
</p>
<p>Si no se acepta tu aplicación, recibirás una <strong>notificación por correo electrónico enviada a tu
cuenta de desarrollador</strong> con un resumen de las áreas que debes abordar. Una vez que
realices los ajustes necesarios, puedes cargar una nueva versión de tu aplicación a la Consola para
desarrolladores.
</p>
<p>
Ten en cuenta que si la aplicación enviada es una actualización para una aplicación existente y tu aplicación actualizada no cumple
los criterios de revisión, se rechazará la actualización y la aplicación existente continuará publicada en la Play
Store de Google.
</p>
<p>Para comprender cómo se evalúan tus aplicaciones, consulta el documento <a href="{@docRoot}distribute/essentials/quality/auto.html">Calidad de las aplicaciones para Auto</a>. </p>
<h3>Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:autolanding"
data-cardSizes="9x6, 6x3x2"
data-maxResults="6">
</div>

View File

@@ -1,584 +0,0 @@
page.title=Consola para desarrolladores
page.metaDescription=Aprende acerca de la Consola para desarrolladores, el lugar desde donde publicarás tu aplicación en Google Play.
page.image=/distribute/images/developer-console.jpg
Xnonavpage=true
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Características de la publicación</h2>
<ol>
<li><a href="#allapps">Todas las aplicaciones</a></li>
<li><a href="#account-details">Detalles de tu cuenta</a></li>
<li><a href="#merchant-account">Cómo vincular tu cuenta de comerciante</a></li>
<li><a href="#multiple-user-accounts">Múltiples cuentas de usuario</a></li>
<li><a href="#alpha-beta">Pruebas alfa y beta</a></li>
<li><a href="#staged-rollouts">Implementaciones por fases</a></li>
<li><a href="#multiple-apk">Compatibilidad con múltiples APK</a></li>
<li><a href="#selling-pricing-your-products">Venta y fijación de precios</a></li>
<li><a href="#in-app-products">Productos ofrecidos en la aplicación</a></li>
<li><a href="#distribution-controls">Controles de distribución</a></li>
<li><a href="#reviews-reports">Reseñas de usuarios, informes de errores</a></li>
<li><a href="#app-stats">Estadísticas de la aplicación</a></li>
<li><a href="#related-resources">Recursos relacionados</a></li>
</ol>
</div>
</div>
<p>
La <a href="https://play.google.com/apps/publish/">Consola para desarrolladores de
Google Play</a> es el lugar donde realizas las operaciones de publicación y donde tienes tus herramientas.
</p>
<!-- <img src="{@docRoot}images/gp-dc-startscreen.jpg" style="width:480px;" /> -->
<img src="{@docRoot}images/gp-devconsole-home.png" style="width:480px;">
<p>
Carga aplicaciones, crea páginas para tus productos, configura precios y distribución, y
publica. Puedes administrar todas las fases de publicación en Google Play a través de la
Consola para desarrolladores, desde cualquier explorador web.
</p>
<p>
Una vez que te hayas <a href="{@docRoot}distribute/googleplay/start.html">registrado</a> y recibas la
verificación por correo electrónico, puedes iniciar sesión en tu Consola para desarrolladores de Google Play.
</p>
<div class="headerLine">
<h2 id="allapps">
Todas las aplicaciones
</h2>
</div>
<p>
Comienza en Todas las aplicaciones, que te proporciona un vistazo rápido de tus aplicaciones y
te permite saltar a estadísticas, reseñas y detalles del producto, o cargar una aplicación nueva.
</p>
<div style="padding:1em 0em 0em 0em;">
<img src="{@docRoot}images/gp-dc-home.png" class="border-img">
</div>
<div class="headerLine" style="margin-top:-6px">
<h2 id="account-details">
Detalles de tu cuenta
</h2>
</div>
<p>
Especifica información básica del perfil de desarrollador sobre ti o tu compañía en la
página de detalles de la cuenta. Esto te identifica ante Google Play y tus
clientes. Puedes volver en cualquier momento para editar la información y cambiar tu
configuración.
</p>
<div>
<img src="{@docRoot}images/gp-dc-profile.png" class="frame">
</div>
<p>
Tu perfil de desarrollador contiene lo siguiente:
</p>
<ul>
<li>
<p>
Nombre del desarrollador, exhibido en la página del directorio de tu tienda y en otras partes de
Google Play.
</p>
</li>
<li>
<p>
Información de contacto, que solo Google utiliza y no está visible para tus
clientes.
</p>
</li>
<li>
<p>
URL del sitio web, exhibida en la página del directorio de tu tienda.
</p>
</li>
</ul>
<p>
En la página de detalles de la cuenta, también puedes agregar acceso restringido para comerciantes
y otros equipos, registrar una cuenta de comerciante o configurar cuentas de prueba para obtener
licencias de Google Play.
</p>
<div class="headerLine">
<h2 id="merchant-account">
Cómo vincular tu cuenta de comerciante
</h2>
</div>
<p>
Si quieres vender aplicaciones y productos integrados en la aplicación, vincula tu cuenta de comerciante en Google Wallet
a tu perfil de desarrollador. Google Play utiliza la cuenta de comerciante
vinculada para la identificación financiera e impositiva, como también para el procesamiento mensual de los pagos
provenientes de las ventas.
</p>
<div class="headerLine">
<h2 id="multiple-user-accounts">
Múltiples cuentas de usuario
</h2>
</div>
<p>
Configura cuentas de usuario para que otros miembros del equipo puedan acceder a diferentes partes de tu
Consola para desarrolladores.
</p>
<div style="width:550px;">
<img src="{@docRoot}images/gp-dc-invite.png" class="frame">
</div>
<p>
La primera cuenta registrada es la del <em>propietario de la cuenta</em>, con acceso pleno
a todas las partes de la consola. El propietario puede agregar <em>cuentas de usuario</em> y
administrar el acceso a la consola.
</p>
<p>
Por ejemplo, un propietario puede permitir el acceso de los usuarios a la configuración de publicación y de la
aplicación, pero no a los informes financieros. Aprende ahora a <a href="https://support.google.com/googleplay/android-developer/answer/2528691">configurar
múltiples cuentas</a>.
</p>
<div class="headerLine">
<h2 id="store-listing-details">
Detalles del directorio de la tienda
</h2>
</div>
<p>
Utiliza la Consola para desarrolladores para configurar una <em>página de Directorio de la tienda</em>. Esa página será
la página de inicio de tu aplicación en Google Play. Es la página que los usuarios ven en sus teléfonos
celulares o en la Web y donde obtienen información sobre tu aplicación y la descargan.
</p>
<p>
Carga recursos personalizados de la marca, capturas de pantalla y videos para destacar las
mejores características de tu aplicación. Proporciona una descripción localizada, agrega notas acerca de la última
versión y más. Puedes actualizar el directorio de tu tienda en cualquier momento.
</p>
<div>
<img src="{@docRoot}images/gp-dc-details.png" class="frame">
</div>
<div class="headerLine">
<h2 id="upload-instantly-publish">
Carga y publica instantáneamente
</h2>
</div>
<p>
Desde la Consola para desarrolladores, puedes cargar y publicar rápidamente un archivo de paquete de
una aplicación para Android lista para su lanzamiento. La aplicación es un <em>borrador</em> hasta que la
publicas, y en ese momento Google Play comienza a exhibir la página de directorio de tu tienda y la aplicación
a los usuarios; tu aplicación aparece en los directorios de tiendas en solo horas,
no semanas.
</p>
<p>
Una vez que se publica tu aplicación, puedes actualizarla cuantas veces quieras: Cambia
los precios, la configuración y las opciones de distribución en cualquier momento, sin la necesidad
de actualizar el archivo binario de la aplicación.
</p>
<p>
A medida que agregas funciones o abordas problemas de código, puedes publicar un archivo binario actualizado
en cualquier momento. La nueva versión estará disponible prácticamente de inmediato, y se les comunicará
a los clientes existentes que hay una actualización lista para descargar. Los usuarios también pueden
aceptar actualizaciones automáticas para tu aplicación, de modo que tus actualizaciones se entregan
e instalan ni bien las publicas. Puedes cancelar la publicación de tu aplicación en cualquier
momento.
</p>
<div class="headerLine">
<h2 id="alpha-beta">
Pruebas alfa y beta
</h2>
</div>
<p>
Siempre es bueno obtener la opinión real de los usuarios, especialmente antes del
lanzamiento. Google Play facilita la distribución de versiones de tu aplicación
previas al lanzamiento a grupos de prueba alfa y beta en cualquier parte del mundo.
</p>
<p>
En la sección <strong>APK</strong> de tu Consola para desarrolladores de Google Play
encontrarás las pestañas <strong>Pruebas alfa</strong> y <strong>Pruebas
beta</strong>. Aquí puedes cargar versiones de los archivos APK de tus aplicaciones
y definir una lista de evaluadores como un <a href="https://support.google.com/groups/answer/46601">Grupo de Google</a> o una <a href="https://support.google.com/plus/topic/2888488">Comunidad de Google+</a>. Una vez
que hagas esto, recibirás una URL que enviarás a tus evaluadores,
desde la cual podrán acceder al programa de prueba.
</p>
<div>
<img src="{@docRoot}images/gp-dc-ab.png" class="frame">
</div>
<p>
Una vez que accedan, los evaluadores se dirigirán a la página de producto de tu aplicación, y cuando
descarguen la aplicación, Google Play les proporcionará la versión alfa o beta
, según corresponda. Por cierto, si un usuario accede a ambos grupos
de prueba, Google Play siempre les proporcionará la versión de prueba alfa.
</p>
<p>
Recuerda que los usuarios no pueden proporcionar comentarios ni reseñas en las versiones alfa
y beta de tus aplicaciones. Para obtener sus opiniones, puedes usar el <a href="https://support.google.com/groups/answer/46601">Grupo de Google</a> o la <a href="https://support.google.com/plus/topic/2888488">Comunidad de Google+</a>, o bien
configurar una dirección de correo electrónico o tu propio sitio web.
</p>
<p>
Puedes usar estos programas de prueba para <a href="{@docRoot}distribute/essentials/optimizing-your-app.html">optimizar tus
aplicaciones</a>, ayudar con la <a href="{@docRoot}distribute/users/expand-to-new-markets.html">implementación en nuevos
mercados</a> y comenzar <a href="{@docRoot}distribute/users/build-community.html">a crear tu
comunidad</a>. Puedes encontrar más información acerca de cómo usar la prueba beta en la
<a href="{@docRoot}distribute/tools/launch-checklist.html">Lista de comprobación
para el lanzamiento</a> y la <a href="{@docRoot}distribute/tools/localization-checklist.html">Lista de comprobación
para la localización</a>.
</p>
<div class="headerLine">
<h2 id="staged-rollouts">
Implementaciones por fases
</h2>
</div>
<p>
También puedes dividir la implementación de tus aplicaciones en fases mediante la pestaña Producción en la sección
APK de tu Consola para desarrolladores de Google Play. Allí podrás definir el
porcentaje de usuarios que podrán descargar tu aplicación.
</p>
<p>
Organizar tu implementación en fases te ayudará a limitar el impacto de errores imprevistos o de la carga del
servidor y te permitirá medir la respuesta de los usuarios a través de una muestra imparcial de usuarios.
Durante las implementaciones en fases, los usuarios pueden calificar y reseñar tus aplicaciones, de modo que
si estás indeciso, comienza la implementación en un porcentaje pequeño de usuarios. Asegúrate de estar atento
a las reseñas negativas y responderlas.
</p>
<p>
Ten en cuenta que no se admiten reversiones debido a los <a href="{@docRoot}tools/publishing/versioning.html">requisitos de versión para la aplicación</a>
de la plataforma Android. Si necesitas realizar una reversión, considera la posibilidad de lanzar un
APK anterior con un nuevo número de versión. No obstante, solo se debe recurrir a esta
práctica como último recurso ya que los usuarios perderán el acceso a las funciones nuevas y es posible
que tu aplicación anterior no sea directamente compatible con los cambios realizados en el servidor o los formatos de datos,
por lo que debes asegurarte de ejecutar <a href="#alpha-beta">pruebas alfa y beta</a> de tus
actualizaciones.
</p>
<div class="headerLine">
<h2 id="multiple-apk">
Compatibilidad con múltiples APK
</h2>
</div>
<p>
En la mayoría de los casos, todo lo que necesitas es un solo paquete de aplicaciones (APK), y generalmente es la manera
más sencilla de administrar y mantener la aplicación. Sin embargo, si necesitas
proporcionar un APK distinto para diferentes dispositivos, Google Play te
permite hacerlo.
</p>
<p>
<em>Compatibilidad con múltiples APK</em> te permite crear múltiples paquetes de aplicaciones que utilizan
el mismo nombre de paquete pero difieren en sus formatos de compresión de texturas OpenGL,
en la compatibilidad con diferentes tamaños de pantalla o en las versiones de la plataforma Android admitidas. Puedes simplemente
cargar todos los APK en una misma lista de productos y Google Play seleccionará
los mejores para proporcionárselos a los usuarios en función de las características de sus
dispositivos.
</p>
<p>
También puedes cargar hasta dos descargas secundarias para cada APK publicado,
incluidos múltiples APK, mediante la opción <em>Archivos de expansión de APK</em>. Cada
archivo de expansión puede tener un tamaño máximo de 2 GB y contener cualquier tipo de código o recursos.
Google Play los aloja de forma gratuita y administra la descarga de los archivos como parte
de la instalación habitual de la aplicación.
</p>
<div class="headerLine">
<h2 id="selling-pricing-your-products">
Venta y fijación de precios de tus productos
</h2>
</div>
<div class="figure-right">
<img src="{@docRoot}images/gp-buyer-currency.png" class="frame">
</div>
<p>
Tienes las herramientas que necesitas para fijar los precios de tu aplicación y de los productos que ofreces en la aplicación. La descarga
de tu aplicación puede ser gratuita o paga, en cuyo caso se requerirá el pago antes de poder descargarla.
</p>
<ul>
<li>Si publicas tu aplicación como gratuita, debe <strong>continuar siendo gratuita durante toda su
vida útil</strong>. Todos los usuarios en Google Play pueden descargar aplicaciones gratuitas.
</li>
<li>Si la publicas como paga, más adelante puedes cambiarla a gratuita. Solo los usuarios
que hayan registrado un método de pago en Google Play pueden comprar
y descargar aplicaciones pagas.
</li>
</ul>
<div class="sidebox-wrapper" style="float:right;">
<div class="sidebox">
<p>
Consulta <a href="http://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=138294&amp;topic=2365624&amp;ctx=topic">
Países admitidos para la distribución de aplicaciones</a> para obtener una lista de
los países donde puedes distribuir o vender tus aplicaciones.
</p>
</div>
</div>
<p>
También puedes ofrecer productos y suscripciones en la aplicación, independientemente
de que la aplicación sea gratuita o paga. Fija precios de forma independiente para las aplicaciones pagas, los productos que se ofrecen en la aplicación y las
suscripciones.
</p>
<p>
Cuando los usuarios examinan las páginas de productos de tu aplicación o inician una compra, Google Play
les muestra el precio que deberán pagar en su moneda local.
</p>
<p>
Para cada producto, debes fijar inicialmente un precio predeterminado en tu propia moneda. Si
no haces más que eso, Google Play fijará automáticamente los precios locales para tu aplicación una vez al mes
en función del precio del dólar estadounidense.
</p>
<p>
No obstante, Google Play te ofrece el control total de la fijación de precios para tus
productos en cada país. Para comenzar, puedes establecer manualmente precios locales fijos
a partir del precio predeterminado mediante la función <strong>convertir precios automáticamente ahora</strong>
. Luego puedes revisar esos precios y fijar precios nuevos para los países
que desees; el precio para cada país es independiente, por lo que puedes ajustar
un precio sin afectar los demás. Para la mayoría de los países, el precio que fijas es
el precio final que se cobra a los usuarios, con impuestos incluidos.
</p>
<p>
Para obtener más información sobre cómo fijar precios para tus aplicaciones, consulta <a href="{@docRoot}distribute/users/expand-to-new-markets.html#localize-your-google-play-listing">
Expansión a nuevos mercados</a>.
</p>
<div class="headerLine">
<h2 id="in-app-products">
Productos ofrecidos en la aplicación
</h2>
</div>
<p>
Puedes vender productos y suscripciones en la aplicación mediante el uso de la <a href="{@docRoot}google/play/billing/index.html">Facturación integrada en la aplicación de Google Play</a> como
una forma de monetizar tus aplicaciones. Los productos que se ofrecen en la aplicación constituyen compras únicas, mientras que
las suscripciones son cargos recurrentes que se aplican mensualmente o anualmente.
</p>
<p>
En la sección <strong>Productos ofrecidos en la aplicación</strong> para un APK específico publicado o
en borrador, puedes:
</p>
<ul>
<li>Crear listas de productos para productos y suscripciones ofrecidos en la aplicación.
</li>
<li>Fijar precios.
</li>
<li>Publicar los productos en la aplicación o retirar los productos obsoletos.
</li>
</ul>
<p>
Para obtener información detallada acerca de cómo implementar la facturación integrada en la aplicación, consulta la documentación para desarrolladores <a href="{@docRoot}google/play/billing/index.html">Facturación integrada en la aplicación</a>
. Puedes utilizar los productos que ofreces en la aplicación en los modelos de monetización <a href="{@docRoot}distribute/monetize/premium.html">Premium</a>, <a href="{@docRoot}distribute/monetize/freemium.html">Gratuitos</a> y <a href="{@docRoot}distribute/monetize/subscriptions.html">Suscripción</a>
.
</p>
<div class="headerLine">
<h2 id="distribution-controls">
Controles de distribución
</h2>
</div>
<p>
Administra en qué países y territorios distribuirás tus aplicaciones. Para algunos
países, puedes elegir los operadores a los que quieres apuntar. También puedes ver
la lista de dispositivos compatibles con tu aplicación conforme a las
reglas de distribución declaradas en su archivo de manifiesto.
</p>
<h3 id="geotargeting">
Perfilamiento geográfico
</h3>
<p>
Puedes usar los controles de la Consola para desarrolladores de Google Play para administrar fácilmente
la distribución geográfica de tus aplicaciones, sin realizar ningún cambio en el
archivo binario de tu aplicación. Puedes especificar los países y territorios donde quieres
distribuir, e incluso los operadores (para algunos países).
</p>
<p>
Cuando los usuarios visitan la tienda, Google Play se asegura de que se encuentren en
uno de los países que seleccionaste antes de que puedan descargar tu aplicación. Puedes cambiar tu
selección de países y operadores en cualquier momento, para lo que simplemente deberás guardar los cambios en la
Consola para desarrolladores de Google Play.
</p>
<div class="figure-right" style="width:500px;">
<img src="{@docRoot}images/gp-supported-dev-requirements.png" class="frame">
</div>
<p>
Para optimizar la comercialización a usuarios alrededor del mundo, puedes <a href="{@docRoot}distribute/tools/launch-checklist.html#start-localization">localizar
el directorio de tu tienda</a> e incluir detalles y la descripción de tu aplicación, gráficos
promocionales, capturas de pantalla y más.
</p>
<h3 id="captargeting">
Perfilamiento de funcionalidades
</h3>
<p>
Google Play también te permite controlar la distribución de acuerdo con las funciones o capacidades de
los dispositivos en las que se base tu aplicación. Existen diversos tipos de
dependencias que la aplicación puede definir en su manifiesto, como características de
hardware, formatos de compresión de texturas OpenGL, bibliotecas, versiones de la plataforma Android
y otras.
</p>
<p>
Cuando cargas tu aplicación, Google Play lee las dependencias y configura las
reglas de distribución necesarias. Para obtener información técnica acerca de cómo declarar
dependencias, lee <a href="{@docRoot}google/play/filters.html">Filtros
en Google Play</a>.
</p>
<p>
Para determinar con precisión el control de la distribución, Google Play te permite ver todos los
dispositivos para los que tu aplicación está disponible en función de sus dependencias (si las hubiera). Desde la
Consola para desarrolladores de Google Play, puedes indicar los dispositivos admitidos e incluso
excluir dispositivos específicos si fuera necesario.
</p>
<div class="headerLine">
<h2 id="reviews-reports">
Reseñas de usuarios e informes de errores
</h2>
</div>
<div class="figure-right" style="width:500px;">
<img src="{@docRoot}images/gp-dc-reviews.png" class="frame">
<p class="img-caption">
La sección Reseñas de los usuarios te permite acceder a las reseñas de los usuarios para una aplicación
específica. Puedes filtrar reseñas de diversas maneras para identificar problemas con
mayor facilidad y brindar soporte a tus clientes de forma más eficaz.
</p>
</div>
<p>
Google Play permite a los usuarios enviar reseñas de tu aplicación de forma fácil
para el beneficio de otros usuarios. Las reseñas te brindan información sobre utilidad, solicitudes
de soporte y detalles acerca de problemas importantes de funcionalidad que
proporcionan tus clientes.
</p>
<p>
Utiliza informes de errores para depurar y mejorar tu aplicación. Puedes ver los informes
de errores mediante el seguimiento de la pila y otros datos, enviados automáticamente desde dispositivos
Android.
</p>
<div class="headerLine">
<h2 id="app-stats">
Estadísticas de la aplicación
</h2>
</div>
<div class="figure" style="width:500px">
<img src="{@docRoot}images/gp-dc-stats.png">
<p class="img-caption">
<b>Página de estadísticas de la aplicación</b>: Te muestra una variedad de estadísticas acerca del
rendimiento de una instalación específica de la aplicación.
</p>
</div>
<p>
Puedes obtener estadísticas detalladas acerca del rendimiento de la instalación de tu aplicación.
</p>
<p>
Consulta las métricas de instalación obtenidas por usuarios y por dispositivos
exclusivos. Visualiza la cantidad de instalaciones activas, instalaciones totales, actualizaciones, instalaciones y
desinstalaciones diarias, y métricas acerca de las calificaciones.
</p>
<p>
Sumérgete en los números de instalación por métrica, incluida la versión de
plataforma de Android, el dispositivo, el país, el idioma, la versión de la aplicación y el operador. Visualiza los
datos de instalación para cada dimensión en cuadros con línea de tiempo.
</p>
<p>
Esos cuadros resaltan los picos de instalación de tu aplicación y las tendencias a largo plazo,
y te ayudan a comprender el comportamiento de aceptación del usuario, a relacionar estadísticas con
promociones, a observar el efecto de las mejoras realizadas a la aplicación y otros factores. Concéntrate
en los datos de una dimensión al agregar puntos específicos a la línea de tiempo.
</p>
<p style="clear:both">
</p>
<div class="dynamic-grid">
<div class="headerLine">
<h2 id="related-resources">Recursos relacionados</h2>
</div>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/googleplay/developerconsole"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>
</div>

View File

@@ -1,61 +0,0 @@
page.title=Diseñado para la familia
page.metaDescription=Diseñado para la familia te ayuda a que cualquier familia pueda descubrir más fácilmente tus aplicaciones y juegos.
page.image=/distribute/images/about-dff-sm.jpg
meta.tags="families, googleplay, distribution"
page.tags="families"
@jd:body
<p>
En algunas semanas, una nueva experiencia en Google Play centrada en la familia les ofrecerá a los
usuarios nuevas maneras de examinar, buscar y descubrir aplicaciones y juegos de alta calidad
para sus familias.
</p>
<p>
A fin de construir una tienda más accesible para toda la familia, se invita a los desarrolladores a incluir
aplicaciones y juegos orientados a la familia en el nuevo programa Diseñado para la familia. Las aplicaciones
que cumplan con los <a href="https://support.google.com/googleplay/android-developer/answer/6184502">requisitos
del programa</a> se mostrarán en la nueva experiencia para la familia, de modo que los
padres puedan encontrar más fácilmente aplicaciones y juegos adecuados, confiables y de alta calidad.
</p>
<img src="{@docRoot}distribute/images/about-dff-sm.jpg">
<p>
Incluye tus aplicaciones y juegos hoy mismo con las herramientas y los procesos que actualmente
usas para administrar tus aplicaciones en la Consola para desarrolladores. Al incluir tus aplicaciones en el programa
puedes beneficiarte de una mayor capacidad de detección y de la posibilidad de mantener sus
categorías, calificaciones y reseñas existentes en cualquier otra parte de la Play Store
de Google.
</p>
<h2 id="elibibility">Elegibilidad</h2>
<p>
Las aplicaciones que forman parte de la experiencia para toda la familia en Google Play serán más fáciles
de descubrir para los padres y las familias que esperan que las aplicaciones sean aptas para
determinadas edades. El programa Diseñado para la familia tiene como objetivo la inclusión de
aplicaciones creadas para niños como también aquellas que puede disfrutar
toda la familia. Para poder abordar ese público, existen pautas y políticas
específicas que tus aplicaciones deben cumplir y que se evaluarán en una revisión de contenido de
las aplicaciones.
</p>
<p>
Asegúrate de conocer las políticas que tu aplicación debe
cumplir. Esas políticas incluyen <a href="http://play.google.com/about/developer-content-policy.html">políticas
de contenido</a>, el <a href="http://play.google.com/about/developer-distribution-agreement.html">Acuerdo de
distribución para desarrolladores</a> y el <a href="https://play.google.com/intl/ALL_us/about/families/developer-distribution-agreement-addendum.html">
Anexo de DDA para Diseñado para la familia</a>.
</p>
<p>
Tu aplicación también debe cumplir los requisitos del <a href="https://support.google.com/googleplay/android-developer/answer/6184502">programa Diseñado
para la familia</a> que se indican en el Centro de ayuda para desarrolladores de
Google Play.
</p>
<div class="paging-links" style="padding-top:.75em;">
<a href="{@docRoot}distribute/googleplay/families/start.html" class="next-class-link">A continuación: Inclusión</a>
</div>

View File

@@ -1,329 +0,0 @@
page.title=Preguntas frecuentes
meta.tags="families", "guidelines", "quality"
page.tags="families", "addendum"
page.metaDescription=Preguntas y respuestas acerca de Diseñado para familias
@jd:body
<style>
dt {
font-weight:bold;
}
</style>
<div id="qv-wrapper">
<ol id="qv">
<h2>En este documento:</h2>
<ol>
<li><a href="#review">Reseña e inclusión de aplicaciones</a></li>
<li><a href="#monetization">Monetización</a></li>
<li><a href="#other">Otras preguntas</a></li>
</ol>
</div>
<p>
Las secciones a continuación proporcionan más información acerca de Diseñado para familias
y responde preguntas comunes que podrías tener.
</p>
<h2 id="review">Reseña e inclusión de aplicaciones</h2>
<dl>
<dt>¿Cómo incluyo mis aplicaciones?</dt>
<dl>
<dd>
Puedes incluir tus aplicaciones en Diseñado para familias a través de la pestaña Fijación de precios y distribución
para tu aplicación en la Consola para desarrolladores de Google Play. Aquí te mostramos <a href="{@docRoot}distribute/googleplay/families/start.html">paso a paso
cómo hacerlo</a>.
</dd>
<dt>
¿Dónde anuncio las funciones interactivas de mi aplicación? ¿Por qué recopilan
esta información?
</dt>
<dd>
El anuncio de las funciones interactivas forma parte del cuestionario sobre
clasificación de contenido. Tienes la oportunidad de revisar tus anuncios como
parte del flujo de inclusión en el programa Diseñado para familias. Recopilamos esta
información para que los usuarios puedan tomar decisiones informadas mientras evalúan tu
aplicación.
</dd>
<dt>
¿Qué es COPPA?
</dt>
<dd>
COPPA es la Ley de Protección de la Privacidad Infantil en Internet de la
Comisión Federal de Comercio (FTC). Puedes encontrar más información en las <a href="http://www.ftc.gov/tips-advice/business-center/guidance/complying-coppa-frequently-asked-questions">
Preguntas frecuentes de la FTC acerca de COPPA</a>. Ten en cuenta que Google Play no puede proporcionar asesoramiento legal a los desarrolladores
acerca de cómo cumplir con COPPA u otros estatutos en relación con niños.
</dd>
<dt>
¿Debo proporcionar una política de privacidad actualizada y dónde lo hago?
</dt>
<dd>
Sí, debes proporcionar un vínculo a una política de privacidad constante en
el directorio de tu tienda y confirmar el cumplimiento con los estatutos de privacidad locales
en la Consola para desarrolladores. Para agregar o revisar tu política de privacidad, selecciona tu
aplicación en la Consola para desarrolladores y luego desplázate a la parte inferior de la sección
<strong>Directorio de la tienda</strong>.
</dd>
<dt>
¿Cuántos grupos de edades puedo seleccionar?
</dt>
<dd>
Puedes seleccionar hasta dos grupos de edades adyacentes. Los grupos de edades son los siguientes: 5 años y
menores, de 6 a 8 años y de 9 a 12 años. No obstante, si tu aplicación está orientada a públicos
de niños y adultos, debes seleccionar la categoría <em>Público
general</em>.
</dd>
<dt>
¿Cuántas categorías de contenido puedo seleccionar en el programa
Diseñado para familias?
</dt>
<dd>
Puedes seleccionar una categoría como parte del programa Diseñado para familias
y otra categoría para la tienda general de Google Play.
</dd>
<dt>
¿Cuáles son las categorías de Diseñado para familias?
</dt>
<ul>
<li><strong>Acción y aventura</strong>: Se trata de aplicaciones o juegos orientados a la acción e incluyen de todo
desde juegos de carreras, aventuras de cuentos de hadas y más.
</li>
<li style="list-style: none"><strong>Juegos de ingenio</strong>: Esta categoría incluye juegos que
hacen pensar al usuario e incluye rompecabezas, juegos de coincidencias y otros juegos
similares.
</li>
<li><strong>Creatividad</strong>: Se trata de aplicaciones o juegos que estimulan la creatividad.
Algunos ejemplos de los tipos de aplicaciones y juegos que esperamos ver en esta categoría incluyen dibujo,
pintura y otros juegos donde puedas crear cosas.
</li>
<li><strong>Educación</strong>: Se trata de aplicaciones o juegos con valor educativo e incluyen
matemática, ciencia, aprender el alfabeto, aprender a contar y muchos otros tipos de
contenido educativo, como geografía e historia.
</li>
<li><strong>Música y videos</strong> Se trata de aplicaciones o juegos que contienen un elemento musical o un
componente de video, e incluyen de todo desde tocar el
piano hasta ver videos y más.
</li>
<li><strong>Juego de roles</strong>: Se trata de aplicaciones o juegos en los que una persona puede fingir un
rol, como simular ser un cocinero o un médico.
</li>
</ul>
<dl>
<dt>
¿Demorará mucho tiempo más la publicación de mi aplicación si decido incluirla en el programa
Diseñado para familias?
</dt>
<dd>
Cuando accedes a Diseñado para familias, Google Play revisa tu aplicación para
confirmar que es apta para familias. Suponiendo que tu aplicación cumple con todos los requisitos
del programa, prevemos que el tiempo de publicación no debería prolongarse
más allá de lo habitual; no obstante, puede haber una demora en la publicación de la aplicación si se
rechaza durante la revisión para la inclusión en Diseñado para familias.
</dd>
<dt>
¿Qué ocurre si se rechaza mi aplicación del programa Diseñado para familias?
</dt>
<dd>
Si se rechaza tu aplicación del programa Diseñado para familias, te
indicaremos el motivo en la Consola para desarrolladores y en detalle en un correo electrónico. Tendrás
la oportunidad de corregir los problemas y volver a enviar tu aplicación al programa,
o cambiar tu respuesta de inclusión. Ten en cuenta que si tienes una aplicación existente que
está activa en Google Play, solo se rechazará la actualización de la aplicación (la aplicación
continuará activa en la Play Store de Google). Si enviaste una nueva aplicación al
programa Diseñado para familias y no cumple con los requisitos,
se rechazará la presentación completa de la aplicación y no se publicará en
Google Play. Luego podrás abordar los problemas identificados y volver a enviar la aplicación al
programa Diseñado para familias o abandonar la idea de incluirla.
</dd>
<dt>
¿Qué ocurre si se determina que mi aplicación no cumple con los
requisitos del programa Diseñado para familias después de haberse publicado?
</dt>
<dd>
Se puede eliminar o suspender tu aplicación de la Play Store de Google,
no solo del programa Diseñado para familias. En las aplicaciones eliminadas se pueden
utilizar las mismas soluciones que en las aplicaciones rechazadas. Las aplicaciones suspendidas se pueden apelar mediante el
proceso de apelación para desarrolladores.
</dd>
<dt>
¿Si logro acceder al programa Diseñado para familias, puedo retirarme más adelante?
</dt>
<dd>
Sí, puedes retirarte del programa en cualquier momento. Ten en cuenta que al
retirarte perderás tu lugar en la nueva experiencia para la familia
y también los demás beneficios del programa.
</dd>
<dt>
¿Qué ocurre cuando actualizo mi aplicación después de haber sido aceptada en el
programa?
</dt>
<dd>
Las aplicaciones que forman parte del programa Diseñado para familias deben
cumplir los requisitos de elegibilidad en todo momento. Si necesitas
editar los metadatos de Diseñado para familias asociados con tu aplicación, dirígete
a la sección Fijación de precios y distribución de la Consola para desarrolladores de Google Play
y edita esa información. Si la actualización de tu aplicación implica un
cambio de público, te recomendamos que alertes a los usuarios que ya
instalaron tu aplicación.
</dd>
<dt>
¿Se pueden incluir las aplicaciones y los juegos que utilizan los servicios Google Sign-In o
Google Play Game en el programa Diseñado para familias?
</dt>
<dd>
Las aplicaciones que participan en el programa Diseñado para familias están centradas
exclusivamente en los niños; es decir, están orientadas a los siguientes grupos de edades: Los niños de 5 años y menores,
de 6 a 8 años o de 9 a 12 años <strong>no pueden</strong> usar los servicios Google+ Sign-in
o Google Play Game como experiencia de inicio de sesión para su
aplicación.
<p>
Las aplicaciones que participan en Diseñado para familias orientadas a un público
infantil y adulto pueden usar los servicios Google+ Sign-in o Google Play Game
como una función <strong>opcional</strong>. Los niños deben poder acceder a la totalidad de la aplicación
o el juego sin la necesidad de iniciar sesión en los servicios Google+ o Google Play Game.
</p>
</dd>
<dt>
Mi aplicación está incluida en Google Play for Education y está integrada a Google Sign-in
; por lo tanto, los estudiantes pueden iniciar sesión con sus cuentas escolares. ¿Debo cambiar la manera en la que
funciona Google Sign-in en mi aplicación?
</dt>
<dd>
Las aplicaciones que participan en Google Play for Education pueden utilizar Google Sign-in para
las cuentas de estudiantes siempre que no sea un requisito limitador para todos los usuarios de la aplicación
</dd>
</dl>
<h2 id="monetization">
Monetización del programa Diseñado para familias
</h2>
<dl>
<dt>
¿Pueden darme más detalles acerca de las políticas de publicidad para Diseñado
para familias?
</dt>
<dd>
Lee la <a href="https://support.google.com/googleplay/android-developer/answer/6184502#ads">
política de anuncios publicitarios para Diseñado para familias</a>.
</dd>
<dt>
¿Puede mi aplicación exhibir anuncios intersticiales?
</dt>
<dd>
Los anuncios intersticiales pueden ser adecuados para algunas aplicaciones. No obstante, el usuario debe
poder navegar a la actividad principal antes de que se exhiban anuncios publicitarios.
</dd>
<dt>
¿Cómo sé si mi red de anuncios cumple con las políticas de
publicidad de Diseñado para familias?
</dt>
<dd>
Comunícate con tu red de publicidad para consultar acerca de sus políticas de contenido
y prácticas publicitarias. Si usas AdMob, consulta el <a href="https://support.google.com/admob/answer/3248194">Centro de ayuda de AdMob</a> para
obtener información detallada acerca de cómo etiquetar tu aplicación o una unidad de publicidad específica para indicar que
está orientada a niños. Es responsabilidad del desarrollador garantizar que la experiencia
de usuario global con publicidad en la aplicación cumpla con los requisitos del programa <a href="https://support.google.com/googleplay/android-developer/answer/6184502">Diseñado
para familias</a>.
</dd>
<dt>
¿Puedo incluir compras integradas en la aplicación en mi aplicación?
</dt>
<dd>
No hay restricciones específicas con respecto a las compras integradas en la aplicación (IAP) para
las aplicaciones que participan del programa Diseñado para familias además del
cumplimiento con el <a href="https://play.google.com/intl/ALL_us/about/families/developer-distribution-agreement-addendum.html">
DDA de Diseñado para familias</a> y otros requisitos legales correspondientes, pero
Google Play se reserva el derecho de rechazar aplicaciones que empleen tácticas comerciales
extremadamente agresivas. Google Play aplicará la protección de IAP con contraseña en todas las aplicaciones
que participen del programa Diseñado para familias y que apunten principalmente
a un público infantil a fin de garantizar que los padres, no los niños, estén autorizando
las compras. Ten en cuenta que este tratamiento no se extiende a las aplicaciones
orientadas al público en general.
</dd>
</dl>
<h2 id="other">
Otras preguntas
</h2>
<dl>
<dt>
¿Cuál es el público previsto para las aplicaciones que participan en Diseñado para
familias?
</dt>
<dd>
Nuestro objetivo es proporcionar una excelente experiencia de usuario en la Play Store de Google para
que padres y tutores descubran aplicaciones maravillosas para niños y
familias creadas por desarrolladores y marcas confiables.
</dd>
<dt>
¿Está el programa Diseñado para familias disponible únicamente para desarrolladores
en ciertos países?
</dt>
<dd>
Diseñado para familias es un programa global.
</dd>
<dt>
¿Qué ocurre con las aplicaciones que se publican en la categoría actual
Juegos para la familia?
</dt>
<dd>
La categoría actual Juegos para la familia quedará obsoleta en mayo de 2015. Las aplicaciones
que actualmente se encuentren en la categoría Juegos para la familia deberán
trasladarse a otra categoría en la tienda de Google Play. Las aplicaciones para las que no se haya seleccionado otra
categoría se asignarán a la categoría Juegos casuales.
</dd>
</dl>
<div class="paging-links" style="padding-top:.75em;">
<a href="https://docs.google.com/forms/d/1EtvUWqlkxS6RxHJjeI-3-7uzdbIZx6n9Cocy2D369B8/viewform" class="next-class-link">A continuación: Mantente en contacto</a>
</div>

View File

@@ -1,106 +0,0 @@
page.title=Accede a Diseñado para familias
meta.tags="families", "guidelines", "quality"
page.tags="families", "addendum"
page.metaDescription=Únete a Diseñado para familias en pocos pasos sencillos.
@jd:body
<p>
Si estás creando una aplicación diseñada para niños y familias, hay algunas
cosas que debes hacer <em>antes</em> de que estés listo para acceder al programa Diseñado para
familias:
</p>
<ul>
<li>Completa el cuestionario de calificación de contenido para tu aplicación y cumple con una calificación
de ESRB, que puede ser Todos o Todos 10+.
</li>
<li>Agrega un vínculo de la política de privacidad a la página <strong>Directorio de la tienda</strong>
de tu aplicación.
</li>
<li>Asegúrate de que tu aplicación cumpla todos los <a href="https://support.google.com/googleplay/android-developer/answer/6184502">requisito
del programa Diseñado para familias.</a>
</li>
</ul>
<p>
Ahora que tu aplicación está lista para la publicación, puedes acceder a Diseñado para
familias directamente desde la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores</a>. Acceder al programa
significa que quieres que tu aplicación esté disponible en la nueva experiencia
para la familia en Google Play, además de la categoría que hayas seleccionado en la
Play Store de Google.
</p>
<p>
La inclusión en el programa también confirma que tu aplicación cumple con las <a href="http://play.google.com/about/developer-content-policy.html">Políticas del programa para desarrolladores de
Google Play</a> y con el <a href="http://play.google.com/about/developer-distribution-agreement.html">Acuerdo de
distribución para desarrolladores</a>, incluido el<a href="https://play.google.com/intl/ALL_us/about/families/developer-distribution-agreement-addendum.html">
Anexo de DDA para Diseñado para familias</a>. Si no estás familiarizado con los documentos de
estas políticas o con el anexo, asegúrate de leerlos antes de solicitar la inclusión.
</p>
<p>
Cuando estés listo, sigue estas instrucciones de inclusión en Diseñado para familias para una aplicación específica:
</p>
<ol>
<li>En la página <strong>Todas las aplicaciones</strong> de la Consola para desarrolladores, haz clic en la aplicación que quieres
incluir. En Fijación de precios y distribución, desplázate hacia abajo hasta encontrar <strong>Diseñado para
familias</strong> y la casilla de verificación para la inclusión.<img src="/images/gp-dff-optin.png" style="border:2px solid #ddd;margin:1em 0;">
</li>
<li>Comienza el flujo de inclusión y confirma que tu aplicación cumple los requisitos de
elegibilidad.</li>
<li>Si tu aplicación tiene anuncios publicitarios, confirma que cumplen con la política de anuncios publicitarios.
<img src="/images/gp-dff-appinfo.png" style="border:2px solid #ddd;margin:1em 0;"></li>
<li>Selecciona tus grupos etarios objetivo entre los siguientes: 5 años y menores, de 6 a 8 años, de 9
a 12 años o Público general (para aplicaciones orientadas a niños y a públicos
mayores). Si tu aplicación está orientada a más de un grupo etario, puedes seleccionar hasta
dos grupos etarios adyacentes. Las aplicaciones con una calificación de ESRB de 10+ solo pueden seleccionar la
edad objetivo de 9 a 12 años o Público general.
</li>
<li>Selecciona una categoría para tu aplicación para la nueva experiencia centrada en la familia en
Google Play. Los usuarios también podrán encontrar tu aplicación en su categoría actual en
Google Play.</li>
<li>Lee y acepta los documentos vinculados y luego haz clic en
<strong>Incluir</strong>. Por último, haz clic en <strong>Enviar actualización</strong> en la página
Fijación de precios y distribución para publicar o actualizar tu aplicación.
</li>
</ol>
<p>
Una vez que hayas incluido tu aplicación, se la someterá a una revisión exhaustiva antes de recibir la
aprobación para el programa Diseñado para familias.
</p>
<p class="note">
<strong>Nota</strong>: Las aplicaciones publicadas en el programa Diseñado para familias
también están disponibles para todos los usuarios en Google Play.
</p>
<p>
Si incluyes una aplicación que estás publicando por primera vez y no cumple
los requisitos del programa Diseñado para familias, no estará disponible
en Google Play hasta que actualices la aplicación para que cumpla
los requisitos del programa <strong>o</strong> canceles la selección de la casilla de verificación para la inclusión y
apruebes la revisión estándar de Google Play.
</p>
<p>
Si incluyes una aplicación que ya está publicada en Google Play y no cumple
los requisitos del programa, continuará estando disponible para todos los usuarios, pero no
se agregará a la nueva experiencia para la familia hasta que actualices la aplicación de modo que cumpla los
requisitos del programa.
</p>
<p>
Si publicas una actualización para una aplicación que ya forma parte de Diseñado para familias,
la actualización de la aplicación debe aprobar la revisión de Diseñado para familias antes de que
esté disponible para todos los usuarios en Google Play.</p>
<div class="paging-links" style="padding-top:.75em;">
<a href="{@docRoot}distribute/googleplay/families/faq.html" class="next-class-link">A continuación: Preguntas frecuentes</a>
</div>

View File

@@ -1,70 +0,0 @@
page.title=Cómo tener éxito en Google Play
page.metaDescription=Una guía que te ayudará a tener éxito con tu aplicación o juego en Google Play.
meta.tags="distribute", "bestpractices"
page.tags="google play", "business", "monetize", "engagement"
page.image=distribute/images/play_dev_guide.png
@jd:body
<p>
Creamos una guía para descargar que te ayudará a tener éxito con tu aplicación o
juego en Google Play. En la guía encontrarás funciones, sugerencias y mejores
prácticas que te ayudarán a crear una estrategia eficaz.
</p>
<p>
La guía se divide en las siguientes secciones:
</p>
<ul>
<li>
<strong>Publicación en Google Play</strong> &mdash; Mediante la Consola para desarrolladores de Google Play
podrás distribuir tu aplicación a más de mil millones de usuarios de Android
en todo el mundo.
</li>
<li>
<strong>Calidad</strong> &mdash; Los aspectos básicos para crear una excelente aplicación
e información acerca de las pautas y las políticas de Google Play.
</li>
<li>
<strong>Capacidad de detección y alcance</strong> &mdash; Optimización de la
capacidad de detección de tu aplicación y llegada al público más amplio posible.
</li>
<li>
<strong>Atracción y retención</strong> &mdash; Transformación de
las instalaciones en usuarios activos y optimización de la retención de usuarios.
</li>
<li>
<strong>Monetización</strong> &mdash; Estrategias de monetización para generar
flujos de ingresos constantes y en aumento.
</li>
<li>
<strong>Medición con Google Analytics</strong> &mdash; Comprensión
de tus usuarios y optimización de la experiencia, las conversiones y la comercialización de tu aplicación.
</li>
<li>
<strong>Alcance global</strong> &mdash; Lanzamiento de tu aplicación en mercados locales
alrededor del mundo.
</li>
</ul>
<p>
Para descargar la guía, haz clic en la imagen a continuación o <a href="http://goo.gl/DFjbrS">consíguela en Google Play</a>.
</p>
<p>
En los próximos meses, publicaremos la guía en más idiomas. Regresa a este
sitio web con frecuencia para consultar la información que publiquemos acerca de nuevas funciones y mejores
prácticas que te ayudarán a distribuir y monetizar tu aplicación.
</p>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:play_dev_guide"
data-cardSizes="9x6"
data-maxResults="1">
</div>

View File

@@ -1,488 +0,0 @@
page.title=Calidad de las aplicaciones para Auto
page.metaDescription=Las aplicaciones para Auto se integran con los controles de entrada y la pantalla del vehículo, y minimizan la distracción del conductor para crear una excelente experiencia.
page.image=/distribute/images/gp-auto-quality.png
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Criterios de calidad</h2>
<ol>
<li><a href="#core">Calidad de la aplicación principal</a></li>
<li><a href="#ux">Diseño visual e interacción</a></li>
<li><a href="#fn">Funcionalidad</a></li>
<li><a href="#faq">Preguntas frecuentes</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/core.html">
Calidad de la aplicación principal</a></li>
<li><a href="{@docRoot}distribute/essentials/optimizing-your-app.html">
Optimiza tu aplicación</a></li>
<li><a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">Pautas de la Experiencia de usuario de Android Auto
para aplicaciones de audio</a></li>
<li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">Pautas de la Experiencia de usuario de Android Auto
para aplicaciones de mensajería</a></li>
</ol>
</div>
</div>
<img src="{@docRoot}distribute/images/gp-auto-quality.png" style="width:480px;">
<p>Al abordar la compatibilidad de tu aplicación con Android Auto, evita la distracción del conductor por sobre todas las cosas.
Las aplicaciones que funcionan con la interfaz de usuario Auto deben minimizar las distracciones a las que está expuesto el conductor;
esto se logra mediante la aplicación de las mejores prácticas, como comandos de voz y un diseño visual muy simple.
</p>
<p>
Las mejores experiencias para Auto son predictivas y predecibles. Las aplicaciones compatibles con Android Auto
deben mostrar información oportuna al conductor solo cuando sea relevante, y deben usar
patrones simples y predecibles para las tareas comunes.
</p>
<p class="caution">
<strong>Importante:</strong> Los criterios que se indican en esta página corresponden a la interfaz de usuario y al comportamiento
de tu aplicación cuando se ejecuta en dispositivos conectados a una pantalla de Android Auto. Las aplicaciones deben cumplir esos
criterios para poder calificar como una aplicación Android Auto en Google Play.
</p>
<div class="headerLine">
<h2 id="core">
Calidad de la aplicación principal
</h2>
<p>
Además de los criterios específicos para Auto antes mencionados, las aplicaciones para Auto deben cumplir todos los criterios de calidad
de la aplicación principal para la plataforma Android, tal como se detalla en los
criterios de <a href="{@docRoot}distribute/essentials/quality/core.html">Calidad de la aplicación principal</a>. Prueba
tu aplicación en función de esos criterios para asegurarte de que cumple con los estándares de Android para navegación y
diseño. Luego prueba tu aplicación nuevamente en función de los criterios específicos para Auto, y recuerda que
al ejecutar la aplicación en un dispositivo conectado a Android Auto, esta debe cumplir los requisitos
que se indican en esta página.
<div class="headerLine">
<h2 id="ux">
Diseño visual e interacción del usuario
</h2>
</div>
<p>
Estos criterios permiten que te asegures de que tu aplicación cumpla con los patrones clave de diseño e interacción
a fin de garantizar una experiencia de usuario uniforme, intuitiva y agradable en Android Auto. Muchos elementos,
como cajón de navegación, fondos de tarjetas, fuentes y colores de iconos, son establecidos y proporcionados
por el sistema. Tus elementos de diseño propios, específicos para la aplicación, deben cumplir los siguientes criterios.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
Prueba
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="5" id="safety">
Atención del conductor
</td>
<td id="AU-MV">
AU-MV
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no se muestra en los elementos animados de la pantalla Auto, como gráficos animados, juegos, video o
barras de progreso.
</p>
</td>
</tr>
<tr>
<td id="AU-VA">
AU-VA
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no muestra ningún tipo de publicidad visual o textual en la pantalla Auto. Solo se aceptan
anuncios publicitarios en audio.
</p>
</td>
</tr>
<tr>
<td id="AU-IM">
AU-IM
</td>
<td>
<p style="margin-bottom:.5em;">
Los elementos de la aplicación no muestran imágenes en la pantalla Auto. Excepciones: la aplicación puede mostrar
una sola imagen fija como
contexto del contenido en el fondo de la pantalla de consumo, como la tapa de un álbum, y la aplicación puede
mostrar iconos en el cajón de navegación del contenido.
</p>
</td>
</tr>
<tr>
<td id="AU-DS">
AU-DS
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no incluye funciones que pueden distraer al conductor.
</p>
</td>
</tr>
<tr>
<td id="AU-VI">
AU-VI
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no presenta ninguna forma de información visual (notificaciones, alertas, video, imágenes,
publicidad, etc.) en la pantalla del teléfono mientras se encuentra activa en Android Auto.
</p>
</td>
</tr>
<tr>
<td rowspan="3" id="layout">
Diseño
</td>
<td id="AU-SC">
AU-SC
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no muestra texto con desplazamiento automático.
</p>
</td>
</tr>
<tr>
<td id="AU-FT">
AU-FT
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación muestra todas las cadenas con las fuentes Roboto predeterminadas en los dos tamaños aprobados.
</p>
</td>
</tr>
<tr>
<td id="AU-ST">
AU-ST
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no muestra una cadena individual que contenga más de 120 caracteres.
</p>
</td>
</tr>
<tr>
<td rowspan="4" id="contrast">
Contraste visual
</td>
<td id="AU-DM">
AU-DM
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación admite el modo día, que muestra texto y controles oscuros sobre un fondo claro.
(<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="AU-NM">
AU-NM
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación admite el modo noche, que muestra texto y controles claros sobre un fondo oscuro.
(<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="AU-WI">
AU-WI
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación ofrece conjuntos de iconos blancos que el sistema colorea para proporcionar
compensación de contraste automática.
(<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="AU-OC">
AU-OC
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación ofrece colores que el sistema puede optimizar para facilitar la lectura en el vehículo.
(<a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="2" id="interaction">
Interacción
</td>
<td id="AU-VC">
AU-VC
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación debe admitir comandos de voz.
</p>
</td>
</tr>
<tr>
<td id="AU-AB">
AU-AB
</td>
<td>
<p style="margin-bottom:.5em;">
Los botones específicos de la aplicación responden a las acciones del usuario en no más de dos segundos.
</p>
</td>
</tr>
</table>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/autoqualityguidelines/visualdesign"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="fn">
Funcionalidad
</h2>
</div>
<p>
Estos criterios garantizan que tu aplicación esté correctamente configurada y proporcione el comportamiento
funcional previsto.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
Prueba
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="5" id="general">
General
</td>
<td id="AU-LT">
AU-LT
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación se carga en 10 segundos como máximo.
</p>
</td>
</tr>
<tr>
<td id="AU-FP">
AU-FP
</td>
<td>
<p style="margin-bottom:.5em;">
La funcionalidad Auto de la aplicación funciona según lo previsto o descrito en el directorio de la tienda de la aplicación en la Play Store de Google.
</p>
</td>
</tr>
<tr>
<td id="AU-RL">
AU-RL
</td>
<td>
<p style="margin-bottom:.5em;">
Cuando se reinicia la aplicación desde la pantalla de inicio, esta restaura su estado al estado anterior
con la mayor precisión posible.
</p>
</td>
</tr>
<tr>
<td id="AU-SS">
AU-SS
</td>
<td>
<p style="margin-bottom:.5em;">
Ninguna de las tareas de la aplicación requieren más de seis pasos para completarse.
</p>
</td>
</tr>
<tr>
<td id="AU-GO">
AU-GO
</td>
<td>
<p style="margin-bottom:.5em;">
Los botones de la aplicación que no funcionen o estén inhabilitados deben visualizarse de color gris.
</p>
</td>
</tr>
<tr>
<td rowspan="2" id="media">
Medios
</td>
<td id="AU-PA">
AU-PA
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no tiene más de cuatro acciones principales más una alternancia de desbordamiento de acciones optativa (o cinco si
no se utiliza el desbordamiento de acciones).
(<a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="AU-SA">
AU-SA
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no tiene más de cuatro acciones secundarias opcionales más una alternancia de desbordamiento de acciones.
(<a href="{@docRoot}shareables/auto/AndroidAuto-audio-apps.pdf">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="2" id="notifications">
Notificaciones
</td>
<td id="AU-NA">
AU-NA
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no presenta anuncios publicitarios mediante notificaciones.
</p>
</td>
</tr>
<tr>
<td id="AU-NT">
AU-NT
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación muestra notificaciones solo cuando es relevante para las necesidades del conductor.
</p>
<p>
Ejemplos:<br />
Está bien: Notificar al usuario acerca de un nuevo mensaje que acaba de recibir.<br />
Está mal: Notificar al usuario acerca del lanzamiento de un nuevo álbum.
</p>
</td>
</tr>
</table>
<!--
<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/autoqualityguidelines/functionality"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
-->
<div class="headerLine">
<h2 id="faq">
Preguntas frecuentes
</h2>
</div>
<p style="margin-top:30px;">
<strong>Después de enviar mi aplicación, ¿cómo sabré si mi aplicación no cumple todos
los requisitos para Android Auto?</strong>
</p>
<p>Si estás pensando en desarrollar aplicaciones para Auto, te alentamos a que empieces a habilitar y probar
tus aplicaciones ahora mismo. No obstante, en este momento no se pueden publicar aplicaciones compatibles con Auto. Únete a la
<a href="http://g.co/AndroidAutoDev" class="external-link">comunidad de
desarrolladores de Auto en Google+</a> para acceder a actualizaciones acerca de cuándo podrás enviar
tus aplicaciones compatibles con Auto.</p>
</p>
<p style="margin-top:30px;">
<strong>Mi aplicación abarca más allá de Android Auto. Si mi aplicación no cumple con los
requisitos de Auto, ¿aún aparecerá mi aplicación nueva o actualizada en Google Play para teléfonos y
tablets?</strong>
</p>
<p>
No. Cuando Google inicie el proceso de aprobación, tu aplicación para Auto se someterá a una revisión de
seguridad del conductor y no estará
disponible para distribución hasta que se apruebe. Dado que es el mismo APK que el
que utilizas para teléfonos y tablets, tus actualizaciones en la Play Store para esos dispositivos no estará disponible hasta que
finalice el proceso de aprobación para Auto.
</p>
<p class="caution">
<strong>Importante:</strong> Debido a esta restricción, no debes utilizar tu APK
de producción en las pruebas de compatibilidad con Auto.
</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,846 +0,0 @@
page.title=Calidad de las aplicaciones para tablets
page.metaDescription=Las tablets son un componente de rápido crecimiento en la base de instalaciones de Android, que ofrece nuevas oportunidades para tus aplicaciones.
page.image=/distribute/images/tablet-guidelines-color.jpg
Xnonavpage=true
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Lista de comprobación</h2>
<ol>
<li><a href="#core-app-quality">1. Realiza una prueba de Calidad básica de las aplicaciones para tablets</a></li>
<li><a href="#optimize-layouts">2. Optimiza los diseños</a></li>
<li><a href="#use-extra-space">3. Utiliza el área adicional de la pantalla</a></li>
<li><a href="#use-tablet-icons">4. Utiliza recursos diseñados para tablets</a></li>
<li><a href="#adjust-font-sizes">5. Ajusta las fuentes y los controles táctiles objetivo</a></li>
<li><a href="#adjust-widgets">6. Ajusta los widgets de la pantalla de inicio</a></li>
<li><a href="#offer-full-feature-set">7. Ofrece un conjunto completo de funciones</a></li>
<li><a href="#android-versions">8. Aborda correctamente las versiones de Android</a></li>
<li><a href="#hardware-requirements">9. Declara dependencias correctamente</a></li>
<li><a href="#support-screens">10. Declara la compatibilidad con pantallas de tablets</a></li>
<li><a href="#google-play">11. Presenta tu IU para tablets</a></li>
<li><a href="#google-play-best-practices">12. Sigue las mejores prácticas para publicar en Google Play</a></li>
</ol>
<h2>Prueba</h2>
<ol>
<li><a href="#test-environment">Configuración de un entorno de prueba</a></li>
</ol>
</div></div>
<div class="todp-right-float" style="padding-right:0;margin-bottom:1em;">
<img src="{@docRoot}distribute/images/tablet-guidelines-color.jpg" style="width:480px;">
</div>
<p>
Las tablets son un componente en aumento de la base de instalaciones de Android y ofrecen nuevas
oportunidades de interacción con los <a href="{@docRoot}distribute/stories/tablets.html">usuarios
y monetización</a>. Las pautas que se indican en este documento te ayudarán
a cumplir las expectativas de los usuarios de tablets a través de funciones atractivas y
una IU intuitiva y bien diseñada.
</p>
<p>
Si bien las pautas están numeradas, puedes abordarlas en cualquier orden. Debes
abordar cada una de las recomendaciones que se proporcionan en las pautas en la medida en que
resulte apropiado para tu aplicación; no obstante, para poder proporcionar el mejor
producto a tus clientes, sigue las recomendaciones en la mayor medida
posible.
</p>
<p>
A lo largo del documento, encontrarás vínculos a recursos que pueden
ayudarte a abordar cada una de las recomendaciones incluidas.
</p>
<div class="headerLine"><h2 id="core-app-quality">1. Realiza una prueba de Calidad básica de las aplicaciones para tablets</h2></div>
<p>El primer paso en la provisión de una excelente experiencia con la aplicación en tablets es asegurarte
de que la aplicación cumpla con los <em>criterios de calidad de la aplicación principal</em> en todos los dispositivos
y formatos a los que apunte. Para obtener información completa, consulta las <a href="{@docRoot}distribute/essentials/quality/core.html">Pautas de calidad de la aplicación principal</a>.
</p>
<p>
Antes de publicar, asegúrate también de que tu aplicación apruebe los controles técnicos básicos y los criterios de lanzamiento, como los siguientes:
</p>
<ul>
<li><a href="#android-versions">Apunta a las versiones de Android adecuadas</a></li>
<li><a href="#hardware-requirements">Especifica correctamente las dependencias de hardware</a></li>
<li><a href="#support-screens">Declara la compatibilidad con las pantallas adecuadas</a></li>
<li><a href="#use-extra-space">Utiliza todo el espacio de pantalla disponible</a></li>
<li><a href="#google-play">Las capturas de pantalla se cargan a Google Play</a></li>
</ul>
<p>Si tu aplicación está cargada en la Consola para desarrolladores de Google Play, puedes
ver cómo le está yendo en función de esos controles
al visitar la página <a href="#google-play-optimization-tips">Sugerencias para
la optimización</a>.</p>
<div class="headerLine">
<h2 id="optimize-layouts">2. Optimiza los diseños para pantallas más grandes</h2></div>
<p>
Android facilita el desarrollo de una aplicación que se ejecute bien en una amplio rango de
tamaños de pantalla y formatos de dispositivos. Esta amplia compatibilidad funciona a tu favor,
ya que te ayuda a diseñar una aplicación única que puedes distribuir extensamente
a todos los dispositivos a los que apuntes. No obstante, para ofrecer a tus usuarios la mejor
experiencia posible en cada configuración de pantalla, en especial en
tablets, debes optimizar tus diseños y otros componentes de la IU para
cada configuración de pantalla que admitas. En las tablets, la optimización de tu IU te permite
aprovechar al máximo el espacio de pantalla adicional disponible, por ejemplo, para ofrecer nuevas
funciones, presentar contenido nuevo o mejorar la experiencia de otras maneras con el objetivo
de aumentar la interacción del cliente.
</p>
<p>
Si desarrollaste tu aplicación para teléfonos celulares y ahora quieres distribuirla a
tablets, puedes comenzar por realizar ajustes menores en tus diseños, fuentes
y espaciado. En algunos casos, como para tablets de 7 pulgadas o para un juego
con lienzos grandes, esos ajustes podrían ser todo lo que necesitas hacer para que tu
aplicación se vea genial. En otros casos, como para tablets más grandes, puedes rediseñar
partes de tu IU para reemplazar la "IU estirada" con una IU multipanel eficaz,
navegación más simple y contenido adicional.
</p>
<div style="width:500px;margin:1.5em;margin-top:-16px;">
<img src="{@docRoot}images/training/app-navigation-multiple-sizes-multipane-bad.png" style="padding:4px;margin-bottom:0em;">
<p class="img-caption"><span
style="font-weight:500;">Despídete de tu IU "estirada"</span>: En las tablets, los diseños
de panel único generan un espacio en blanco raro y líneas demasiado extensas. Utiliza relleno
para reducir el ancho de los elementos de la IU y considera la posibilidad de usar diseños multipanel.</p>
</div>
<p>Aquí te proporcionamos alguna sugerencias:</p>
<ul>
<li>Proporciona diseños personalizados, según sea necesario, para las pantallas <code>large</code> y
<code>xlarge</code>. También puedes proporcionar diseños que se cargarán
en función de la <a href="{@docRoot}guide/practices/screens_support.html#NewQualifiers">dimensión
más corta</a> de la pantalla o la <a href="{@docRoot}guide/practices/screens_support.html#NewQualifiers">altura y el ancho
mínimos disponibles</a>.
</li>
<li>Como mínimo, personaliza las dimensiones, como los tamaños de las fuentes, los márgenes, el espaciado
para pantallas más grandes, para mejorar el uso del espacio y la legibilidad del contenido.
</li>
<li>Ajusta el posicionamiento de los controles de la IU de modo que los usuarios puedan
acceder fácilmente a ellos mientras sujetan una tablet, como hacia los laterales cuando se encuentre en posición
horizontal.
</li>
<li>El relleno de los elementos de la IU normalmente debería ser más voluminoso en las tablets que en
los teléfonos celulares. Se recomienda un ritmo de<a href="{@docRoot}design/style/metrics-grids.html#48dp-rhythm">
48 dp</a> (y una cuadrícula de 16 dp).
</li>
<li>Rellena correctamente el contenido de texto de modo que no se alinee directamente a lo largo de
los bordes de la pantalla. Usa un relleno <code>16dp</code> mínimo alrededor del contenido cercano a los
bordes de la pantalla.
</li>
</ul>
<p>En especial, asegúrate de que tus diseños no aparezcan "estirados"
a lo ancho de la pantalla:</p>
<ul>
<li>Las líneas de texto no deben ser excesivamente largas; optimízalas para que tengan una cantidad máxima de
100 caracteres por línea, con mejores resultados entre 50 y 75.</li>
<li>Los menús y ListViews no deben usar el ancho completo de la pantalla.</li>
<li>Usa relleno para manejar los anchos de los elementos en pantalla o cambiar a una
IU multipanel para tablets (consulta la siguiente sección).</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/optimize"
data-sortOrder="-timestamp"
data-cardSizes="6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="use-extra-space">3. Aprovecha el área adicional de la pantalla</h2></div>
<div style="width:340px;float:right;margin:1.5em;margin-bottom:0;margin-top:0;">
<img src="{@docRoot}images/training/app-navigation-multiple-sizes-multipane-good.png" style="padding:4px;margin-bottom:0em;">
<p class="img-caption"><span
style="font-weight:500;">Los diseños multipanel</span> proporcionan un mejor equilibrio
visual en pantallas de tablets, y ofrecen una mayor utilidad y legibilidad.</p>
</div>
<p>Las pantallas de las tablets proporcionan un estado mucho más real de pantalla para tu aplicación,
especialmente cuando se sujeta en posición horizontal. Principalmente, las tablets de 10 pulgadas ofrecen un
área enormemente expandida, pero incluso las tablets de 7 pulgadas te proporcionan más espacio
para mostrar contenido e interactuar con los usuarios. </p>
<p>Mientras consideras la IU de tu aplicación para ejecutarse en tablets, asegúrate de que
esté aprovechando completamente el área de pantalla adicional disponible en las tablets. Aquí te proporcionamos
algunas sugerencias:</p>
<ul>
<li>Busca oportunidades de incluir contenido adicional o usar un tratamiento
alternativo del contenido existente.</li>
<li>Usa <a href="{@docRoot}design/patterns/multi-pane-layouts.html">diseños
multipanel</a> en las pantallas de las tablets para combinar vistas individuales en una vista compuesta. Esto
te permite usar el área de pantalla adicional de forma más eficiente y facilitar para
los usuarios la navegación en tu aplicación. </li>
<li>Piensa cómo quieres que se reorganicen los paneles de las vistas compuestas
cuando la pantalla cambie de orientación.</li>
<div style="width:490px;margin:1.5em auto 1.5em 0;">
<div style="">
<img src="{@docRoot}images/ui-ex-single-panes.png" style="width:490px;padding:4px;margin-bottom:0em;" align="middle">
<img src="{@docRoot}images/ui-ex-multi-pane.png" style="width:490px;padding:4px;margin-bottom:0em;">
<p class="image-caption" style="padding:.5em"><span
style="font-weight:500;">Las vistas compuestas</span> combinan varias vistas individuales de la
IU de un teléfono celular <em>(antes mencionado)</em> en una IU enriquecida y más eficaz para tablets
<em>(a continuación)</em>. </p>
</div>
</div>
<li>Si bien una pantalla individual se implementa como una subclase {@link android.app.Activity}
, considera la implementación de paneles de contenido individuales como subclases {@link
android.app.Fragment}. Esto te permite
maximizar la reutilización de códigos entre diferentes factores y pantallas que
compartan contenido.</li>
<li>Decide en qué tamaños de pantalla usarás una IU multipanel y luego proporciona los
diferentes diseños en los depósitos para el tamaño de pantalla correspondiente (como
<code>large</code>/<code>xlarge</code>) o anchos mínimos de pantalla (como
<code>sw600dp</code>/<code>sw720</code>).</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/extrascreen"
data-sortOrder="-timestamp"
data-cardSizes="6x3,6x3,6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="use-tablet-icons">4. Utiliza recursos diseñados para pantallas de tablets</h2></div>
<div><img src="{@docRoot}design/media/devices_displays_density@2x.png"></div>
<p>Para garantizar que tu aplicación se vea lo mejor posible, proporciona iconos y otros recursos
de mapa de bits para cada densidad en el rango que comúnmente admiten las tablets. Específicamente, debes
diseñar tus iconos para la barra de acciones, las notificaciones y el menú de inicio de acuerdo con las pautas de
<a href="{@docRoot}design/style/iconography.html">Iconografía</a>, y proporcionarlos
en múltiples densidades de modo que se visualicen en el tamaño adecuado en todas las pantallas
sin verse borrosos y sin otros defectos de escala.</p>
<p class="table-caption"><strong>Tabla 1</strong>. Tamaños de recursos sin formato para los tipos de icono.<table>
<tr>
<th>Densidad</th>
<th>Lanzador</th>
<th>Barra de acciones</th>
<th>Notificación</th>
<th>pequeña/contextual</th>
</tr>
<tr>
<td><code>mdpi</code></td>
<td>48x48 px</td>
<td>32x32 px</td>
<td>16x16 px</td>
<td>24x24 px</td>
</tr>
<tr>
<td><code>hdpi</code></td>
<td>72x72 px</td>
<td>48x48 px</td>
<td>24x24 px</td>
<td>36x36 px</td>
</tr>
<tr>
<td><code>tvdpi</code></td>
<td><em>(usar hdpi)</em></td>
<td><em>(usar hdpi)</em></td>
<td><em>(usar hdpi)</em></td>
<td><em>(usar hdpi)</em></td>
</tr>
<tr>
<td><code>xhdpi</code></td>
<td>96x96 px</td>
<td>64x64 px</td>
<td>32x32 px</td>
<td>48x48 px</td>
</tr>
<tr>
<td><code>xxhdpi</code></td>
<td>144x144 px</td>
<td>96x96 px</td>
<td>48x48 px</td>
<td>72x72 px</td>
</tr>
</table>
<p>
Como mínimo, proporciona una versión de cada icono y recurso de mapa de bits optimizada
para <strong>al menos</strong> las siguientes densidades comunes de pantalla
de tablets:
</p>
<ul>
<li><code>hdpi</code></li>
<li><code>xhdpi</code></li>
<li><code>xxhdpi</code></li>
</ul>
<p>Otras sugerencias:</p>
<ul>
<li>Cuando diseñes iconos, usa formas vectoriales de modo que puedas escalarlos sin perder nitidez en los detalles ni los bordes.</li>
<li>Usa <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
calificadores de recursos</a> específicos para la densidad a fin de garantizar que se carguen los iconos correctos para cada densidad de pantalla.</li>
<li>Las tablets y otros dispositivos con pantallas grandes a menudo requieren un icono para el menú de inicio que sea un tamaño de densidad
más grande que la densidad real del dispositivo, de modo que debes proporcionar el icono del
menú de inicio en la mayor densidad posible. Por ejemplo, si una tablet tiene una pantalla de {@code xhdpi},
requerirá la versión {@code xxhdpi} del icono del menú de inicio.</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/assets"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="adjust-font-sizes">5.
Ajusta las fuentes y los controles táctiles objetivo</h2></div>
<p>Para asegurarte de que tu aplicación sea fácil de usar en tablets, dedica un tiempo a ajustar los
tamaños de fuente y los controles táctiles en la IU para tablets para todas las configuraciones
de pantalla que admitas. Puedes ajustar los tamaños de fuente mediante <a href="{@docRoot}guide/topics/ui/themes.html">atributos modificables</a> o <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">recursos
de dimensión</a>, y puedes ajustar los controles táctiles mediante diseños y recursos de mapa de bits
dibujables, como se mencionó más arriba. </p>
<p>Aquí te proporcionamos algunas consideraciones:</p>
<ul>
<li>El texto no debe ser excesivamente grande ni pequeño en los tamaños y densidades de pantalla de las
tablets. Asegúrate de que las etiquetas estén dimensionadas correctamente para los elementos de la IU con los que se
corresponden, y comprueba que no haya saltos de línea
inadecuados en las etiquetas, los títulos y otros elementos.</li>
<li>El tamaño recomendado para los controles táctiles en pantalla es de 48dp (32dp
como mínimo); puede ser necesario que realices algunos ajustes en tu IU para tablets. Lee <a href="{@docRoot}design/style/metrics-grids.html">Métricas y
cuadrículas
</a> para obtener más información acerca de la implementación de estrategias para ayudar a la mayoría de los usuarios. Para
satisfacer las necesidades de accesibilidad de ciertos usuarios, puede ser conveniente que uses
controles táctiles más grandes. </li>
<li>Cuando sea posible, para los iconos más pequeños, expande el área táctil a más de
48dp con {@link android.view.TouchDelegate}
o simplemente centrando el icono dentro del botón transparente.</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/fonts"
data-sortOrder="-timestamp"
data-cardSizes="9x3,9x3,6x3,6x3,6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="adjust-widgets">6. Ajusta el tamaño de los widgets de la pantalla de inicio</h2></div>
<p>Si tu aplicación incluye un widget en la pantalla de inicio, aquí te mostramos algunos puntos que debes considerar
para garantizar una excelente experiencia de usuario en las pantallas de tablets: </p>
<ul>
<li>Configura la altura y el ancho predeterminados del widget de forma correcta
para las pantallas de tablets, como también la altura y el ancho mínimos y máximos.
</li>
<li>El tamaño del widget se debe poder modificar hasta los 420 dp o más para abarcar 5 o más
filas (si se trata de un widget vertical o cuadrado) o columnas (si se trata de un
widget horizontal o cuadrado) de la pantalla de inicio. </li>
<li>Asegúrate de que las imágenes de 9-patch se visualicen correctamente.</li>
<li>Usa los márgenes predeterminados del sistema.</li>
<li>Configura el <code>targetSdkVersion</code> de la aplicación en 14 o más, si es
posible.</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/widgets"
data-sortOrder="-timestamp"
data-cardSizes="6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="offer-full-feature-set">7. Conjunto completo de funciones para usuarios de tablets</h2></div>
<div class="centered-full-image" style="width:600px;margin:1.5em"><img src="{@docRoot}images/gp-tablets-full-feature-set.png" alt="Tablet feature sets"></div>
<p>Permite que tus usuarios accedan a las mejores funciones de tu aplicación. Aquí te proporcionamos
algunas recomendaciones:</p>
<ul>
<li>Diseña tu aplicación para que ofrezca al menos el mismo conjunto de funciones en tablets y
en teléfonos.
</li>
<li>En casos excepcionales, tu aplicación podría omitir o reemplazar ciertas funciones en
las tablets si no son compatibles con el hardware o el caso de uso de la mayoría de las
tablets. Por ejemplo:
<ul>
<li>Si el teléfono celular utiliza funciones de telefonía pero el servicio de telefonía no está disponible
en la tablet actual, puedes omitir o reemplazar la funcionalidad relacionada.
</li>
<li>Muchas tablets tienen un sensor GPS, pero la mayoría de los usuarios generalmente
no llevarían sus tablets con ellos mientras corren. Si tu aplicación para teléfonos proporciona
una funcionalidad que permite a los usuarios grabar un registro de GPS de sus carreras
mientras llevan sus teléfonos con ellos, no será necesario que la aplicación proporcione esa
funcionalidad en las tablets ya que el caso de uso no lo requiere.
</li>
</ul>
</li>
<li>Si piensas omitir una función o capacidad de tu IU para tablets, asegúrate
de que los usuarios no puedan acceder o que ofrezca “degradación estable”
a una función de reemplazo (consulta también la sección a continuación acerca de las funciones de hardware).
</li>
</ul>
<div class="headerLine"><h2 id="android-versions">8. Aborda correctamente las versiones de Android</h2></div>
<p>
Para garantizar la distribución más amplia posible para tablets, asegúrate de que tu
aplicación aborde correctamente las versiones de Android compatibles con tablets. La compatibilidad
inicial con tablets se agregó en <a href="{@docRoot}about/versions/android-3.0.html">Android 3.0</a> (Nivel de API 11).
La compatibilidad unificada en el marco de la IU para tablets, teléfonos y otros dispositivos se
introdujo en <a href="{@docRoot}about/versions/android-4.0.html">Android
4.0</a>
</p>
<p>
Puedes configurar el rango de versiones de Android admitidas por tu aplicación en el archivo de
manifiesto en el elemento <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
. En la mayoría de los casos, puedes abordar versiones de Android correctamente al configurar
el atributo <code>targetSdkVersion</code> del elemento en el nivel de API más
alto posible.
</p>
<p style="margin-bottom:.5em;">
Como mínimo, comprueba el elemento <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
para asegurarte de lo siguiente:
</p>
<ol style="list-style-type:lower-alpha;margin-top:0em;">
<li>
<code>targetSdkVersion</code> está declarado con un valor de 11 o superior (se recomienda 14 o
superior), O
</li>
<li>
<code>minSdkVersion</code> está declarado con un valor de 11 o superior.
</li>
<li>Si se declara un atributo <code>maxSdkVersion</code>, debe tener un
valor de 11 o superior. Ten en cuenta que, en general,
<em>no se recomienda</em> el uso de <code>maxSdkVersion</code>.
</li>
</ol>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/versions"
data-sortOrder="-timestamp"
data-cardSizes="6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="hardware-requirements">9. Declara correctamente dependencias de características de hardware</h2></div>
<p>
Los teléfonos celulares y las tablets generalmente ofrecen compatibilidad de hardware para
sensores, cámara, telefonía y otras funciones algo diferente. Por ejemplo, muchas tablets
se encuentran disponibles en una configuración "Wi-Fi" que no incluye compatibilidad con telefonía.
</p>
<p>
A fin de que puedas distribuir un APK único de forma extensiva a toda tu base de
clientes de teléfonos y tablets, asegúrate de que tu aplicación no declare
requisitos para características de hardware que no se ofrezcan comúnmente en las tablets.
En su lugar, declara la características de hardware como <em>no obligatorias</em> en el manifiesto de la
aplicación, como se describe a continuación.
</p>
<ul>
<li>En el manifiesto de tu aplicación, busca elementos <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
. Específicamente, busca características de hardware que podrían no estar
disponibles en algunas tablets, como por ejemplo:
<ul>
<li><code>android.hardware.telephony</code></li>
<li><code>android.hardware.camera</code> (hace referencia a la cámara posterior), o</li>
<li><code>android.hardware.camera.front</code></li>
</ul></li>
<li>Declara los elementos <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
como <em>no obligatorios</em> al incluir el atributo <code>android:required=”false”</code>
.
<p>
Por ejemplo, aquí te mostramos la manera correcta de declarar una dependencia en
<code>android.hardware.telephony</code> de modo que aún puedas
distribuir tu aplicación de forma extensiva, incluso a dispositivos que no ofrezcan telefonía:
</p>
<pre>&lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;</pre></li>
<li>En forma similar, revisa el manifiesto para detectar elementos <a href="{@docRoot}guide/topics/manifest/permission-element.html"><code>&lt;permission&gt;</code></a> que
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions">impliquen requisitos
de características de hardware</a> que no sean adecuadas para tablets. Si encuentras esos
permisos, asegúrate de declarar explícitamente un elemento
<code>&lt;uses-feature&gt;</code> correspondiente para las características e incluye el
atributo <code>android:required=”false”</code>.</li>
</ul>
<p>
Después de declarar las características de hardware como <em>no obligatorias</em>, prueba
tu aplicación en diferentes dispositivos. La aplicación debe funcionar normalmente cuando las
características de hardware que utiliza no estén disponibles, y debe ofrecer "degradación
estable" y funcionalidades alternativas cuando corresponda.
</p>
<p>
Por ejemplo, si una aplicación utiliza normalmente GPS para establecer la ubicación, pero el
dispositivo no admite GPS, la aplicación podría permitirle al usuario establecer la ubicación manualmente
. La aplicación puede comprobar la presencia de capacidades de hardware en el dispositivo durante el runtime y manipularlas
según resulte necesario.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/hardware"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="support-screens">10. Declara la compatibilidad con pantallas de tablets</h2></div>
<p>Para garantizar que puedes distribuir tu aplicación a una amplia gama de tablets, la aplicación debe
declarar la compatibilidad con diferentes tamaños de pantalla de tablets en su archivo de manifiesto de la siguiente manera:</p>
<ul>
<li>Un
elemento <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><code>&lt;supports-screens&gt;</code></a>
, si se declara, no debe especificar <code>android:largeScreens="false"</code>
ni <code>android:xlargeScreens="false"</code>.</li>
<li>Para las aplicaciones que apuntan a un valor de <code>minSdkVersion</code> inferior a 13, se debe declarar un elemento
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><code>&lt;supports-screens&gt;</code></a>
con <code>android:largeScreens="true"</code> y
<code>android:xlargeScreens="true"</code>.</li>
</ul>
<p>Si la aplicación declara un elemento
<a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html"><code>&lt;compatible-screens&gt;</code></a>
en el manifiesto, el elemento debe incluir atributos que especifiquen
<em>todas las combinaciones de tamaño y densidad para pantallas de tablets</em> que admita
la aplicación. Recuerda que, si fuera posible, debes evitar el uso del
elemento <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html"><code>&lt;compatible-screens&gt;</code></a>
en tu aplicación.</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/tabletscreens"
data-sortOrder="-timestamp"
data-cardSizes="9x3,6x3,6x3"
data-maxResults="6"></div>
<div class="headerLine"><h2 id="google-play">11. Presenta tu IU para tablets en Google Play</h2></div>
<p>
Cuando termines de crear una IU enriquecida y optimizada para tu aplicación
para tablets, asegúrate de que tus clientes lo sepan. Aquí te ofrecemos algunas
estrategias clave para promocionar tu aplicación para tablets a los usuarios en Google Play.
</p>
<div><img class="border-img" src="{@docRoot}images/gp-tablet-quality-4.jpg"></div>
<h4>
Carga capturas de pantalla de tu IU para tablets
</h4>
<p>
Los usuarios de tablets quieren saber cómo se ve tu aplicación en una tablet, no en un
teléfono. Si desarrollaste una aplicación para tablets, asegúrate de cargar capturas de pantalla
de tu IU para tablets a la Consola para desarrolladores de Google Play. Aquí te proporcionamos algunas pautas:
</p>
<ul style="margin-top:0;">
<li>Exhibe la funcionalidad central de tu aplicación, no
una página de inicio ni de inicio de sesión. Dondequiera que los usuarios pasen la mayor parte del tiempo, eso
es lo que debes mostrar en tus capturas de pantalla.
</li>
<li>Agrega capturas de pantalla tomadas en tablets de 7 y 10 pulgadas.
</li>
<li>Agrega capturas de pantalla tomadas en orientación vertical
y horizontal, si fuera posible.
</li>
<li>Usa imágenes de la pantalla si fuera posible. Evita mostrar el hardware del dispositivo en tus
capturas de pantalla.</li>
<li>La resolución recomendada para las capturas de pantalla de tu tablet es <strong>1280 x 720</strong>
o superior en cada orientación.
</li>
<li>Carga hasta 8 capturas de pantalla de tu IU para tablets para tablets de 7 pulgadas
y 8 capturas de pantalla para tablets de 10 pulgadas.
</li>
</ul>
<h4>
Actualiza la descripción y las notas de distribución de tu aplicación
</h4>
<ul>
<li>En la descripción de tu aplicación, asegúrate de resaltar que la aplicación ofrece
una IU optimizada para tablets y excelentes funciones para los usuarios de tablets. Agrega algunos
detalles acerca de cómo funciona tu IU para tablets y por qué les gustará a los usuarios.
</li>
<li>Incluye información acerca de la compatibilidad para tablets en las notas de distribución de la tablet y
actualiza la información.
</li>
</ul>
<h4>
Actualiza tu video promocional
</h4>
<p>
Muchos usuarios miran el video promocional de una aplicación para tener una idea de cómo se ve la
aplicación y si la disfrutarán. En el caso de los usuarios de tablets, aprovecha este
interés al resaltar la IU para tablets de tu aplicación en tu video promocional. Aquí
te proporcionamos algunas sugerencias y pautas:
</p>
<ul>
<li>Agrega una o más capturas de tu aplicación ejecutándose en una tablet. Para atraer a los
usuarios de tablets de forma más eficaz, se recomienda que promociones tu IU para
tablets en una proporción aproximadamente similar a la de tu IU para teléfonos.
</li>
<li>Muestra tu IU para tablets al comienzo del video, si fuera posible. No des por sentado que
los usuarios de tablets esperarán pacientemente que finalice el recorrido por las funciones de una IU para teléfonos.
Lo ideal es que captes su interés de inmediato al mostrarles la IU de para tablets durante
los primeros 10 segundos, o en el mismo momento que presentas la IU para teléfonos.
</li>
<li>Para dejar en claro que estás mostrando una IU para tablets, incluye imágenes de tu
aplicación ejecutándose en una tablet.
</li>
<li>Resalta la IU para tablets de tu aplicación en el relato o la narración grabada del video.
</li>
</ul>
<h4>
Presenta la IU para tablets en tus campañas promocionales
</h4>
<p>
Asegúrate de dar a conocer tu IU para tablets a los usuarios de tablets a través de tus
campañas promocionales, sitio web, publicaciones en redes sociales, anuncios publicitarios y en otros sitios. Aquí te proporcionamos
algunas sugerencias:
</p>
<ul>
<li>Planifica una campaña publicitaria o de comercialización que resalte el uso de tu
aplicación en tablets.</li>
<li>Muestra los mejores aspectos de tu aplicación para tablets en tus campañas promocionales; utiliza el <a href="{@docRoot}distribute/tools/promote/device-art.html">Generador de material gráfico para dispositivos</a> para
crear rápidamente una imagen promocional de alta calidad de tu aplicación ejecutándose
en una tablet de 7 o 10 pulgadas, en la orientación que prefieras, con o sin
sombra paralela y brillo de pantalla. Es tan sencillo como realizar una captura, arrastrar y soltar.
</li>
<li>Incluye una insignia de Google Play en tus promociones por Internet para que los usuarios
puedan acceder directamente al directorio de tienda de tu aplicación. Puedes generar una insignia en
diferentes idiomas con el <a href="{@docRoot}distribute/tools/promote/badges.html">Generador de insignias</a>.
</li>
</ul>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/showcase"
data-sortOrder="-timestamp"
data-cardSizes="9x3,9x3,9x3,9x3"
data-maxResults="6"></div>
<div class="headerLine">
<h2 id="google-play-best-practices">
12. Sigue las mejores prácticas para publicar en Google Play
</h2>
</div>
<p>
Aquí te mostramos algunas mejores prácticas para distribuir una aplicación para tablets exitosa en Google
Play.
</p>
<div>
<img class="border-img" src="{@docRoot}images/gp-tablet-quality-5.jpg" style="1px solid #ddd">
</div>
<h4 id="google-play-optimization-tips">
Repasa las sugerencias de optimización para tu aplicación
</h4>
<p>La Consola para desarrolladores de Google Play ahora ofrece una página de Sugerencias para la optimización
que te permite comprobar rápidamente cómo le está yendo a tu aplicación en función de pautas básicas para la calidad
y distribución de aplicaciones para tablets. Para visitar la página, inicia sesión en la Consola para desarrolladores,
carga la aplicación desde Todas las aplicaciones y haz clic en Sugerencias para la optimización en el
panel de navegación de la izquierda.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Cómo enviar comentarios</h2>
<p>Utiliza en vínculo que se proporciona a continuación para enviar
comentarios o solicitar una revisión manual de tus Sugerencias para la optimización.</p>
<p>Antes de enviar comentarios, asegúrate de leer las secciones relevantes de las
pautas de calidad de las aplicaciones para tablets.</p>
<p><strong><a href="https://support.google.com/googleplay/android-developer/contact/tabletq" target="_googleplay" style="white-space:nowrap">Formulario de contacto de Diseñado para tablets &raquo;</a></strong></p>
</div>
</div>
<p>La Consola para desarrolladores crea la página de Sugerencias para la optimización de tu aplicación
al ejecutar una serie de comprobaciones para verificar los criterios básicos
de calidad. Si detecta problemas, te los notificará como elementos "Pendientes"
en la página de Sugerencias para la optimización.</p>
<p>Si desarrollaste una experiencia de tablet para tu aplicación, asegúrate de
visitar la página de Sugerencias para la optimización para ver cómo le está yendo a la aplicación
en relación con las comprobaciones básicas. Si se indican errores, te
recomendamos que los abordes en tu aplicación y, si fuera necesario, cargues un nuevo archivo binario para
distribución. </p>
<p>Si la página de Sugerencias para la optimización indica problemas "Pendientes" que crees que no
corresponden a tu aplicación o afectan la calidad de la aplicación en las tablets,
usa el <a href="https://support.google.com/googleplay/android-developer/contact/tabletq" target="_googleplay" style="white-space:nowrap">Formulario de contacto de Diseñado para tablets&raquo;</a> para comunicárnoslo. Revisaremos
tu aplicación y actualizaremos tu página de Sugerencias para la optimización
según corresponda.</p>
<h4>Confirma el filtrado de la aplicación</h4>
<p>
Después de cargar la aplicación a la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores</a>, examina la
lista de dispositivos admitidos por el APK para asegurarte de que la aplicación no se haya excluido de la filtración
de tablets a las que quieres apuntar.
</p>
<h4>Distribuye un solo APK</h4>
<p>
Se recomienda que publiques tu aplicación como un solo APK para todos los
tamaños de pantalla (teléfonos y tablets), con un solo directorio en Google Play. Este enfoque
ofrece muchas ventajas importantes.
</p>
<ul style="margin-top:.25em;">
<li>Es más fácil para los usuarios encontrar tu aplicación en búsquedas, exploraciones o promociones.
</li>
<li>Es más fácil para los usuarios restaurar tu aplicación automáticamente si adquieren un
dispositivo nuevo.
</li>
<li>Tus estadísticas de descarga y calificaciones se consolidan a través de todos los dispositivos.
</li>
<li>Si publicas una aplicación para tablets en un segundo directorio, esto puede reducir las calificaciones para
tu marca.
</li>
</ul>
<p>
Si fuera necesario, puedes seleccionar, como alternativa, distribuir tu aplicación con <a href="{@docRoot}google/play/publishing/multiple-apks.html">Compatibilidad con múltiples APK</a>,
aunque en la mayoría de los casos se recomienda firmemente usar un solo APK
que abarque todos los dispositivos.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/googleplay"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>
<div class="headerLine">
<h2 id="test-environment">
Configuración de un entorno de prueba para tablets
</h2>
</div>
<p>
Evalúa la calidad de tu aplicación en tablets; tanto la calidad de la aplicación principal
como la calidad de la aplicación para tablets, con un hardware adecuado o un entorno de simulación
para la realización de pruebas.
</p>
<p>
En comparación con el <a href="{@docRoot}distribute/essentials/quality/core.html#test-environment">entorno de prueba
recomendado</a> para probar la aplicación en función de los criterios de calidad para la aplicación principal,
incluye tablets de tamaño mediano y tablets con más o menos características de
hardware/software.
</p>
<p class="table-caption"><strong>Tabla 1</strong>. Un entorno de prueba típico para tablets
debería incluir uno o más dispositivos de cada fila de la tabla que aparece a continuación, con una de las
versiones de plataforma, configuraciones de pantalla y configuraciones de características de hardware indicadas.</p>
<table>
<tr>
<th>Tipo</th>
<th>Tamaño</th>
<th>Densidad</th>
<th>Versión</th>
<th>Máscara del AVD</th>
</tr>
<tr>
<td>Tablet de 7 pulgadas</td>
<td><span style="white-space:nowrap"><code>large</code> o</span><br /><code>-sw600</code></td>
<td><code>hdpi</code>,<br /><code>tvdpi</code></td>
<td>Android 4.0+ (nivel de API 14 o superior)</td>
<td>WXGA800-7in</td>
</tr>
<tr>
<td><span style="white-space:nowrap">Tablet de</span> 10 pulgadas</td>
<td><span style="white-space:nowrap"><code>xlarge</code> o</span><br /><code>-sw800</code></td>
<td><code>mdpi</code>,<br /><code>hdpi</code>,<br /><code>xhdpi</code></td>
<td>Android 3.2+ (nivel de API 13 o superior)</td>
<td>WXGA800</td>
</tr>
</table>
<div class="headerLine"><h2 id="related-resources">Recursos relacionados</h2></div>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>

View File

@@ -1,509 +0,0 @@
page.title=Calidad de las aplicaciones para TV
page.metaDescription=La televisión es un segmento en aumento de dispositivos Android que requiere atención específica en el diseño y la funcionalidad de las aplicaciones a fin de crear una excelente experiencia.
page.image=/distribute/images/gp-tv-quality.png
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Criterios de calidad</h2>
<ol>
<li><a href="#ux">Diseño e interacción</a></li>
<li><a href="#fn">Funcionalidad</a></li>
<li><a href="#faq">Preguntas frecuentes</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/core.html">
Calidad de la aplicación principal</a></li>
<li><a href="{@docRoot}distribute/essentials/optimizing-your-app.html">
Optimiza tu aplicación</a></li>
</ol>
</div>
</div>
<div class="top-right-float" style="padding-right:0;margin-bottom:1em;">
<img src="{@docRoot}distribute/images/gp-tv-quality.png" style="width:480px;">
</div>
<p>
Los usuarios tienen diferentes expectativas cuando miran televisión, en comparación con el uso de un teléfono o una tablet.
Un usuario de TV típico se sienta a aproximadamente 3 metros de distancia de la pantalla, por lo que los detalles pequeños son menos perceptibles
y el texto pequeño resulta difícil de leer. Dado que los usuarios se sientan lejos del televisor, deben usar un dispositivo de mando
a distancia para navegar y seleccionar, en lugar de tocar los elementos que aparecen en pantalla. Esas
diferencias cambian significativamente los requisitos de lo que sería una buena experiencia del usuario de TV.
</p>
<p>
El primer paso para crear una excelente experiencia para usuarios de TV es leer y seguir las
<a href="{@docRoot}design/tv/index.html">pautas de diseño para Android TV</a>, que proporcionan
instrucciones acerca de cómo crear aplicaciones para TV que proporcionen la mejor experiencia del usuario. También debes leer la capacitación
<a href="{@docRoot}training/tv/start/index.html">Cómo crear aplicaciones para TV</a> a fin de comprender
los requisitos de implementación básicos de una aplicación para TV.
</p>
<p class="caution">
<strong>Importante:</strong> Para garantizar una excelente experiencia del usuario, las aplicaciones para dispositivos de TV deben cumplir algunos
requisitos de utilidad específicos. Solo las aplicaciones que cumplan con los siguientes criterios de calidad
calificarán como una aplicación de Android TV en Google Play.
</p>
<p class="note"><strong>Nota:</strong> Para obtener información acerca de cómo publicar tus aplicaciones para TV en Google Play,
consulta <a href="{@docRoot}distribute/googleplay/tv.html">Distribución para Android TV</a>.</p>
<div class="headerLine">
<h2 id="ux">
Diseño visual e interacción del usuario
</h2>
</div>
<p>
Estos criterios permiten que te asegures de que tu aplicación cumpla con los patrones clave de diseño e interacción
a fin de garantizar una experiencia del usuario uniforme, intuitiva y agradable en dispositivos de TV.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
Prueba
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="4" id="launcher">
Lanzador
</td>
<td id="TV-LM">
TV-LM
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación exhibe un icono del Lanzador de Android TV después de la instalación.
(<a href="{@docRoot}training/tv/start/start.html#tv-activity">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-LB">
TV-LB
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación exhibe un banner de 320 px x 180 px como su icono de Lanzador de Android TV.
(<a href="{@docRoot}design/tv/patterns.html#banner">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-BN">
TV-BN
</td>
<td>
<p style="margin-bottom:.5em;">
El banner de inicio de la aplicación contiene el nombre de la aplicación.
(<a href="{@docRoot}design/tv/patterns.html#banner">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-LG">
TV-LG
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación es un juego, aparece en la fila Juegos del Lanzador de Android TV.<br>
(<a href="{@docRoot}training/tv/games/index.html#manifest">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="5" id="layout">
Diseño
</td>
<td id="TV-LO">
TV-LO
</td>
<td>
<p style="margin-bottom:.5em;">
Las interfaces de la aplicación se presentan en orientación horizontal.
(<a href="{@docRoot}training/tv/start/layouts.html#structure">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-TC">
TV-TC
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación exhibe el texto central en un tamaño de 16 sp o más grande.
(<a href="{@docRoot}design/tv/style.html#typography">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-TA">
TV-TA
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación exhibe todo el texto en un tamaño de 12 sp o más grande.
(<a href="{@docRoot}design/tv/style.html#typography">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-OV">
TV-OV
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no exhibe texto ni funcionalidades que estén parcialmente
cortados por los bordes de la pantalla.
(<a href="{@docRoot}training/tv/start/layouts.html#overscan">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-TR">
TV-TR
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no opaca parcialmente otras aplicaciones. La aplicación ocupa toda la pantalla y tiene
un fondo que no es transparente.
</p>
</td>
</tr>
<tr>
<td rowspan="3" id="navigation">
Navegación
</td>
<td id="TV-DP">
TV-DP
</td>
<td>
<p style="margin-bottom:.5em;">
La funcionalidad de la aplicación se puede navegar con los controles del mando de 5 direcciones, a menos que la aplicación
requiera un controlador para juegos como se especifica en <a href="#TV-GP">TV-GP</a>.
(<a href="{@docRoot}training/tv/start/navigation.html#d-pad-navigation">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-DK">
TV-DK
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación requiere un controlador para juegos, como se especifica en <a href="#TV-GP">TV-GP</a>; se puede
navegar por toda la funcionalidad con las teclas de un controlador para juegos de Android estándar.
(<a href="{@docRoot}training/game-controllers/controller-input.html#button">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-DM">
TV-DM
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación no requiere que el mando a distancia tenga un botón de Menú para acceder a los controles de la
interfaz de usuario.
(<a href="{@docRoot}training/tv/start/navigation.html#d-pad-navigation">Obtén más información</a>)
</p>
</td>
</tr>
</table>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/tvqualityguidelines/visualdesign"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="fn">
Funcionalidad
</h2>
</div>
<p>
Estos criterios garantizan que tu aplicación esté correctamente configurada y proporcione el comportamiento
funcional previsto.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
Prueba
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="2" id="manifest">
Manifiesto
</td>
<td id="TV-ML">
TV-ML
</td>
<td>
<p style="margin-bottom:.5em;">
El manifiesto de la aplicación establece un tipo previsto de {@link android.content.Intent#ACTION_MAIN} con la categoría
{@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER}.
(<a href="{@docRoot}training/tv/start/start.html#tv-activity">Obtén más información</a>)
</p>
</td>
</tr>
</tr>
<td id="TV-MT">
TV-MT
</td>
<td>
<p style="margin-bottom:.5em;">
El manifiesto de la aplicación establece la característica de hardware {@code android.hardware.touchscreen} como no obligatoria.
(<a href="{@docRoot}training/tv/start/hardware.html#declare-hardware-requirements">Obtén
más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="2" id="game-controllers">
Controladores para juegos
</td>
<td id="TV-GP">
TV-GP
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación utiliza un controlador para juegos como su método de entrada principal, debe declarar el requisito
correspondiente con la etiqueta del manifiesto <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a>.
(<a href="{@docRoot}training/tv/games/index.html#gamepad">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-GC">
TV-GC
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación proporciona instrucciones visuales para el uso de controladores para juegos, las instrucciones
no deben contener recursos de marca y deben exhibir un diseño de botones compatible.
(<a href="{@docRoot}training/tv/games/index.html#ControllerHelp">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="4" id="advertising">
Publicidad
</td>
<td id="TV-AP">
TV-AP
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación permite la interacción con anuncios publicitarios mediante el uso de los controles del mando de dirección.
(<a href="{@docRoot}training/tv/start/navigation.html#d-pad-navigation">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-AD">
TV-AD
</td>
<td>
<p style="margin-bottom:.5em;">
Para la publicidad que utilice anuncios en pantalla completa que no sean en video, la aplicación le
permite al usuario omitir de inmediato el anuncio con los controles del mando de dirección.
</p>
</td>
</tr>
<tr>
<td id="TV-AU">
TV-AU
</td>
<td>
<p style="margin-bottom:.5em;">
Para la publicidad que utilice anuncios que admitan clics, no ocupen la pantalla completa y no sean en video, la aplicación no permite que los
anuncios vinculen a una URL.
</p>
</td>
</tr>
<tr>
<td id="TV-AA">
TV-AA
</td>
<td>
<p style="margin-bottom:.5em;">
Para la publicidad que utilice anuncios que admitan clics, no ocupen la pantalla completa y no sean en video, la aplicación no permite que los
anuncios vinculen a otra aplicación que no está disponible para dispositivos de TV.
</p>
</td>
</tr>
<tr>
<td rowspan="1" id="web">
Contenido web
</td>
<td id="TV-WB">
TV-WB
</td>
<td>
<p style="margin-bottom:.5em;">
Para el contenido web, la aplicación utiliza componentes {@link android.webkit.WebView} y no intenta
ejecutar una aplicación de explorador web.
</p>
</td>
</tr>
<tr>
<td rowspan="3" id="media-playback">
Reproducción multimedia
</td>
<td id="TV-NP">
TV-NP
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación continúa reproduciendo sonido después de que el usuario sale de ella, la aplicación proporciona una tarjeta <em>Reproduciendo
ahora</em> en la fila de recomendación de la pantalla de inicio de modo que los usuarios puedan regresar a la aplicación
para controlar la reproducción.
(<a href="{@docRoot}training/tv/playback/now-playing.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-PA">
TV-PA
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación proporciona una tarjeta <em>Reproduciendo ahora</em>, cuando el usuario la seleccione pasará a una
pantalla que permite pausar la reproducción.
(<a href="{@docRoot}training/tv/playback/now-playing.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="TV-PP">
TV-PP
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación reproduce contenido de video o música, alternará entre reproducción y pausado del contenido
multimedia cuando se envíe un evento clave de reproducción o pausado durante la reproducción.<br>
(<a href="{@docRoot}reference/android/view/KeyEvent.html#KEYCODE_MEDIA_PLAY_PAUSE">Obtén
más información</a>)
</p>
</td>
</tr>
</table>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/tvqualityguidelines/functionality"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="faq">
Preguntas frecuentes
</h2>
</div>
<p style="margin-top:30px;">
<strong>Después de enviar mi aplicación, ¿cómo sabré si mi aplicación no cumple todos los requisitos para
dispositivos de TV?</strong>
</p>
<p>
Si tu aplicación no cumple los requisitos de utilidad que se describen en esta página, el equipo de la Play Store
se comunicará contigo a la dirección de correo electrónico que especificaste en la cuenta principal de la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores de Google Play</a> asociada con
la aplicación.
</p>
<p class="caution">
<strong>Advertencia:</strong> Asegúrate de que tu aplicación incluya las <a href="{@docRoot}preview/tv/start/index.html#tv-activity">entradas obligatorias del manifiesto</a> para dispositivos de TV;
de lo contrario, la aplicación no se considerará una aplicación para TV y no se revisará conforme a los requisitos de utilidad para
TV.
</p>
<p style="margin-top:30px;">
<strong>Mi aplicación abarca más que dispositivos de TV. Si mi aplicación no cumple con los
requisitos para dispositivos de TV, ¿aparecerá todavía mi aplicación nueva o actualizada en Google Play para teléfonos y
tablets?</strong>
</p>
<p>
Sí. Los requisitos que se describen más arriba solo restringen la distribución en la Play Store de Google para dispositivos
de TV. La distribución a otros tipos de dispositivos, como teléfonos, tablets, etc., no se verá
afectada.
</p>
<p style="margin-top:30px;">
<strong>Si mi aplicación cumple los requisitos de publicación, ¿cuándo estará disponible en la Play Store
de Google para dispositivos de TV?</strong>
</p>
<p>
Las aplicaciones que cumplen los requisitos para TV aparecerán en la Play Store de Google para dispositivos de TV
<em>después</em> del lanzamiento oficial de Android 5.0.
</p>

View File

@@ -1,452 +0,0 @@
page.title=Calidad de las aplicaciones para Wear
page.tags="wear","wearables","quality","guidelines"
page.metaDescription=Los dispositivos portátiles (wearables) son dispositivos más pequeños diseñados para permitir la captura de información de un vistazo y requieren aplicaciones exclusivas que proporcionen la información correcta en el momento adecuado.
page.image=/distribute/images/gp-wear-quality.png
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Criterios de calidad</h2>
<ol>
<li><a href="#ux">Diseño e interacción</a></li>
<li><a href="#fn">Funcionalidad</a></li>
<li><a href="#faq">Preguntas frecuentes</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/core.html">
Calidad de la aplicación principal</a></li>
<li><a href="{@docRoot}distribute/essentials/optimizing-your-app.html">
Optimiza tu aplicación</a></li>
<li><a href="{@docRoot}design/patterns/notifications.html">
Notificaciones</a></li>
</ol>
</div>
</div>
<img src="{@docRoot}distribute/images/gp-wear-quality.png" style="width:480px;">
<p>
Android Wear tiene como objetivo proporcionar a los usuarios la información correcta en el momento adecuado. Las increíbles
experiencias de Android Wear se inician automáticamente, permiten captar información de un vistazo y prácticamente no requieren la interacción del
usuario. Diseñar aplicaciones para wearables es muy diferente a diseñar para teléfonos o
tablets. Hay fortalezas y debilidades diferentes, casos de uso diferentes y ergonomías
diferentes que se deben tener en cuenta.
</p>
<p>
El primer paso para crear una excelente experiencia para usuarios de Wear es leer las
<a href="{@docRoot}design/wear/index.html">pautas de diseño para Android Wear</a>, que proporcionan
instrucciones acerca de cómo crear aplicaciones para Wear que proporcionen la mejor experiencia de usuario. También debes leer la capacitación
<a href="{@docRoot}training/building-wearables.html">Cómo crear aplicaciones para dispositivos portátiles (wearables)</a> a fin de
comprender los requisitos de implementación básicos de una aplicación para Wear.
</p>
<p class="caution">
<strong>Importante:</strong> Para garantizar una excelente experiencia de usuario, las aplicaciones para wearables deben cumplir algunos
requisitos de utilidad específicos. Solo las aplicaciones que cumplan con los siguientes criterios de calidad
calificarán como una aplicación de Android Wear en Google Play. Si califica como aplicación de Wear, los usuarios de
Android Wear podrán descubrir de forma más fácil tu aplicación en Google Play.
</p>
<p class="note">
<strong>Nota:</strong> Para obtener información acerca de cómo publicar tus aplicaciones para Wear en Google Play, consulta <a href="{@docRoot}distribute/googleplay/wear.html">Distribución para Android Wear</a>.
</p>
<div class="headerLine">
<h2 id="fn">
Funcionalidad
</h2>
</div>
<p>
Estos criterios garantizan que tu aplicación esté correctamente configurada y proporcione el comportamiento
funcional previsto.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
ID
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="3" id="general">
General
</td>
<td id="WR-GL">
WR-GL
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación para dispositivos portátiles incluye notificaciones con funcionalidad específica para wearables o una aplicación
para wearables que se ejecuta directamente en el dispositivo Wear.
(<a href="{@docRoot}training/building-wearables.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-VF">
WR-VF
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación posee funcionalidad Wear visible para el usuario.
</p>
</td>
</tr>
<tr>
<td id="WR-BF">
WR-BF
</td>
<td>
<p style="margin-bottom:.5em;">
La funcionalidad Wear funciona según lo previsto o descrito en el directorio de la tienda en la Play Store de Google.
</p>
</td>
</tr>
<tr>
<td rowspan="1" id="packaging">
Integración
</td>
<td id="WR-PK">
WR-PK
</td>
<td>
<p style="margin-bottom:.5em;">
Las aplicaciones para wearables que dependen de una aplicación para dispositivos portátiles para adquirir su plena funcionalidad están integradas dentro de esa
aplicación para wearables.
(<a href="{@docRoot}training/wearables/apps/packaging.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="3" id="functional-notifications">
Notificaciones
</td>
<td id="WR-FW">
WR-FW
</td>
<td>
<p style="margin-bottom:.5em;">
Las notificaciones con funcionalidad específica para wearables usan un {@code RemoteInput} o
{@code WearableExtender}.
(<a href="{@docRoot}training/wearables/notifications/index.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-FR">
WR-FR
</td>
<td>
<p style="margin-bottom:.5em;">
Las notificaciones para aplicaciones de mensajería permiten a los usuarios responder mediante entradas de voz o respuestas rápidas.
(<a href="{@docRoot}training/wearables/notifications/voice-input.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-FG">
WR-FG
</td>
<td>
<p style="margin-bottom:.5em;">
Las notificaciones similares se agrupan en una pila.
(<a href="{@docRoot}training/wearables/notifications/stacks.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="2" id="gestures">
Gestos
</td>
<td id="WR-GP">
WR-GP
</td>
<td>
<p style="margin-bottom:.5em;">
Las actividades en pantalla completa usan el gesto de presión prolongada únicamente para salir.
<br/>
(<a href="{@docRoot}training/wearables/ui/exit.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-GD">
WR-GD
</td>
<td>
<p style="margin-bottom:.5em;">
Si la aplicación deshabilita el gesto “deslizar para descartar” en una actividad en pantalla completa, responderá al
gesto “presionar de forma prolongada para descartar” en esa actividad.
(<a href="{@docRoot}training/wearables/ui/exit.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="1" id="watchface">
Cara de reloj
</td>
<td id="WR-WF">
WR-WF
</td>
<td>
<p style="margin-bottom:.5em;">
Las aplicaciones que incluyen caras de reloj usan la API oficial de Cara de reloj.
(<a href="{@docRoot}training/wearables/watch-faces/index.html">Obtén más información</a>)
</p>
</td>
</tr>
</table>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/wearqualityguidelines/functionality"
data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="ux">
Diseño visual e interacción con el usuario
</h2>
</div>
<p>
Estos criterios permiten que te asegures de que tu aplicación cumpla con los patrones clave de diseño e interacción a fin de proporcionar
una experiencia de usuario uniforme, intuitiva y agradable en wearables.
</p>
<table>
<tr>
<th style="width:2px;">
Tipo
</th>
<th style="width:54px;">
ID
</th>
<th>
Descripción
</th>
</tr>
<tr>
<td rowspan="3" id="layout">
Diseño
</td>
<td id="WR-LS">
WR-LS
</td>
<td>
<p style="margin-bottom:.5em;">
La interfaz de usuario de la aplicación tiene el formato correcto para pantallas cuadradas. El contenido de la aplicación
se ajusta al área física de la pantalla y no se visualiza texto ni controles cortados por los bordes de la pantalla.
<br/>
(<a href="{@docRoot}training/wearables/ui/layouts.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-LR">
WR-LR
</td>
<td>
<p style="margin-bottom:.5em;">
La interfaz de usuario de la aplicación tiene el formato correcto para pantallas circulares, incluidos dispositivos con un
bajorrelieve (o “mentón”) en la parte inferior de la pantalla. El contenido de la aplicación se ajusta al área física
de la pantalla y no se visualiza texto ni controles cortados por los bordes de la pantalla.
<br/>
(<a href="{@docRoot}training/wearables/ui/layouts.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-TC">
WR-TC
</td>
<td>
<p style="margin-bottom:.5em;">
El texto en pantalla es grande y permite captar la información de un vistazo con un tamaño mínimo sugerido de 16 sp.
(<a href="{@docRoot}design/wear/style.html#Typography">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="1" id="launcher">
Lanzador
</td>
<td id="WR-LN">
WR-LN
</td>
<td>
<p style="margin-bottom:.5em;">
La cadena del selector de la aplicación es el nombre de la aplicación y no una frase de comando.
(<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="5" id="notifications">
Notificaciones
</td>
<td id="WR-NC">
WR-NC
</td>
<td>
<p style="margin-bottom:.5em;">
Cuando corresponde, la aplicación muestra animaciones de confirmación.
(<a href="{@docRoot}design/wear/patterns.html#Countdown">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-NR">
WR-NR
</td>
<td>
<p style="margin-bottom:.5em;">
Las tarjetas de notificación tienen el icono de la aplicación visible en el borde superior derecho. La única excepción es
cuando la tarjeta de notificación tiene controles de acción individual; por ejemplo, una tarjeta de reproducción multimedia.
<br/>
(<a href="{@docRoot}design/wear/style.html#Assets">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-WI">
WR-WI
</td>
<td>
<p style="margin-bottom:.5em;">
Las acciones de notificación tienen un icono blanco, un título de acción y fondo transparente.
<br/>
(<a href="{@docRoot}training/wearables/notifications/creating.html#ActionButtons">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-PB">
WR-PB
</td>
<td>
<p style="margin-bottom:.5em;">
Los fondos de las notificaciones con foto se utilizan únicamente para proporcionar información, no para exhibir una marca en una tarjeta.
(<a href="{@docRoot}design/wear/style.html#Branding">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td id="WR-PR">
WR-PR
</td>
<td>
<p style="margin-bottom:.5em;">
Los fondos de las notificaciones con foto tienen una resolución de 400x400 como mínimo.
(<a href="{@docRoot}training/wearables/notifications/creating.html#AddWearableFeatures">Obtén más información</a>)
</p>
</td>
</tr>
<tr>
<td rowspan="1" id="googleplay">
Google Play
</td>
<td id="WR-GS">
WR-GS
</td>
<td>
<p style="margin-bottom:.5em;">
La aplicación incluye al menos una captura de pantalla de Wear en su directorio en la Play Store.
(<a href="https://support.google.com/googleplay/android-developer/answer/1078870?hl=en">Obtén más información</a>)
</p>
</td>
</tr>
</table>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/wearqualityguidelines/visualdesign"
data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="faq">
Preguntas frecuentes
</h2>
</div>
<p style="margin-top:30px;">
<strong>Después de enviar mi aplicación para la revisión de Android Wear, ¿cómo sabré si mi aplicación no
cumple todos los requisitos para Wear?</strong>
</p>
<p>
Si tu aplicación no cumple los requisitos de utilidad que se describen en esta página, el equipo de la Play Store
se comunicará contigo a la dirección de correo electrónico que especificaste en la cuenta de la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores de Google Play</a> asociada con
la aplicación.
</p>
<p class="caution">
<strong>Advertencia:</strong> Asegúrate de que tu aplicación cumpla los <a href="#fn">requisitos de
funcionalidad</a>, de lo contrario, la aplicación no se considerará una aplicación para Wear y no se revisará
para determinar si cumple con los requisitos de <a href="#ux">diseño e interacción</a> de Wear.
</p>
<p class="note">
<strong>Nota:</strong> Para obtener información acerca de cómo publicar tus aplicaciones para Wear en Google Play, consulta <a href="{@docRoot}distribute/googleplay/wear.html">Distribución para Android Wear</a>.
</p>
<p style="margin-top:30px;">
<strong>Si mi aplicación no cumple con los requisitos de Wear, ¿aparecerá todavía mi aplicación nueva o actualizada en
Google Play para teléfonos y tablets, y aún se podrá instalar en wearables?</strong>
</p>
<p>
Sí. Los requisitos antes descritos solo determinan si tu aplicación se identificará como una aplicación de
Android Wear en Google Play y si los usuarios de Android Wear podrán descubrirla de forma más fácil. Si tu aplicación no
se acepta como una aplicación para Wear, aún estará disponible para otros dispositivos, como teléfonos y
tablets, y aún podrá instalarse en wearables.
</p>

View File

@@ -1,156 +0,0 @@
page.title=Comienza a publicar
page.metaDescription=Comienza a publicar en Google Play en minutos al crear una cuenta de desarrollador.
meta.tags="publishing"
page.tags="google play", "publishing", "register", "signup"
page.image=/distribute/images/getting-started.jpg
@jd:body
<div class="top-right-float" style="margin-right:24px;margin-top:-18px">
<a href="https://play.google.com/apps/publish/"><img src="{@docRoot}images/gp-start-button.png"></a>
</div>
<p>
Comienza a publicar en Google Play en minutos de la siguiente manera:
</p>
<ul>
<li>Regístrate para una cuenta de publicador en Google Play.
</li>
<li>Si piensas vender aplicaciones o productos integrados en la aplicación,
configura una cuenta de comerciante en Google Wallet.
</li>
<li>Explora la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores
en Google Play</a> y las herramientas de publicación.
</li>
</ul>
<p>
Cuando estés listo, usa el botón Inicio para ingresar a la Consola para desarrolladores.
</p>
<div class="headerLine">
<h2>
Regístrate para una cuenta de publicador
</h2>
</div>
<div class="sidebox-wrapper" style="float:right;">
<div class="sidebox">
<h2>
Sugerencias
</h2>
<ul>
<li>Para poder registrarte, necesitas una cuenta de Google. Puedes crear una durante el
proceso.
</li>
<li>Si eres una organización, considera la opción de registrar una nueva cuenta de Google
en lugar de usar una cuenta personal.
</li>
<li>Consulta los <a href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=138294">
países para desarrolladores</a> y los <a href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=150324">
países para comerciantes</a> en los que puedes distribuir y vender aplicaciones.
</li>
</ul>
</div>
</div>
<ol>
<li>Visita la <a href="https://play.google.com/apps/publish/">Consola para desarrolladores
de Google Play</a>.
</li>
<li>Ingresa información básica acerca de tu <strong>identidad como desarrollador </strong>
&mdash; por ejemplo, nombre, dirección de correo electrónico, etc. Puedes modificar esa información
más adelante.
</li>
<li>Lee y acepta el <strong>Acuerdo de distribución para desarrolladores</strong> para
tu país o región. Ten en cuenta que las aplicaciones y los directorios de tienda que publiques en
Google Play deben cumplir las políticas del programa para desarrolladores y las leyes de exportación de los
EE. UU.
</li>
<li>Paga un <strong>cargo de registro de $25 USD</strong> mediante Google Wallet. Si
no tienes una cuenta de Google Wallet, puedes configurar una rápidamente durante el
proceso.
</li>
<li>Una vez que se verifique tu registro, recibirás una notificación en la
dirección de correo electrónico que ingresaste durante el registro.
</li>
</ol>
<div class="headerLine">
<h2 id="merchant-account">
Configura una cuenta de comerciante en Google Wallet
</h2>
</div>
<div class="figure" style="width:200px;">
<img src="{@docRoot}images/gp-start-wallet-icon.png">
</div>
<p>
Si quieres vender aplicaciones pagas, productos integrados en la aplicación o suscripciones, necesitarás
una cuenta de comerciante en Google Wallet. Puedes configurar una en cualquier momento, pero
primero consulta la lista de <a href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=en&amp;answer=150324">
países para comerciantes</a>.<br>
<br>
Para configurar una cuenta de comerciante en Google Wallet:<br>
<br>
</p>
<ol>
<li>
<strong>Inicia sesión</strong> en tu Consola para desarrolladores de Google Play en <a href="https://play.google.com/apps/publish/" target="_blank">https://play.google.com/apps/publish/</a>.
</li>
<li>Abre <strong>Informes financieros</strong> <img src="{@docRoot}images/distribute/console-reports.png"> en el panel de navegación lateral.
</li>
<li>Haz clic en <strong>Configurar una cuenta de comerciante ahora</strong>.
</li>
</ol>
<p>
Esto te llevará al sitio de Google Wallet; para completar este paso, necesitarás información
acerca de tu negocio.
</p>
<div class="headerLine">
<h2>
Explora la Consola para desarrolladores
</h2>
</div>
<p>
Una vez que se haya verificado tu registro, podrás iniciar sesión en la Consola para
desarrolladores, que es el lugar de Google Play desde donde realizarás las operaciones de publicación de tu aplicación y donde encontrarás
herramientas.
</p>
<div>
<img src="{@docRoot}images/gp-dc-home.png" class="border-img">
</div>
<div class="headerLine">
<h2 id="related-resources">Recursos relacionados</h2><hr />
</div>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/googleplay/gettingstarted"
data-sortOrder="-timestamp"
data-cardSizes="9x3"
data-maxResults="6"></div>

View File

@@ -1,305 +0,0 @@
page.title=Distribución para Android TV
page.image=/design/tv/images/atv-home.jpg
meta.tags="tv", "publish", "quality"
page.tags="tv", "publish", "googleplay"
page.metaDescription=Distribuye tus aplicaciones, juegos y contenido para Android TV.
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Cómo participar</h2>
<ol>
<li><a href="#understand_guidelines">Comprende las pautas</a></li>
<li><a href="#develop_app">Desarrolla una aplicación excelente para TV</a></li>
<li><a href="#test_app">Prueba la calidad de la aplicación para TV</a></li>
<li><a href="#opt_in">Incluye la aplicación</a></li>
<li><a href="#track_review">Realiza un seguimiento de tu revisión</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a></li>
<li><a href="{@docRoot}distribute/essentials/quality/core.html">Calidad de la aplicación principal</a></li>
</ol>
</div></div>
<p>
Si creaste una aplicación o un juego genial, Android TV y Google Play pueden ayudarte
a llevarla directo a las salas de los usuarios. Podrás ofrecer tus
aplicaciones y juegos en una experiencia de vidriera optimizada para TV. Puedes
ampliar tus aplicaciones nuevas o existentes para TV y luego publicarlas en Google Play usando herramientas
y procesos ya conocidos.
</p>
<p>
Para comenzar, repasa las secciones de este documento para aprender a
distribuir a los usuarios tus aplicaciones para TV a través de Google Play. Asegúrate de leer
<a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a>
para obtener información sobre las pautas de utilidad y calidad que tu aplicación debe
cumplir. Cuando tu aplicación esté lista, puedes incluirla para su publicación en la vidriera de Android TV
de la Consola para desarrolladores.
</p>
<h2 id="how_to_participate">
Cómo participar
</h2>
<p>
Google Play te permite exhibir tus aplicaciones para TV frente a un nuevo público de usuarios en
sus salas. Puedes desarrollar y publicar mediante el uso de tu cuenta existente
de la Consola para desarrolladores y tu configuración actual para distribución y fijación de precios. Participar
es fácil; las siguientes secciones describen el proceso.
</p>
<div style="float:right;margin:1em 0 1.5em 2em;">
<img src="{@docRoot}images/gp-tv-process.png">
</div>
<h3 id="understand_guidelines">
1. Comprende las pautas y los requisitos
</h3>
<p>
Para prepararte para un lanzamiento exitoso en Android TV, comienza por revisar las
pautas para crear experiencias de aplicación excelentes en TV. Consulta las <a href="{@docRoot}design/tv/index.html">pautas de diseño para Android TV</a> para obtener ideas
acerca de cómo ampliar tu aplicación para que sea compatible con TV y detalles sobre diseño y utilidad.
</p>
<p>
Cuando comiences a diseñar tu experiencia para TV, asegúrate de leer y
comprender los criterios de calidad de las aplicaciones para TV. La experiencia de Google Play para
Android TV <strong>solo exhibe aplicaciones que pueden usarse en un televisor</strong>
&mdash; tus aplicaciones pueden participar siempre que cumplan con un grupo de criterios de calidad
básicos. Consulta <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad
de las aplicaciones para TV</a> para obtener información detallada.
</p>
<h3 id="develop_app">2. Desarrolla una aplicación excelente para TV</h3>
<p>
Una aplicación excelente para TV es la que se diseña para utilizar en la sala y aprovecha las
capacidades de Android TV y recursos de entrada relacionados como controladores
de juegos, mandos de dirección y mandos a distancia. La aplicación se pule para ofrecer una experiencia
nítida y de alta calidad en pantallas grandes y proporciona un conjunto de funciones
atractivas para los usuarios.
</p>
<p>
Mientras consideras la posibilidad de desarrollar una aplicación para TV, lee la <a href="{@docRoot}training/tv/start/index.html">documentación para desarrolladores</a> y las
pautas de utilidad, y considera aplicarlas en la mayor medida
posible. Asegúrate de diseñar una excelente experiencia relajada para los usuarios y créala
con la biblioteca Leanback que se incluye en el SDK. Te recomendamos que optimices
otras partes de tu aplicación para que puedan usarse en la TV y que las identifiques
al principio del proceso de desarrollo.
</p>
<p>
En la mayoría de los casos, recomendamos que ofrezcas tu experiencia para TV como parte de tu
aplicación actual para teléfonos, tablets y otros dispositivos con el mismo nombre de paquete
y el mismo directorio de la tienda. Este enfoque permite a los usuarios cambiar a tu experiencia de TV
sin inconvenientes y también te permite aprovechar las reseñas y calificaciones que obtuviste
en tu aplicación para teléfonos y tablets.
</p>
<p>
Puedes agrupar tus intentos para TV, la biblioteca Leanback, el código específico
para TV y los recursos en una sola solución de APK para todos los dispositivos admitidos. Si
fuera necesario, puedes usar la <a href="{@docRoot}google/play/publishing/multiple-apks.html">Compatibilidad con múltiples
APK</a> para proporcionar un archivo binario personalizado para dispositivos Android TV con el mismo nombre
de paquete y directorio de la tienda que usas para teléfonos y tablets.
</p>
<p>
Durante la fase de diseño y desarrollo, es importante que cuentes con un dispositivo adecuado
en el que puedas experimentar y probar tu experiencia de usuario. Debes adquirir uno
o más dispositivos Android TV o emuladores y configurar tu entorno de prueba
lo antes posible. El dispositivo de hardware recomendado para realizar las pruebas en el
entorno Android TV es Nexus Player, que está <a href="http://www.google.com/intl/all/nexus/player/">disponible en Google Play</a>
y en otras tiendas, y también debes adquirir un controlador para juegos y otros dispositivos de
entrada para TV.
</p>
<h3 id="test_app">3. Prueba la calidad de la aplicación para TV</h3>
<p>
Tus aplicaciones para TV deben estar diseñadas para que funcionen bien, se vean increíbles en Android TV
y ofrezcan la mejor experiencia de usuario posible. Google Play exhibe
aplicaciones de alta calidad para que los usuarios puedan encontrarlas fácilmente en Google Play. Aquí te mostramos
cómo puedes participar y ofrecer una aplicación para Android TV que los usuarios disfrutarán.
</p>
<ul>
<li>Cumple las pautas de Calidad de la aplicación principal
<ul>
<li>Sigue las <a href="{@docRoot}design/index.html">pautas de
Diseño Android</a>. Presta especial atención al uso de <a href="http://www.google.com/design/spec/material-design/introduction.html">Material
Design</a> en tu aplicación.
</li>
<li>Prueba tus aplicaciones conforme a las <a href="{@docRoot}distribute/essentials/quality/core.html">pautas de calidad de la aplicación
principal</a>.
</li>
</ul>
</li>
<li>Cumple las pautas de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones
para TV</a>
<ul>
<li>Sigue nuestras mejores prácticas para el<a href="{@docRoot}training/tv/index.html">
desarrollo de aplicaciones para TV</a></li>
<li>Asegúrate de que tu aplicación cumpla todos los criterios de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a>.</li>
</ul>
</li>
<li>Apunta a la sencillez y la máxima utilidad</li>
</ul>
<h3 id="opt_in">4. Incluye tu aplicación en Android TV y publícala</h3>
<p>
Una vez que hayas creado tu APK listo para el lanzamiento y lo hayas probado para asegurarte de que cumple
todas las pautas de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las
aplicaciones para TV</a>, cárgalo a la Consola para desarrolladores. Actualiza el directorio de tu
tienda con capturas de pantalla y banners de tu aplicación para TV, y configura opciones de distribución,
según sea necesario. Si no sabes cómo prepararte para el lanzamiento en Google Play,
consulta la <a href="{@docRoot}distribute/googleplay/publish/preparing.html">Lista de comprobación
para el lanzamiento.</a>
</p>
<p>
Antes de que puedas publicar para usuarios de Android TV, debes acceder a Android
TV desde la sección <strong>Fijación de precios y distribución</strong> de la
Consola para desarrolladores. Acceder significa que quieres que tu aplicación esté disponible
para los usuarios de Android TV a través de Google Play, y que
tu aplicación cumple las pautas de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad
de las aplicaciones para TV</a>.
</p>
<p>
Puedes acceder únicamente si tu aplicación cumple dos criterios
de calidad preliminares que se verifican automáticamente al cargar al APK:
</p>
<ul>
<li>El manifiesto de tu aplicación debe incluir un tipo de intento <a href="{@docRoot}reference/android/content/Intent.html#ACTION_MAIN"><code>ACTION_MAIN</code></a>
con la categoría <a href="{@docRoot}reference/android/content/Intent.html#CATEGORY_LEANBACK_LAUNCHER">
<code>CATEGORY_LEANBACK_LAUNCHER</code></a>. Obtén más información <a href="{@docRoot}training/tv/start/start.html#tv-activity">aquí</a>.
</li>
<li>Tu aplicación debe declarar que no requiere una pantalla táctil. El
manifiesto debe declarar el hardware <code>android.hardware.touchscreen</code>
con <code>android:required="false”</code>. Obtén más información <a href="{@docRoot}training/tv/start/hardware.html#declare-hardware-requirements">aquí</a>.
</li>
</ul>
<p>
Si tu aplicación cumple los criterios preliminares, verás una casilla de verificación para inclusión para
Android TV, como se muestra a continuación. Si la casilla de verificación para inclusión no está habilitada, revisa
tu APK para asegurarte de que cumpla con los criterios preliminares.
</p>
<p>
Después de realizar la inclusión y guardar los cambios, puedes publicar tu aplicación como lo haces habitualmente.
Antes de que tu aplicación esté disponible para los usuarios de Android TV, Google Play envía
tu aplicación para revisión conforme a los criterios de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a>
y te notifica el resultado. Consulta la siguiente sección para obtener información detallada
sobre cómo realizar un seguimiento del estado de aprobación de tu aplicación.
</p>
<p>
Si tu aplicación cumple los criterios de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las
aplicaciones para TV</a>, Google Play la exhibe a los usuarios de
Android TV. Tu aplicación también es elegible para acceder a una mayor visibilidad si se exhibe en
colecciones de aplicaciones y promociones. Para que los usuarios de todas partes sepan que tu aplicación está
diseñada para Android TV, Google Play decora el directorio de tienda de la aplicación con una
insignia de TV.
</p>
<p>
Ten en cuenta que la inclusión y la revisión no afectan la disponibilidad de tu aplicación para
otros dispositivos en la Play Store de Google; por
ejemplo, para teléfonos y tablets tu aplicación estará disponible ni bien la publiques.
</p>
<p>
Aquí te mostramos los pasos que debes seguir en la Consola para desarrolladores para incluir tu aplicación en Android TV:
</p>
<ol>
<li>Asegúrate de que tu aplicación cumpla todos los criterios de <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a>.
</li>
<li>Agrega capturas de pantalla de tu aplicación para TV y gráficos de banner al directorio de tienda de la aplicación
</li>
<li>En la página <strong>Todas las aplicaciones</strong>, haz clic en la aplicación que quieres incluir.
</li>
<li>En <strong>Fijación de precios y distribución</strong>, desplázate hacia abajo hasta encontrar <em>Android TV</em> y la
casilla de verificación para la inclusión.
</li>
<li>Haz clic en la casilla de verificación junto a <em>Distribuye tu aplicación para Android TV</em>.
</li>
<li>Haz clic en <strong>Guardar</strong> para guardar tus cambios.
</li>
</ol>
<div style="padding-top:1em">
<img style="border:2px solid #ddd;" src="{@docRoot}images/gp-tv-opt-in.png">
<p class="caption">
<strong>Incluye la aplicación para TV:</strong> Incluye tu aplicación en Android TV desde la
Consola para desarrolladores.
</p>
</div>
<h3 id="track_review">5. Realiza un seguimiento de tu revisión y aprobación</h3>
<p>
Si tu aplicación cumple los requisitos técnicos y de calidad para Android TV, como se describe más arriba,
estará disponible para que los usuarios la disfruten en Android TV. Si la aplicación no cumple
los criterios, recibirás una <strong>notificación por correo electrónico enviada a tu cuenta
de desarrollador</strong> con un resumen de las áreas que debes abordar. Una vez que realices
los ajustes necesarios, puedes cargar una nueva versión de tu aplicación a la Consola para
desarrolladores.
</p>
<p>
En cualquier momento, puedes comprobar el estado de revisión y aprobación de tu aplicación en la
Consola para desarrolladores, bajo <em>Android TV</em> en la página <strong>Fijación de precios y distribución</strong>
de la aplicación.
</p>
<p>
Existen tres estados de aprobación:
</p>
<ul>
<li>
<em>Pendiente</em>: tu aplicación se envió a revisión pero la revisión aún no ha
finalizado.
</li>
<li>
<em>Aprobada</em>: se revisó tu aplicación y se aprobó. La aplicación
estará disponible de forma directa para los usuarios de Android TV.
</li>
<li>
<em>No aprobada</em>: se revisó tu aplicación y no se aprobó. Lee el
correo electrónico de notificación para obtener información acerca de los motivos por los que no se aprobó la aplicación. Puedes
solucionar los problemas e incluirla y publicarla nuevamente para iniciar otra
revisión.
</li>
</ul>
<p>Para comprender cómo se evalúan tus aplicaciones, consulta el documento <a href="{@docRoot}distribute/essentials/quality/tv.html">Calidad de las aplicaciones para TV</a>. </p>
<h3>Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:tvlanding"
data-cardSizes="9x6, 6x3x2"
data-maxResults="6">
</div>

View File

@@ -1,262 +0,0 @@
page.title=Distribución para Android Wear
page.image=/design/media/wear/ContextualExample.008_2x.png
meta.tags="wear", "publish", "quality"
page.tags="wear", "publish", "googleplay"
page.metaDescription=Distribuye tus aplicaciones, juegos y contenido para Android Wear.
@jd:body
<div id="qv-wrapper"><div id="qv">
<h2>Cómo participar</h2>
<ol>
<li><a href="#understand_guidelines">Comprende las pautas</a></li>
<li><a href="#develop_app">Desarrolla una aplicación excelente para Wear</a></li>
<li><a href="#test_app">Prueba la calidad de la aplicación para Wear</a></li>
<li><a href="#opt_in">Incluye la aplicación</a></li>
<li><a href="#track_review">Realiza un seguimiento de tu revisión</a></li>
</ol>
<h2>También deberías leer</h2>
<ol>
<li><a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a></li>
<li><a href="{@docRoot}distribute/essentials/quality/core.html">Calidad de la aplicación principal</a></li>
</ol>
</div></div>
<p>
Si desarrollaste una aplicación excelente, Android Wear y Google Play pueden ayudarte a acercarla a los usuarios. Si bien todas las
aplicaciones pueden enviar notificaciones básicas para dispositivos Android Wear, puedes ir mucho más allá.
Extiende tus aplicaciones para que admitan interacciones personalizadas con Wear y ofrezcan una experiencia de usuario refinada e
interactiva en todos los dispositivos Wear. Si tu aplicación cumple las pautas de calidad de la aplicación principal en dispositivos portátiles y
proporciona una experiencia de alta calidad para los dispositivos Android Wear, Google Play exhibirá tus aplicaciones
y facilitará su descubrimiento.
</p>
<p>
Para comenzar, repasa las secciones de este documento para aprender a distribuir a los usuarios tus aplicaciones
para Wear a través de Google Play. Asegúrate de leer <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a> para obtener información sobre
las pautas de utilidad y calidad que tus aplicaciones deben cumplir. Cuando tu aplicación esté lista, puedes
incluirla para su designación como aplicación de Android Wear en la Consola para desarrolladores.
</p>
<h2 id="how_to_participate">
Cómo participar
</h2>
<p>
Google Play permite que tus aplicaciones para Wear sean más fáciles de descubrir para los usuarios de Wear. Puedes desarrollar y
publicar mediante el uso de tu cuenta existente de la Consola para desarrolladores y tu configuración actual para distribución y fijación de
precios. Participar es fácil; las siguientes secciones describen el proceso.
</p>
<h3 id="understand_guidelines">
1. Comprende las pautas y los requisitos
</h3>
<div style="float:right;margin:1em 0 1.5em 2em;">
<img src="{@docRoot}images/gp-wear-process.png">
</div>
<p>
Si quieres prepararte para un lanzamiento exitoso en Android Wear, comienza por revisar las pautas para
crear experiencias excelentes en Wear. Consulta las <a href="{@docRoot}design/wear/index.html">Pautas
de diseño para Android Wear</a> para obtener ideas acerca de cómo ampliar tu aplicación para que sea compatible con Wear y detalles sobre diseño y
utilidad.
</p>
<p>
Cuando comiences a diseñar tu experiencia para Wear, asegúrate de leer y comprender los criterios
de calidad de las aplicaciones para Wear. Únicamente las aplicaciones compatibles con Wear se designarán aplicaciones Wear en
Google Play; tus aplicaciones pueden participar si cumplen con un conjunto de criterios de calidad básicos. Consulta <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a> para obtener información detallada.
</p>
<h3 id="develop_app">2. Desarrolla una aplicación excelente para Wear</h3>
<p>
Una vez que hayas leído las pautas, el paso siguientes es desarrollar tu aplicación. Las siguientes secciones
describen cómo comenzar a crear una aplicación para Wear que proporcione una excelente experiencia.
</p>
<h4>Primero el diseño</h4>
<p>
Android Wear tiene como objetivo proporcionar a los usuarios la información correcta en el momento adecuado. Las increíbles
experiencias de Android Wear se inician automáticamente, permiten captar de información de un solo vistazo y
prácticamente no requieren la interacción del usuario. Si bien todas las aplicaciones pueden enviar notificaciones básicas a dispositivos Wear
sin la necesidad de realizar modificaciones, las aplicaciones excelentes creadas para Wear se refinan para ofrecer una experiencia pulida y
de alta calidad, admitir diferentes diseños de pantalla y proporcionar a los usuarios un conjunto de aplicaciones
atractivas.
</p>
<p>
Mientras consideras la posibilidad de desarrollar una aplicación para Wear, lee la <a href="{@docRoot}training/building-wearables.html">documentación para desarrolladores</a> y las<a href="{@docRoot}design/wear/index.html"> pautas de utilidad</a>, y considera aplicarlas en la
mayor medida posible. Puedes diseñar una magnífica experiencia de notificación para los usuarios con las API
que se proporcionan en el SDK y la biblioteca de soporte. También puedes optar por crear una aplicación que
pueda ejecutarse directamente en el wearable.
</p>
<h4>Integra tu aplicación</h4>
<p>
Te recomendamos que ofrezcas tu experiencia para Wear como parte de tu aplicación actual para teléfonos,
tablets y otros dispositivos con el mismo nombre de paquete y el mismo directorio de la tienda. Este enfoque
permite a los usuarios cambiar a tu experiencia de Wear sin inconvenientes, y también te permite aprovechar las reseñas y
calificaciones que obtuviste en tu aplicación para teléfonos y tablets. Las aplicaciones para wearables que dependen de una
aplicación para adquirir su plena funcionalidad deben estar integradas a esa aplicación. Para aprender a hacerlo, lee <a href="{@docRoot}training/wearables/apps/packaging.html">Integración de aplicaciones para wearables</a>.
</p>
<h4>Realiza pruebas en diferentes dispositivos</h4>
<p>
Durante la fase de diseño y desarrollo, es importante que cuentes con dispositivos adecuados en los que puedas
experimentar y probar tu experiencia de usuario. Te recomendamos enfáticamente que adquieras uno o más dispositivos Android Wear
o desarrolles con diferentes configuraciones de simulación y configures tu entorno de prueba
lo antes posible. Es importante que optimices tu diseño para formatos cuadrados y circulares.
</p>
<h3 id="test_app">3. Prueba la calidad de la aplicación para Wear</h3>
<p>
Tus aplicaciones para Wear deben estar diseñadas para que funcionen bien y se vean increíbles en Android Wear
, y deben ofrecer la mejor experiencia de usuario posible. Google Play exhibirá aplicaciones para Wear
seleccionadas de alta calidad a fin de que los usuarios puedan encontrarlas fácilmente. Aquí te mostramos cómo puedes participar y ofrecer una aplicación para Android Wear que
los usuarios disfrutarán:
</p>
<ul>
<li>Cumple las pautas de Calidad de la aplicación principal.
<ul>
<li>Sigue las <a href="{@docRoot}design/index.html">pautas de
Diseño Android</a>. Presta especial atención al uso de <a href="http://www.google.com/design/spec/material-design/introduction.html">Material
Design</a> en tu aplicación.
</li>
<li>Prueba tus aplicaciones conforme a las <a href="{@docRoot}distribute/essentials/quality/core.html">pautas de calidad de la aplicación
principal</a>.
</li>
</ul>
</li>
<li>Cumple los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las
aplicaciones para Wear</a>.
<ul>
<li>Sigue nuestras mejores prácticas para el <a href="{@docRoot}training/building-wearables.html">
desarrollo de aplicaciones para Wear</a>.</li>
<li>Asegúrate de que tu aplicación cumpla todos los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a>.</li>
</ul>
</li>
</ul>
<h3 id="opt_in">4. Incluye tu aplicación en Android Wear y publícala</h3>
<p>
Una vez que hayas creado tu APK listo para el lanzamiento y lo hayas probado para asegurarte de que cumple todos los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a>, cárgalo
a la Consola para desarrolladores. Actualiza el directorio de tu tienda con capturas de pantalla de tu aplicación para Wear y configura opciones
de distribución, según sea necesario. Si no sabes cómo prepararte para el lanzamiento en Google Play, consulta la
<a href="{@docRoot}distribute/googleplay/publish/preparing.html">Lista de comprobación para el lanzamiento.</a>
</p>
<p>
Antes de que puedas publicar para los usuarios, debes incluir la aplicación para Android Wear desde la sección <strong>Fijación de precios
y distribución</strong> de la Consola para desarrolladores. Inclusión significa que quieres que tu aplicación sea
más fácil de encontrar para los usuarios de Android Wear a través de Google Play, y que tu aplicación cumple los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a>.
</p>
<p>
Después de realizar la inclusión y guardar los cambios, puedes publicar tu aplicación como lo haces habitualmente. Además, Google
Play envía tu aplicación para revisión conforme a los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a> y
te notifica el resultado. Consulta la siguiente sección para obtener información detallada sobre cómo realizar un seguimiento del estado de aprobación
de tu aplicación.
</p>
<p>
Si tu aplicación cumple todos los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las
aplicaciones para Wear</a>, Google Play permite que sea más fácil de descubrir para los usuarios de Android Wear. Tu aplicación también
es elegible para acceder a una mayor visibilidad si se exhibe en colecciones de aplicaciones y promociones.
</p>
<p>
Ten en cuenta que la inclusión y la revisión no afectan la disponibilidad de tu aplicación en la Play Store de Google;
es decir, tu aplicación estará disponible ni bien la publiques.
</p>
<p>
Aquí te mostramos los pasos que debes seguir en la Consola para desarrolladores para incluir tu aplicación en Android Wear:
</p>
<ol>
<li>Asegúrate de que tu aplicación cumpla todos los criterios de <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a>.
</li>
<li>Agrega capturas de pantalla de tu aplicación para Wear al directorio de tienda de la aplicación
</li>
<li>En la página <strong>Todas las aplicaciones</strong>, haz clic en la aplicación que quieres incluir.
</li>
<li>En <strong>Fijación de precios y distribución</strong>, desplázate hacia abajo hasta encontrar <em>Android Wear</em>
y la casilla de verificación para la inclusión.
</li>
<li>Haz clic en la casilla de verificación junto a <em>Distribuye tu aplicación para Android Wear</em>.
</li>
<li>Haz clic en <strong>Guardar</strong> para guardar los cambios que realizaste en Fijación de precios y distribución.
</li>
</ol>
<div style="padding-top:1em">
<img style="border:2px solid #ddd;" src="{@docRoot}images/gp-wear-opt-in.png">
<p class="caption">
<strong>Incluye la aplicación para Wear:</strong> Incluye tu aplicación en Android Wear desde la
Consola para desarrolladores.
</p>
</div>
<h3 id="track_review">5. Realiza un seguimiento de tu revisión y aprobación</h3>
<p>
Si tu aplicación cumple los requisitos técnicos y de calidad para Android Wear, como se describe más arriba,
será más fácil de descubrir para los usuarios en Android Wear. Si la aplicación no cumple los
criterios, recibirás una <strong>notificación por correo electrónico enviada a tu cuenta
de desarrollador</strong> con un resumen de las áreas que debes abordar. Una vez que realices
los ajustes necesarios, puedes cargar una nueva versión de tu aplicación a la Consola para desarrolladores.
</p>
<p>
En cualquier momento, puedes comprobar el estado de revisión y aprobación de tu aplicación en la Consola para desarrolladores,
bajo <em>Android Wear</em> en la página <strong>Fijación de precios y distribución</strong>
de la aplicación.
</p>
<p>
Existen tres estados de aprobación:
</p>
<ul>
<li>
<em>Pendiente</em>: tu aplicación se envió a revisión pero la revisión aún no ha finalizado.
</li>
<li>
<em>Aprobada</em>: se revisó tu aplicación y se aprobó. La aplicación será más fácil de descubrir
para los usuarios de Android Wear.
</li>
<li>
<em>No aprobada</em>: se revisó tu aplicación y no se aprobó. Lee el correo electrónico de notificación
para obtener información acerca de los motivos por los que no se aprobó la aplicación. Puedes solucionar los problemas e incluirla y
publicarla nuevamente para iniciar otra revisión.
</li>
</ul>
<p>Para comprender cómo se evalúan tus aplicaciones, consulta el documento <a href="{@docRoot}distribute/essentials/quality/wear.html">Calidad de las aplicaciones para Wear</a>. </p>
<h3>Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:wearlanding"
data-cardSizes="6x2"
data-maxResults="3">
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -1,937 +0,0 @@
page.title=Lista de comprobación para la localización
page.metaDescription=Aprovecha el público mundial que te ofrecen Android y Google Play. Lee esta lista de comprobación para obtener información general acerca de cómo distribuir tu producto en los mercados de todo el mundo.
meta.tags="localizing, publishing, disttools"
page.tags="local, l10n, translation, language"
page.image=/distribute/images/localization-checklist.jpg
@jd:body
<div id="qv-wrapper">
<div id="qv" style="width:280px">
<h2>Lista de comprobación</h2>
<ol>
<li><a href="#identify-languages">1. Identifica idiomas y configuraciones regionales de destino</a></li>
<li><a href="#design">2. Diseña con la localización en mente</a></li>
<li><a href="#manage-strings">3. Administra cadenas para localización</a></li>
<li><a href="#translate-strings">4. Traduce las cadenas de la IU y otros recursos</a></li>
<li><a href="#test">5. Prueba tu aplicación localizada</a></li>
<li><a href="#prepare-launch">6. Prepárate para el lanzamiento internacional</a></li>
<li><a href="#support-users">7. Brinda soporte a los usuarios internacionales después del lanzamiento</a></li>
</ol>
</div>
</div>
<div class="top-right-float" style="width:194px">
<img src="{@docRoot}distribute/images/localization-checklist.jpg">
</div>
<p>
Android y Google Play te ofrecen un público global para tus aplicaciones con una
base de usuarios que puedes usar y que crece muy rápidamente en países como Japón,
Corea, India, Brasil y Rusia. Te alentamos firmemente a que localices, ya que
puede maximizar las posibilidades de distribución de tus aplicaciones y dar lugar a la obtención de calificaciones
de usuarios de todo el mundo.
</p>
<p>
La localización comprende una variedad de tareas durante el ciclo de
desarrollo de la aplicación, y la planificación anticipada es fundamental. Este documento te ayuda a identificar
aspectos clave de la localización para que dejes tu aplicación lista y capaz de un lanzamiento
exitoso en Google Play.
</p>
<div class="headerLine">
<h2 id="identify-languages">
1. Identifica idiomas y configuraciones regionales de destino
</h2>
</div>
<p>
Un paso básico pero importante en la preparación para la localización es identificar los
países en los que distribuirás tus aplicaciones y los idiomas que allí se hablan.
Es especialmente importante que localices tus aplicaciones en países donde
exista una gran oportunidad de mercado y no se use ampliamente el
inglés u otro idioma internacional.
</p>
<p>
Para los usuarios internacionales, puedes administrar tus aplicaciones en tres dimensiones principales:
país, configuración regional e idioma. De esas dimensiones, el idioma constituye una consideración clave
para la localización (la configuración regional también puede ser importante dadas las diferencias en
formatos de fecha, hora, moneda e información similar). Los usuarios controlan
el idioma y la configuración regional de sus dispositivos Android, y estos afectan
la manera en la que se visualiza tu aplicación.
</p>
<p>
Generalmente, primero deberás decidir en qué países quieres distribuir en función del tamaño del
mercado y las oportunidades, la categoría de la aplicación, el panorama competitivo, los precios
locales, factores financieros, etc. Luego, en función de tu selección de
países, deberás determinar los idiomas que debes admitir en tus
aplicaciones.
</p>
<p>
A continuación podrás decidir localizar en algunos o todos los idiomas del país de
destino. Quizá te convenga comenzar con un idioma regional principal y agregar
más idiomas a medida que crece la base de usuarios.
</p>
<p>
Una vez que identifiques tus idiomas objetivo, puedes concentrarte en el
desarrollo, la traducción, la prueba y la comercialización en esos mercados.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/identifylocales"
data-sortorder="-timestamp" data-cardsizes="9x3," data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="design">
2. Diseña con la localización en mente
</h2>
</div>
<p>
Después de que determines tus idiomas objetivo para la localización, evalúa
qué necesitas hacer para admitirlos en tus aplicaciones y planifica el trabajo de forma temprana.
Ten en cuenta la expansión del vocabulario, los requisitos de script, el espaciado entre caracteres y las
limitaciones de ajuste de texto, admisión de texto de izquierda a derecha y de derecha a izquierda, y otros
factores potenciales en cada idioma.
</p>
<h4>
<strong>Crea un conjunto único de diseños flexibles</strong>
</h4>
<p>
Mientras creas tus diseños, asegúrate de que los elementos de la IU que contienen texto
se diseñen sin restricciones. Se recomienda dejar más espacio que el necesario
(hasta un 30% más es normal) para que tu idioma incorpore otros idiomas.
</p>
<p>
Asimismo, los elementos deben poder expandirse horizontalmente o verticalmente para
adaptarse a las variaciones en el ancho y la altura de las cadenas de la IU o el texto de entrada.
Las cadenas de texto no deben superponerse a los bordes ni al límite de la pantalla en ninguno de tus
idiomas objetivo.
</p>
<p>
Si diseñas la IU cuidadosamente, generalmente podrás usar un solo conjunto de
diseños para todos los idiomas que admitas. Consulta <a href="{@docRoot}training/basics/fragments/fragment-ui.html">Creación de una IU
flexible</a> para obtener más información.
</p>
<h4>
<strong>Cuando sea necesario, usa diseños alternativos</strong>
</h4>
<p>
Cuando tu IU no pueda incluir texto en uno de tus idiomas
objetivo, puedes crear un <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
diseño alternativo</a> solo para ese idioma. Android facilita la
declaración de la carga de conjuntos de diseños y otros recursos para idiomas,
configuraciones regionales, tamaños de pantalla específicos, etc., al etiquetarlos con los
calificadores de recursos adecuados. Si bien la flexibilidad de diseños alternativos es real, también
podría hacer que tus aplicaciones sean más difíciles de mantener con el paso del tiempo. En general, se prefiere el uso
de un solo diseño más flexible.
</p>
<h4>
<strong>Admite diseños y texto RTL</strong>
</h4>
<p>
Si estás distribuyendo a países donde se usan scripts de derecha a izquierda (RTL),
debes considerar la implementación de compatibilidad con diseños y
visualización y edición de texto RTL en la mayor medida posible.
</p>
<p>
Android 4.1 introdujo compatibilidad limitada con texto bidireccional, que permite que las aplicaciones
exhiban y editen texto tanto en scripts de izquierda a derecha (LTR) como de derecha a izquierda (RTL)
. Android 4.2 agregó <a href="http://android-developers.blogspot.fr/2013/03/native-rtl-support-in-android-42.html">
compatibilidad nativa plena para diseños RTL</a>, que incluye la duplicación del diseño, de modo que
puedas proporcionar las mismas excelentes experiencias con la aplicación a todos tus usuarios.
</p>
<p>
Como mínimo, para los usuarios de Android 4.2, es fácil agregar duplicación básica de diseño
RTL, que es un gran avance hacia la satisfacción de las necesidades de los usuarios de RTL.
</p>
<h4>
<strong>Usa formatos proporcionados por el sistema para fechas, horas, números y
monedas</strong>
</h4>
<p>
Cuando tus aplicaciones especifiquen fechas, horas, números, monedas y otras entidades
que puedan variar según la configuración regional, asegúrate de usar los formatos proporcionados por el sistema, en lugar
de formatos específicos de la aplicación. Recuerda que no todas las configuraciones regionales usan el mismo
separador de miles, separador decimal o signo de porcentaje.
</p>
<p>
Android ofrece una variedad de utilidades para dar formatear y convertir
patrones entre diferentes configuraciones regionales, como <a href="{@docRoot}reference/android/text/format/DateUtils.html">DateUtils</a> y
<a href="{@docRoot}reference/java/text/DateFormat.html">DateFormat</a> para
fechas, <a href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,%20java.lang.Object...)">
String.format()</a> o <a href="{@docRoot}reference/java/text/DecimalFormat.html">DecimalFormat</a> para
números y monedas, <a href="{@docRoot}reference/android/telephony/PhoneNumberUtils.html">PhoneNumberUtils</a>
para números de teléfono, y otros.
</p>
<p>
Codificar tus formatos en función de suposiciones acerca de la configuración regional del usuario puede
provocar problemas cuando el usuario pase a otra configuración regional. Se recomienda firmemente usar
los formatos y las utilidades que proporciona el sistema.
</p>
<h4>
<strong>Incluye un conjunto completo de recursos predeterminados</strong>
</h4>
<p>
Asegúrate de que tus aplicaciones puedan ejecutarse correctamente independientemente del idioma o la
configuración adicional al proporcionar un conjunto completo de recursos predeterminados. Los recursos predeterminados de la aplicación
son aquellos que <em>no están marcados</em> con ningún calificador de idioma o configuración regional;
por ejemplo, los que se guardan en res/drawable/ y res/values/. Si
tus aplicaciones intentan cargar un recurso que no está disponible en el idioma
actual o en el conjunto predeterminado, colapsarán.
</p>
<p>
Cualquiera sea el idioma predeterminado que uses en tus aplicaciones, asegúrate de
guardar los diseños, los recursos dibujables y las cadenas asociados en directorios
de recursos predeterminados, sin calificadores de idioma o configuraciones regionales.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/tools/loc/designforloc" data-sortorder="-timestamp"
data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="manage-strings">
3. Administra cadenas para localización
</h2>
</div>
<p>
Es importante que administres correctamente las cadenas de la IU de tus aplicaciones de modo
que puedas proporcionar una excelente experiencia para los usuarios y permitir que la localización se realice sin inconvenientes.
</p>
<h4>
<strong>Mueve todas las cadenas a strings.xml</strong>
</h4>
<p>
Mientras creas aplicaciones, recuerda no codificar las cadenas. En su lugar, declara
<em>todas</em> las cadenas como recursos en un archivo strings.xml predeterminado que
facilite la actualización y la localización. Las cadenas en el archivo strings.xml se pueden
extraer, traducir y volver a integrar en tu aplicación (con los calificadores
adecuados) sin la necesidad de realizar cambios en el código compilado.
</p>
<p>
Si creas imágenes con texto, coloca también esas cadenas en el archivo strings.xml
y vuelve a generar las imágenes después de la traducción.
</p>
<h4>
<strong>Sigue las pautas de Android para las cadenas de la IU</strong>
</h4>
<p>
Mientras diseñas y desarrollas tus IU, asegúrate de prestar mucha atención a
<em>cómo</em> te diriges al usuario. En general, utiliza un <a href="{@docRoot}design/style/writing.html">estilo conciso y comprimido</a> que sea
amigable pero breve, y usa un estilo uniforme en todas tus IU.
</p>
<p>
Asegúrate de leer y seguir las recomendaciones de Diseño Android para el
<a href="{@docRoot}design/style/writing.html">estilo de escritura y la elección de
palabras</a>. Al hacerlo, tus aplicaciones se verán más pulidas y
esto ayudará a los usuarios a comprender tu IU más rápidamente.
</p>
<p>
Siempre que sea posible, usa la terminología estándar de Android; por ejemplo,
para los elementos de la IU como la "barra de acciones", el "menú de opciones", la "barra del sistema"
, las "notificaciones", etc. El uso correcto y uniforme de los términos de Android
facilita la traducción y permite ofrecer un mejor producto final para los usuarios.
</p>
<h4>
<strong>Proporciona suficiente contexto para las cadenas declaradas</strong>
</h4>
<p>
Cuando declares cadenas en tu archivo strings.xml, asegúrate de describir
el contexto en el que se usa la cadena. Esta información será muy valiosa para los
traductores, dará lugar a una traducción de mejor calidad y también te ayudará a
administrar tus cadenas de forma más eficiente con el paso del tiempo.
</p>
<p>
Aquí te mostramos un ejemplo:
</p>
<pre class="prettyprint">
&lt;!-- The action for submitting a form. This text is on a button that can fit 30 chars --&gt;
&lt;string name="login_submit_button"&gt;Sign in&lt;/string&gt;
</pre>
<p>
Considera la posibilidad de proporcionar información contextual, que podría incluir:
</p>
<ul>
<li>
<p>
¿Para qué sirve esta cadena? ¿Cuándo/dónde se le presenta al usuario?
</p>
</li>
<li>
<p>
¿En qué parte del diseño se encuentra? Por ejemplo, si se trata de un botón, las traducciones
son menos flexibles que las de un cuadro de texto.
</p>
</li>
</ul>
<h4>
<strong>Marca las partes de un mensaje que no deben traducirse</strong>
</h4>
<p>
A menudo, las cadenas contienen texto que no se debe traducir a otros
idiomas. Algunos ejemplos comunes podrían incluir un código, un marcador de posición para un
valor, un símbolo especial o un nombre. Mientras preparas tus cadenas para la
traducción, busca y marca el texto que no debe traducirse
de modo que los traductores no lo cambien.
</p>
<p>
Para marcar texto que no debe traducirse, utiliza una etiqueta de marcador de posición
<code>&lt;xliff:g&gt;</code>. Aquí te mostramos un ejemplo de etiqueta que
garantiza que el texto "%1$s" no se modificará durante la traducción (de lo contrario,
rompería el mensaje):
</p>
<pre class="prettyprint">
&lt;string name="countdown"&gt;
&lt;xliff:g id="time" example="5 days&gt;%1$s&lt;/xliff:g&gt;until holiday
&lt;/string&gt;
</pre>
<p>
Cuando declaras una etiqueta de marcador de posición, agrega siempre un atributo de identificación que explique
para qué sirve el marcador de posición. Si tus aplicaciones luego reemplazarán el valor del
marcador de posición, asegúrate de proporcionar un atributo de ejemplo para aclarar el uso previsto.
</p>
<p>
Aquí te mostramos algunos ejemplos de etiquetas de marcadores de posición:
</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;!-- Example placeholder for a special unicode symbol --&gt;
&lt;string name="star_rating"&gt;Check out our 5
&lt;xliff:g id="star"&gt;\u2605&lt;/xliff:g&gt;
&lt;/string&gt;
&lt;!-- Example placeholder for a for a URL --&gt;
&lt;string name="app_homeurl"&gt;
Visit us at &lt;xliff:g id="application_homepage"&gt;http://my/app/home.html&lt;/xliff:g&gt;
&lt;/string&gt;
&lt;!-- Example placeholder for a name --&gt;
&lt;string name="prod_name"&gt;
Learn more at &lt;xliff:g id="prod_gamegroup"&gt;Game Group&lt;/xliff:g&gt;
&lt;/string&gt;
&lt;!-- Example placeholder for a literal --&gt;
&lt;string name="promo_message"&gt;
Please use the "&lt;xliff:g id="promotion_code"&gt;ABCDEFG&lt;/xliff:g&gt;” to get a discount.
&lt;/string&gt;
...
&lt;/resources&gt;
</pre>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/managestrings"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="translate-strings">
4. Traduce las cadenas de la IU y otros recursos
</h2>
</div>
<p>
Traducir las cadenas de la IU y los recursos de tus aplicaciones a tus idiomas objetivo es
la fase clave de la localización y es la que requiere la mayor cantidad de atención
y planificación.
</p>
<p>
Te recomendamos que trabajes con un traductor profesional (consulta <a href="#gp-trans">Compra traducciones profesionales</a>) para asegurarte de contar con traducciones
de alta calidad que aumenten el valor de tu aplicación. Si bien las traducciones automáticas
son una opción, es posible que no produzcan una experiencia igual de buena para los usuarios.
</p>
<h4>
<strong>Prepárate para la traducción</strong>
</h4>
<p>
La calidad de la traducción dependerá, en parte, de la información que proporciones; por lo tanto, asegúrate
de que tu archivo strings.xml esté bien organizado, bien comentado y sea
preciso.
</p>
<p>
Aquí te indicamos algunas maneras de preparar tus cadenas para la traducción:
</p>
<ul>
<li>
<p>
Asegúrate de haber formateado tus cadenas de forma correcta y uniforme.
</p>
</li>
<li>
<p>
Sigue las recomendaciones para cadenas que se indican más arriba en <a href="#manage-strings">Administra cadenas para localización</a>.
</p>
</li>
<li>
<p>
Limpia el archivo strings.xml y elimina las cadenas que no se utilicen.
</p>
</li>
<li>
<p>
Proporciona comentarios en el archivo para identificar al propietario, el origen y la versión
del archivo, y también instrucciones especiales para los traductores.
</p>
</li>
<li>
<p>
Identifica las traducciones existentes, si las hubiera, e inclúyelas en un archivo
comprimido saliente u otro paquete que envíes a los traductores.
</p>
</li>
<li>
<p>
Identifica los recursos dibujables u otros recursos que requieran traducción e
inclúyelos en el paquete para los traductores.
</p>
</li>
<li>
<p>
Además, considera la posibilidad de traducir los detalles del directorio de tienda de tus aplicaciones
(título y descripción de la aplicación, notas de lanzamiento, etc.)
y otros materiales de comercialización internacional.
</p>
</li>
<li>
<p>
Crea una lista terminológica que explique el significado y el uso de términos clave
que se encuentren en tu producto, tu mercado o la tecnología subyacente. Agrega la
lista al paquete para los traductores.
</p>
</li>
</ul>
<h4>
<strong>Envía tus cadenas para traducción</strong>
</h4>
<p>
Al inicio del ciclo de desarrollo, comunícate con traductores profesionales para tener
una idea del costo y el tiempo de entrega. Asegúrate de incluir múltiples
repeticiones acerca del costo. Puedes buscar traductores en línea o utilizar los
servicios de traducción disponibles directamente desde la Consola para desarrolladores de Google Play
(consulta <a href="#gp-trans">Compra traducciones profesionales</a>).
</p>
<p>
Cuando tus traducciones estén terminadas, échales un vistazo preliminar
. Comprueba que se hayan traducido todos los archivos, busca posibles
problemas de codificación y asegúrate de que los formatos de la declaración estén intactos.
</p>
<p>
Si todo se ve bien, traslada cuidadosamente los directorios y archivos localizados
nuevamente a los recursos de tus aplicaciones. Asegúrate de etiquetar los directorios con
los calificadores de idioma y configuración regional correctos de modo que luego se carguen
de forma adecuada.
</p>
<p>
Después de insertar las traducciones en tu aplicación, comienza a <a href="#test">probar la aplicación localizada</a>.
</p>
<h4 id="gp-trans">
<strong>Compra traducciones profesionales en Google Play</strong>
</h4>
<p>
El Servicio de traducción de aplicaciones de Google Play puede ayudarte a encontrar y comprar
rápidamente traducciones de tu aplicación. En la Consola para desarrolladores, puedes examinar una lista de
proveedores externos precalificados por Google para ofrecer traducciones de
alta calidad a precios competitivos. Puedes cargar las cadenas que quieres
traducir, seleccionar los idiomas en los que quieres que se traduzcan y seleccionar el
traductor en función del tiempo y el precio.
</p>
<p>
Cuando compres traducciones, recibirás un correo electrónico del traductor.
Tus traducciones son un acuerdo comercial directo entre tú y tu
proveedor; deberás trabajar directamente con el traductor para administrar el
proceso de traducción y las entregas, y solucionar cualquier problema de soporte.
</p>
<div>
<img src="{@docRoot}images/gp-localization-trans-0.png" class="border-img">
</div>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/translatestrings"
data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="test">
5. Prueba tu aplicación localizada
</h2>
</div>
<p>
Una vez que recibas tus cadenas y recursos traducidos y los insertes en
tus aplicaciones, debes probar las aplicaciones para asegurarte de que estén
listas para distribución a tus usuarios internacionales.
</p>
<p>
La prueba manual puede ayudarte a detectar problemas de localización en tus diseños y
en las cadenas que puedan afectar la satisfacción del usuario y, en última instancia, la calificación del usuario para
tus aplicaciones.
</p>
<h4>
<strong>Configura un entorno de prueba</strong>
</h4>
<p>
Para probar tu aplicación localizada, debes configurar un entorno que conste
de múltiples dispositivos (o dispositivos virtuales) y tamaños de pantalla, en función de los
mercados y formatos a los que apuntes. Ten en cuenta que el rango de dispositivos en
regiones específicas podría ser diferente. Si fuera posible, empareja tus dispositivos de prueba a
los dispositivos reales que probablemente estén disponibles para los usuarios.
</p>
<h4>
<strong>Busca problemas comunes de localización</strong>
</h4>
<p>
En cada dispositivo de prueba, establece el idioma o la configuración regional en Configuración. Instala e
inicia la aplicación, y luego navega por todos los flujos de la IU, los diálogos y las
interacciones con los usuarios. Ingresa texto en las entradas. Algunas cosas que debes buscar incluyen:
</p>
<ul>
<li>
<p>
Texto recortado o texto que se superpone al borde de los elementos de la IU o a la pantalla.
</p>
</li>
<li>
<p>
Ajuste de línea insuficiente
</p>
</li>
<li>
<p>
Separación de palabras o puntuación incorrectas
</p>
</li>
<li>
<p>
Orden alfabético incorrecto
</p>
</li>
<li>
<p>
Orientación incorrecta del diseño o el texto
</p>
</li>
<li>
<p>
Texto sin traducir: si se muestran tus cadenas predeterminadas en lugar
de cadenas traducidas, es posible que te hayas salteado esas cadenas
en la traducción o hayas marcado el directorio de recursos con un calificador de idioma
incorrecto.
</p>
</li>
</ul>
<p>
Cuando tus cadenas se hayan extendido debido a la traducción y ya no se ajusten a
tus diseños, te recomendamos que intentes simplificar el texto predeterminado, simplificar
el texto traducido o ajustar tus diseños predeterminados. Si ninguna de esas
opciones soluciona el problema, puedes crear un diseño personalizado para el idioma.
</p>
<h4>
<strong>Prueba tus recursos predeterminados</strong>
</h4>
<p>
Después de haber probado tus aplicaciones en todos los idiomas y las configuraciones regionales admitidos,
asegúrate de probarlas nuevamente en un <em>idioma y una configuración regional</em> no admitidos.
Esto te ayudará a asegurarte de que tus aplicaciones incluyen un conjunto completo de cadenas
y recursos predeterminados, de modo que todos los usuarios puedan utilizarlas, independientemente
de su idioma preferido.
</p>
<h4>
<strong>Realiza una revisión con hablantes nativos</strong>
</h4>
<p>
Durante o después de la prueba, se recomienda que hablantes nativos revisen
tus aplicaciones localizadas. Una forma de hacerlo es a través de pruebas beta con usuarios
regionales; Google Play puede ayudarte. <!-- </p>
<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/localizationchecklist/test"
data-sortOrder="-timestamp"
data-cardSizes="9x3,9x3,6x3,9x3,9x3,9x3"
data-maxResults="6"></div> -->
</p>
<div class="headerLine">
<h2 id="prepare-launch">
6. Prepárate para el lanzamiento internacional
</h2>
</div>
<p>
Traducir tus aplicaciones es una parte fundamental de la localización, pero para ayudar a tu
producto a atraer usuarios y ganar visibilidad, debes prepararte para el lanzamiento
en tus países objetivo y crear un lanzamiento y un plan de comercialización más amplios para
los usuarios internacionales.
</p>
<h4>
<strong>Localiza tu directorio en Google Play</strong>
</h4>
<div class="sidebox-wrapper" style="float:right;">
<div class="sidebox">
<h2>
Localiza tu directorio en Google Play
</h2>
<p>
El directorio de la tienda en la Play Store de Google es la primera impresión que los usuarios internacionales
tendrán de tu aplicación. Debes resaltar qué hace que tu aplicación sea excelente
para todos tus usuarios. Localiza tu directorio en la Consola para desarrolladores,
incluido lo siguiente:
</p>
<ul>
<li>Título y descripción de la aplicación
</li>
<li>Capturas de pantalla de la aplicación en teléfonos y tablets
</li>
<li>Gráficos y videos promocionales
</li>
</ul>
</div>
</div>
<p>
Si quieres que tus aplicaciones tengan éxito en mercados internacionales, es fundamental
que localices el directorio de tu tienda en Google Play. Puedes administrar tu
directorio localizado en la Consola para desarrolladores.
</p>
<p>
Mucho tiempo antes del lanzamiento, decide el título de tu aplicación, una descripción, texto promocional,
nombres y programas de comercialización, y otros textos e imágenes. Envía el texto y las
imágenes de tu directorio para traducción con mucho tiempo de anticipación, de modo que estén listos cuando comiencen las
pruebas beta. Cuando recibas el texto traducido, puedes agregarlo
a través de la Consola para desarrolladores.
</p>
<div class="sidebox-wrapper" style="float:right;">
<div class="sidebox">
<h2>
Traducción del directorio de la tienda en Google Play
</h2>
<p>
Puedes usar el servicio de traducción de aplicaciones de Google Play para traducir
el directorio de tu tienda. Prepara un archivo XML con la información del directorio de la tienda
y cárgalo como lo harías con el archivo strings.xml file (consulta <a href="#gp-trans">Compra traducciones profesionales</a>).
</p>
</div>
</div>
<p>
Y ya que hiciste el esfuerzo de crear una excelente aplicación localizada, ¡haz
que los usuarios la conozcan! Toma capturas de pantalla de tu IU en cada idioma, para teléfonos y
tablets de 7 y 10 pulgadas. Puedes cargar capturas de pantalla a la Consola para desarrolladores
para cada idioma que admitas. Serán un recurso muy valioso para los usuarios que examinen
los directorios de tus aplicaciones en otros idiomas.
</p>
<p>
También es fundamental crear versiones localizadas de tus gráficos y videos
promocionales. Por ejemplo, el gráfico central de tus aplicaciones podría incluir texto que
debe traducirse para lograr la máxima eficacia, o quizá quieras utilizar
enfoques visuales distintos para diferentes países. Puedes
crear versiones diferentes de tus gráficos promocionales para cada idioma y
cargarlos a la Consola para desarrolladores. Si ofreces un video promocional, puedes
crear versiones localizadas y luego agregar un vínculo al video localizado
correspondiente para cada idioma que admitas.
</p>
<h4>
<strong>Planifica un lanzamiento beta en países clave</strong>
</h4>
<div class="sidebox-wrapper" style="float:right;">
<div class="sidebox">
<h2>
Prueba beta sencilla
</h2>
<p>
Google Play ahora te permite configurar grupos de evaluadores alfa y beta
ubicados en cualquier lugar del mundo. La próxima vez que inicies sesión en la Consola
para desarrolladores, échale un vistazo a esta poderosa función.
</p>
</div>
</div>
<p>
Antes de lanzar tus aplicaciones, te recomendamos que obtengas la opinión real
de los usuarios; más aún cuando estés lanzando una aplicación en un nuevo
idioma, país o región. En esos casos, es altamente recomendable que
distribuyas una versión previa al lanzamiento de tus aplicaciones a los usuarios de tus mercados
clave, y les proporciones medios sencillos para que puedan brindarte su opinión e informar
errores.
</p>
<p>
Google Play puede ayudarte a configurar un programa beta para tus aplicaciones. Después de iniciar sesión
en la Consola para desarrolladores y cargar tu APK, puedes configurar grupos de
usuarios para que realicen pruebas alfa y beta en tu aplicación. Puedes comenzar con un grupo pequeño
de evaluadores alfa y luego avanzar a un grupo más grande de evaluadores beta.
</p>
<p>
Una vez que agregues los usuarios, estos podrán acceder al directorio de la tienda de tu aplicación e instalar la
aplicación.<strong> Los usuarios que utilicen las versiones alfa o beta no podrán escribir reseñas ni calificar
la aplicación</strong>, por lo que <strong>no corre riesgo tu calificación</strong> en
Google Play; no obstante, esto significa que deberás establecer un mecanismo para que los
evaluadores te proporcionen sus comentarios: considera la posibilidad de crear una página de <a href="http://www.google.com/+/business/">Google+</a> o <a href="https://groups.google.com/forum/#!overview">Google Groups</a>.
</p>
<p>
Los comentarios que recibas te ayudarán a ajustar tu IU, las traducciones y el
directorio de la tienda para garantizar una excelente experiencia para los usuarios.
</p>
<h4>
<strong>Planifica la comercialización internacional</strong>
</h4>
<p>
Para adquirir la máxima visibilidad en los diferentes países, considera la posibilidad de realizar una
campaña publicitaria o de comercialización internacional. El alcance de la campaña variará en función de la
insignia que puedas admitir, pero en general resulta rentable y productivo
realizar campañas de comercialización regionales o específicas para un país durante el lanzamiento y después.
</p>
<h4>
<strong>Crea insignias localizadas de Google Play</strong>
</h4>
<p>
Si estás preparando la comercialización internacional, asegúrate de incluir una <a href="{@docRoot}distribute/tools/promote/badges.html">insignia localizada de
Google Play</a> para indicarles a los usuarios que estás en Google Play. Puedes usar el generador de
de insignias para crear rápidamente insignias localizadas que puedes usar en sitios web o
en los materiales de comercialización. También se encuentran disponibles recursos en alta resolución.
</p>
<h4>
<strong>Crea material gráfico para los dispositivos localizados</strong>
</h4>
<p>
Si exhibes fotos de tus aplicaciones ejecutándose en dispositivos Android,
asegúrate de que esas fotos se vean magníficas y reflejen los dispositivos Android más modernos.
Para ayudarte a crear material de comercialización de alta calidad, usa el
<a href="{@docRoot}distribute/tools/promote/device-art.html">Generador de material gráfico
para dispositivos</a> con la función arrastrar y colocar para enmarcar rápidamente tu captura de pantalla en un dispositivo Nexus.
</p>
<h4>
<strong>Consulta las sugerencias para la optimización</strong>
</h4>
<p>
Mientras te preparas para el lanzamiento, asegúrate de iniciar sesión en la Consola para desarrolladores y
consultar las sugerencias para la optimización de tus aplicaciones. Las Sugerencias para la optimización te informan
cuando faltan partes del directorio localizado de tu tienda y te proporcionan
otros recordatorios útiles para un lanzamiento localizado exitoso.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/preplaunch"
data-sortorder="-timestamp" data-cardsizes="9x3,9x3,6x3,9x3,9x3,9x3"
data-maxresults="6">
</div>
<div class="headerLine">
<h2 id="support-users">
7. Brinda soporte a los usuarios internacionales después del lanzamiento
</h2>
</div>
<p>
Después de lanzar tus aplicaciones a nivel internacional, debes estar preparado para brindar
soporte a los usuarios en una variedad de idiomas y zonas horarias. El alcance del
soporte que brindes a los usuarios internacionales depende de tu presupuesto, pero como mínimo,
debes controlar cuidadosamente tus calificaciones, reseñas y estadísticas de descarga después del
lanzamiento.
</p>
<p>
Aquí te proporcionamos alguna sugerencias:
</p>
<ul>
<li>
<p>
Usa las estadísticas de la aplicación en la Consola para desarrolladores para comparar tus descargas,
instalaciones, desinstalaciones y calificaciones entre diferentes idiomas
y países. Si tus descargas o calificaciones no se mantienen en
idiomas o países específicos, considera algunas opciones para mejorar tu
producto o cambiar el enfoque de comercialización.
</p>
</li>
<li>
<p>
Lee las reseñas con frecuencia. Google Play traduce todas las reseñas de los usuarios por
ti, de modo que puedas estar informado acerca de cómo se sienten los usuarios internacionales en relación con
tus aplicaciones, qué funciones les gustan y qué problemas los afectan. Al
leer las reseñas, puedes detectar problemas técnicos que podrían afectar a los usuarios en
un país determinado, luego solucionarlos y actualizar tus aplicaciones.
</p>
</li>
<li>
<p>
Responde las reseñas, si fuera posible. Te recomendamos que interactúes
con los usuarios internacionales en sus idiomas o en un idioma común, si fuera posible.
Si no lo es, puedes intentar utilizar herramientas de traducción, aunque es posible que no puedas
prever los resultados. Si tu aplicación se vuelve muy popular en un idioma, considera
la posibilidad de obtener ayuda por parte de hablantes nativos para brindar soporte.
</p>
</li>
<li>
<p>
Asegúrate de que en tu sitio web haya un vínculo a cualquier recurso de soporte que tengas.
Puedes configurar grupos de usuarios para un idioma específico, comunidades de Google+
u otros foros de soporte.
</p>
</li>
</ul>
<p>
Al seguir estas prácticas para la localización de tus aplicaciones, la promoción
y comercialización a usuarios internacionales y la provisión de soporte continuo, puedes
atraer nuevos usuarios a tus aplicaciones y mantener su fidelidad.
</p>
<p>
Asegúrate de leer la <a href="{@docRoot}distribute/tools/launch-checklist.html">Lista de comprobación para el lanzamiento</a> para
obtener más información acerca de cómo planificar, crear y lanzar tu aplicación en Google Play.
</p>
<h3 class="rel-resources clearfloat">Recursos relacionados</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/localizationchecklist/supportlaunch"
data-sortOrder="-timestamp"
data-cardSizes="9x3,9x3,6x3,9x3,9x3,9x3"
data-maxResults="6"></div>

View File

@@ -1,439 +0,0 @@
page.title=Filtros en Google Play
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Vista rápida</h2>
<ul>
<li>Google Play utiliza filtros para controlar qué dispositivos Android pueden descargar
tu aplicación de la tienda.</li>
<li>El filtrado garantiza que tus aplicaciones estén disponibles solo para los usuarios cuyos dispositivos cumplen los requisitos de compatibilidad de la aplicación.
<li>El filtrado se determina en función de los requisitos de configuración que declares en el archivo
de manifiesto de tu aplicación, y también en otros factores.</li>
</ul>
<h2>En este documento:</h2>
<ol>
<li><a href="#how-filters-work">Cómo funcionan los filtros en Google Play</a></li>
<li><a href="#manifest-filters">Filtrado en función de los elementos del manifiesto</a>
</li>
<li><a href="#other-filters">Otros filtros</a></li>
<li><a href="#MultiApks">Publicación de múltiples APK con diferentes filtros</a></li>
</ol>
<h2>Consulta también</h2>
<ol>
<li><a href="{@docRoot}guide/practices/compatibility.html">Compatibilidad con Android</a></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></li>
<li><code><a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</code></a></li>
</ol>
</div>
</div>
<p>Cuando un usuario busca o examina aplicaciones para descargar en Google Play, los
resultados se filtran en función de las aplicaciones compatibles con el dispositivo.
Por ejemplo, si una aplicación requiere una cámara, Google Play no mostrará la aplicación a los dispositivos
que no tengan cámara. Este <em>filtrado</em> ayuda a los desarrolladores a administrar la
distribución de sus aplicaciones y también ayuda a garantizar la mejor experiencia posible para los
usuarios.</p>
<p>El filtrado en Google Play se basa en diversos tipos de metadatos de las aplicaciones y en los
ajustes de configuración, incluidos los enunciados del manifiesto, las bibliotecas
requeridas, las dependencias de arquitectura y los controles de distribución configurados en la Consola para desarrolladores
de Google Play, como el perfilamiento geográfico, la fijación de precios, etc.</p>
<p>El filtrado en Google Play se basa en los enunciados del manifiesto y en otros
aspectos del marco de Android, pero los comportamientos de filtrado reales son diferentes
de los del marco y no están condicionados a niveles de API específicos. Este documento
especifica las reglas actuales de filtrado que utiliza Google Play.</p>
<h2 id="how-filters-work">Cómo funcionan los filtros en Google Play</h2>
<p>Google Play utiliza las restricciones de filtrado que se describen a continuación para determinar
si se exhibirá tu aplicación a los usuarios que examinen o busquen
aplicaciones en la Play Store de Google.</p>
<p>Para determinar si se exhibirá o no tu aplicación, Google Play comprueba los requisitos de
hardware y software del dispositivo, como también su operador, ubicación y otras
características. Luego los compara con las restricciones y
dependencias que se indican en el archivo de manifiesto de la aplicación y en los detalles de
publicación. </p>
<p>Si la aplicación es compatible con el dispositivo, de acuerdo con las reglas de
filtrado, Google Play le muestra la aplicación al usuario. De lo contrario, Google Play
oculta tu aplicación en los resultados de búsqueda y la exploración de categorías aunque un usuario
solicite específicamente la aplicación al hacer clic en un vínculo profundo que apunte directamente a la
ID de la aplicación en Google Play.</p>
<p>Puedes usar cualquier combinación de los filtros disponibles para tu aplicación. Por ejemplo, puedes establecer un requisito
<code>minSdkVersion</code> de <code>"4"</code> y configurar <code>smallScreens="false"</code>
en la aplicación; luego, al cargar la aplicación a Google Play, podrías apuntar a países (operadores) europeos
únicamente. De este modo, los filtros de Google Play evitarán que la aplicación esté disponible en un dispositivo
que no coincida con estos tres requisitos. </p>
<p>Todas las restricciones de filtrado están asociadas con una versión de la aplicación y pueden
diferir entre versiones. Por ejemplo, si un usuario instaló tu aplicación y publicas una
actualización que permite que la aplicación esté visible para el usuario, el usuario no verá que hay una actualización
disponible.</p>
<h4>Filtrado en el sitio web de Google Play</h4>
<p>Cuando los usuarios examinan el <a href="http://play.google.com/apps">sitio web de Google
Play</a>, pueden ver todas las aplicaciones publicadas. No obstante, el sitio web de Google Play
compara los requisitos de la aplicación para cada uno de los dispositivos registrados del usuario
a fin de determinar la compatibilidad, y solo les permite instalar la aplicación si
es compatible con su dispositivo.</p>
<h2 id="manifest-filters">Filtrado en función del manifiesto de la aplicación</h2>
<p>La mayoría de los filtros son activados por elementos del archivo de manifiesto de una
aplicación, <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
(aunque no todo lo que se encuentra en el archivo de manifiesto puede desencadenar el filtrado).
La tabla 1 contiene los elementos del manifiesto que debes usar para desencadenar el
filtrado y explica cómo funciona el filtrado para cada elemento.</p>
<p id="table1" class="table-caption"><strong>Tabla 1.</strong> Elementos del manifiesto que
desencadenan el filtrado en Google Play.</p>
<table>
<tr>
<th>Elemento del manifiesto</th>
<th>Nombre del filtro</th>
<th>Cómo funciona</th>
</tr>
<tr>
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>
<!-- ##api level 4## --></td>
<td valign="top">Tamaño de pantalla</td>
<td valign="top">
<p>Una aplicación indica el tamaño de pantalla que puede admitir mediante
la configuración de atributos del elemento <code>&lt;supports-screens&gt;</code>. Cuando
se publica la aplicación, Google Play usa esos atributos para determinar si puede
mostrar la aplicación a los usuarios en función de los tamaños de pantalla de sus
dispositivos. </p>
<p>Como regla general, Google Play asume que la plataforma del dispositivo puede adaptar
diseños más pequeños a pantallas más grandes, pero no puede adaptar diseños grandes a pantallas
más pequeñas. Por lo tanto, si una aplicación declara compatibilidad con el tamaño de pantalla "normal" únicamente,
Google Play exhibe la aplicación para dispositivos con pantallas normales y grandes,
pero filtra la aplicación de modo que no esté disponible para dispositivos con
pantalla pequeña.</p>
<p>Si una aplicación no declara atributos para
<code>&lt;supports-screens&gt;</code>, Google Play utiliza los valores predeterminados para esos
atributos, que varían según el nivel de API. Específicamente: </p>
<ul>
<li><p>Para las aplicaciones que tienen <code><a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
minSdkVersion</a></code> o <code><a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
targetSdkVersion</a></code> configurados en 3 o menos, el elemento <code>&lt;supports-screens&gt;</code> se considera
no definido y no habrá atributos disponibles. En ese caso, Google Play supone que
la aplicación se diseñó para pantallas de tamaño normal y exhibe la aplicación a
dispositivos con pantallas de tamaño normal o más grande. </p>
<li>Cuando <code><a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
minSdkVersion</a></code> o <code><a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
targetSdkVersion</a></code> están configurados en 4 o más, el valor predeterminado para todos los atributos es
<code>"true"</code>. De esta manera, se considera que la aplicación es compatible, de forma predeterminada, con todos los tamaños
de pantalla.</li>
</ul>
<p><strong>Ejemplo 1</strong><br />
El manifiesto establece <code>&lt;uses-sdk android:minSdkVersion="3"&gt;</code>
y no incluye un elemento <code>&lt;supports-screens&gt;</code>.
<strong>Resultado</strong>: Google Play no le mostrará la aplicación a un usuario que tenga
un dispositivo con pantalla pequeña, pero se la mostrará a los usuarios con dispositivos con pantallas de tamaño normal y grande,
a menos que se apliquen otros filtros. </p>
<p><strong>Ejemplo 2<br />
</strong>El manifiesto establece <code>&lt;uses-sdk android:minSdkVersion="3"
android:targetSdkVersion="4"&gt;</code> y no incluye un
elemento <code>&lt;supports-screens&gt;</code>.
<strong>Resultado</strong>: Google Play mostrará la aplicación a los usuarios de todo tipo de dispositivos,
a menos que se apliquen otros filtros. </p>
<p><strong>Ejemplo 3<br />
</strong>El manifiesto establece <code>&lt;uses-sdk android:minSdkVersion="4"&gt;</code>
y no incluye un elemento <code>&lt;supports-screens&gt;</code>.
<strong>Resultado</strong>: Google Play mostrará la aplicación a todos los usuarios,
a menos que se apliquen otros filtros. </p>
<p>Para obtener más información acerca de cómo declarar la compatibilidad con tamaños de pantalla en tu
aplicación, consulta <code><a
href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>
y <a href="{@docRoot}guide/practices/screens_support.html">Admisión de múltiples
pantallas</a>.</p>
</td>
</tr>
<tr>
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>
<!-- ##api level 3## --></td>
<td valign="top">Configuración del
dispositivo: <br />
teclado, navegación, pantalla táctil</td>
<td valign="top"><p>Una aplicación puede
requerir ciertas características de hardware, y Google Play mostrará la aplicación únicamente a los dispositivos que tengan el hardware requerido.</p>
<p><strong>Ejemplo 1<br />
</strong>El manifiesto incluye <code>&lt;uses-configuration android:reqFiveWayNav=&quot;true&quot; /&gt;</code>, y un usuario está buscando aplicaciones en un dispositivo que no cuenta con un control de navegación de cinco vías. <strong>Resultado</strong>: Google Play no le mostrará la aplicación al usuario. </p>
<p><strong>Ejemplo 2<br />
</strong>El manifiesto no incluye un elemento <code>&lt;uses-configuration&gt;</code>. <strong>Resultado</strong>: Google Play mostrará la aplicación a todos los usuarios, a menos que se apliquen otros filtros.</p>
<p>Para obtener información detallada, consulta <a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><code>&lt;uses-configuration&gt;</code></a>.</p></td>
</tr>
<tr>
<td rowspan="2" valign="top" style="white-space:nowrap;"><code><a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a>
</code>
<!-- ##api level 4## --></td>
<td valign="top">Funciones del dispositivo<br />
(<code>name</code>)</td>
<td valign="top"><p>Una aplicación puede requerir que el dispositivo tenga
ciertas funciones. Esta funcionalidad se introdujo en Android 2.0 (API
de nivel 5).</p>
<p><strong>Ejemplo 1<br />
</strong>El manifiesto incluye <code>&lt;uses-feature
android:name=&quot;android.hardware.sensor.light&quot; /&gt;</code>, y un usuario
está buscando aplicaciones en un dispositivo que no tiene sensor de luz.
<strong>Resultado</strong>: Google Play no le mostrará la aplicación al usuario. </p>
<p><strong>Ejemplo 2<br />
</strong>El manifiesto no incluye un elemento <code>&lt;uses-feature&gt;</code>
. <strong>Resultado</strong>: Google Play mostrará la aplicación a todos los usuarios,
a menos que se apliquen otros filtros.</p>
<p>Para obtener información completa, consulta <code><a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a>
</code>.</p>
<p><em>Filtrado basado en funciones implícitas:</em> En algunos casos, Google
Play interpreta los permisos requeridos a través de
elementos <code>&lt;uses-permission&gt;</code> como requisitos de funciones equivalentes
a los declarados en los elementos <code>&lt;uses-feature&gt;</code>. Consulta <a href="#uses-permission-filtering"><code>&lt;uses-permission&gt;</code></a>
a continuación.</p>
</td>
</tr>
<tr>
<td valign="top">Versión de
OpenGL-ES<br />
(<code>openGlEsVersion</code>)</td>
<td valign="top"><p>Una aplicación puede requerir que el dispositivo admita una
versión de OpenGL-ES específica mediante el atributo <code>&lt;uses-feature
android:openGlEsVersion=&quot;int&quot;&gt;</code>.</p>
<p><strong>Ejemplo 1<br />
</strong>Una aplicación
exige múltiples versiones de OpenGL-ES al especificar <code>openGlEsVersion</code> varias veces en el
manifiesto. <strong>Resultado</strong>: Google Play asume que la aplicación requiere las últimas actualizaciones de las versiones indicadas.</p>
<p><strong>Ejemplo 2<br />
</strong>Una aplicación
exige la versión 1.1 de OpenGL-ES y un usuario busca aplicaciones en un dispositivo que admite la versión 2.0 de OpenGL-ES. <strong>Resultado</strong>: Google Play le mostrará la aplicación al usuario, a menos que se apliquen otros filtros. Si un
dispositivo informa que admite la versión <em>X</em> de OpenGL-ES, Google Play asume que
también admite las versiones anteriores a <em>X</em>.
</p>
<p><strong>Ejemplo 3<br />
</strong>Un usuario está buscando aplicaciones en un dispositivo que no
contiene información acerca de la versión de OpenGL-ES (por ejemplo, un dispositivo que ejecuta Android 1.5 o anterior). <strong>Resultado</strong>: Google Play asume que el dispositivo
solo admite OpenGL-ES 1.0. Google Play le mostrará al usuario únicamente aplicaciones que no especifiquen <code>openGlEsVersion</code> o aplicaciones que no especifiquen una versión de OpenGL-ES posterior a 1.0. </p>
<p><strong>Ejemplo 4<br />
</strong>El manifiesto no especifica <code>openGlEsVersion</code>. <strong>Resultado</strong>: Google Play mostrará la aplicación a todos los usuarios, a menos que se apliquen otros filtros. </p>
<p>Para obtener información detallada, consulta <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>.</p></td>
</tr>
<tr>
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code></td>
<td valign="top">Bibliotecas de software</td>
<td valign="top"><p>Una aplicación puede requerir que el dispositivo
tenga bibliotecas compartidas específicas. </p>
<p><strong>Ejemplo 1<br />
</strong>Una aplicación exige la biblioteca <code>com.google.android.maps</code>, y un usuario está buscando aplicaciones en un dispositivo que no tiene la biblioteca <code>com.google.android.maps</code>. <strong>Resultado</strong>: Google Play no le mostrará la aplicación al usuario. </p>
<p><strong>Ejemplo 2</strong><br />
El manifiesto no incluye un elemento <code>&lt;uses-library&gt;</code>. <strong>Resultado</strong>: Google Play mostrará la aplicación a todos los usuarios, a menos que se apliquen otros filtros.</p>
<p>Para obtener información detallada, consulta <a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>.</p></td>
</tr>
<tr id="uses-permission-filtering">
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></td>
<td valign="top">&nbsp;</td>
<td valign="top">De forma estricta, Google Play no filtra en función de los elementos
<code>&lt;uses-permission&gt;</code>. No obstante, sí lee los
elementos para determinar si la aplicación tiene requisitos de características de hardware
que podrían no haberse declarado correctamente en los elementos <code>&lt;uses-feature&gt;</code>
. Por ejemplo, si una aplicación requiere el permiso <code>CAMERA</code>
pero no declara un elemento <code>&lt;uses-feature&gt;</code> para
<code>android.hardware.camera</code>, Google Play considera que la
aplicación requiere una cámara y no se le mostrará a los usuarios cuyos dispositivos no
tengan cámara.</p>
<p>En general, si una aplicación requiere elementos relacionados con hardware,
Google Play asume que la aplicación requiere las características de hardware
subyacentes, aunque no se correspondan con los enunciados de
<code>&lt;uses-feature&gt;</code>. Luego, Google Play establece el
filtrado en función de las funciones denotadas por los enunciados de <code>&lt;uses-feature&gt;</code>
.</p>
<p>Para acceder a una lista de los permisos que denotan características de hardware, consulta
la documentación para el elemento <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features"><code>&lt;uses-feature&gt;</code></a>
.</p>
</td>
</tr>
<tr>
<td rowspan="2" valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code></td>
<td valign="top">Versión mínima del Framework (<code>minSdkVersion</code>)</td>
<td valign="top"><p>Una aplicación puede requerir un nivel de API mínimo. </p>
<p><strong>Ejemplo 1</strong><br />
El manifiesto incluye <code>&lt;uses-sdk
android:minSdkVersion=&quot;3&quot;&gt;</code>, y la aplicación utiliza API que pertenecen al nivel de API 3. Un usuario busca aplicaciones en un dispositivo con nivel de API 2. <strong>Resultado</strong>: Google Play no le mostrará la aplicación al usuario. </p>
<p><strong>Ejemplo 2</strong><br />
El manifiesto no incluye <code>minSdkVersion</code>, y la aplicación utiliza API que pertenecen al nivel de API 3. Un usuario busca aplicaciones en un dispositivo con nivel de API 2. <strong>Resultado</strong>: Google Play asume que <code>minSdkVersion</code> es "1" y que la aplicación es compatible con todas las versiones de Android. Google Play le muestra la aplicación al usuario y le permite descargarla. La aplicación colapsa durante la ejecución. </p>
<p>Para evitar esta segunda situación, te recomendamos que siempre declares un <code>minSdkVersion</code>. Para obtener información detallada, consulta <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min"><code>android:minSdkVersion</code></a>.</p></td>
</tr>
<tr>
<td valign="top">Versión máxima del Framework (<code>maxSdkVersion</code>)</td>
<td valign="top"><p><em>Obsoleto.</em> Android
2.1 y posteriores no comprueban ni aplican el atributo <code>maxSdkVersion</code>, y
el SDK no se compilará si se establece <code>maxSdkVersion</code> en el manifiesto de la aplicación. Para los dispositivos
ya compilados con <code>maxSdkVersion</code>, Google Play lo respetará y lo utilizará para el
filtrado.</p>
<p> <em>No</em> se recomienda declarar <code>maxSdkVersion</code>. Para obtener información detallada, consulta <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max"><code>android:maxSdkVersion</code></a>.</p></td>
</tr>
</table>
<h3 id="advanced-filters">Filtros avanzados del manifiesto</h3>
<p>Además de los elementos del manifiesto que se indican en la <a href="#table1">tabla 1</a>, Google Play también puede
filtrar aplicaciones en función de los elementos avanzados del manifiesto que se indican en la tabla 2.</p>
<p>Estos elementos del manifiesto y el filtrado que desencadenan se utilizan únicamente en casos
excepcionales. Se diseñaron para ciertos tipos de juegos de alto rendimiento y aplicaciones similares que
requieren controles estrictos de distribución de la aplicación. <strong>La mayoría de las aplicaciones no deberían
utilizar estos filtros</strong>.</p>
<p id="table2" class="table-caption"><strong>Tabla 2.</strong> Elementos avanzados del manifiesto para
filtrado en Google Play.</p>
<table>
<tr><th>Elemento del manifiesto</th><th>Resumen:</th></tr>
<tr>
<td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
<compatible-screens>}</a></nobr></td>
<td>
<p>Google Play filtra la aplicación si el tamaño de pantalla del dispositivo no coincide con
ninguna de las configuraciones de pantalla (declaradas por un elemento {@code <screen>}) en el elemento {@code
<compatible-screens>}.</p>
<p class="caution"><strong>Advertencia:</strong> Normalmente, <strong>no deberías usar este elemento
del manifiesto</strong>. El uso de este elemento puede reducir
notablemente la base de usuarios potenciales para tu aplicación, al excluir todas las combinaciones de tamaño de pantalla
y densidad que no indicaste. En su lugar, debes usar el elemento del manifiesto <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
<supports-screens>}</a> (descrito anteriormente en la <a href="#table1">tabla
1</a>) para habilitar el modo de compatibilidad de pantalla para las configuraciones de pantalla que no abarcaste
con recursos adicionales.</p>
</td>
</tr>
<tr>
<td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
<supports-gl-texture>}</a></nobr></td>
<td>
<p>Google Play filtrará la aplicación a menos que uno o más de los formatos de compresión
de texturas GL compatibles con la aplicación también sean compatibles con el dispositivo. </p>
</td>
</tr>
</table>
<h2 id="other-filters">Otros filtros</h2>
<p>Google Play utiliza otras características de la aplicación para determinar si mostrará u ocultará una aplicación a un usuario específico o un dispositivo determinado, tal como se describe en la tabla a continuación. </p>
<p id="table3" class="table-caption"><strong>Tabla 3.</strong> Características de la aplicación y la
publicación que afectan el filtrado en Google Play.</p>
<table> <tr>
<th>Nombre del filtro</th> <th>Cómo funciona</th> </tr>
<tr>
<td valign="top">Estado de la publicación</td> <td valign="top"><p>Únicamente las aplicaciones publicadas aparecerán en las
búsquedas y exploraciones en Google Play.</p> <p>Incluso cuando una aplicación no esté publicada
, se la podrá instalar si los usuarios pueden visualizarla en el área de Descargas entre las aplicaciones que
compraron, instalaron o desinstalaron recientemente.</p> <p>Si se suspende una aplicación,
los usuarios no podrán volver a instalarla ni actualizarla, aunque aparezca en sus Descargas.</p> </td></tr>
<tr>
<td valign="top">Estado
pago</td> <td valign="top"><p>No todos los usuarios pueden ver aplicaciones pagas. Para mostrar aplicaciones pagas, un dispositivo
debe tener una tarjeta SIM y ejecutar Android 1.1 o posterior, y debe encontrarse en un
país (según lo determine el operador SIM) en el que las aplicaciones pagas estén disponibles.</p></td>
</tr> <tr>
<td valign="top">Perfilamiento de país</td> <td valign="top"> <p>Cuando cargas tu aplicación a
Google Play, puedes seleccionar los países en los que quieres distribuir la aplicación; para ello, deberás ingresar
en <strong>Fijación de precios y distribución</strong>. Luego, la aplicación
estará disponible para los usuarios únicamente de los países que selecciones.</p>
</td> </tr> <tr>
<td valign="top" style="white-space:nowrap;">Arquitectura de CPU (ABI)</td>
<td valign="top"><p>Las aplicaciones que incluyen bibliotecas
nativas que apuntan a una arquitectura de CPU específica (por ejemplo: ARM EABI v7 o x86) solo
pueden visualizarse en dispositivos que admiten esa arquitectura. Para obtener información detallada acerca del NDK y del uso de
bibliotecas nativas, consulta <a href="{@docRoot}tools/sdk/ndk/index.html#overview">¿Qué es el
NDK de Android?</a></p> </tr> <tr>
<td valign="top">Aplicaciones protegidas contra copia</td> <td valign="top"><p class="caution">Google
Play ya no admite la función Protección contra copia en la Consola para desarrolladores, y ya no
filtra aplicaciones de acuerdo con esa función. Para proteger tu aplicación, utiliza en su lugar <a href="{@docRoot}google/play/licensing/index.html">
Licencias de aplicaciones</a>. Consulta <a href="{@docRoot}google/play/licensing/overview.html#CopyProtection">
Reemplazo de protección contra copias</a> para obtener más información.</p></td> </tr> </table>
<h2 id="MultiApks">Publicación de múltiples APK con diferentes filtros</h2>
<p>Algunos filtros específicos de Google Play te permiten publicar múltiples APK para la misma
aplicación a fin de proporcionar un APK distinto para diferentes configuraciones de dispositivos. Por ejemplo, si estás
creando un videojuego que utiliza recursos gráficos de alta fidelidad, te recomendamos que crees
dos APK y que cada uno admita diferentes formatos de compresión de texturas. De este modo, puedes reducir el
tamaño del archivo del APK al incluir solo las texturas necesarias para la configuración de cada
dispositivo. Según la compatibilidad de cada dispositivo con tus formatos de compresión de texturas, Google
Play le proporcionará el APK que hayas declarado como compatible con ese dispositivo.</p>
<p>Actualmente, Google Play te permite publicar múltiples APK para la misma aplicación únicamente
cuando cada APK proporcione diferentes filtros en función de las siguientes configuraciones:</p>
<ul>
<li>Formatos de compresión de texturas OpenGL
<p>Mediante el uso del elemento <a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
<supports-gl-texture>}</a>.</p>
</li>
<li>Tamaño de pantalla (y, opcionalmente, densidad de la pantalla)
<p>Mediante el uso del elemento <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
<supports-screens>}</a> o <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
<compatible-screens>}</a>.</p>
</li>
<li>Nivel de API
<p>Mediante el uso del elemento <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code
<uses-sdk>}</a>.</p>
</li>
<li>Arquitectura de CPU (ABI)
<p>Mediante la inclusión de bibliotecas nativas creadas con el <a href="{@docRoot}tools/sdk/ndk/index.html">NDK de
Android</a> que apunta a una arquitectura de CPU específica (por ejemplo, ARM EABI v7 o x86).</p>
</li>
</ul>
<p>Todos los demás filtros continúan funcionado de la forma habitual, pero estos cuatro son los únicos filtros que pueden
distinguir un APK de otro dentro del mismo directorio de la aplicación en Google Play. Por ejemplo,
<em>no puedes</em> publicar múltiples APK para la misma aplicación si los APK solo difieren en función de
si el dispositivo tiene cámara.</p>
<p class="caution"><strong>Advertencia:</strong> La publicación de múltiples APK para la misma aplicación se
considera una función avanzada y <strong>la mayoría de las aplicaciones deben publicar un solo
APK que admita una amplia variedad de configuraciones de dispositivos</strong>. La publicación de múltiples APK
requiere que sigas reglas específicas dentro de tus filtros y que prestes especial atención a los
códigos de versión para cada APK a fin de garantizar las vías de actualización adecuadas para cada configuración.</p>
<p>Si necesitas más información acerca de cómo publicar múltiples APK en Google Play, lee <a href="{@docRoot}google/play/publishing/multiple-apks.html">Compatibilidad con múltiples APK</a>.</p>

View File

@@ -1,197 +0,0 @@
page.title=Funciones del lenguaje Java 8
page.keywords="android N", "Java 8", "Jack"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<ol>
<li>
<a href="#supported-features">Funciones y API admitidas del lenguaje Java 8</a>
</li>
<li>
<a href="#configuration">Habilitar funciones de Java 8 y del conjunto de herramientas Jack</a>
</li>
</ol>
</div>
</div>
<p>En Android N se ofrece compatibilidad con funciones
del idioma Java 8 que puedes usar al desarrollar aplicaciones orientadas a Android N.
En esta página se describen las funciones de idioma compatibles con la Android N
Preview, también la manera adecuada de configurar tu proyecto para usarlas y muchos problemas
conocidos que puedes experimentar.
</p>
<p>Para comenzar a usar estas funciones, debes descargar y configurar Android
Studio 2.1 y el Android N Preview SDK, en el que se incluyen el conjunto de herramientas
Jack y el complemento de Android para Gradle. Si aún no
instalaste el Android N Preview SDK, consulta <a href="{@docRoot}preview/setup-sdk.html">Configuración para desarrollar con Android N</a>.</p>
<p class="note">
<strong>Nota:</strong> No es obligatorio usar las nuevas funciones del lenguaje Java 8
para desarrollar aplicaciones orientadas a la plataforma de Android N. Si
no deseas escribir código con funciones del lenguaje Java 8, puedes mantener los
valores de compatibilidad de origen y destino de tu proyecto en Java 7, pero debes
usar JDK 8 para crear la compilación en función de la plataforma de Android N.
</p>
<h2 id="supported-features">
Funciones y API admitidas del lenguaje Java 8
</h2>
<p>
Actualmente, Android no admite todas las funciones del lenguaje Java 8. Sin embargo, las
siguientes características ahora se encuentran disponibles para el desarrollo de aplicaciones orientadas a la
Android N Preview:
</p>
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">métodos de interfaz
predeterminados y estáticos;</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">
expresiones Lambda</a> (también disponible en API nivel 23 e inferiores);
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html">anotaciones
reiterables;</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html">
referencias de métodos</a> (también disponible en API nivel 23 e inferiores).
</li>
</ul>
<p class="note">
<strong>Nota:</strong> Para probar expresiones Lambda y métodos de referencia en
versiones anteriores de Android, accede al archivo {@code build.gradle}
y fija {@code compileSdkVersion} y {@code targetSdkVersion} en 23 o
un valor inferior. Tendrás que <a href="#configuration">habilitar la cadena de herramientas
Jack</a> para usar estas funciones de Java 8.
</p>
<p>
A su vez, las siguientes API de funciones del lenguaje Java 8 ahora se encuentran disponibles:
</p>
<ul>
<li>Las API Reflection y las relacionadas con el lenguaje:
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html">
{@code java.lang.FunctionalInterface}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Repeatable.html">
{@code java.lang.annotation.Repeatable}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--">
{@code java.lang.reflect.Method.isDefault()}</a>
</li>
<li>También las API Reflection asociadas con anotaciones reiterables, como
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotationsByType-java.lang.Class-">
{@code AnnotatedElement.getAnnotationsByType(Class)}</a>
</li>
</ul>
</li>
<li>API de utilidades:
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html">
{@code java.util.function}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html">
{@code java.util.stream}</a>
</li>
</ul>
</li>
</ul>
<h2 id="configuration">
Habilitar funciones de Java 8 y del conjunto de herramientas Jack
</h2>
<p>
Para usar las nuevas funciones del lenguaje Java 8, también debes usar el
nueva <a class="external-link" href="https://source.android.com/source/jack.html">conjunto de herramientas Jack</a>. Este nueva
conjunto de herramientas de Android permite compilar fuentes del lenguaje Java en código de bytes dex legible a través de
Android, también tiene su propio formato de biblioteca {@code .jack} y proporciona la mayoría de las funciones de conjunto de
herramientas como parte de una única herramienta: reempaquetado, reducción, alteración y
MultiDex.
</p>
<p>A continuación, se muestra una comparación de los conjuntos de herramientas empleados para generar archivos DEX de Android:</p>
<ul>
<li>Conjunto de herramientas javac heredada:<br>
<b>javac</b> ({@code .java} --&gt; {@code .class}) --&gt; <b>dx</b> ({@code
.class} --&gt; {@code .dex})
</li>
<li>Nueva cadena de herramientas Jack:<br>
<b>Jack</b> ({@code .java} --&gt; {@code .jack} --&gt; {@code .dex})
</li>
</ul>
<h3>
Configuración de Gradle
</h3>
<p>
Si deseas habilitar las funciones del lenguaje Java 8 y de Jack para tu proyecto, escribe lo
siguiente en tu archivo de nivel de módulo {@code build.gradle}:
</p>
<pre>
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
</pre>
<h3 id="known-issues">
Problemas conocidos
</h3>
<p>
Actualmente, <a href="{@docRoot}tools/building/building-studio.html#instant-run">Instant
Run</a> no funciona con Jack y permanecerá deshabilitado cuando se use
el nuevo conjunto de herramientas.
</p>
<p>Debido a que Jack no genera archivos de clase intermedia al compilar una
aplicación, las herramientas que dependen de estos archivos actualmente no funcionan con Jack. Algunos
ejemplos de estas herramientas:</p>
<ul>
<li>Detectores Lint que funcionan en archivos de clases;
</li>
<li>Herramientas y bibliotecas que requieren los archivos de clase de la aplicación (como
pruebas de instrumentación con JaCoCo).
</li>
</ul>
<p>Si experimentas otros problemas al usar Jack, <a href="http://tools.android.com/filing-bugs">envía un error</a>.</p>

View File

@@ -1,589 +0,0 @@
page.title=Compatibilidad con ventanas múltiples
page.metaDescription=Nueva compatibilidad en Android N para mostrar más de una aplicación a la vez.
page.keywords="multi-window", "android N", "split screen", "free-form"
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#overview">Información general</a></li>
<li><a href="#lifecycle">Ciclo de vida en modo de ventanas múltiples</a></li>
<li><a href="#configuring">Configuración de tu aplicación para el modo de
ventanas múltiples</a></li>
<li><a href="#running">Ejecución de tu aplicación en modo de ventanas múltiples</a></li>
<li><a href="#testing">Prueba de la compatibilidad de tu aplicación con el uso de ventanas múltiples</a></li>
</ol>
<h2>Consulta también</h2>
<ol>
<li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Aplicación de ejemplo para la
prueba de ventanas múltiples</a></li>
<li><a class="external-link" href="https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64">Cinco tips para prepararse para ventanas múltiples en Android N</a></li>
</ol>
</div>
</div>
<p>
Android N agrega compatibilidad con la visualización de más de una aplicación
a la vez. En dispositivos portátiles, se pueden ejecutar dos aplicaciones una al lado de la otra o
una por encima de la otra en modo de <em>pantalla dividida</em>. En dispositivos de TV, las aplicaciones pueden
usar el modo <em>picture-in-picture</em> para continuar la reproducción de video mientras los usuarios
interactúan con otra aplicación.
</p>
<p>
Si compilas tu aplicación con el N Preview SDK, puedes configurar la manera en que tu aplicación
administra la visualización de ventanas múltiples. Por ejemplo, puedes especificar las dimensiones
mínimas permitidas de tu actividad. También puedes inhabilitar la visualización de ventanas múltiples para
tu aplicación asegurándote de que el sistema solo muestre tu aplicación en modo de
pantalla completa.
</p>
<h2 id="overview">Información general</h2>
<p>
Android N permite que varias aplicaciones compartan la pantalla al mismo tiempo. Por
ejemplo, un usuario podría dividir la pantalla y ver una página web a la izquierda
mientras escribe un correo electrónico a la derecha. La experiencia de usuario depende
del dispositivo:
</p>
<ul>
<li>Los dispositivos portátiles con Android N ofrecen modo de
pantalla dividida. En este modo, el sistema ocupa la pantalla con dos aplicaciones y las muestra
una al lado de la otra o una encima de la otra. El usuario puede arrastrar la línea que divide
las dos aplicaciones para visualizar una más grande que la otra.
</li>
<li>En dispositivos Nexus Player con Android N, las aplicaciones pueden ubicarse automáticamente
en <a href="picture-in-picture.html">modo Picture-in-picture</a>, lo que les permite
continuar mostrando contenido mientras el usuario explora o interactúa con
otras aplicaciones.
</li>
<li>Los fabricantes de dispositivos más grandes pueden optar por habilitar el modo
de forma libre, en el que el usuario puede modificar libremente el tamaño de cada actividad. Si el
fabricante habilita está función, el dispositivo ofrecerá modo de forma libre además
del modo de pantalla dividida.
</li>
</ul>
<img src="{@docRoot}images/android-7.0/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}images/android-7.0/mw-splitscreen.png 1x,
{@docRoot}images/android-7.0/mw-splitscreen_2x.png 2x," id="img-split-screen" />
<p class="img-caption">
<strong>Figura 1:</strong> Dos aplicaciones ejecutándose una al lado de la otra en modo de pantalla dividida.
</p>
<p>
El usuario puede cambiar a modo de ventanas múltiples de la siguiente manera:
</p>
<ul>
<li>Si el usuario abre la <a href="{@docRoot}guide/components/recents.html">pantalla
Overview</a> y presiona durante un momento el
título de una actividad, puede arrastrar esa actividad a una parte resaltada de la
pantalla para llevarla a modo de ventanas múltiples.
</li>
<li>Si el usuario presiona durante un momento el botón Overview, el dispositivo coloca
la actividad actual en modo de ventanas múltiples y abre la pantalla Overview para
permitirle al usuario seleccionar otra actividad para compartir la pantalla.
</li>
</ul>
<p>
Los usuarios pueden <a href="{@docRoot}guide/topics/ui/drag-drop.html">arrastrar y
soltar</a> datos de una actividad a otra mientras las actividades comparten
la pantalla. (Antes, los usuarios solo podían arrastrar y soltar datos dentro de una sola
actividad).
</p>
<h2 id="lifecycle">Ciclo de vida en modo de ventanas múltiples</h2>
<p>
El modo de ventanas múltiples no cambia el <a href="{@docRoot}training/basics/activity-lifecycle/index.html">ciclo de vida
de la actividad</a>.
</p>
<p>
En modo de ventanas múltiples, solo la actividad con la que el usuario interactuó más recientemente
está activa en un momento determinado. Esa actividad se considera la <em>principal</em>.
Todas las demás actividades están pausadas, aunque estén visibles.
No obstante, el sistema les da a esas actividades pausadas pero visibles una prioridad más alta
que las actividades que no están visibles. Si el usuario interactúa con una de las
actividades pausadas, se reanuda esa actividad y se pausa la actividad que antes
era la principal.
</p>
<p class="note">
<strong>Nota:</strong> En modo de ventanas múltiples, una aplicación puede estar pausada
y aún visible para el usuario. Es posible que una aplicación necesite continuar sus
actividades mientras está pausada. Por ejemplo, una aplicación de reproducción de video que está
pausada pero visible debería continuar mostrando el video. Por ese
motivo, recomendamos que las actividades que reproducen video <em>no</em> pausen el
video en sus controladores{@link android.app.Activity#onPause onPause()}.
En su lugar, deben pausar el video en {@link android.app.Activity#onStop
onStop()} y reanudar la reproducción en {@link android.app.Activity#onStart
onStart()}.
</p>
<p>
Cuando el usuario coloca una aplicación en modo de ventanas múltiples, el sistema le notifica a la
actividad de un cambio de configuración, tal como se especifica en <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Control de cambios en
tiempo de ejecución</a>. Esto también sucede cuando el usuario modifica el tamaño de la aplicación o coloca la aplicación
nuevamente en el modo de pantalla completa.
Básicamente, este cambio tiene las mismas consecuencias en el ciclo de vida
de la actividad que cuando el sistema notifica a la aplicación que el dispositivo cambió de
modo vertical a modo de paisaje, excepto porque se modifican las dimensiones del dispositivo
en lugar de intercambiarse solamente. Como se aborda en <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Control de cambios en
tiempo de ejecución</a>, tu actividad puede administrar el cambio de configuración por sí misma, o
puede permitir que el sistema destruya la actividad y la vuelva a crear con las nuevas
dimensiones.
</p>
<p>
Si el usuario cambia el tamaño de una ventana y la agranda en cualquier dirección, el
sistema modifica el tamaño de la actividad para que coincida con la acción del usuario y emite <a href="{@docRoot}guide/topics/resources/runtime-changes.html">cambios en tiempo de ejecución</a>
según sean necesarios. Si la aplicación se retrasa en el trazado de áreas recientemente expuestas, el
sistema rellena esas áreas con el color especificado por el atributo {@link
android.R.attr#windowBackground windowBackground} o por el atributo de estilo predeterminado
<code>windowBackgroundFallback</code>.
</p>
<h2 id="configuring">Configuración de tu aplicación para el modo de ventanas múltiples</h2>
<p>
Si tu aplicación está orientada a Android N, puedes configurar cómo y
si quieres que las actividades de tu aplicación admitan la visualización de ventanas múltiples. Puedes establecer
atributos en tu manifiesto para controlar el tamaño y el diseño.
La configuración de atributos de una actividad raíz se aplica a todas las actividades
de su pila de tareas. Por ejemplo, si
<code>android:resizeableActivity</code> está configurado en true para la actividad raíz, se puede modificar el tamaño de todas las actividades
de la pila de tareas.
</p>
<p class="note">
<strong>Nota:</strong> Si compilas una aplicación con múltiples orientaciones con una versión del
SDK anterior a Android N, y el usuario usa la aplicación en
modo de ventanas múltiples, el sistema cambia el tamaño de la aplicación de forma forzada. El sistema presenta un
cuadro de diálogo en el que se advierte al usuario que la aplicación puede comportarse de forma inesperada. El sistema
<em>no</em> modifica el tamaño de aplicaciones con orientación fija; si
el usuario intenta abrir una aplicación con orientación fija en modo de ventanas múltiples,
la aplicación ocupará toda la pantalla.
</p>
<h4 id="resizeableActivity">android:resizeableActivity</h4>
<p>
Establece este atributo en el nodo <code>&lt;activity&gt;</code> o
<code>&lt;application&gt;</code> de tu manifiesto para habilitar o inhabilitar la visualización
en modo de ventanas múltiples:
</p>
<pre>
android:resizeableActivity=["true" | "false"]
</pre>
<p>
Si este atributo se establece en true, la actividad puede iniciarse en
los modos de pantalla dividida y forma libre. Si el atributo se establece en false, la
actividad no admite el modo de ventanas múltiples. Si el valor es false, y el
usuario intenta iniciar la actividad en modo de ventanas múltiples, la actividad ocupará
toda la pantalla.
</p>
<p>
Si tu aplicación está orientada a Android N, pero no especificas un valor
para este atributo, el valor predeterminado del atributo será true.
</p>
<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
<p>
Establece este atributo en el nodo <code>&lt;activity&gt;</code> de tu manifiesto
para indicar si la actividad admite la visualización de Picture-in-picture. Este
atributo se ignora si <code>android:resizeableActivity</code> es false.
</p>
<pre>
android:supportsPictureInPicture=["true" | "false"]
</pre>
<h3 id="layout">Atributos de diseño</h3>
<p>
Con Android N, el elemento de manifiesto <code>&lt;layout&gt;</code>
admite varios atributos que afectan cómo se comporta una actividad en
modo de ventanas múltiples:
</p>
<dl>
<dt>
<code>android:defaultWidth</code>
</dt>
<dd>
Ancho predeterminado de la actividad cuando se inicia en modo de forma libre.
</dd>
<dt>
<code>android:defaultHeight</code>
</dt>
<dd>
Altura predeterminada de la actividad cuando se inicia en modo de forma libre.
</dd>
<dt>
<code>android:gravity</code>
</dt>
<dd>
Ubicación inicial de la actividad cuando se inicia en modo de forma libre. Consulta la referencia
{@link android.view.Gravity} para obtener valores adecuados.
</dd>
<dt>
<code>android:minimalHeight</code>, <code>android:minimalWidth</code>
</dt>
<dd>
Altura y ancho mínimos para la actividad tanto en el modo de pantalla dividida como en el
modo de forma libre. Si el usuario mueve la línea divisoria en el modo de pantalla dividida
para reducir el tamaño respecto del tamaño mínimo especificado, el sistema recorta
la actividad para ajustarla a los requisitos del usuario.
</dd>
</dl>
<p>
Por ejemplo, el siguiente código muestra cómo especificar el tamaño
y la ubicación predeterminados de una actividad, y su tamaño mínimo, cuando la actividad se visualiza en
modo de forma libre:
</p>
<pre>
&lt;activity android:name=".MyActivity"&gt;
&lt;layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minimalHeight="450dp"
android:minimalWidth="300dp" /&gt;
&lt;/activity&gt;
</pre>
<h2 id="running">Ejecución de tu aplicación en modo de ventanas múltiples</h2>
<p>
Android N ofrece nuevas funcionalidades para admitir aplicaciones que puedan ejecutarse
en modo de ventanas múltiples.
</p>
<h3 id="disabled-features">Funciones deshabilitadas en modo de ventanas múltiples</h3>
<p>
Ciertas funciones están deshabilitadas o se ignoran cuando un dispositivo se encuentra en modo de
ventanas múltiples, ya que no resultan útiles para una actividad que podría estar compartiendo la
pantalla del dispositivo con otras actividades o aplicaciones. Esas funciones incluyen las siguientes:
<ul>
<li>Algunas opciones de personalización de la <a href="{@docRoot}training/system-ui/index.html">IU del sistema</a>
están deshabilitadas; por ejemplo, las aplicaciones no pueden ocultar la barra de
estado si no se están ejecutando en modo de pantalla completa.
</li>
<li>El sistema ignora los cambios en el atributo <code><a href=
"{@docRoot}guide/topics/manifest/activity-element.html#screen"
>android:screenOrientation</a></code>.
</li>
</ul>
<h3 id="change-notification">Notificación y consulta de cambios en modo de ventanas múltiples</h3>
<p>
Se agregaron los siguientes métodos nuevos a la clase {@link android.app.Activity}
para admitir la visualización de ventanas múltiples. Para obtener información detallada sobre cada método, consulta la
<a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referencia sobre N Preview SDK
</a>.
</p>
<dl>
<dt>
<code>Activity.isInMultiWindowMode()</code>
</dt>
<dd>
Realiza una llamada para averiguar si la actividad está en modo de ventanas múltiples.
</dd>
<dt>
<code>Activity.isInPictureInPictureMode()</code>
</dt>
<dd>
Realiza una llamada para averiguar si la actividad está en modo Picture-in-picture.
<p class="note">
<strong>Nota:</strong> El modo Picture-in-picture es un caso especial del
modo de ventanas múltiples. Si <code>myActivity.isInPictureInPictureMode()</code>
devuelve un valor true, <code>myActivity.isInMultiWindowMode()</code> también
devuelve un valor true.
</p>
</dd>
<dt>
<code>Activity.onMultiWindowModeChanged()</code>
</dt>
<dd>
El sistema llama a este método siempre que la actividad entra en modo de ventanas
múltiples o sale de él. El sistema le pasa al método un valor de true si la
actividad entra en modo de ventanas múltiples y false si la actividad
sale del modo de ventanas múltiples.
</dd>
<dt>
<code>Activity.onPictureInPictureModeChanged()</code>
</dt>
<dd>
El sistema llama a este método siempre que la actividad entra en modo Picture-in-picture
o sale de él. El sistema le pasa al método un valor de true si
la actividad entra en modo Picture-in-picture y false si la actividad
sale de dicho modo.
</dd>
</dl>
<p>
También hay versiones {@link android.app.Fragment} de cada uno de esos
métodos; por ejemplo, <code>Fragment.isInMultiWindowMode()</code>.
</p>
<h3 id="entering-pip">Cómo entrar en modo Picture-in-picture</h3>
<p>
Para que una actividad entre en modo de Picture-in-picture, debes llamar al nuevo método
<code>Activity.enterPictureInPictureMode()</code>. Este método no tiene efecto si
el dispositivo no admite el modo de imagen en imagen. Para obtener más información,
consulta la documentación de <a href="picture-in-picture.html">Picture-in-Picture</a>.
</p>
<h3 id="launch">Inicia nuevas actividades en modo de ventanas múltiples</h3>
<p>
Cuando inicias una nueva actividad, puedes indicarle al sistema que la nueva
actividad se debe mostrar adyacente a la actual, si fuera posible. Para hacer
esto, usa el marcador
<code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Pasar
este marcador requiere el siguiente comportamiento:
</p>
<ul>
<li>Si el dispositivo está en modo de pantalla dividida, el sistema intenta crear la
nueva actividad junto a la actividad que lo inició, de modo que las dos actividades
compartan la pantalla. No se garantiza que el sistema pueda hacerlo, pero
ubicará las actividades de forma adyacente si fuera posible.
</li>
<li>Si el dispositivo no está en modo de pantalla dividida, este marcador no tendrá efecto.
</li>
</ul>
<p>
Si un dispositivo está en modo de forma libre e inicias una nueva actividad, puedes
especificar las dimensiones y la ubicación de la pantalla de la nueva actividad al llamar a
<code>ActivityOptions.setLaunchBounds()</code>. Este método no tiene efecto si
el dispositivo no está en modo de ventanas múltiples.
</p>
<p class="note">
<strong>Nota:</strong> Si inicias una actividad en una pila de tareas, esa
actividad reemplaza la actividad en pantalla y hereda todas sus
propiedades de ventanas múltiples. Si quieres iniciar la nueva actividad en una ventana
independiente en modo de ventanas múltiples, debes iniciarla en una nueva pila de tareas.
</p>
<h3 id="dnd">Admisión de la funcionalidad de arrastrar y soltar</h3>
<p>
Los usuarios pueden <a href="{@docRoot}guide/topics/ui/drag-drop.html">arrastrar y
soltar</a> datos de una actividad a otra mientras las dos actividades
comparten la pantalla. (Antes, los usuarios solo podían arrastrar y soltar datos dentro de una
sola actividad). Por este motivo, te recomendamos que agregues la funcionalidad de arrastrar y
soltar a tu aplicación si es que aún no la admite.
</p>
<p>
El N Preview SDK amplía el paquete <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a>
para admitir la funcionalidad de arrastrar y soltar entre aplicaciones diferentes. Para obtener información detallada sobre las siguientes
clase y métodos, consulta la <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referencia
del N Preview SDK</a>.
</p>
<dl>
<dt>
<code>android.view.DropPermissions</code>
</dt>
<dd>
Objeto token responsable de especificar los permisos otorgados a la aplicación
que recibe datos mediante la funcionalidad de arrastrar y soltar.
</dd>
<dt>
<code>View.startDragAndDrop()</code>
</dt>
<dd>
Nuevo alias para {@link android.view.View#startDrag View.startDrag()}. Para
habilitar la funcionalidad arrastrar y soltar entre diferentes actividades, pasa el nuevo marcador
<code>View.DRAG_FLAG_GLOBAL</code>. Si necesitas otorgar permisos de URI a
la actividad receptora, pasa los nuevos marcadores
<code>View.DRAG_FLAG_GLOBAL_URI_READ</code> o
<code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code>, según corresponda.
</dd>
<dt>
<code>View.cancelDragAndDrop()</code>
</dt>
<dd>
Cancela una operación de arrastrar actualmente en curso. Solo puede ser llamado por la
aplicación que originó la operación de arrastrar.
</dd>
<dt>
<code>View.updateDragShadow()</code>
</dt>
<dd>
Reemplaza la sombra del arrastre por una operación de arrastrar actualmente en curso. Solo
puede ser llamado por la aplicación que originó la operación de arrastrar.
</dd>
<dt>
<code>Activity.requestDropPermissions()</code>
</dt>
<dd>
Solicita los permisos para los URI de contenido que se pasan con el {@link
android.content.ClipData} incluido en un {@link android.view.DragEvent}.
</dd>
</dl>
<h2 id="testing">Prueba de la compatibilidad de tu aplicación con el uso de ventanas múltiples</h2>
<p>
Ya sea que actualices o no tu aplicación para Android N, debes
verificar la forma en que se comporta en modo de ventanas múltiples en caso de que un usuario intente iniciarla
en modo de ventanas múltiples en un dispositivo con Android N.
</p>
<h3 id="configuring">Configuración de un dispositivo de prueba</h3>
<p>
Si instalas Android N en un dispositivo, se admite automáticamente el modo
de pantalla dividida.
</p>
<h3 id="test-non-n">Si tu aplicación no se compiló con el N Preview SDK</h3>
<p>
Si no creaste tu aplicación con el N Preview SDK y el usuario intenta usar
la aplicación en modo de ventanas múltiples, el sistema cambia el tamaño de la aplicación de forma forzada, a menos que la aplicación
declare una orientación fija.
</p>
<p>
Si tu aplicación no declara una orientación fija, debes iniciar tu aplicación
en un dispositivo con Android N e intentar colocar la aplicación en
modo de pantalla dividida. Cuando se modifique el tamaño de la aplicación de forma forzada,
verifica que la experiencia de usuario sea aceptable.
</p>
<p>
Si la aplicación declara una orientación fija, debes intentar colocar la aplicación en
modo de ventanas múltiples. Cuando lo hagas, verifica que la aplicación
continúe en modo de pantalla completa.
</p>
<h3 id="test-mw">Si admites el modo de ventanas múltiples</h3>
<p>
Si compilaste tu aplicación con el N Preview SDK y no deshabilitaste
la compatibilidad con ventanas múltiples, verifica el siguiente comportamiento tanto en modo de pantalla dividida
como en modo de forma libre.
</p>
<ul>
<li>Inicia la aplicación en modo de pantalla completa y luego cambia al modo de ventanas múltiples al presionar
durante un momento el botón Overview. Verifica que la aplicación pase de un modo a otro correctamente.
</li>
<li>Inicia la aplicación directamente en modo de ventanas múltiples y verifica que se
inicie correctamente. Puedes iniciar una aplicación en modo de ventanas múltiples al presionar el
botón Overview, luego presionar durante un momento la barra de título de la aplicación y arrastrarla
a una de las áreas resaltadas de la pantalla.
</li>
<li>Cambia el tamaño de tu aplicación en modo de pantalla dividida al arrastrar la línea divisoria.
Verifica que la aplicación cambie de tamaño sin fallar y que estén visibles los elementos
necesarios de la IU.
</li>
<li>Si especificaste dimensiones mínimas para tu aplicación, intenta cambiar el tamaño
de la aplicación a dimensiones más bajas que las especificadas. Verifica que no puedas modificar el tamaño de la aplicación
para que sea más pequeña que la dimensión mínima especificada.
</li>
<li>En todas las pruebas, verifica que el rendimiento de la aplicación sea aceptable. Por
ejemplo, verifica que la actualización de la IU después de cambiar el tamaño de la aplicación
no demore mucho.
</li>
</ul>
<h4 id="test-checklist">Lista de comprobación de pruebas</h4>
<p>
Para verificar el rendimiento de tu aplicación en modo de ventanas múltiples, intenta las siguientes
operaciones. Debes probar estas operaciones tanto en modo de pantalla dividida como en
modo de ventanas múltiples, excepto cuando se indique algo diferente.
</p>
<ul>
<li>Ingresa en modo de ventanas múltiples y luego sal.
</li>
<li>Pasa de tu aplicación a otra y verifica que la aplicación se comporte
correctamente mientras esté visible pero no activa. Por ejemplo, si tu aplicación está
reproduciendo video, comprueba que el video se siga reproduciendo mientras el usuario interactúe
con otra aplicación.
</li>
<li>En modo de pantalla dividida, prueba mover la barra divisora para agrandar y
achicar la aplicación. Realiza estas operaciones en las configuraciones una al lado de la otra y
una encima de la otra. Verifica que la aplicación no falle,
que las funcionalidades necesarias estén visibles y que la operación de cambio de tamaño no demore
mucho.
</li>
<li>Realiza varias operaciones de cambio de tamaño en una sucesión rápida. Verifica que tu
aplicación no falle ni pierda memoria. Para obtener información acerca de cómo comprobar el uso de memoria
de tu aplicación, consulta <a href="{@docRoot}tools/debugging/debugging-memory.html">
Averiguación del uso de RAM</a>.
</li>
<li>Usa tu aplicación normalmente en diferentes configuraciones de ventanas y
verifica que la aplicación se comporte correctamente. Verifica que el texto sea legible y que
los elementos de la IU sean lo suficientemente grandes para interactuar con ellos.
</li>
</ul>
<h3 id="test-disabled-mw">Si deshabilitaste la compatibilidad con el modo de ventanas múltiples</h3>
<p>
Si deshabilitaste la compatibilidad con el modo de ventanas múltiples al configurar
<code>android:resizableActivity="false"</code>, debes iniciar tu aplicación en
un dispositivo con Android N e intentar colocar la aplicación en los
modos de forma libre y pantalla dividida. Cuando lo hagas, verifica que la aplicación
continúe en modo de pantalla completa.
</p>

View File

@@ -1,91 +0,0 @@
fullpage=true
excludeFromSuggestions=true
page.metaDescription=The official site for Android developers. Provides the Android SDK and documentation for app developers and designers.
page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" />
@jd:body
<section class="dac-expand dac-hero" style="background-color:#b2dfdb;">
<div class="wrap" style="max-width:1000px;margin-top:0">
<div class="col-7of16 col-push-8of16">
<a href="{@docRoot}about/versions/nougat/index.html">
<h1 class="dac-hero-title" style="color:#004d40">Android 7.0 Nougat!</h1>
<p class="dac-hero-description" style="color:#004d40">
<strong>Android 7.0 Nougat is here!</strong>
Get your apps ready for the latest version of Android, with new system
behaviors to <strong>save battery and memory</strong>.
Extend your apps with <strong>multi-window UI</strong>,
<strong>direct reply notifications</strong> and more.
</p>
<a class="dac-hero-cta" href="{@docRoot}about/versions/nougat/index.html" style="color:#004d40">
<span class="dac-sprite dac-auto-chevron" style="background-color:#b2dfdb"></span>
Learn more
</a>
</a>
</a>
</div>
<div class="col-6of16 col-pull-6of16 dac-hero-figure" style="padding-left:1em;padding-top:1em;">
<a href="{@docRoot}about/versions/nougat/index.html">
<img class="dac-hero-image" src="{@docRoot}images/home/nougat_bg.jpg"
srcset="{@docRoot}images/home/nougat_bg.jpg 1x,
{@docRoot}images/home/nougat_bg_2x.jpg 2x">
</a>
</div>
</div>
</section>
<div class="dac-section dac-slim dac-gray dac-expand">
<div class="wrap dac-offset-parent">
<a class="dac-fab dac-scroll-button" data-scroll-button href="#build-apps">
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
<ul class="dac-actions">
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}sdk/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Get the SDK
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}samples/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Browse sample code
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}distribute/stories/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Watch stories
</a>
</li>
</ul>
</div><!-- end .wrap -->
</div><!-- end .dac-actions -->
<section class="dac-section dac-light" id="build-apps"><div class="wrap">
<h1 class="dac-section-title">Build Beautiful Apps</h1>
<div class="dac-section-subtitle">
Resources to get you started with designing and developing for Android.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:index/primary"
data-cardSizes="6x6"
data-maxResults="3"></div>
</div></section>
<div class="dac-hero-carousel" data-carousel-query="collection:index/secondary/carousel">
</div>
<section class="dac-section dac-gray"><div class="wrap">
<div class="cols"><div class="col-10of12 col-push-1of12">
<h1 class="dac-section-title">Creado para un mundo de múltiples pantallas</h1>
<div class="dac-section-subtitle">
Android se ejecuta en cientos de millones de dispositivos de todo el mundo, <br>
y ahora es compatible con estos innovadores factores de forma.
</div>
</div></div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:index/multiscreen"
data-cardSizes="6x6"
data-maxResults="3"></div>
</div></section>

View File

@@ -1,181 +0,0 @@
page.title=Inicio directo
page.keywords=preview,sdk,direct boot
page.tags=androidn
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#run">Solicitar acceso para ejecutar durante el inicio directo</a></li>
<li><a href="#access">Acceder al almacenamiento encriptado por dispositivo</a></li>
<li><a href="#notification">Recibir notificaciones sobre el desbloqueo del usuario</a></li>
<li><a href="#migrating">Migrar datos existentes</a></li>
<li><a href="#testing">Probar la aplicación con reconocimiento de encriptación</a></li>
</ol>
</div>
</div>
<p>Android N se ejecuta en un modo <i>de inicio directo</i> seguro
cuando el dispositivo se enciende pero el usuario no lo ha
desbloqueado. Para permitir esto, el sistema brinda dos ubicaciones de almacenamiento para los datos:</p>
<ul>
<li><i>Almacenamiento encriptado por credencial: </i>es la ubicación de almacenamiento predeterminada
y solo está disponible después de que el usuario desbloquea el dispositivo.</li>
<li><i>Almacenamiento encriptado por dispositivo: </i>es una ubicación de almacenamiento que está disponible tanto
durante el modo de inicio directo como después de que el usuario desbloquea el dispositivo.</li>
</ul>
<p>De forma predeterminada, las aplicaciones no se ejecutan durante el modo de inicio directo.
Si necesitas que tu aplicación se ejecute durante el modo de inicio directo, puedes registrar
los componentes de la aplicación que deberían ejecutarse durante este modo. Algunos casos comunes de
aplicaciones que necesitan ejecutarse durante el modo de inicio directo incluyen los siguientes:</p>
<ul>
<li>aplicaciones que tienen notificaciones programadas, como aplicaciones
de alarma;</li>
<li>aplicaciones que generan notificaciones de usuario importantes, como aplicaciones de mensajes SMS;</li>
<li>aplicaciones que brindan servicios de accesibilidad, como Talkback.</li>
</ul>
<p>Si necesitas que tu aplicación acceda a datos mientras se ejecuta el modo de inicio directo, usa
el almacenamiento encriptado por dispositivo. Este tipo de almacenamiento contiene datos
encriptados con una clave que solo está disponible luego de que el dispositivo haya realizado un inicio
verificado correctamente.</p>
<p>Para los datos que se deben cifrar con una clave asociada con credenciales del
usuario, como un PIN o una contraseña, usa el almacenamiento encriptado por credencial.
Este tipo de almacenamiento solo está disponible luego de que el usuario haya desbloqueado
correctamente el dispositivo y hasta que el usuario reinicie nuevamente el dispositivo. Si el
usuario habilita el bloqueo de pantalla luego de desbloquear el dispositivo, esto no bloquea
el almacenamiento encriptado por credencial.</p>
<h2 id="run">Solicitar acceso para ejecutar durante el inicio directo</h2>
<p>Debes registrar los componentes de las aplicaciones con el sistema antes de que estas puedan
ejecutarse durante el modo de inicio directo o acceder al almacenamiento encriptado por
dispositivo. Para registrar una aplicación en el sistema, debes marcar los componentes como
<i>"con reconocimiento de encriptación"</i>. Para marcar tu dispositivo como "con reconocimiento de encriptación", configura el atributo
<code>android:directBootAware</code> como verdadero en el manifiesto.<p>
<p>Los componentes con reconocimiento de encriptación pueden registrarse para recibir un mensaje de transmisión
<code>LOCKED_BOOT_COMPLETED</code> del
sistema cuando el dispositivo se haya reiniciado. En este momento, el almacenamiento
encriptado por dispositivo está disponible, y el componente puede ejecutar tareas que se deben
ejecutar durante el modo de inicio directo, como disparar una alarma programada.</p>
<p>El siguiente fragmento de código es un ejemplo de cómo registrar un
{@link android.content.BroadcastReceiver} como reconocimiento de encriptación y de cómo agregar un
filtro de intents para <code>LOCKED_BOOT_COMPLETED</code> en el manifiesto de la aplicación:</p>
<pre>
&lt;receiver
android:directBootAware="true" &gt;
...
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /&gt;
&lt;/intent-filter&gt;
&lt;/receiver&gt;
</pre>
<p>Una vez que el usuario haya desbloqueado el dispositivo, todos los componentes podrán acceder tanto al
almacenamiento encriptado por dispositivo como al almacenamiento cifrado por credencial.</p>
<h2 id="access">Acceder al almacenamiento encriptado por dispositivo</h2>
<p>Para acceder al almacenamiento encriptado por dispositivo, crea una segunda
instancia de {@link android.content.Context} llamando a
<code>Context.createDeviceProtectedStorageContext()</code>. Todas las llamadas
de API de almacenamiento que se hacen usando este contexto acceden al almacenamiento encriptado por dispositivo. El siguiente
ejemplo accede al almacenamiento encriptado por dispositivo y abre un archivo de datos de la aplicación
existente:</p>
<pre>
Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...
</pre>
<p>Solo debes usar el almacenamiento encriptado por dispositivo para
información que debe ser accesible durante el modo de inicio directo.
No uses este tipo de almacenamiento como un almacenamiento encriptado de propósito general.
Para información privada del usuario o datos encriptados que no son necesarios durante
el modo de inicio directo, usa el almacenamiento encriptado por credencial.</p>
<h2 id="notification">Recibir notificaciones sobre el desbloqueo del usuario</h2>
<p>Una vez que el usuario desbloquea el dispositivo después de reiniciarlo, la aplicación puede cambiar y acceder
al almacenamiento encriptado por credencial y usar servicios del sistema comunes que
dependen de credenciales de usuario.</p>
<p>Para recibir una notificación cuando el usuario desbloquea el dispositivo luego de reiniciarlo,
registra un {@link android.content.BroadcastReceiver} de un componente en ejecución
para que escuche el mensaje <code>ACTION_USER_UNLOCKED</code>. O puedes
recibir el mensaje existente {@link android.content.Intent#ACTION_BOOT_COMPLETED
ACTION_BOOT_COMPLETED}, que ahora indica que el dispositivo se ha iniciado y
que el usuario ha desbloqueado el dispositivo.</p>
<p>Puedes consultar directamente si el usuario ha desbloqueado el dispositivo llamando a
<code>UserManager.isUserUnlocked()</code>.</p>
<h2 id="migrating">Migrar datos existentes</h2>
<p>Si un usuario actualiza el dispositivo para usar el modo de inicio directo, es posible que haya
datos existentes que se deban migrar al almacenamiento encriptado por dispositivo. Usa
<code>Context.moveSharedPreferencesFrom()</code> y
<code>Context.moveDatabaseFrom()</code> para migrar los datos de preferencia y de base de datos
del almacenamiento encriptado por credencial al almacenamiento encriptado por dispositivo.</p>
<p>Debes tener cuidado cuando decidas qué datos migrar entre
estos dos tipos de almacenamiento. No deberías migrar
información de usuario privada, como contraseñas o tokens de autorización, al
almacenamiento encriptado por dispositivo. En algunos casos, es posible que debas gestionar
conjuntos separados de datos en ambos tipos de almacenamiento encriptado.</p>
<h2 id="testing">Probar la aplicación con reconocimiento de encriptación</h2>
<p>Prueba la aplicación con reconocimiento de encriptación usando el nuevo modo de inicio directo. Hay dos
maneras de habilitar el inicio directo.</p>
<p class="caution"><strong>Advertencia:</strong> Habilitar el inicio directo
borrará todos los datos de usuario del dispositivo.</p>
<p>Para los dispositivos compatibles que tienen Android N instalado, habilita
el inicio directo mediante una de las siguientes opciones:</p>
<ul>
<li>En el dispositivo, habilita las <b>Developer options</b> si no lo haz hecho aún
yendo a <b>Settings &gt; About phone</b> y presionando <b>Build number</b>
siete veces. Una vez que aparezca la pantalla Developer options, dirígete a
<b>Settings &gt; Developer options</b> y selecciona
<b>Convert to file encryption</b>.</li>
<li>Usa los siguientes comandos shell ADB para habilitar el modo de inicio directo:
<pre class="no-pretty-print">
$ adb reboot-bootloader
$ fastboot --wipe-and-use-fbe
</pre>
</li>
</ul>
<p>También está disponible un modo de inicio directo emulado en caso de que debas cambiar
de modo en los dispositivos de prueba. El modo emulado solo debería usarse durante
el desarrollo, y puede provocar la pérdida de datos. Para habilitar el modo de inicio directo emulado,
debes establecer un patrón de bloqueo en el dispositivo, elegir "No thanks" si te pregunta si deseas un
inicio seguro cuando estás estableciendo el patrón de bloqueo y, luego, usar el
siguiente comando shell ADB:</p>
<pre class="no-pretty-print">
$ adb shell sm set-emulate-fbe true
</pre>
<p>Para deshabilitar el modo de inicio directo emulado, usa el siguiente comando:</p>
<pre class="no-pretty-print">
$ adb shell sm set-emulate-fbe false
</pre>
<p>Usar estos comandos provoca el reinicio del dispositivo.</p>

View File

@@ -1,148 +0,0 @@
page.title=Acceso a directorios determinados
page.keywords=preview,sdk,scoped directory access
page.tags=androidn
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#accessing">Acceder a un directorio de almacenamiento externo</a></li>
<li><a href="#removable">Acceder a un directorio de un medio extraíble</a></li>
<li><a href="#best">Prácticas recomendadas</a></li>
</ol>
</div>
</div>
<p>Las aplicaciones como las aplicaciones de fotografía generalmente solo necesitan acceso a directorios de
almacenamiento externo, como el directorio <code>Pictures</code>. Los métodos
existentes para acceder a almacenamiento externo no están diseñados para brindar un
acceso fácil a determinados directorios para estos tipos de aplicaciones. Por ejemplo:</p>
<ul>
<li>Solicitar {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
o {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} en tu manifiesto
permite el acceso a todos los directorios públicos de un almacenamiento externo, lo cual podría ser
un acceso mayor que el que necesita tu aplicación.</li>
<li>Usar el
<a href="{@docRoot}guide/topics/providers/document-provider.html">framework
de acceso al almacenamiento</a> generalmente implica que el usuario seleccione directorios
mediante un sistema de IU, lo cual no es necesario si tu aplicación siempre accede al mismo
directorio externo.</li>
</ul>
<p>Android N brinda una API nueva y simplificada para acceder a
directorios de almacenamiento externo comunes. </p>
<h2 id="accessing">Acceder a un directorio de almacenamiento externo</h2>
<p>Usa la clase <code>StorageManager</code> para obtener la instancia de
<code>StorageVolume</code> correcta. Luego, crea una intent llamando al
método <code>StorageVolume.createAccessIntent()</code> de esa instancia.
Usa esta intención para acceder a directorios de almacenamiento externo. Para obtener una lista de
todos los volúmenes disponibles, incluidos los volúmenes de medios extraíbles, usa
<code>StorageManager.getVolumesList()</code>.</p>
<p>Si tienes información sobre un archivo específico, usa
<code>StorageManager.getStorageVolume(File)</code> para obtener el
<code>StorageVolume</code> que contiene el archivo. Llama a
<code>createAccessIntent()</code> en este <code>StorageVolume</code> para acceder al
directorio de almacenamiento externo del archivo.</p>
<p>
En el caso de los volúmenes secundarios, como las tarjetas SD externas, pasa un valor nulo cuando llames a
<code>StorageVolume.createAccessIntent()</code> para solicitar acceso al volumen
completo, en lugar de un directorio específico.
<code>StorageVolume.createAccessIntent()</code> regresa un valor nulo si pasas un
valor nulo para el volumen principal o si pasas un nombre de directorio no válido.
</p>
<p>El siguiente fragmento de código es un ejemplo de cómo abrir el
directorio <code>Pictures</code> en el almacenamiento compartido principal:</p>
<pre>
StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = sm.getPrimaryVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);
</pre>
<p>El sistema intenta otorgar acceso al directorio externo y, si
es necesario, confirma el acceso con el usuario usando una IU simplificada:</p>
<img src="{@docRoot}images/android-7.0/scoped-directory-access-framed.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-framed.png 1x,
{@docRoot}images/android-7.0/scoped-directory-access-framed_2x.png 2x" />
<p class="img-caption"><strong>Imagen 1.</strong> Una aplicación solicitando
acceso al directorio Pictures.</p>
<p>Si el usuario otorga el acceso, el sistema llama a tu
anulación de <code>onActivityResult()</code> con un código resultante de
<code>Activity.RESULT_OK</code> y datos de intents que contienen el URI. Usa
el URI brindado para acceder a la información del directorio. Es similar a usar URI
generados por el
<a href="{@docRoot}guide/topics/providers/document-provider.html">framework
de acceso al almacenamiento</a>.</p>
<p>Si el usuario no otorga el acceso, el sistema llama a tu
anulación de <code>onActivityResult()</code> con un código resultante de
<code>Activity.RESULT_CANCELED</code> y datos de intents nulos.</p>
<p class="note"><b>Nota</b>: Obtener acceso a un directorio externo específico
también otorga el acceso a los subdirectorios de ese directorio.</p>
<h2 id="removable">Acceder a un directorio de un medio extraíble</h2>
<p>Para usar el acceso a directorios determinados para acceder a directorios de medios extraíbles,
primero debes agregar un {@link android.content.BroadcastReceiver} que escuche la
notificación{@link android.os.Environment#MEDIA_MOUNTED}, por ejemplo:</p>
<pre>
&lt;receiver
android:name=".MediaMountedReceiver"
android:enabled="true"
android:exported="true" &gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MEDIA_MOUNTED" /&gt;
&lt;data android:scheme="file" /&gt;
&lt;/intent-filter&gt;
&lt;/receiver&gt;
</pre>
<p>Cuando el usuario conecta un medio extraíble, como una tarjeta SD, el sistema envía una
notificación{@link android.os.Environment#MEDIA_MOUNTED}. Esta notificación
brinda un objeto <code>StorageVolume</code> en los datos de intents que puedes
usar para acceder a directorios del medio extraíble. El siguiente ejemplo
accede al directorio <code>Pictures</code> de medios extraíbles:</p>
<pre>
// BroadcastReceiver has already cached the MEDIA_MOUNTED
// notification Intent in mediaMountedIntent
StorageVolume volume = (StorageVolume)
mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, request_code);
</pre>
<h2 id="best">Prácticas recomendadas</h2>
<p>Cuando sea posible, sigue usando el URI de acceso a directorios externos de modo que no tengas
que solicitarle acceso al usuario continuamente. Una vez que el usuario haya otorgado el acceso, llama a
<code>getContentResolver().takePersistableUriPermssion()</code> con el
URI de acceso a directorios. El sistema continuará el URI, y las siguientes solicitudes
de acceso generarán <code>RESULT_OK</code> y no le mostrarán una IU de confirmación al
usuario.</p>
<p>Si el usuario deniega el acceso a un directorio externo, no vuelvas a solicitar el
acceso inmediatamente. Hacer esto provocaría una mala experiencia
de usuario. Si el usuario deniega una solicitud y la aplicación solicita acceso
nuevamente, aparece la casilla de verificación <b>Don't ask again</b> en la IU:</p>
<img src="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png" srcset="{@docRoot}images/android-7.0/scoped-directory-access-dont-ask.png 1x,
{@docRoot}images/android-7.0/scoped-directory-access-dont-ask_2x.png 2x" />
<p class="img-caption"><strong>Figura 1.</strong> Una aplicación que presenta una
segunda solicitud para obtener acceso a medios extraíbles.</p>
<p>Si el usuario selecciona <b>Don't ask again</b> y deniega la solicitud, todas las
solicitudes futuras que presente la aplicación para el directorio determinado se denegarán
automáticamente, y el usuario no recibirá ninguna IU de solicitud.</p>

View File

@@ -1,747 +0,0 @@
page.title=Configuración de seguridad de la red
page.keywords=androidn,security,network
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#manifest">Agregar un archivo de configuración de seguridad</a></li>
<li><a href="#CustomTrust">Personalizar las CA de confianza</a>
<ol>
<li><a href="#ConfigCustom">Configurar una CA de confianza personalizada</a></li>
<li><a href="#LimitingCas">Limitar el conjunto de CA de confianza</a></li>
<li><a href="#TrustingAdditionalCas">Otorgar confianza a CA adicionales</a></li>
</ol>
</li>
<li><a href="#TrustingDebugCa">CA de solo depuración</a></li>
<li><a href="#UsesCleartextTraffic">Desactivar el tráfico de Cleartext</a></li>
<li><a href="#CertificatePinning">Fijar certificados</a></li>
<li><a href="#ConfigInheritance">Comportamiento de herencia de configuración</a></li>
<li><a href="#FileFormat">Formato del archivo de configuración</a></li>
</ol>
</div>
</div>
<p>
Android N incluye una función de configuración de seguridad de la red
que les permite a las aplicaciones personalizar los ajustes de seguridad de la red mediante un archivo
de configuración declarativo seguro sin que haya que modificar el código de la aplicación. Estos ajustes se pueden
configurar para dominios específicos y para una aplicación específica. Las capacidades
clave de esta función son las siguientes:
</p>
<ul>
<li>
<b>Anclajes de confianza personalizados:</b> personalizar qué autoridades de certificado (CA)
son de confianza para las conexiones de seguridad de una aplicación. Por ejemplo,
confiar en certificados autofirmados particulares
o restringir el conjunto de CA públicas en las que confía la aplicación.
</li>
<li>
<b>Anulaciones de solo depuración:</b> depurar de forma segura conexiones
de una aplicación sin riesgos adicionales para la base instalada.
</li>
<li>
<b>Desactivación del tráfico de Cleartext:</b> proteger a las aplicaciones del
uso accidental de tráfico de Cleartext.
</li>
<li>
<b>Fijación de certificados:</b> restringir la conexión segura de una aplicación
a certificados en particular.
</li>
</ul>
<h2 id="manifest">Agregar un archivo de configuración de seguridad</h2>
<p>
La función de configuración de seguridad de la red usa un archivo XML donde
se especifican los ajustes para la aplicación. Debes incluir una entrada en el manifiesto de tu
aplicación que apunte a este archivo. El siguiente fragmento de código de un manifiesto
demuestra cómo crear esta entrada:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest ... &gt;
&lt;application ... &gt;
&lt;meta-data android:name="android.security.net.config"
android:resource="@xml/network_security_config" /&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<h2 id="CustomTrust">Personalizar las CA de confianza</h2>
<p>
Una aplicación podría querer otorgar confianza a un conjunto personalizado de CA en lugar de hacerlo según los ajustes
predeterminados de la plataforma. Las razones más comunes son las siguientes:
</p>
<ul>
<li>Conectarse a un host con una autoridad de certificado personalizada (autofirmado,
emitido por una CA corporativa interna, etc.).
</li>
<li>Limitar el conjunto de CA a CA de confianza establecidas por el usuario y no a cada
CA preinstalada.
</li>
<li>Otorgar confianza a CA adicionales que no están incluidas en el sistema
</li>
</ul>
<p>
De forma predeterminada, las conexiones seguras (p. ej.: TLS, HTTP) de todas las aplicaciones dependen de
las CA preinstaladas del sistema; las aplicaciones que tienen como objetivo a la API nivel 23
(Android M) e inferiores también dependen de la tienda de CA agregada por el usuario de forma predeterminada. Una
aplicación puede personalizar sus propias conexiones usando {@code base-config} (para
la personalización de toda la aplicación) o {@code domain-config} (para la personalización
por dominio).
</p>
<h3 id="ConfigCustom">Configurar una CA de confianza personalizada</h3>
<p>
Supongamos que deseas conectarte a tu host, el cual usa un certificado SSL
autofirmado, o a un host cuyo certificado SSL está emitido por una CA no pública
en la cual confías, como la CA interna de tu empresa.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;domain-config&gt;
&lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
&lt;trust-anchors&gt;
&lt;certificates src="@raw/my_ca"/&gt;
&lt;/trust-anchors&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<p>
Agrega el certificado de CA autofirmado o no público, en formato PEM o DER, a
{@code res/raw/my_ca}.
</p>
<h3 id="LimitingCas">Limitar el conjunto de CA de confianza</h3>
<p>
Una aplicación que no desee confiar en todas las CA en que confía el sistema puede,
en su lugar, especificar su propio conjunto reducido de CA en las que confía. Esto protege a la aplicación
de certificados fraudulentos emitidos por cualquiera de las demás CA.
</p>
<p>
La configuración para limitar el conjunto de CA de confianza es similar a <a href="#TrustingACustomCa">confiar en una CA personalizada</a> para un dominio específico, con la diferencia
de que se brindan múltiples CA en el recurso.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;domain-config&gt;
&lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
&lt;domain includeSubdomains="true"&gt;cdn.example.com&lt;/domain&gt;
&lt;trust-anchors&gt;
&lt;certificates src="@raw/trusted_roots"/&gt;
&lt;/trust-anchors&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<p>
Agrega las CA de confianza, en formato PEM o DER, a {@code res/raw/trusted_roots}.
Ten en cuenta que, si usas el formato PEM, el archivo debe incluir <em>solo</em> datos PEM
y ningún texto adicional. También puedes brindar elementos
<a href="#certificates"><code>&lt;certificates&gt;</code></a>
múltiples en lugar de solo uno.
</p>
<h3 id="TrustingAdditionalCas">
Otorgar confianza a CA adicionales
</h3>
<p>
Una aplicación podría querer otorgar confianza a CA adicionales en las cuales el sistema no confía,
ya sea porque el sistema aún no incluye la CA o porque la CA no
cumple con los requisitos de inclusión del sistema Android. La
aplicación puede hacerlo especificando múltiples fuentes de certificado para una
configuración.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;base-config&gt;
&lt;trust-anchors&gt;
&lt;certificates src="@raw/extracas"/&gt;
&lt;certificates src="system"/&gt;
&lt;/trust-anchors&gt;
&lt;/base-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<h2 id="TrustingDebugCa">Configurar las CA para depuración</h2>
<p>
Cuando depuras una aplicación que se conecta mediante HTTPS, podrías querer
conectarte a un servidor de desarrollo local que no tiene el certificado
SSL de tu servidor de producción. Para poder hacerlo sin
tener que modificar el código de tu aplicación, puedes especificar CA de solo depuración que
solo <i>son</i> de confianza cuando <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">
android:debuggable</a>
es {@code true} usando {@code debug-overrides}. Generalmente, las herramientas de IDE
y de compilación configuran esta marca automáticamente para las compilaciones que no son de lanzamiento.
</p>
<p>
Esto es más seguro que el código condicional habitual ya que, como precaución
de seguridad, las tiendas de aplicaciones no aceptan aplicaciones que están marcadas
como depurables.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;debug-overrides&gt;
&lt;trust-anchors&gt;
&lt;certificates src="@raw/debug_cas"/&gt;
&lt;/trust-anchors&gt;
&lt;/debug-overrides&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<h2 id="UsesCleartextTraffic">Desactivar el tráfico de Cleartext</h2>
<p>
Las aplicaciones que deseen conectarse a destinos usando solo conexiones
seguras pueden desactivar Cleartext (usando el protocolo
HTTP no encriptado en lugar del protocolo HTTPS) para esos destinos. Esta opción ayuda a prevenir
las regresiones accidentales en aplicaciones debido a cambios en direcciones URL generados por fuentes
externas como servidores backend.
Consulta {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted
NetworkSecurityPolicy.isCleartextTrafficPermitted()} para obtener más información.
</p>
<p>
Por ejemplo, una aplicación puede querer garantizar que todas las conexiones a {@code
secure.example.com} se hagan siempre mediante HTTPS para proteger el tráfico sensible
de redes hostiles.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;domain-config usesCleartextTraffic="false"&gt;
&lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<h2 id="CertificatePinning">Fijar certificados</h2>
<p>
Generalmente, una aplicación otorga confianza a todas las CA preinstaladas. Si alguna de estas CA emitiera
un certificado fraudulento, la aplicación estaría en riesgo de sufrir un ataque
MiTM. Algunas aplicaciones eligen limitar el conjunto de certificados que aceptan
ya sea limitando el conjunto de CA al que otorgan confianza o fijando certificados.
</p>
<p>
La fijación de certificados se hace brindando un conjunto de certificados por hash de la
clave pública (SubjectPublicKeyInfo del certificado X.509). De este modo,
una cadena de certificados solo es válida si contiene al menos una de
las claves públicas fijadas.
</p>
<p>
Ten en cuenta que, cuando uses la fijación de certificados, siempre debes incluir una clave
de respaldo para que, si te ves obligado a cambiar a claves nuevas o a cambiar de CA (cuando
fijas un certificado de CA o un intermediario de esa CA), la conectividad
de la aplicación no se vea afectada. Si no, deberás actualizar
la aplicación para recuperar la conectividad.
</p>
<p>
Además, se puede configurar un tiempo de expiración para las fijaciones,
luego del cual las fijaciones dejan de realizarse. Esto ayuda a evitar los problemas de conectividad
en aplicaciones que no se han actualizado. Sin embargo, configurar un tiempo de expiración
para las fijaciones puede habilitar la omisión de fijaciones.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;domain-config&gt;
&lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
&lt;pin-set expiration="2018-01-01"&gt;
&lt;pin digest="SHA-256"&gt;7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=&lt;/pin&gt;
&lt;!-- backup pin --&gt
&lt;pin digest="SHA-256"&gt;fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=&lt;/pin&gt;
&lt;/pin-set&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<h2 id="ConfigInheritance">Comportamiento de herencia de configuración</h2>
<p>
Los valores que no se establecen en una configuración específica se heredan. Este comportamiento permite configuraciones
más complejas y un archivo de configuración de fácil lectura.
</p>
<p>
Si no se establece un valor en una entrada específica, se usa el valor de
la siguiente entrada más general. Los valores no establecidos en una {@code domain-config} se
toman de la {@code domain-config} primaria, si están anidados, o de la {@code
base-config}, si no están anidados. Los valores no establecidos en la {@code base-config} usan
los valores predeterminados de la plataforma.
</p>
<p>
Por ejemplo, cuando todas las conexiones a subdominios de {@code
example.com} deben usar un conjunto personalizado de CA. Además, el tráfico de Cleartext a
estos dominios se permite <em>excepto</em> con las conexiones a {@code
secure.example.com}. Anidando la configuración para {@code
secure.example.com} dentro de la configuración para {@code example.com},
{@code trust-anchors} no necesita duplicación.
</p>
<p>
<code>res/xml/network_security_config.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;domain-config&gt;
&lt;domain includeSubdomains="true"&gt;example.com&lt;/domain&gt;
&lt;trust-anchors&gt;
&lt;certificates src="@raw/my_ca"/&gt;
&lt;/trust-anchors&gt;
&lt;domain-config cleartextTrafficPermitted="false"&gt;
&lt;domain includeSubdomains="true"&gt;secure.example.com&lt;/domain&gt;
&lt;/domain-config&gt;
&lt;/domain-config&gt;
&lt;/network-security-config&gt;
</pre>
</p>
<h2 id="FileFormat">Formato del archivo de configuración</h2>
<p>
La función de configuración de seguridad de la red usa un formato de archivo XML.
La estructura general del archivo se muestra en el siguiente ejemplo de código:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;network-security-config&gt;
&lt;base-config&gt;
&lt;trust-anchors&gt;
&lt;certificates src="..."/&gt;
...
&lt;/trust-anchors&gt;
&lt;/base-config&gt;
&lt;domain-config&gt;
&lt;domain&gt;android.com&lt;/domain&gt;
...
&lt;trust-anchors&gt;
&lt;certificates src="..."/&gt;
...
&lt;/trust-anchors&gt;
&lt;pin-set&gt;
&lt;pin digest="..."&gt;...&lt;/pin&gt;
...
&lt;/pin-set&gt;
&lt;/domain-config&gt;
...
&lt;debug-overrides&gt;
&lt;trust-anchors&gt;
&lt;certificates src="..."/&gt;
...
&lt;/trust-anchors&gt;
&lt;/debug-overrides&gt;
&lt;/network-security-config&gt;
</pre>
<p>
Las siguientes secciones describen la sintaxis y otros detalles del formato
de archivo.
</p>
<h3 id="network-security-config">
&lt;network-security-config&gt;
</h3>
<dl class="xml">
<dt>
PUEDE CONTENER:
</dt>
<dd>
0 o 1 de <code><a href="#base-config">&lt;base-config&gt;</a></code><br>
Cualquier cantidad de <code><a href=
"#domain-config">&lt;domain-config&gt;</a></code><br>
0 o 1 de <code><a href="#debug-overrides">&lt;debug-overrides&gt;</a></code>
</dd>
</dl>
<h3 id="base-config">
&lt;base-config&gt;
</h3>
<dl class="xml">
<dt>
SINTAXIS:
</dt>
</dl>
<pre class="stx">
&lt;base-config <a href=
"#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
...
&lt;/base-config&gt;
</pre>
<dl class="xml">
<dt>
PUEDE CONTENER:
</dt>
<dd>
<code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
</dd>
<dt>
DESCRIPCIÓN:
</dt>
<dd>
La configuración predeterminada usada por todas las conexiones cuyo destino no
está cubierto por una <a href="#domain-config"><code>domain-config</code></a>.
<p>
Los valores que no están configurados usan los valores predeterminados de la plataforma. La configuración predeterminada
para aplicaciones con API nivel 24 o superior es:
</p>
<pre>
&lt;base-config usesCleartextTraffic="true"&gt;
&lt;trust-anchors&gt;
&lt;certificates src="system" /&gt;
&lt;/trust-anchors&gt;
&lt;/base-config&gt;
</pre>
La configuración predeterminada para aplicaciones con API nivel 23 o inferior es:
<pre>
&lt;base-config usesCleartextTraffic="true"&gt;
&lt;trust-anchors&gt;
&lt;certificates src="system" /&gt;
&lt;certificates src="user" /&gt;
&lt;/trust-anchors&gt;
&lt;/base-config&gt;
</pre>
</dd>
</dl>
<h3 id="domain-config">&lt;domain-config&gt;</h3>
<dl class="xml">
<dt>SINTAXIS:</dt>
<dd>
<pre class="stx">&lt;domain-config <a href="#usesCleartextTraffic">usesCleartextTraffic</a>=["true" | "false"]&gt;
...
&lt;/domain-config&gt;</pre>
</dd>
<dt>PUEDE CONTENER:</dt>
<dd>
1 o más <code><a href="#domain">&lt;domain&gt;</a></code>
<br/>0 o 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
<br/>0 o 1 <code><a href="#pin-set">&lt;pin-set&gt;</code></a>
<br/>Cualquier cantidad de <code>&lt;domain-config&gt;</code> anidadas</dd>
<dt>DESCRIPCIÓN</dt>
<dd>Configuración usada para conexiones con destinos específicos, como los definidos por elementos de {@code domain}.
<p>Ten en cuenta que, si múltiples elementos de {@code domain-config} cubren un destino, la configuración con la regla de coincidencia de dominio más específica (más larga)
es la que se usa.</p></dd>
</dl>
<h3 id="domain">&lt;domain&gt;</h3>
<dl class="xml">
<dt>
SINTAXIS:
</dt>
<dd>
<pre class="stx">
&lt;domain includeSubdomains=["true" | "false"]&gt;example.com&lt;/domain&gt;
</pre>
</dd>
<dt>
ATRIBUTOS:
</dt>
<dd>
<dl class="attr">
<dt>
{@code includeSubdomains}
</dt>
<dd>
Si es {@code "true"}, esta regla de dominio coincide con el dominio
y con todos los subdominios, incluidos los subdominios de subdominios. Si no, la regla
solo se aplica a coincidencias exactas.
</dd>
</dl>
</dd>
<dt>
DESCRIPCIÓN:
</dt>
</dl>
<h3 id="debug-overrides">&lt;debug-overrides&gt;</h3>
<dl class="xml">
<dt>
sintaxis:
</dt>
<dd>
<pre class="stx">
&lt;debug-overrides&gt;
...
&lt;/debug-overrides&gt;
</pre>
</dd>
<dt>
PUEDE CONTENER:
</dt>
<dd>
0 o 1 <code><a href="#trust-anchors">&lt;trust-anchors&gt;</a></code>
</dd>
<dt>
DESCRIPCIÓN:
</dt>
<dd>
Sobrescrituras que se deben aplicar cuando <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
es {@code "true"}, que es, generalmente, el caso de las compilaciones que no sean de lanzamiento
generadas por herramientas de IDE y de compilación. Los anclajes de confianza especificados en {@code
debug-overrides} se agregan a todas las demás configuraciones, y la fijación
de certificados no se lleva a cabo cuando la cadena de certificados del servidor usa uno de estos
anclajes de confianza de solo depuración. Si <a href="{@docRoot}guide/topics/manifest/application-element.html#debug">android:debuggable</a>
es {@code "false"}, entonces, esta sección se omite por completo.
</dd>
</dl>
<h3 id="trust-anchors">&lt;trust-anchors&gt;</h3>
<dl class="xml">
<dt>
SINTAXIS:
</dt>
<dd>
<pre class="stx">
&lt;trust-anchors&gt;
...
&lt;/trust-anchors&gt;
</pre>
</dd>
<dt>
PUEDE CONTENER:
</dt>
<dd>
Cualquier cantidad de <code><a href="#certificates">&lt;certificates&gt;</a></code>
</dd>
<dt>
DESCRIPCIÓN:
</dt>
<dd>
Conjunto de anclajes de confianza para conexiones seguras.
</dd>
</dl>
<h3 id="certificates">&lt;certificates&gt;</h3>
<dl class="xml">
<dt>SINTAXIS:</dt>
<dd><pre class="stx">&lt;certificates src=["system" | "user" | "<i>raw resource</i>"]
overridePins=["true" | "false"] /&gt;
</pre></dd>
<dt>DESCRIPCIÓN:</dt>
<dd>Conjunto de certificados X.509 para elementos de {@code trust-anchors}.</dd>
<dt>ATRIBUTOS:</dt>
<dd><dl class="attr">
<dt>{@code src}</dt>
<dd>
La fuente de los certificados de CA puede ser una de las siguientes opciones:
<ul>
<li>Una ID de recurso sin procesar que apunta a un archivo que contiene certificados X.509.
Los certificados deben estar codificados en formato DER o PEM. En el caso de los certificados
PEM, el archivo <em>no debe</em> contener datos adicionales que no sean de PEM, como
comentarios.
</li>
<li>{@code "system"} para los certificados de CA preinstalados del sistema.
</li>
<li>{@code "user"} para los certificados de CA agregados por el usuario.
</li>
</ul>
</dd>
<dt>{@code overridePins}</dt>
<dd>
<p>
Especifica si las CA de esta fuente omiten la fijación de certificados. Si es {@code
"true"}, las cadenas de certificados se encadenan mediante una de estas CA
desde esta fuente, y la fijación no se lleva a cabo. Esto puede ser útil para CA de depuración
o para poder permitirle al usuario hacer un ataque MiTM al tráfico seguro de la aplicación.
</p>
<p>
Es {@code "false"} de forma predeterminada, a menos que se especifique en un elemento de {@code debug-overrides}
, en cuyo caso, es {@code "true"} de forma predeterminada.
</p>
</dd>
</dl>
</dd>
<h3 id="pin-set">&lt;pin-set&gt;</h3>
<dl class="xml">
<dt>
SINTAXIS:
</dt>
<dd>
<pre class="stx">
&lt;pin-set expiration="date"&gt;
...
&lt;/pin-set&gt;
</pre>
</dd>
<dt>
PUEDE CONTENER:
</dt>
<dd>
Cualquier cantidad de <code><a href="#pin">&lt;pin&gt;</a></code>
</dd>
<dt>
DESCRIPCIÓN:
</dt>
<dd>
Un conjunto de fijaciones de claves públicas. Para que una conexión segura sea de confianza, una de las
claves públicas de la cadena de confianza debe estar en el conjunto de fijaciones. Consulta
<code><a href="#pin">&lt;pin&gt;</a></code> para el formato de las fijaciones.
</dd>
<dt>
ATRIBUTOS:
</dt>
<dd>
<dl class="attr">
<dt>
{@code expiration}
</dt>
<dd>
La fecha, en formato {@code yyyy-MM-dd}, a partir de la cual
expiran las fijaciones, lo cual deshabilita la fijación. Si el atributo no está establecido, las fijaciones
no expiran.
<p>
La expiración ayuda a evitar problemas de conectividad en aplicaciones que no
reciben actualizaciones para el conjunto de fijaciones, por ejemplo, porque el usuario
deshabilitó las actualizaciones de la aplicación.
</p>
</dd>
</dl>
</dd>
</dl>
<h3 id="pin">&lt;pin&gt;</h3>
<dl class="xml">
<dt>
sintaxis:
</dt>
<dd>
<pre class="stx">
&lt;pin digest=["SHA-256"]&gt;base64 encoded digest of X.509
SubjectPublicKeyInfo (SPKI)&lt;/pin&gt;
</pre>
</dd>
<dt>
ATRIBUTOS:
</dt>
<dd>
<dl class="attr">
<dt>
{@code digest}
</dt>
<dd>
Resumen del algoritmo usado para generar la fijación. Actualmente, solo se admite
{@code "SHA-256"}.
</dd>
</dl>
</dd>
</dl>

View File

@@ -1,234 +0,0 @@
page.title=Ahorro de datos
metaDescription=User-enabled data usage optimization.
page.keywords="android N", "data usage", "metered network"
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>
En este documento
</h2>
<ol>
<li>
<a href="#status">Verificación de las preferencias de ahorro de datos</a>
<ol>
<li>
<a href="#request-whitelist">Solicitud de permisos de lista blanca</a>
</li>
</ol>
</li>
<li>
<a href="#monitor-changes">Control de cambios en las preferencias
de ahorro de datos</a>
</li>
<li>
<a href="#testing">Pruebas con comandos de Android Debug Bridge</a>
</li>
</ol>
</div>
</div>
<p>
Durante la vida útil de un smartphone, el costo de un plan de datos móviles puede
superar fácilmente el costo del propio dispositivo. En la versión N Developer Preview, los usuarios pueden
habilitar el ahorro de datos en todo el dispositivo a fin de reducir el uso de datos, ya sea con
servicio de itinerancia, cerca del final del ciclo de facturación o con un pequeño paquete de datos prepago.
</p>
<p>
Cuando un usuario habilita el ahorro de datos en <strong>Settings</strong> y el dispositivo está conectado
a una red de uso medido, el sistema bloquea el uso de datos en segundo plano y envía señales
a las aplicaciones para que utilicen menos datos en primer plano siempre que sea posible. Los usuarios pueden
incluir aplicaciones específicas en la lista blanca para permitir el uso de datos medidos en segundo plano, incluso cuando está activado el ahorro
de datos.
</p>
<p>
La N Developer Preview extiende la API {@link android.net.ConnectivityManager}
para que las aplicaciones puedan <a href="#status">recuperar las preferencias de
ahorro de datos del usuario</a> y <a href="#monitor-changes">controlar
los cambios en las preferencias</a>. Se considera una buena práctica que las aplicaciones verifiquen si el
usuario habilitó el ahorro de datos y se esfuercen por reducir el uso de datos en primer
y segundo plano.
</p>
<h2 id="status">
Verificación de las preferencias de ahorro de datos
</h2>
<p>
En la N Developer Preview, las aplicaciones pueden utilizar la API {@link
android.net.ConnectivityManager} para determinar qué restricciones
de uso de datos se aplican. Mediante el método {@code getRestrictBackgroundStatus()}
, se devuelve uno de los siguientes valores:
</p>
<dl>
<dt>
{@code RESTRICT_BACKGROUND_STATUS_DISABLED}
</dt>
<dd>
El ahorro de datos está inhabilitado.
</dd>
<dt>
{@code RESTRICT_BACKGROUND_STATUS_ENABLED}
</dt>
<dd>
El usuario habilitó el ahorro de datos para esta aplicación. Las aplicaciones deben esforzarse por reducir
el uso de datos en primer plano y manejar correctamente las restricciones para
el uso de datos en segundo plano.
</dd>
<dt>
{@code RESTRICT_BACKGROUND_STATUS_WHITELISTED}
</dt>
<dd>
El usuario habilitó el ahorro de datos, pero la aplicación se encuentra en la lista blanca. Las aplicaciones aún deben
esforzarse por reducir el uso de datos en primer y segundo plano.
</dd>
</dl>
<p>
Se considera una buena práctica limitar el uso de datos siempre que el dispositivo esté
conectado a una red de uso medido, incluso si el ahorro de datos está deshabilitado o la aplicación
se encuentra en la lista blanca. El siguiente código de muestra utiliza {@link
android.net.ConnectivityManager#isActiveNetworkMetered
ConnectivityManager.isActiveNetworkMetered()} y {@code
ConnectivityManager.getRestrictBackgroundStatus()} para determinar la cantidad de datos
que la aplicación debe utilizar:
</p>
<pre>
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Checks if the device is on a metered network
if (connMgr.isActiveNetworkMetered()) {
// Checks users Data Saver settings.
switch (connMgr.getRestrictBackgroundStatus()) {
case RESTRICT_BACKGROUND_STATUS_ENABLED:
// Background data usage is blocked for this app. Wherever possible,
// the app should also use less data in the foreground.
case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
// The app is whitelisted. Wherever possible,
// the app should use less data in the foreground and background.
case RESTRICT_BACKGROUND_STATUS_DISABLED:
// Data Saver is disabled. Since the device is connected to a
// metered network, the app should use less data wherever possible.
}
} else {
// The device is not on a metered network.
// Use data as required to perform syncs, downloads, and updates.
}
</pre>
<h3 id="request-whitelist">
Solicitud de permisos de lista blanca
</h3>
<p>
Si la aplicación necesita utilizar datos en segundo plano, esta puede solicitar permisos de
lista blanca mediante el envío de una intent
<code>Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS</code>
que contenga un URI del nombre de paquete de la aplicación, como por ejemplo,
<code>package:MY_APP_ID</code>.
</p>
<p>
Mediante el envío de la intent y el URI, se inicia la aplicación <strong>Settings</strong> y
se muestra la configuración de uso de datos para la aplicación. El usuario luego puede decidir si
habilita los datos en segundo plano para la aplicación. Antes de enviar esta intent, resulta
buena práctica consultarle primero al usuario acerca de si desea iniciar la aplicación
<strong>Settings</strong> con el objetivo de habilitar el uso de datos
en segundo plano.
</p>
<h2 id="monitor-changes">
Control de cambios en las preferencias de ahorro de datos
</h2>
<p>
Las aplicaciones pueden controlar los cambios en las preferencias de ahorro de datos mediante la creación de un {@link
android.content.BroadcastReceiver} para escuchar {@code
ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} y mediante un registro
dinámico del receptor con {@link android.content.Context#registerReceiver
Context.registerReceiver()}. Cuando una aplicación recibe esta transmisión, debe
<a href="#status">verificar si las nuevas preferencias de ahorro de datos afectan los
permisos; para ello,</a> la aplicación debe llamar a {@code
ConnectivityManager.getRestrictBackgroundStatus()}.
</p>
<p class="note">
<strong>Nota:</strong> El sistema únicamente envía esta transmisión a las aplicaciones que
se registran dinámicamente para recibirla con {@link
android.content.Context#registerReceiver Context.registerReceiver()}. Las aplicaciones
que en su manifiesto registran que la reciben no la
recibirán.
</p>
<h2 id="testing">
Pruebas con comandos de Android Debug Bridge
</h2>
<a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (ADB)</a>
ofrece algunos comandos que puedes utilizar para verificar y configurar los permisos
de red:
<dl>
<dt>
<code>$ adb shell dumpsys netpolicy</code>
</dt>
<dd>
Se genera un informe en el que se incluyen la configuración global actual de restricciones de red
en segundo plano, los UID de paquetes que se encuentran actualmente en una lista blanca y los permisos
de red de otros paquetes conocidos.
</dd>
<dt>
<code>$ adb shell cmd netpolicy</code>
</dt>
<dd>
Se muestra una lista completa de los comandos del administrador de políticas de red (políticas de red).
</dd>
<dt>
<code>$ adb shell cmd netpolicy set restrict-background
&lt;boolean&gt;</code>
</dt>
<dd>
Se habilita o deshabilita el modo de ahorro de datos cuando se asignan los valores <code>true</code> o
<code>false</code>, respectivamente.
</dd>
<dt>
<code>$ adb shell cmd netpolicy add restrict-background-whitelist
&lt;UID&gt;</code>
</dt>
<dd>
Se agrega el UID del paquete específico a la lista blanca para permitir el uso de datos
medidos en segundo plano.
</dd>
<dt>
<code>$ adb shell cmd netpolicy remove restrict-background-whitelist
&lt;UID&gt;</code>
</dt>
<dd>
Se quita el UID del paquete específico de la lista blanca para bloquear el uso de datos
medidos en segundo plano mientras el ahorro de datos está habilitado.
</dd>
</dl>

View File

@@ -1,550 +0,0 @@
page.title=Definir animaciones personalizadas
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Touch">Personalizar la respuesta táctil</a></li>
<li><a href="#Reveal">Usar el efecto Revelar</a></li>
<li><a href="#Transitions">Personalizar transiciones de actividades</a></li>
<li><a href="#ViewState">Animar cambios de estados de las vistas</a></li>
<li><a href="#AnimVector">Animar interfaces dibujables en vector</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Las animaciones en Material Design proporcionan a los usuarios comentarios sobre sus acciones y continuidad visual
a medida que los usuarios interactúan con su aplicación. El tema material proporciona algunas animaciones predeterminadas
para botones y transiciones de actividades; Android 5.0 (API nivel 21) y superior te permite personalizar estas
animaciones y crear unas nuevas:</p>
<ul>
<li>Respuesta táctil</li>
<li>Efecto revelar circular</li>
<li>Transiciones de actividades</li>
<li>Movimiento curvo</li>
<li>Ver cambios de estados</li>
</ul>
<h2 id="Touch">Personalizar la respuesta táctil</h2>
<p>La respuesta táctil en Material Design proporciona una confirmación visual instantánea en el punto
de contacto cuando los usuarios interactúan con los elementos de la IU. Las animaciones predeterminadas de la respuesta táctil para
botones usan la nueva clase {@link android.graphics.drawable.RippleDrawable}, que realiza una transición
entre diferentes estados con un efecto de ondas.</p>
<p>En la mayoría de los casos, debes aplicar esta funcionalidad en la vista XML especificando el fondo
de la vista como:</p>
<ul>
<li><code>?android:attr/selectableItemBackground</code> para un efecto de ondas con límites.</li>
<li><code>?android:attr/selectableItemBackgroundBorderless</code> para un efecto de ondas que se extiende más allá de
la vista. Se lo dibujará en la vista primaria más cercana de la vista (que lo limitará) con un fondo de valor no
nulo.</li>
</ul>
<p class="note"><strong>Nota:</strong> <code>selectableItemBackgroundBorderless</code> es un nuevo
atributo introducido en la API de nivel 21.</p>
<p>Alternativamente, puedes definir un {@link android.graphics.drawable.RippleDrawable}
como un recurso XML que usa el elemento <code>ripple</code>.</p>
<p>Puedes asignar un color a los objetos {@link android.graphics.drawable.RippleDrawable}. Para cambiar
el color predeterminado de la respuesta táctil, usa el atributo <code>android:colorControlHighlight</code>
del tema.</p>
<p>Para más información, consulta la referencia de la API para la clase {@link
android.graphics.drawable.RippleDrawable}.</p>
<h2 id="Reveal">Usar el efecto revelar</h2>
<p>Las animaciones del efecto revelar proporcionan a los usuarios una continuidad visual cuando muestras u ocultas un grupo de elementos
de la IU. El método {@link android.view.ViewAnimationUtils#createCircularReveal
ViewAnimationUtils.createCircularReveal()} te permite animar un círculo de recorte para
revelar u ocultar una vista.</p>
<p>Para revelar una vista previamente invisible usando este efecto:</p>
<pre>
// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
</pre>
<p>Para ocultar una vista previamente invisible usando este efecto:</p>
<pre>
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
&#64;Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
</pre>
<h2 id="Transitions">Personalizar transiciones de actividades</h2>
<!-- shared transition video -->
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay="">
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4">
<source src="{@docRoot}design/material/videos/ContactsAnim.webm">
<source src="{@docRoot}design/material/videos/ContactsAnim.ogv">
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Figura 1</strong>: una
transición con elementos compartidos.</p>
<em>Para volver a reproducir la película, haz clic en la pantalla del dispositivo.</em>
</div>
</div>
<p>Las transiciones de actividades en las aplicaciones de Material Design proporcionan conexiones visuales entre diferentes estados
mediante el movimiento y las transformaciones entre elementos comunes. Puedes especificar las animaciones personalizadas para
entrar y salir de las transiciones y para las transiciones de elementos compartidos entre actividades.</p>
<ul>
<li>Una transición de <strong>entrada</strong> determina cómo entran en escena las vistas en una actividad.
Por ejemplo, en la transición de entrada <em>expandir</em>, las vistas entran en escena desde el exterior
y vuelan hacia el centro de la pantalla.</li>
<li>Una transición de <strong>salida</strong> determina cómo salen de escena las vistas en una actividad. Por
ejemplo, en la transición de salida <em>expandir</em>, las vistas salen de escena lejos del
centro.</li>
<li>Una transición de <strong>elementos compartidos</strong> determina cómo las vistas que están compartidas entre
dos actividades realizan la transición entre estas. Por ejemplo, si dos actividades tienen la misma
imagen en diferentes posiciones y tamaños, la transición de elementos compartidos <em>changeImageTransform</em>
traduce y escala la imagen suavemente entre estas actividades.</li>
</ul>
<p>Android 5.0 (API nivel 21) admite estas transiciones de entrada y salida:</p>
<ul>
<li><em>expandir</em>: desplaza vistas hacia adentro o hacia afuera del centro de la escena.</li>
<li><em>deslizar</em>: desplaza vistas hacia adentro o hacia afuera de uno de los bordes de la escena.</li>
<li><em>difuminar</em>: agrega o quita una vista de la escena al cambiar su opacidad.</li>
</ul>
<p>Toda transición que extiende la clase {@link android.transition.Visibility} se admite
como una transición de entrada o salida. Para más información, consulta la referencia de la API para la clase
{@link android.transition.Transition}.</p>
<p>Android 5.0 (API nivel 21) también admite estas transiciones de elementos compartidos:</p>
<ul>
<li><em>changeBounds</em>: anima los cambios en los límites de las vistas de destino.</li>
<li><em>changeClipBounds</em>: anima los cambios en los límites de recorte de las vistas de destino.</li>
<li><em>changeTransform</em>: anima los cambios en escala y rotación de las vistas de destino.</li>
<li><em>changeImageTransform</em>: anima los cambios de tamaño y escala de imágenes de destino.</li>
</ul>
<p>Cuando habilitas las transiciones de actividades en tu aplicación, la transición entre difuminados predeterminada se
activa entre las actividades que ingresan y salen.</p>
<img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" />
<p class="img-caption">
  <strong>Figura 2</strong>: una transición de escena con un elemento compartido.
</p>
<h3>Especificar transiciones personalizadas</h3>
<p>Primero, habilita las transiciones de contenido de la ventana con el atributo <code>android:windowContentTransitions</code>
cuando definas un estilo que herede del tema material. También puedes especificar
transiciones de entrada, salida y elementos compartidos en tu definición de estilo:</p>
<pre>
&lt;style name="BaseAppTheme" parent="android:Theme.Material">
&lt;!-- enable window content transitions -->
&lt;item name="android:windowContentTransitions">true&lt;/item>
&lt;!-- specify enter and exit transitions -->
&lt;item name="android:windowEnterTransition">@transition/explode&lt;/item>
&lt;item name="android:windowExitTransition">@transition/explode&lt;/item>
&lt;!-- specify shared element transitions -->
&lt;item name="android:windowSharedElementEnterTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;item name="android:windowSharedElementExitTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;/style>
</pre>
<p>La transición <code>change_image_transform</code> en este ejemplo se define en la siguiente forma:</p>
<pre>
&lt;!-- res/transition/change_image_transform.xml -->
&lt;!-- (see also Shared Transitions below) -->
&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
&lt;changeImageTransform/>
&lt;/transitionSet>
</pre>
<p>El elemento <code>changeImageTransform</code> corresponde a la clase
{@link android.transition.ChangeImageTransform}. Para más información, consulta la referencia de la
API para {@link android.transition.Transition}.</p>
<p>Para habilitar las transiciones del contenido de las ventanas en tu código, llama al método
{@link android.view.Window#requestFeature Window.requestFeature()}:</p>
<pre>
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an exit transition
getWindow().setExitTransition(new Explode());
</pre>
<p>Para especificar transiciones en tu código, llama a estos métodos con un objeto {@link
android.transition.Transition}:</p>
<ul>
<li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li>
<li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li>
<li>{@link android.view.Window#setSharedElementEnterTransition
Window.setSharedElementEnterTransition()}</li>
<li>{@link android.view.Window#setSharedElementExitTransition
Window.setSharedElementExitTransition()}</li>
</ul>
<p>Los métodos {@link android.view.Window#setExitTransition setExitTransition()} y {@link
android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} definen
la transición de salida para la actividad que realiza la llamada. Los métodos {@link android.view.Window#setEnterTransition
setEnterTransition()} y {@link android.view.Window#setSharedElementEnterTransition
setSharedElementEnterTransition()} definen la transición de entrada para la actividad invocada.</p>
<p>Para obtener el efecto completo de una transición, debes habilitar las transiciones de contenido de las ventanas tanto para las
actividades que realizan la llamada como para aquellas que son invocadas. De lo contrario, la actividad que realiza la llamada comenzará la transición de salida,
pero luego observarás una ventana de transición (como escalar o difuminar).</p>
<p>Para comenzar una transición de entrada lo antes posible, usa el método
{@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()}
en la actividad invocada. Esto te permite tener transiciones de entrada más intensas.</p>
<h3>Iniciar una actividad mediante el uso de transiciones</h3>
<p>Si permites transiciones y estableces una transición de salida para una actividad, la transición se activa
cuando inicias otra actividad, como alguna de las siguientes:</p>
<pre>
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
</pre>
<p>Si estableciste una transición de entrada para la segunda actividad, la transición también se activa
cuando se inicia la actividad. Para deshabilitar las transiciones cuando inicias otra actividad, proporciona
una agrupación de opciones <code>null</code>.</p>
<h3>Iniciar una actividad con un elemento compartido</h3>
<p>Para realizar una animación de transiciones de pantallas entre dos actividades que tienen un elemento compartido:</p>
<ol>
<li>Habilita las transiciones de contenido de ventanas en tu tema.</li>
<li>Especifica una transición de elementos compartidos en tu estilo.</li>
<li>Define tu transición como un recurso XML.</li>
<li>Asigna un nombre en común para los elementos compartidos en ambos diseños con el atributo
<code>android:transitionName</code>.</li>
<li>Usa el método {@link android.app.ActivityOptions#makeSceneTransitionAnimation
ActivityOptions.makeSceneTransitionAnimation()}.</li>
</ol>
<pre>
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);
// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);
// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
&#64;Override
public void onClick(View view) {
Intent intent = new Intent(this, Activity2.class);
// create the transition animation - the images in the layouts
// of both activities are defined with android:transitionName="robot"
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, androidRobotView, "robot");
// start the new activity
startActivity(intent, options.toBundle());
}
});
</pre>
<p>Para las vistas dinámicas compartidas que generas en tu código, usa el método
{@link android.view.View#setTransitionName View.setTransitionName()} para especificar un nombre de
elemento en común en ambas actividades.</p>
<p>Para invertir la animación de transición de escenas cuando terminas la segunda actividad, llama al método
{@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()}
en lugar del {@link android.app.Activity#finish Activity.finish()}.</p>
<h3>Iniciar una actividad con múltiples elementos compartidos</h3>
<p>Para realizar una animación de transición de escenas entre dos actividades que tienen más de un elemento
compartido, define los elementos compartidos en ambos diseños con el atributo <code>android:transitionName</code>
(o usa el método {@link android.view.View#setTransitionName View.setTransitionName()}
en ambas actividades) y crea un objeto {@link android.app.ActivityOptions} como se indica a continuación:</p>
<pre>
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));
</pre>
<h2 id="CurvedMotion">Usar movimiento curvo</h2>
<p>Las animaciones en Material Design se basan en curvas para la interpolación de tiempo y los modelos de movimiento
espacial. Con Android 5.0 (API nivel 21) y superior, puedes definir las curvas de sincronización personalizadas y
los modelos de movimientos curvos para las animaciones.</p>
<p>La clase {@link android.view.animation.PathInterpolator} es un nuevo interpolador que se basa en una curva
Bézier o un objeto {@link android.graphics.Path}. Este interpolador especifica una curva de movimiento
en un cuadrado de 1x1, con puntos de anclaje a (0,0) y (1,1), y puntos de control según lo especificado en los argumentos del
constructor. También puedes definir un interpolador para la ruta de acceso como un recurso XML:</p>
<pre>
&lt;pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.4"
android:controlY1="0"
android:controlX2="1"
android:controlY2="1"/>
</pre>
<p>El sistema proporciona recursos XML para las tres curvas básicas en la especificación
de Material Design:</p>
<ul>
<li><code>&#64;interpolator/fast_out_linear_in.xml</code></li>
<li><code>&#64;interpolator/fast_out_slow_in.xml</code></li>
<li><code>&#64;interpolator/linear_out_slow_in.xml</code></li>
</ul>
<p>Puedes pasar un objeto {@link android.view.animation.PathInterpolator} al método {@link
android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p>
<p>La clase {@link android.animation.ObjectAnimator} tiene nuevos constructores que te permiten animar
coordenadas junto a una ruta de acceso, usando dos o más propiedades a la vez. Por ejemplo, el siguiente animador
usa un objeto{@link android.graphics.Path} para animar las propiedades X e Y de una vista:</p>
<pre>
ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();
</pre>
<h2 id="ViewState">Animar cambios de estados de las vistas</h2>
<p>La clase {@link android.animation.StateListAnimator} te permite definir los animadores que se ejecutan cuando
cambia el estado de una vista. En el siguiente ejemplo, se muestra cómo definir un {@link
android.animation.StateListAnimator} como un recurso XML:</p>
<pre>
&lt;!-- animate the translationZ property of a view when pressed -->
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:state_pressed="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="2dp"
android:valueType="floatType"/>
&lt;!-- you could have other objectAnimator elements
here for "x" and "y", or other properties -->
&lt;/set>
&lt;/item>
&lt;item android:state_enabled="true"
android:state_pressed="false"
android:state_focused="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="100"
android:valueTo="0"
android:valueType="floatType"/>
&lt;/set>
&lt;/item>
&lt;/selector>
</pre>
<p>Para adjuntar animaciones personalizadas de los estados de visualizaciones, define un animador usando el elemento
<code>selector</code> en un archivo de recurso XML como en este ejemplo y asígnalo a tu
vista con el atributo <code>android:stateListAnimator</code>. Para asignar un animador de lista de estados
a una vista en tu código, usa el método {@link android.animation.AnimatorInflater#loadStateListAnimator
AnimationInflater.loadStateListAnimator()} y asigna el animador a tu vista con el método
{@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p>
<p>Cuando tu tema extiende al tema material, los botones tendrán una animación Z de manera predeterminada. Para evitar este
comportamiento en los botones, establece el atributo <code>android:stateListAnimator</code> en
<code>@null</code>.</p>
<p>La clase {@link android.graphics.drawable.AnimatedStateListDrawable} te permite crear elementos de diseño
que muestren animaciones entre los cambios de estados de la vista asociada. Algunos de los widgets del sistema en
Android 5.0 usan estas animaciones de manera predeterminada. En el siguiente ejemplo, se muestra cómo
definir un {@link android.graphics.drawable.AnimatedStateListDrawable} como un recurso XML:</p>
<pre>
&lt;!-- res/drawable/myanimstatedrawable.xml -->
&lt;animated-selector
xmlns:android="http://schemas.android.com/apk/res/android">
&lt;!-- provide a different drawable for each state-->
&lt;item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
android:state_pressed="true"/>
&lt;item android:id="@+id/focused" android:drawable="@drawable/drawableF"
android:state_focused="true"/>
&lt;item android:id="@id/default"
android:drawable="@drawable/drawableD"/>
&lt;!-- specify a transition -->
&lt;transition android:fromId="@+id/default" android:toId="@+id/pressed">
&lt;animation-list>
&lt;item android:duration="15" android:drawable="@drawable/dt1"/>
&lt;item android:duration="15" android:drawable="@drawable/dt2"/>
...
&lt;/animation-list>
&lt;/transition>
...
&lt;/animated-selector>
</pre>
<h2 id="AnimVector">Animar interfaces dibujables en vector</h2>
<p>Las <a href="{@docRoot}training/material/drawables.html#VectorDrawables">interfaces dibujables en vector</a> son
escalables sin perder definición. La clase {@link android.graphics.drawable.AnimatedVectorDrawable}
te permite animar las propiedades de un elemento de diseño en vector.</p>
<p>Generalmente, las interfaces animadas dibujables en vector se definen en tres archivos XML:</p>
<ul>
<li>Una interfaz dibujable en vector con el elemento <code>&lt;vector&gt;</code> en
<code>res/drawable/</code></li>
<li>Una interfaz dibujable animada en vector con el elemento <code>&lt;animated-vector&gt;</code> en
<code>res/drawable/</code></li>
<li>Uno o más animadores de objeto con el elemento <code>&lt;objectAnimator&gt;</code> en
<code>res/anim/</code></li>
</ul>
<p>Las interfaces animadas dibujables en vector pueden animar los atributos de los elementos <code>&lt;group&gt;</code> y
<code>&lt;path&gt;</code>. Los elementos <code>&lt;group&gt;</code> definen un conjunto de
rutas de acceso o subgrupos y el elemento <code>&lt;path&gt;</code> define rutas de acceso para dibujar.</p>
<p>Cuando definas una interfaz dibujable en vector que desees animar, usa el atributo <code>android:name</code>
para asignar un nombre único a grupos o rutas de acceso, de manera que puedas hacer referencia a ellos desde tus definiciones del
animador. Por ejemplo:</p>
<pre>
&lt;!-- res/drawable/vectordrawable.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600">
&lt;group
<strong>android:name="rotationGroup"</strong>
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0" >
&lt;path
<strong>android:name="v"</strong>
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
&lt;/group>
&lt;/vector>
</pre>
<p>La definición de la interfaz animada dibujable en vector hace referencia a grupos y rutas de acceso en el elemento de diseño en vector
por sus nombres:</p>
<pre>
&lt;!-- res/drawable/animvectordrawable.xml -->
&lt;animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable" >
&lt;target
android:name="rotationGroup"
android:animation="@anim/rotation" />
&lt;target
android:name="v"
android:animation="@anim/path_morph" />
&lt;/animated-vector>
</pre>
<p>Las definiciones de animación representan objetos {@link android.animation.ObjectAnimator} o {@link
android.animation.AnimatorSet}. El primer animador en este ejemplo rota el grupo
objetivo unos 360 grados:</p>
<pre>
&lt;!-- res/anim/rotation.xml -->
&lt;objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
</pre>
<p>El segundo animador en este ejemplo transforma la ruta de acceso de la interfaz dibujable en vector de una forma a
otra. Ambas rutas de acceso deben ser compatibles para transformarse: deben tener el mismo número de comandos
y el mismo número de parámetros para cada comando.</p>
<pre>
&lt;!-- res/anim/path_morph.xml -->
&lt;set xmlns:android="http://schemas.android.com/apk/res/android">
&lt;objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />
&lt;/set>
</pre>
<p>Para más información, consulta la referencia de la API para {@link
android.graphics.drawable.AnimatedVectorDrawable}.</p>

View File

@@ -1,168 +0,0 @@
page.title=Mantener la compatibilidad
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Theme">Definir estilos alternativos</a></li>
<li><a href="#Layouts">Proporcionar diseños alternativos</a></li>
<li><a href="#SupportLib">Usar la Biblioteca de soporte</a></li>
<li><a href="#CheckVersion">Comprobar la versión del sistema</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Algunas características de Material Design, como el tema material y las transiciones de actividades personalizadas, solo
están disponibles en Android 5.0 (API nivel 21) y superior. Sin embargo, puedes diseñar tus aplicaciones para
usar estas características cuando se ejecutan en dispositivos que admiten Material Design y aún son compatibles
con dispositivos que ejecutan versiones anteriores de Android.</p>
<h2 id="Theme">Definir estilos alternativos</h2>
<p>Puedes configurar tu aplicación para usar el tema material en los dispositivos que los admiten y revertir
a un tema anterior en los dispositivos que ejecutan versiones anteriores de Android:</p>
<ol>
<li>Define un tema que herede de un tema anterior (como Holo) en
<code>res/values/styles.xml</code>.</li>
<li>Define un tema con el mismo nombre que hereda del tema material en
<code>res/values-v21/styles.xml</code>.</li>
<li>Establece este tema como el tema de tu aplicación en el archivo de manifiesto.</li>
</ol>
<p class="note"><strong>Nota:</strong>
Si tu aplicación usa el tema material pero no proporciona un tema alternativo,
tu aplicación no se ejecutará en versiones de Android anteriores a la versión 5.0.
</p>
<h2 id="Layouts">Proporcionar diseños alternativos</h2>
<p>Si los diseños que realizas de acuerdo con las pautas de Material Design no usan ninguno de
los nuevos atributos XML introducidos en Android 5.0 (API nivel 21), estos trabajarán en
versiones anteriores de Android. De lo contrario, puedes proporcionar diseños alternativos. También puedes proporcionar diseños
alternativos para personalizar la apariencia de tu aplicación en versiones anteriores de Android.</p>
<p>Crea tus archivos de diseño para Android 5.0 (API nivel 21) dentro de <code>res/layout-v21/</code> y
tus archivos de diseño alternativo para versiones anteriores de Android dentro de <code>res/layout/</code>.
Por ejemplo, <code>res/layout/my_activity.xml</code> es un diseño alternativo para
<code>res/layout-v21/my_activity.xml</code>.</p>
<p>Para evitar duplicación de código, define tus estilos en <code>res/values/</code>, modifica
estilos en <code>res/values-v21/</code> para las nuevas API y usa transmisión por herencia de estilos, definiendo estilos
base en <code>res/values/</code> y heredando de los que están en <code>res/values-v21/</code>.</p>
<h2 id="SupportLib">Usar la Biblioteca de soporte</h2>
<p>Las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de soporte v7</a>
r21 y superiores incluyen las siguientes características de Material Design:</p>
<ul>
<li><a href="{@docRoot}training/material/theme.html">Estilos de Material Design</a> para algunos widgets
del sistema cuando aplicas uno de los temas <code>Theme.AppCompat</code>.</li>
<li><a href="{@docRoot}training/material/theme.html#ColorPalette">Atributos del tema de la paleta de colores</a>
en los temas <code>Theme.AppCompat</code>.</li>
<li>El widget {@link android.support.v7.widget.RecyclerView} para <a href="{@docRoot}training/material/lists-cards.html#RecyclerView">mostrar conjuntos
de datos</a>.</li>
<li>El widget {@link android.support.v7.widget.CardView} para <a href="{@docRoot}training/material/lists-cards.html#CardView">crear tarjetas</a>.</li>
<li>La clase {@link android.support.v7.graphics.Palette} para <a href="{@docRoot}training/material/drawables.html#ColorExtract">extraer colores prominentes de
imágenes</a>.</li>
</ul>
<h3>Widgets del sistema</h3>
<p>Los temas <code>Theme.AppCompat</code> proporcionan estilos de Material Design para estos widgets:</p>
<ul>
<li>{@link android.widget.EditText}</li>
<li>{@link android.widget.Spinner}</li>
<li>{@link android.widget.CheckBox}</li>
<li>{@link android.widget.RadioButton}</li>
<li>{@link android.support.v7.widget.SwitchCompat}</li>
<li>{@link android.widget.CheckedTextView}</li>
</ul>
<h3>Paleta de colores</h3>
<p>Para obtener estilos de Material Design y personalizar la paleta de colores con la Biblioteca de soporte
v7 de Android, aplica uno de los temas <code>Theme.AppCompat</code>:</p>
<pre>
&lt;!-- extend one of the Theme.AppCompat themes -->
&lt;style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
&lt;!-- customize the color palette -->
&lt;item name="colorPrimary">@color/material_blue_500&lt;/item>
&lt;item name="colorPrimaryDark">@color/material_blue_700&lt;/item>
&lt;item name="colorAccent">@color/material_green_A200&lt;/item>
&lt;/style>
</pre>
<h3>Listas y tarjetas</h3>
<p>Los widgets {@link android.support.v7.widget.RecyclerView} y {@link
android.support.v7.widget.CardView} están disponible en versiones anteriores de Android mediante
la Biblioteca de soporte v7 con estas limitaciones:</p>
<ul>
<li>{@link android.support.v7.widget.CardView} regresa a una implementación de sombras programáticas
mediante el uso de espaciado adicional.</li>
<li>{@link android.support.v7.widget.CardView} no recorta las vistas de sus hijos que forman intersecciones
con esquinas redondeadas.</li>
</ul>
<h3>Dependencias</h3>
<p>Para usar estas características en versiones de Android anteriores a la 5.0 (API nivel 21), incluye
en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p>
<pre>
dependencies {
compile 'com.android.support:appcompat-v7:21.0.+'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>
<h2 id="CheckVersion">Comprobar la versión del sistema</h2>
<p>Las siguientes características están disponibles solo en Android 5.0 (nivel de API 21) y superior:</p>
<ul>
<li>Transiciones de actividades</li>
<li>Respuesta táctil</li>
<li>Animaciones con el efecto revelar</li>
<li>Animaciones basadas en rutas</li>
<li>Interfaces dibujables en vector</li>
<li>Matiz de la interfaz dibujable</li>
</ul>
<p>Para conservar la compatibilidad con versiones anteriores de Android, comprueba la {@link
android.os.Build.VERSION#SDK_INT version} del sistema en tiempo de ejecución antes de invocar las API para cualquiera de estas
características:</p>
<pre>
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Call some material design APIs here
} else {
// Implement this feature without material design
}
</pre>
<p class="note"><strong>Nota:</strong> Para especificar qué versiones de Android admite tu aplicación,
usa los atributos <code>android:minSdkVersion</code> y <code>android:targetSdkVersion</code>
en tu archivo de manifiesto. Para usar las características de Material Design en Android 5.0, establece el
atributo <code>android:targetSdkVersion</code> en <code>21</code>. Para más información, consulta
la <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">guía de &lt;uses-sdk&gt; de la
API</a>.</p>

View File

@@ -1,126 +0,0 @@
page.title=Trabajar con interfaces dibujables
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#DrawableTint">Cambiar el matiz de los recursos dibujables</a></li>
<li><a href="#ColorExtract">Extraer colores prominentes de una imagen</a></li>
<li><a href="#VectorDrawables">Crear interfaces dibujables en vector</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Diseño material en Android</a></li>
</ul>
</div>
</div>
<p>Las siguientes capacidades para las interfaces dibujables te ayudan a implementar Material Design en tus aplicaciones:</p>
<ul>
<li>Matiz de la interfaz dibujable</li>
<li>Extracción de color prominente</li>
<li>Interfaces dibujables en vector</li>
</ul>
<p>Esta lección te muestra cómo usar estas características en tu aplicación.</p>
<h2 id="DrawableTint">Cambiar el matiz de los recursos dibujables</h2>
<p>Con Android 5.0 (API nivel 21) y superior, puedes cambiar el matiz de los mapas de bits y nueve parches definidos como
máscaras alfa. Puedes cambiar el matiz con recursos de colores o atributos de temas que se resuelven a
recursos de colores (por ejemplo, <code>?android:attr/colorPrimary</code>). Generalmente, puedes crear estos recursos
solo una vez y agregarles color automáticamente para que coincidan con tu tema.</p>
<p>Puedes aplicar un matiz a los objetos {@link android.graphics.drawable.BitmapDrawable} o {@link
android.graphics.drawable.NinePatchDrawable} con el método {@code setTint()}. También puedes
establecer el color de matiz y el modo en tus diseños con los atributos <code>android:tint</code> y
<code>android:tintMode</code>.</p>
<h2 id="ColorExtract">Extraer colores prominentes de una imagen</h2>
<p>La Biblioteca de soporte de Android r21 y superiores incluye la clase {@link
android.support.v7.graphics.Palette}, que te permite extraer colores prominentes de una imagen.
Esta clase extrae los siguientes colores prominentes:</p>
<ul>
<li>Brillante</li>
<li>Oscuro brillante</li>
<li>Claro brillante</li>
<li>Apagado</li>
<li>Oscuro apagado</li>
<li>Claro apagado</li>
</ul>
<p>Para extraer estos colores, pasa un objeto {@link android.graphics.Bitmap} al método estático
{@link android.support.v7.graphics.Palette#generate Palette.generate()} en el subproceso en
segundo plano en donde cargas tus imágenes. Si no puedes usar dicho subproceso, llama al método
{@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} y proporciona
un gestor de eventos en su lugar.</p>
<p>Puedes recuperar los colores prominentes de la imagen mediante los métodos de obtención en la clase
<code>Palette</code>, como <code>Palette.getVibrantColor</code>.</p>
<p>Para usar la clase {@link android.support.v7.graphics.Palette} en tu proyecto, agrega la siguiente
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Dependencia Gradle</a> al módulo de
tu aplicación:</p>
<pre>
dependencies {
...
compile 'com.android.support:palette-v7:21.0.0'
}
</pre>
<p>Para más información, consulta la referencia de la API para la clase {@link android.support.v7.graphics.Palette}.
</p>
<h2 id="VectorDrawables">Crear interfaces dibujables en vector</h2>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=wlFVIIstKmA" style="margin-top:18px">
<div>
<h3>Video</h3>
<p>Gráficos en vector de Android</p>
</div>
</a>
<p>En Android 5.0 (API nivel 21) y superiores, puedes definir las interfaces dibujables en vector, que escalan sin
perder definición. Solo necesitas un archivo de recurso para una imagen en vector, en oposición a un archivo de recurso para
la densidad de cada pantalla en el caso de imágenes de mapa de bits. Para crear una imagen en vector, defines los detalles
de la forma dentro de un elemento XML <code>&lt;vector&gt;</code>.</p>
<p>El siguiente ejemplo define una imagen en vector con la forma de un corazón:</p>
<pre>
&lt;!-- res/drawable/heart.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
&lt;!-- intrinsic size of the drawable -->
android:height="256dp"
android:width="256dp"
&lt;!-- size of the virtual canvas -->
android:viewportWidth="32"
android:viewportHeight="32">
&lt;!-- draw a path -->
&lt;path android:fillColor="#8fff"
android:pathData="M20.5,9.5
c-1.955,0,-3.83,1.268,-4.5,3
c-0.67,-1.732,-2.547,-3,-4.5,-3
C8.957,9.5,7,11.432,7,14
c0,3.53,3.793,6.257,9,11.5
c5.207,-5.242,9,-7.97,9,-11.5
C25,11.432,23.043,9.5,20.5,9.5z" />
&lt;/vector>
</pre>
<p>Las imágenes en vector están representadas en Android como objetos {@link android.graphics.drawable.VectorDrawable}.
Para más información sobre la sintaxis <code>pathData</code>, consulta la <a href="http://www.w3.org/TR/SVG11/paths.html#PathData">referencia de ruta de acceso SVG</a>. Para más información
sobre la animación de las propiedades de las interfaces dibujables en vector, consulta
<a href="{@docRoot}training/material/animations.html#AnimVector">Animación de interfaces dibujables en vector</a>.</p>

View File

@@ -1,171 +0,0 @@
page.title=Comencemos
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#ApplyTheme">Aplicar el tema Material</a></li>
<li><a href="#Layouts">Realizar tus diseños</a></li>
<li><a href="#Depth">Especificar la elevación en tus vistas</a></li>
<li><a href="#ListsCards">Crear listas y tarjetas</a></li>
<li><a href="#Animations">Personalizar tus animaciones</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Para crear aplicaciones con Material Design:</p>
<ol>
<li style="margin-bottom:10px">
Revisar la <a href="http://www.google.com/design/spec">especificación de Material Design</a>.</li>
<li style="margin-bottom:10px">
Aplicar el <strong>tema</strong> material a tu aplicación.</li>
<li style="margin-bottom:10px">
Crear tus <strong>diseños</strong> siguiendo las pautas de Material Design.</li>
<li style="margin-bottom:10px">
Especificar la <strong>elevación</strong> de tus vistas para convertir sombras.</li>
<li style="margin-bottom:10px">
Usar <strong>widgets</strong> del sistema para listas y tarjetas.</li>
<li style="margin-bottom:10px">
Personalizar las <strong>animaciones</strong> en tu aplicación.</li>
</ol>
<h3>Mantener la compatibilidad con versiones anteriores</h3>
<p>Puedes agregar muchas características de Material Design a tu aplicación mientras mantienes la compatibilidad con las
versiones anteriores a Android 5.0. Para más información, consulta
<a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a>.</p>
<h3>Actualización de tu aplicación con Material Design</h3>
<p>Para actualizar una aplicación existente para incorporar Material Design, actualiza tus diseños siguiendo
las pautas de Material Design. Además, asegúrate de incorporar profundidad, respuesta táctil y
animaciones.</p>
<h3>Crear nuevas aplicaciones con Material Design</h3>
<p>Si creas una nueva aplicación con las características de Material Design, las <a href="http://www.google.com/design/spec">pautas de Material Design</a> te proporcionan un framework
de diseño cohesivo. Sigue estas pautas y usa la nueva funcionalidad del framework de
Android para diseñar y desarrollar tu aplicación.</p>
<h2 id="ApplyTheme">Aplicar el tema Material</h2>
<p>Para aplicar el tema material en tu aplicación, especifica el estilo que hereda de
<code>android:Theme.Material</code>:</p>
<pre>
&lt;!-- res/values/styles.xml -->
&lt;resources>
&lt;!-- your theme inherits from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- theme customizations -->
&lt;/style>
&lt;/resources>
</pre>
<p>El tema material proporciona widgets de sistema actualizados y te permite establecer la paleta de colores y las animaciones
predeterminadas para la respuesta táctil y las transiciones de actividades. Para obtener más detalles, consulta
<a href="{@docRoot}training/material/theme.html">Usar el tema Material</a>.</p>
<h2 id="Layouts">Realizar tus diseños</h2>
<p>Además de aplicar y personalizar el tema material, tus diseños deben cumplir con
las <a href="http://www.google.com/design/spec">pautas de Material Design</a>. Cuando realices
tus diseños, presta especial atención a lo siguiente:</p>
<ul>
<li>Cuadrículas de referencia</li>
<li>Líneas clave</li>
<li>Espaciado</li>
<li>Tamaño del objetivo táctil</li>
<li>Estructura del diseño</li>
</ul>
<h2 id="Depth">Especificar la elevación en tus vistas</h2>
<p>Las vistas pueden proyectar sombras y el valor de elevación de una vista
determina el tamaño de su sombra y el orden en que será dibujada. Para establecer la elevación de una vista, usa el atributo
<code>android:elevation</code> en tus diseños:</p>
<pre>
&lt;TextView
android:id="&#64;+id/my_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/next"
android:background="&#64;color/white"
android:elevation="5dp" />
</pre>
<p>La nueva propiedad <code>translationZ</code> te permite crear animaciones que reflejen cambios
temporales en la elevación de una vista. Los cambios de elevación pueden ser útiles cuando
<a href="{@docRoot}training/material/animations.html#ViewState">responden a gestos
táctiles</a>.</p>
<p>Para obtener más detalles, consulta <a href="{@docRoot}training/material/shadows-clipping.html">Definir
vistas de recorte y sombras</a>.</p>
<h2 id="ListsCards">Crear listas y tarjetas</h2>
<p>{@link android.support.v7.widget.RecyclerView} es una versión más acoplable de {@link
android.widget.ListView} que admite diferentes tipos de diseños y proporciona mejoras en el rendimiento.
{@link android.support.v7.widget.CardView} te permite mostrar partes de información dentro de las tarjetas con
una apariencia uniforme entre distintas aplicaciones. El siguiente ejemplo de códigos muestra cómo incluir un
{@link android.support.v7.widget.CardView} en tu diseño:</p>
<pre>
&lt;android.support.v7.widget.CardView
android:id="&#64;+id/card_view"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="3dp">
...
&lt;/android.support.v7.widget.CardView>
</pre>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/lists-cards.html">Crear listas
y tarjetas</a>.</p>
<h2 id="Animations">Personalizar tus animaciones</h2>
<p>Android 5.0 (API nivel 21) incluye nuevas API para crear animaciones personalizadas en tu aplicación.
Por ejemplo, puedes habilitar las transiciones de actividades y definir una transición de salida dentro de una
actividad:</p>
<pre>
public class MyActivity extends Activity {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// enable transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity_my);
}
public void onSomeButtonClicked(View view) {
getWindow().setExitTransition(new Explode());
Intent intent = new Intent(this, MyOtherActivity.class);
startActivity(intent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
}
}
</pre>
<p>Cuando comienzas otra actividad desde esta actividad, se activa la transición de salida.</p>
<p>Para más información sobre las nuevas API de animación, consulta <a href="{@docRoot}training/material/animations.html">Definir animaciones personalizadas</a>.</p>

View File

@@ -1,60 +0,0 @@
page.title=Material Design para desarrolladores
page.image=images/cards/material_2x.png
page.metaDescription=Aprende a aplicar Material Design a tus aplicaciones.
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependencias y requisitos previos</h2>
<ul>
<li>Android 5.0 (API nivel 21)</li>
</ul>
</div>
</div>
<p>Material Design es una guía integral para el diseño visual, de movimientos y de interacción en distintas
plataformas y dispositivos. Para usar Material Design en tus aplicaciones de Android, sigue las pautas
descritas en la
<a href="http://www.google.com/design/spec/material-design/introduction.html">especificación de Material
Design</a> y usa los nuevos componentes y funcionalidades disponibles en Android 5.0
(API nivel 21).</p>
<p>Esta clase muestra cómo crear aplicaciones de Material Design con los siguientes elementos:</p>
<ul>
<li>Tema Material</li>
<li>Widget para tarjetas y listas</li>
<li>Personalizar sombras y ver recortes</li>
<li>Interfaces dibujables en vector</li>
<li>Animaciones personalizadas</li>
</ul>
<p>Esta clase también te enseña cómo mantener la compatibilidad con versiones anteriores de Android
5.0 (API nivel 21) cuando usas las características de Material Design en tu aplicación.</p>
<h2>Lecciones</h2>
<dl>
<dt><a href="{@docRoot}training/material/get-started.html">Comencemos</a></dt>
<dd>Aprende a actualizar tu aplicación con las características de Material Design.</dd>
<dt><a href="{@docRoot}training/material/theme.html">Usar el tema Material</a></dt>
<dd>Aprende a aplicar los estilos de Material Design a tu aplicación.</dd>
<dt><a href="{@docRoot}training/material/lists-cards.html">Crear listas y tarjetas</a></dt>
<dd>Aprende a crear listas y tarjetas con un aspecto consistente mediante el uso de widgets del sistema.</dd>
<dt><a href="{@docRoot}training/material/shadows-clipping.html">Definir vistas de recorte y sombras</a></dt>
<dd>Aprende a establecer la elevación para tus vistas para crear sombras personalizadas y cómo recortar vistas.</dd>
<dt><a href="{@docRoot}training/material/drawables.html">Trabajar con interfaces dibujables</a></dt>
<dd>Aprende cómo crear interfaces dibujables en vector y cómo agregar un matiz a los recursos dibujables.</dd>
<dt><a href="{@docRoot}training/material/animations.html">Definir animaciones personalizadas</a></dt>
<dd>Aprende a crear animaciones personalizadas para vistas y transiciones de actividades con elementos compartidos.</dd>
<dt><a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a></dt>
<dd>Aprende a mantener la compatibilidad con versiones de plataforma anteriores a Android 5.0.</dd>
</dl>

View File

@@ -1,266 +0,0 @@
page.title=Crear listas y tarjetas
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#RecyclerView">Crear listas</a></li>
<li><a href="#CardView">Crear tarjetas</a></li>
<li><a href="#Dependencies">Agregar dependencias</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Para crear listas completas y tarjetas con estilos de Material Design en tus aplicaciones, puedes usar los widgets
{@link android.support.v7.widget.RecyclerView} y {@link android.support.v7.widget.CardView}.
</p>
<h2 id="RecyclerView">Crear listas</h2>
<p>El widget {@link android.support.v7.widget.RecyclerView} es una versión más
flexible y avanzada de {@link android.widget.ListView}. Este widget es un contenedor para mostrar grandes conjuntos de
datos que se pueden desplazar de manera muy eficiente al mantener una cantidad limitada de vistas. Usa el widget
{@link android.support.v7.widget.RecyclerView} cuando tengas conjuntos de datos cuyos elementos
cambien en tiempo de ejecución sobre la base de la acción del usuario o los eventos de la red.</p>
<p>La clase {@link android.support.v7.widget.RecyclerView} simplifica la pantalla y la manipulación de grandes conjuntos de
datos al proporcionar lo siguiente:</p>
<ul>
<li>Administradores de diseño para el posicionamiento de elementos</li>
<li>Animaciones predeterminadas para las operaciones comunes con elementos, como quitar o agregar elementos</li>
</ul>
<p>También tienes la flexibilidad para definir administradores de diseño personalizados y animaciones para los widgets {@link
android.support.v7.widget.RecyclerView}.</p>
<img src="{@docRoot}training/material/images/RecyclerView.png" alt="" width="550" height="106" />
<p class="img-caption">
<strong>Figura 1</strong>. El widget <code>RecyclerView</code>.
</p>
<p>Para usar el widget {@link android.support.v7.widget.RecyclerView}, tienes que especificar un
adaptador y un administrador de diseño. Para crear un adaptador, extiende la clase {@link
android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}. Los detalles
de la implementación dependen de las especificaciones de tu conjunto de datos y los tipos de vistas. Para más
información, consulta los <a href="#RVExamples">ejemplos</a> que figuran a continuación.</p>
<div style="float:right">
<img src="{@docRoot}design/material/images/list_mail.png" alt="" width="250" height="426" />
<p class="img-caption" style="margin-left:8px">
<strong>Figura 2</strong>. Listas con <code>RecyclerView</code>.
</p>
</div>
<p>Un <strong>administrador de diseño</strong> posiciona las vistas de artículos dentro de un {@link
android.support.v7.widget.RecyclerView} y determina cuándo volver a usar las vistas de elementos que ya
no están visibles para el usuario. Para reutilizar (o <em>reciclar</em>) una vista, un administrador de diseño puede solicitarle al
adaptador que reemplace el contenido de la vista con un elemento diferente del conjunto de datos. De esta manera,
cuando se reciclan las vistas se mejora el rendimiento al evitar la creación de vistas innecesarias o
realizar búsquedas costosas de {@link android.app.Activity#findViewById findViewById()}.</p>
<p>{@link android.support.v7.widget.RecyclerView} te proporciona estos administradores de diseño incorporados:</p>
<ul>
<li>{@link android.support.v7.widget.LinearLayoutManager} muestra elementos en una lista de desplazamiento horizontal o
vertical.</li>
<li>{@link android.support.v7.widget.GridLayoutManager} muestra elementos en una cuadrícula.</li>
<li>{@link android.support.v7.widget.StaggeredGridLayoutManager} muestra elementos en una cuadrícula escalonada.</li>
</ul>
<p>Para crear un administrador de diseño personalizado, extiende la clase {@link
android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.</p>
<h3>Animaciones</h3>
<p>Las animaciones para agregar o eliminar elementos están permitidas en forma predeterminada en {@link
android.support.v7.widget.RecyclerView}. Para personalizar estas animaciones, extiende la clase
{@link android.support.v7.widget.RecyclerView.ItemAnimator RecyclerView.ItemAnimator} y usa
el método {@link android.support.v7.widget.RecyclerView#setItemAnimator RecyclerView.setItemAnimator()}.
</p>
<h3 id="RVExamples">Ejemplos</h3>
<p>El siguiente ejemplo de códigos demuestra cómo agregar el widget
{@link android.support.v7.widget.RecyclerView} a un diseño:</p>
<pre>
&lt;!-- A RecyclerView with some commonly used attributes -->
&lt;android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</pre>
<p>Una vez que hayas agregado un widget {@link android.support.v7.widget.RecyclerView} a tu diseño,
obtén un identificador para el objeto, conéctalo a un administrador de diseño y adjunta un adaptador para los datos
que se van a mostrar:</p>
<pre>
public class MyActivity extends Activity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
...
}
</pre>
<p>El adaptador proporciona acceso a los elementos en tu conjunto de datos, crea vistas para los elementos y
reemplaza el contenido de algunas de las vistas con estos elementos de datos nuevos cuando el elemento original ya no está
visible. El siguiente ejemplo de código muestra una implementación simple para un conjunto de datos que consta
de una matriz de cadenas mostradas mediante el uso de widgets {@link android.widget.TextView}:</p>
<pre>
public class MyAdapter extends RecyclerView.Adapter&lt;MyAdapter.ViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
&#64;Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
...
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
&#64;Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
&#64;Override
public int getItemCount() {
return mDataset.length;
}
}
</pre>
<div style="float:right;margin-top:15px;margin-left:30px">
<img src="{@docRoot}design/material/images/card_travel.png" alt="" width="225" height="383">
<p class="img-caption" style="margin-left:12px">
<strong>Figura 3</strong>. Ejemplos de tarjetas.
</p>
</div>
<h2 id="CardView">Crear tarjetas</h2>
<p>{@link android.support.v7.widget.CardView} extiende la clase {@link android.widget.FrameLayout}
y te permite mostrar información dentro de tarjetas que tienen una apariencia uniforme en la plataforma. Los widgets {@link
android.support.v7.widget.CardView} pueden tener sombras y esquinas redondeadas.</p>
<p>Para crear una tarjeta con una sombra, usa el atributo <code>card_view:cardElevation</code>.
{@link android.support.v7.widget.CardView} usa elevación real y sombras dinámicas en Android 5.0
(API nivel 21) y superior, y regresa a una implementación de sombras programáticas en versiones anteriores.
Para más información, consulta <a href="{@docRoot}training/material/compatibility.html">Mantener
la compatibilidad</a>.</p>
<p>Usa estas propiedades para personalizar la apariencia del widget
{@link android.support.v7.widget.CardView}:</p>
<ul>
<li>Para establecer el radio de la esquina en tus diseños, usa el atributo <code>card_view:cardCornerRadius</code>.
</li>
<li>Para establecer el radio en tu código, usa el método <code>CardView.setRadius</code>.</li>
<li>Para establecer el color de fondo de una tarjeta, usa el atributo <code>card_view:cardBackgroundColor</code>.
</li>
</ul>
<p>El siguiente ejemplo de código muestra cómo incluir un widget {@link android.support.v7.widget.CardView}
en tu diseño:</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
... >
&lt;!-- A CardView that contains a TextView -->
&lt;android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="4dp">
&lt;TextView
android:id="@+id/info_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />
&lt;/android.support.v7.widget.CardView>
&lt;/LinearLayout>
</pre>
<p>Para más información, consulta la referencia de la API para {@link android.support.v7.widget.CardView}.</p>
<h2 id="Dependencies">Agregar dependencias</h2>
<p>Los widgets {@link android.support.v7.widget.RecyclerView} y {@link android.support.v7.widget.CardView}
son parte de las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de
soporte v7</a>. Para usar estos widgets en tu proyecto, agrega estas
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Dependencias de Gradle</a> al módulo
de tu aplicación:</p>
<pre>
dependencies {
...
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>

View File

@@ -1,133 +0,0 @@
page.title=Definir vistas de recorte y sombras
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Elevation">Asignar elevación a tus vistas</a></li>
<li><a href="#Shadows">Personalizar vistas de sombras y contornos</a></li>
<li><a href="#Clip">Recortar vistas</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Material Design introduce una elevación para los elementos de la IU. La elevación ayuda a los usuarios a comprender la
importancia relativa de cada elemento y a centrar su atención en la tarea para realizar.</p>
<p>La elevación de una vista, representada por la propiedad Z, determina la apariencia visual de su
sombra: las vistas con valores Z superiores, proyectan sombras más grandes y suaves. Las vistas con valores Z superiores ocluyen
las vistas con valores Z inferiores. Sin embargo, el valor Z de una vista no afecta el tamaño de la vista.</p>
<p>El padre de la vista elevada se encarga de dibujar las sombras y así, sujetas al recorte de vista estándar, son
recortadas por el padre de manera predeterminada.</p>
<p>La elevación también es útil para crear animaciones donde los widgets suben temporalmente sobre el
plano visual cuando realizan alguna acción.</p>
<p>Para más información sobre la elevación en Material Design, consulta
<a href="http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html">Objetos
en el espacio 3D</a>.</p>
<h2 id="Elevation">Asignar elevación a tus vistas</h2>
<p>El valor Z de una vista cualquiera tiene dos componentes:
<ul>
<li>Elevación: El componente estático.</li>
<li>Traducción: El componente dinámico usado para las animaciones.</li>
</ul>
<p><code>Z = elevation + translationZ</code></p>
<img src="{@docRoot}training/material/images/shadows-depth.png" width="580" height="261" alt="" />
<p class="img-caption"><strong>Figura 1</strong>: sombras para diferentes elevaciones de vistas.</p>
<p>Para establecer la elevación de una vista al definir un diseño, usa el atributo <code>android:elevation</code>.
Para establecer la elevación de una vista en el código de una actividad, usa el método
{@link android.view.View#setElevation View.setElevation()}.</p>
<p>Para establecer la traducción de una vista, usa el método {@link android.view.View#setTranslationZ
View.setTranslationZ()}.</p>
<p>Los nuevos métodos {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} y {@link
android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} te permiten
animar fácilmente la elevación de las vistas. Para más información, consulta la referencia de la API para
{@link android.view.ViewPropertyAnimator} y la guía del desarrollador <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Animación de propiedades</a>.
</p>
<p>También puedes usar un {@link android.animation.StateListAnimator} para
especificar estas animaciones de manera declarativa. Esto es especialmente útil para casos en donde los cambios de
estados desencadenan animaciones, como cuando un usuario pulsa un botón. Para más información, consulta
<a href="{@docRoot}training/material/animations.html#ViewState">Animar cambios de estados de las vistas</a>.</p>
<p>Los valores Z se miden en dp (píxeles independientes de la densidad).</p>
<h2 id="Shadows">Personalizar visualización de sombras y contornos</h2>
<p>Los límites de la interfaz dibujable en segundo plano de una vista determinan la forma predeterminada de su sombra.
Los <strong>contornos</strong> representan la forma externa de un objeto gráfico y definen el área del efecto de ondas
para la respuesta táctil.</p>
<p>Examina esta vista, definida con una interfaz dibujable en segundo plano:</p>
<pre>
&lt;TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />
</pre>
<p>La interfaz dibujable en segundo plano está definida como un rectángulo con esquinas redondeadas:</p>
<pre>
&lt;!-- res/drawable/myrect.xml -->
&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
&lt;solid android:color="#42000000" />
&lt;corners android:radius="5dp" />
&lt;/shape>
</pre>
<p>La vista proyecta una sombra con esquinas redondeadas, ya que la interfaz dibujable en segundo plano
define el contorno de la vista. Un contorno personalizado reemplazaría la forma predeterminada de la sombra de una vista.</p>
<p>Para definir un contorno personalizado para una vista en tu código:<p>
<ol>
<li>Extiende la clase {@link android.view.ViewOutlineProvider}.</li>
<li>Reemplaza el método {@link android.view.ViewOutlineProvider#getOutline getOutline()}.</li>
<li>Asigna el nuevo proveedor de contornos a tu vista con el método {@link
android.view.View#setOutlineProvider View.setOutlineProvider()}.</li>
</ol>
<p>Puedes crear contornos rectangulares y ovalados con esquinas redondeadas mediante el uso de métodos en la clase
{@link android.graphics.Outline}. El proveedor de contornos predeterminado para las
vistas obtiene el contorno a partir del plano de fondo de la vista. Para evitar que una vista proyecte una sombra, establece su proveedor de contornos
en <code>null</code>.</p>
<h2 id="Clip">Recortar vistas</h2>
<p>Recortar vistas te permite cambiar fácilmente la forma de una vista. Puedes recortar vistas para
mantener la uniformidad con otros elementos del diseño o para cambiar la forma de una vista en respuesta a una señal de entrada del usuario.
Puedes recortar una vista a partir de su área de contorno mediante el método {@link android.view.View#setClipToOutline
View.setClipToOutline()} o el atributo <code>android:clipToOutline</code>. Solo
los contornos rectangulares, circulares y redondeados admiten el recorte, según lo determinado por el método
{@link android.graphics.Outline#canClip Outline.canClip()}.</p>
<p>Para recortar una vista a partir de una interfaz dibujable, establece la interfaz dibujable como el plano de fondo de la vista
(como se muestra más arriba) y llama al método {@link android.view.View#setClipToOutline View.setClipToOutline()}.
</p>
<p>Recortar vistas es una operación costosa, así que no animes la forma que usas para
recortar una vista. Para lograr este efecto, usa la animación <a href="{@docRoot}training/material/animations.html#Reveal">Efecto revelar</a>.</p>

View File

@@ -1,131 +0,0 @@
page.title=Usar el tema Material
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#ColorPalette">Personalizar la paleta de colores</a></li>
<li><a href="#StatusBar">Personalizar la barra de estado</a></li>
<li><a href="#Inheritance">Cambiar el tema de vistas individuales</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>El nuevo tema material proporciona:</p>
<ul>
<li>Widgets del sistema que te permiten establecer la paleta de colores.</li>
<li>Animaciones para la respuesta táctil de los widgets del sistema.</li>
<li>Animaciones para transiciones de actividades</li>
</ul>
<p>Puedes personalizar la apariencia del tema material
según la identidad de tu marca, con una paleta de colores que esté bajo tu control. Puedes cambiar el matiz de la barra de acción y
la barra de estado mediante atributos de temas, como se muestra en la <a href="#fig3">figura 3</a>.</p>
<p>Los widgets del sistema tienen un nuevo diseño y animaciones para respuesta táctil. Puedes personalizar tu aplicación cambiando su
paleta de colores, las animaciones de la respuesta táctil y sus transiciones de actividades.</p>
<p>El tema material se define como:</p>
<ul>
<li><code>@android:style/Theme.Material</code> (versión oscura)</li>
<li><code>@android:style/Theme.Material.Light</code> (versión clara)</li>
<li><code>@android:style/Theme.Material.Light.DarkActionBar</code></li>
</ul>
<p>Para obtener una lista de estilos de Material, consulta la referencia de la API para
{@link android.R.style R.style}.</p>
<!-- two columns, dark/light material theme example -->
<div style="width:700px;margin-top:25px;margin-bottom:10px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Figura 1</strong>. Tema Material oscuro</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Figura 2</strong>. Tema Material claro</p>
</div>
</div>
<br style="clear:left">
</div>
<p class="note">
<strong>Nota:</strong> El tema material solo está disponible en Android 5.0 (API nivel 21) y
superior. Las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de soporte v7</a>
proporcionan temas con estilos de Material Design para algunos widgets y admiten la personalización de la paleta de
colores. Para más información, consulta
<a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a>.
</p>
<h2 id="ColorPalette">Personalizar la paleta de colores</h2>
<p style="margin-bottom:30px">Si deseas personalizar los colores base del tema para que se adapten a tu marca, define
tus colores personalizados mediante los atributos de temas cuando heredes del tema material:</p>
<pre>
&lt;resources>
&lt;!-- inherit from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- Main theme colors -->
&lt;!-- your app branding color for the app bar -->
&lt;item name="android:colorPrimary">@color/primary&lt;/item>
&lt;!-- darker variant for the status bar and contextual app bars -->
&lt;item name="android:colorPrimaryDark">@color/primary_dark&lt;/item>
&lt;!-- theme UI controls like checkboxes and text fields -->
&lt;item name="android:colorAccent">@color/accent&lt;/item>
&lt;/style>
&lt;/resources>
</pre>
<div style="float:right;margin-left:25px;margin-top:20px;margin-bottom:10px" id="fig3">
<img src="{@docRoot}training/material/images/ThemeColors.png" width="250" height="445" />
<p class="img-caption" style="margin-bottom:0px">
<strong>Figura 3</strong>. Personalizar el tema material.</p>
</div>
<h2 id="StatusBar">Personalizar la barra de estado</h2>
<p>El tema material te permite personalizar fácilmente la barra de estado, especifica un
color que se adapte a tu marca y proporciona suficiente contraste para mostrar los íconos de estado en blanco. Si
quieres establecer un color personalizado para la barra de estado, usa el atributo <code>android:statusBarColor</code>
cuando extiendas el tema material. <code>android:statusBarColor</code> hereda el
valor de <code>android:colorPrimaryDark</code> en forma predeterminada.</p>
<p>También puedes dibujar por detrás de la barra de estado. Por ejemplo, si quieres que la barra de estado se
muestre en forma transparente sobre una foto, aplica un sutil degradado oscuro para garantizar que los íconos
de estado blancos sigan visibles. Para hacerlo, establece el atributo <code>android:statusBarColor</code> en
<code>&#64;android:color/transparent</code> y ajusta los indicadores de la ventana según lo requerido. También puedes
usar el método {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} para
las animaciones o el difuminado.</p>
<p class="note">
<strong>Nota:</strong> La barra de estado casi siempre debe estar delimitada claramente de la
barra de herramientas principal, excepto para los casos en donde muestres imágenes de un extremo a otro o contenido multimedia detrás
de estas barras, y también cuando uses un degradado para garantizar que los íconos aún sean visibles.
</p>
<p>Cuando personalizas la barra de navegación y la barra de estado, haz que ambas sean transparentes o modifica
solo la barra de estado. La barra de navegación debe permanecer de color negro en todos los otros casos.</p>
<h2 id="Inheritance">Vistas individuales del tema</h3>
<p>Los elementos en las definiciones de diseño XML pueden especificar el atributo <code>android:theme</code>,
que hace referencia al recurso del tema. Este atributo modifica el tema para el elemento y cualquier
elemento secundario, y esto es útil para modificar las paletas de colores de los temas en una porción específica
de una interfaz.</p>

View File

@@ -1,120 +0,0 @@
page.title=Cómo controlar el nivel de batería y el estado de carga
parent.title=Cómo optimizar la duración de la batería
parent.link=index.html
trainingnavtop=true
next.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión
next.link=docking-monitoring.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#DetermineChargeState">Cómo determinar el estado de carga actual</a></li>
<li><a href="#MonitorChargeState">Cómo supervisar los cambios en el estado de carga</a></li>
<li><a href="#CurrentLevel">Cómo determinar el nivel de batería actual</a></li>
<li><a href="#MonitorLevel">Cómo supervisar cambios importantes en el nivel de batería</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intentos y filtros de intentos</a>
</ul>
</div>
</div>
<p>Al modificar la frecuencia de las actualizaciones en segundo plano para reducir el efecto de las mismas en la duración de la batería, te recomendamos que comiences por comprobar el estado de carga y el nivel actual de la batería.</p>
<p>El impacto derivado de actualizar aplicaciones en la duración de la batería varía en función del nivel de batería y del estado de carga del dispositivo, mientras que es insignificante cuando este está conectado a la corriente. Por ello, en la mayoría de los casos, puedes maximizar la frecuencia de actualización cuando el dispositivo esté conectado a un cargador. Por el contrario, si el dispositivo está en proceso de descarga, disminuir la frecuencia de actualización te permitirá aumentar la duración de la batería.</p>
<p>Del mismo modo, puedes comprobar el nivel de carga de la batería y reducir la frecuencia de las actualizaciones o incluso detenerlas cuando la batería esté a punto de agotarse.</p>
<h2 id="DetermineChargeState">Cómo determinar el estado de carga actual</h2>
<p>En primer lugar, te recomendamos que determines el estado de carga actual. {@link android.os.BatteryManager} envía los detalles de carga y de la batería en un {@link android.content.Intent} persistente que incluye el estado de carga.</p>
<p>Se trata de un intento persistente, por lo que no es necesario registrar un {@link android.content.BroadcastReceiver}. Para ello, solo tienes que ejecutar {@code registerReceiver} transmitiendo {@code null} como el receptor (como se muestra en el siguiente fragmento). A continuación, se devuelve el intento de estado actual de la batería. Puedes transmitir un objeto {@link android.content.BroadcastReceiver} real, pero hablaremos sobre las actualizaciones en otra sección, por lo que no es necesario ahora.</p>
<pre>IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);</pre>
<p>Puedes extraer el estado de carga actual y, si el dispositivo está cargando, puedes saber también si se está usando un cargador de corriente alterna o USB:<p>
<pre>// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;</pre>
<p>Normalmente, debes maximizar la frecuencia de las actualizaciones en segundo plano si el dispositivo está conectado a un cargador de corriente alterna, disminuir esa frecuencia si se utiliza un cargador USB y reducirla aún más si la batería se está descargando.</p>
<h2 id="MonitorChargeState">Cómo supervisar los cambios en el estado de carga</h2>
<p>Modificar el estado de carga es tan fácil como conectar el dispositivo a un enchufe o USB. Por ello, es importante que supervises el estado de carga por si se producen cambios y modifiques la frecuencia de actualización según corresponda.</p>
<p>{@link android.os.BatteryManager} emite una acción siempre que el dispositivo se conecta o desconecta de la corriente. Es importante recibir estos eventos aunque la aplicación no esté en ejecución (especialmente porque estos eventos pueden afectar a la frecuencia con la que inicias tu aplicación para actualizarla en segundo plano), por lo que debes registrar un {@link android.content.BroadcastReceiver} en tu archivo de manifiesto para detectar ambos eventos definiendo {@link android.content.Intent#ACTION_POWER_CONNECTED} y {@link android.content.Intent#ACTION_POWER_DISCONNECTED} en un filtro de intentos.</p>
<pre>&lt;receiver android:name=".PowerConnectionReceiver">
&lt;intent-filter>
&lt;action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
&lt;action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
&lt;/intent-filter>
&lt;/receiver></pre>
<p>En la implementación de {@link android.content.BroadcastReceiver} asociada, puedes extraer el método y el estado de carga actual como se describe en el paso anterior.</p>
<pre>public class PowerConnectionReceiver extends BroadcastReceiver {
&#64;Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
}
}</pre>
<h2 id="CurrentLevel">Cómo determinar el nivel de batería actual</h2>
<p>En algunos casos, también es útil determinar el nivel de batería actual. Puedes disminuir la frecuencia de las actualizaciones en segundo plano si el nivel de carga de la batería es inferior a un valor determinado.</p>
<p>Puedes consultar la carga actual de la batería extrayendo el nivel actual de la batería y subir a partir del intento de estado de batería, como se muestra a continuación:</p>
<pre>int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;</pre>
<h2 id="MonitorLevel">Cómo supervisar cambios importantes en el nivel de batería</h2>
<p>No puedes controlar el estado de la batería de forma continua fácilmente, pero tampoco es necesario.</p>
<p>En términos generales, el impacto sobre la batería derivado de controlar continuamente el nivel de batería es mayor que el comportamiento habitual de la aplicación. Por ello, te recomendamos que supervises únicamente los cambios en el nivel de batería más significativos, especialmente cuando el dispositivo tenga poca batería o acabe de cargarse.</p>
<p>El fragmento de manifiesto que aparece a continuación se ha extraído del elemento de filtro de intento de un receptor de emisión. El receptor detecta {@link android.content.Intent#ACTION_BATTERY_LOW} y {@link android.content.Intent#ACTION_BATTERY_OKAY} y se activa cuando el nivel de batería del dispositivo es bajo o cuando se sale de un estado bajo de batería.</p>
<pre>&lt;receiver android:name=".BatteryLevelReceiver">
&lt;intent-filter>
&lt;action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
&lt;action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
&lt;/intent-filter>
&lt;/receiver></pre>
<p>Cuando la batería esté a punto de agotarse, te recomendamos que inhabilites las actualizaciones en segundo plano. Si el teléfono se apaga antes de poder utilizar las aplicaciones, no importa que tengan los datos actualizados.</p>
<p>En muchos casos, el hecho de cargar un dispositivo coincide con la acción de utilizar un conector. En la próxima sección, hablaremos sobre cómo determinar el estado de conexión actual y cómo supervisar los cambios que se produzcan al conectar el dispositivo.</p>

View File

@@ -1,70 +0,0 @@
page.title=Cómo determinar y controlar el estado de la conectividad
parent.title=Cómo optimizar la duración de la batería
parent.link=index.html
trainingnavtop=true
previous.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión
previous.link=docking-monitoring.html
next.title=Cómo manipular los receptores de emisión bajo demanda
next.link=manifest-receivers.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#DetermineConnection">Cómo determinar si tienes conexión a Internet</a></li>
<li><a href="#DetermineType">Cómo determinar el tipo de conexión a Internet</a></li>
<li><a href="#MonitorChanges">Cómo supervisar los cambios en la conectividad</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intentos y filtros de intentos</a>
</ul>
</div>
</div>
<p>Algunos de los usos más comunes para las alarmas con repetición y los servicios en segundo plano es programar actualizaciones regulares de los datos de aplicaciones a partir de recursos de Internet, almacenar datos en la memoria caché o ejecutar descargas a largo plazo. Sin embargo, si no estás conectado a Internet o la conexión es demasiado débil para completar la descarga, ¿para qué activar el dispositivo y programar la actualización?</p>
<p>Puedes utilizar {@link android.net.ConnectivityManager} para comprobar si estás conectado a Internet y, en ese caso, el tipo de conexión que estás utilizando.</p>
<h2 id="DetermineConnection">Cómo determinar si tienes conexión a Internet</h2>
<p>No es necesario programar una actualización basada en un recurso de Internet si no estás conectado. En el fragmento que aparece a continuación, se muestra cómo utilizar {@link android.net.ConnectivityManager} para consultar la red activa y determinar si hay conexión a Internet.</p>
<pre>ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork.isConnectedOrConnecting();</pre>
<h2 id="DetermineType">Cómo determinar el tipo de conexión a Internet</h2>
<p>También puedes determinar el tipo de conexión a Internet que hay disponible.</p>
<p>El dispositivo se puede conectar a Internet a través de conexiones Ethernet, Wi-Fi, WiMAX y de datos móviles. Al consultar el tipo de red activa, como se muestra a continuación, puedes modificar la frecuencia de actualización en función del ancho de banda disponible.</p>
<pre>boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;</pre>
<p>El coste de las conexiones de datos móviles suele ser superior al de las conexiones Wi-Fi, por lo que en la mayoría de los casos, la frecuencia de actualización de tu aplicación debería ser menor si utilizas conexiones móviles. Del mismo modo, las descargas grandes deberían cancelarse hasta que estés conectado a una red Wi-Fi.</p>
<p>Cuando hayas inhabilitado las actualizaciones, es importante que detectes si se hay cambios en la conectividad para poder reanudarlas cuando se haya establecido una conexión a Internet.</p>
<h2 id="MonitorChanges">Cómo supervisar los cambios en la conectividad</h2>
<p>{@link android.net.ConnectivityManager} emite la acción {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code "android.net.conn.CONNECTIVITY_CHANGE"}) cuando se han modificado los detalles de la conectividad. Puedes registrar un receptor de emisión en el archivo de manifiesto para detectar estos cambios y reanudar (o cancelar) las actualizaciones en segundo plano según corresponda.</p>
<pre>&lt;action android:name="android.net.conn.CONNECTIVITY_CHANGE"/></pre>
<p>Los cambios en la conectividad de un dispositivo pueden ser muy frecuentes (esta emisión se activa siempre que cambias de una conexión de datos móviles a una conexión Wi-Fi). Como resultado, te recomendamos que supervises esta emisión únicamente cuando hayas cancelado anteriormente las actualizaciones o las descargas para reanudarlas. Normalmente, basta con comprobar la conexión a Internet antes de iniciar una actualización y, si no hay ninguna, cancelar el resto de actualizaciones hasta que se restablezca la conexión.</p>
<p>Esta técnica requiere que alternes receptores de emisión que hayas declarado en el archivo de manifiesto, que se describe en la próxima sección.</p>

View File

@@ -1,74 +0,0 @@
page.title=Cómo determinar y controlar el tipo de conector y el estado de la conexión
parent.title=Cómo optimizar la duración de la batería
parent.link=index.html
trainingnavtop=true
previous.title=Cómo controlar el nivel de batería y el estado de carga
previous.link=battery-monitoring.html
next.title=Cómo determinar y controlar el estado de la conectividad
next.link=connectivity-monitoring.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#CurrentDockState">Cómo solicitar el foco de audio</a></li>
<li><a href="#DockType">Cómo determinar el tipo de conector actual</a></li>
<li><a href="#MonitorDockState">Cómo supervisar los cambios en el tipo de conector o en el estado del mismo</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intentos y filtros de intentos</a>
</ul>
</div>
</div>
<p>Los dispositivos Android se pueden conectar a distintos tipos de conectores. Por ejemplo, se puede utilizar conectores para coche o domésticos y tanto digitales como analógicos. Normalmente, el estado del conector está vinculado al estado de carga, ya que muchos conectores cargan el dispositivo mientras está conectado.</p>
<p>El modo en el que el estado del conector del teléfono afecta a la frecuencia de actualización depende de tu aplicación. Puedes aumentar la frecuencia de actualización de una aplicación sobre noticias cuando el dispositivo esté conectado a un conector de escritorio o inhabilitar las actualizaciones completamente si está conectado a un conector de coche. Por el contrario, puedes maximizar las actualizaciones si el dispositivo está conectado a un conector de coche y tu servicio en segundo plano se actualiza con el estado del tráfico.</p>
<p>El estado del conector se emite también como un {@link android.content.Intent} persistente, lo que te permite consultar si el dispositivo está conectado o no y, si lo está, determinar el tipo de conector.</p>
<h2 id="CurrentDockState">Cómo determinar el estado de conexión actual</h2>
<p>La información sobre el estado del conector se incluye como información adicional en una emisión persistente de la acción {@link android.content.Intent#ACTION_DOCK_EVENT}. Por ello, no es necesario registrar un {@link android.content.BroadcastReceiver}. Solo tienes que ejecutar {@link android.content.Context#registerReceiver registerReceiver()} transmitiendo {@code null} como el receptor de emisión, como se muestra en el fragmento de código que aparece a continuación.</p>
<pre>IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
Intent dockStatus = context.registerReceiver(null, ifilter);</pre>
<p>Puedes extraer el estado actual de la conexión de la información adicional de {@code EXTRA_DOCK_STATE}:<p>
<pre>int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;</pre>
<h2 id="DockType">Cómo determinar el tipo de conector actual</h2>
<p>Si un dispositivo está insertado en un conector, se puede conectar a cualquiera de estos cuatro tipos de conectores:
<ul><li>coche,</li>
<li>escritorio,</li>
<li>escritorio de gama baja (analógico),</li>
<li>escritorio de gama alta (digital).</li></ul></p>
<p>Ten en cuenta que las últimas dos opciones se introdujeron en Android únicamente en el nivel 11 del API. Por ello, te recomendamos que compruebes las tres opciones solo cuando te interese más el tipo de conector que si se trata de un conector digital o analógico:</p>
<pre>boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
dockState == EXTRA_DOCK_STATE_LE_DESK ||
dockState == EXTRA_DOCK_STATE_HE_DESK;</pre>
<h2 id="MonitorDockState">Cómo supervisar los cambios en el tipo de conector o en el estado del mismo</h2>
<p>Cuando el dispositivo está conectado a un conector o desconectado del mismo, se emite la acción {@link android.content.Intent#ACTION_DOCK_EVENT}. Para controlar los cambios que se produzcan en el estado del conector del dispositivo, solo tienes que registrar un receptor de emisión en el archivo de manifiesto de la aplicación, como se muestra en el fragmento que aparece a continuación:</p>
<pre>&lt;action android:name="android.intent.action.ACTION_DOCK_EVENT"/></pre>
<p>Puedes extraer el estado y el tipo de conector en la implementación del receptor con las mismas técnicas que se han descrito en el paso anterior.</p>

View File

@@ -1,49 +0,0 @@
page.title=Cómo optimizar la duración de la batería
trainingnavtop=true
startpage=true
next.title=Cómo controlar el nivel de batería y el estado de carga
next.link=battery-monitoring.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependencias y requisitos previos</h2>
<ul>
<li>Android 2.0 (nivel 5 del API) o superior</li>
<li>Experiencia con <a href="{@docRoot}guide/components/intents-filters.html">Intentos y filtros de intentos</a></li>
</ul>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/components/services.html">Servicios</a>
</ul>
</div>
</div>
<p>Uno de los objetivos de tu aplicación debe ser limitar su impacto en la duración de la batería del dispositivo en el que esté instalada. Después de leer estas secciones, podrás desarrollar aplicaciones que optimizarán el uso de la batería en función del estado del dispositivo en el que estén instaladas.</p>
<p>Al tomar medidas como inhabilitar las actualizaciones de servicios en segundo plano o disminuir la frecuencia de dichas actualizaciones cuando el nivel de batería sea bajo, puedes garantizar que se minimice el impacto de tu aplicación en la duración de la batería sin afectar a la experiencia del usuario.</p>
<h2>Secciones</h2>
<!-- Create a list of the lessons in this class along with a short description of each lesson.
These should be short and to the point. It should be clear from reading the summary whether someone
will want to jump to a lesson or not.-->
<dl>
<dt><b><a href="battery-monitoring.html">Cómo controlar el nivel de batería y el estado de carga</a></b></dt>
<dd>Obtén más información sobre cómo determinar y controlar el nivel de batería actual y los cambios en el estado de carga para modificar la frecuencia de actualizaciones en segundo plano de tu aplicación.</dd>
<dt><b><a href="docking-monitoring.html">Cómo determinar y controlar el tipo de conector y el estado de la conexión</a></b></dt>
<dd>La frecuencia de actualización óptima puede variar en función de cómo se utilice el dispositivo en el que está instalada la aplicación. Obtén más información sobre cómo determinar y controlar cuándo el dispositivo está conectado a algún sistema de acoplamiento u otra conexión.</dd>
<dt><b><a href="connectivity-monitoring.html">Cómo determinar y controlar el estado de la conectividad</a></b></dt>
<dd>Si no tienes conexión a Internet, no puedes actualizar tu aplicación a partir de una fuente online. Obtén más información sobre cómo comprobar el estado de la conectividad para modificar la frecuencia de actualización en segundo plano de tu aplicación. También puedes obtener más información sobre cómo comprobar la conectividad móvil o Wi-Fi antes de iniciar operaciones que requieran un nivel elevado de ancho de banda.</dd>
<dt><b><a href="manifest-receivers.html">Cómo manipular los receptores de emisión bajo demanda</a></b></dt>
<dd>Los receptores de emisión que declaras en el archivo de manifiesto se pueden alternar durante la ejecución para inhabilitar los que no son necesarios debido al estado actual del dispositivo. Obtén más información sobre cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento y cómo posponer acciones hasta que el dispositivo se encuentre en un estado concreto.</dd>
</dl>

View File

@@ -1,50 +0,0 @@
page.title=Cómo manipular los receptores de emisión bajo demanda
parent.title=Cómo optimizar la duración de la batería
parent.link=index.html
trainingnavtop=true
previous.title=Cómo determinar y controlar el estado de la conectividad
previous.link=connectivity-monitoring.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#ToggleReceivers">Cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intentos y filtros de intentos</a>
</ul>
</div>
</div>
<p>La forma más sencilla de controlar los cambios en el estado del dispositivo es crear un {@link android.content.BroadcastReceiver} para cada estado que vayas a controlar y registrar cada uno de ellos en el archivo de manifiesto de tu aplicación. A continuación, en cada uno de esos receptores solo tienes que volver a programar las alarmas recurrentes en función del estado actual del dispositivo.</p>
<p>Un efecto secundario de este método es que tu aplicación activará el dispositivo siempre que uno de los receptores se active (probablemente, con más frecuencia de la necesaria).</p>
<p>Te recomendamos que inhabilites o habilites los receptores de emisión en el momento de la ejecución. De este modo, puedes utilizar los receptores que hayas declarado en el archivo de manifiesto como alarmas pasivas que se activan mediante los eventos del sistema solo cuando es necesario.</p>
<h2 id="ToggleReceivers">Cómo alternar y superponer receptores de cambio de estado para mejorar el rendimiento </h2>
<p>Se puede utilizar el {@link android.content.pm.PackageManager} para alternar el estado habilitado en cualquier componente definido en el archivo de manifiesto, incluidos los receptores de emisión que quieras habilitar o inhabilitar, como se muestra en el fragmento que aparece a continuación:</p>
<pre>ComponentName receiver = new ComponentName(context, myReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP)</pre>
<p>Al utilizar esta técnica, si determinas que la conectividad se ha perdido, puedes inhabilitar todos los receptores excepto el receptor de cambio de conectividad. Por el contrario, cuando estés conectado, puedes dejar de detectar cambios de conectividad y solo comprobar si tienes conexión antes de realizar una actualización y de volver a programar una alarma de actualización recurrente.</p>
<p>Puedes utilizar la misma técnica para posponer una descarga que requiera un nivel de ancho de banda superior para completarse. Solo tienes que habilitar un receptor de emisión que detecte los cambios de conectividad y que inicie la descarga solo cuando estés conectado a una red Wi-Fi.</p>

View File

@@ -1,212 +0,0 @@
page.title=Cómo implementar interfaces de usuario adaptables
parent.title=Cómo diseñar aplicaciones para varias pantallas
parent.link=index.html
trainingnavtop=true
previous.title=Cómo admitir varias densidades de pantalla
previous.link=screendensities.html
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#TaskDetermineCurLayout">Cómo determinar el diseño actual</a></li>
<li><a href="#TaskReactToLayout">Cómo reaccionar en función del diseño actual</a></li>
<li><a href="#TaskReuseFrag">Cómo volver a utilizar fragmentos en otras actividades</a></li>
<li><a href="#TaskHandleConfigChanges">Cómo gestionar los cambios en la configuración de la pantalla</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Cómo admitir tablets y dispositivos móviles</a></li>
</ul>
<h2>¡Pruébalo!</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Descargar la aplicación de ejemplo</a>
<p class="filename">NewsReader.zip</p>
</div>
</div>
</div>
<p>En función del diseño actual de tu aplicación, la interfaz puede variar. Por ejemplo, si tu aplicación está en modo de panel dual, haz clic en un elemento del panel izquierdo para que aparezca en el panel de la derecha. Asimismo, si está en modo de panel único, el contenido debería aparecer por sí mismo (en otra actividad).</p>
<h2 id="TaskDetermineCurLayout">Cómo determinar el diseño actual</h2>
<p>Dado que la implementación de cada diseño variará en cierta medida, probablemente una de las primeras cosas que tendrás que hacer será determinar el diseño que el usuario puede ver en ese momento. Por ejemplo, puedes determinar si el usuario utiliza el modo de "panel único" o de "panel dual". Para ello, puedes consultar si una vista determinada existe y es visible:</p>
<pre class="prettyprint">
public class NewsReaderActivity extends FragmentActivity {
boolean mIsDualPane;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
View articleView = findViewById(R.id.article);
mIsDualPane = articleView != null &amp;&amp;
articleView.getVisibility() == View.VISIBLE;
}
}
</pre>
<p>Ten en cuenta que este código consulta la disponibilidad del panel del "artículo", lo que es mucho más flexible que incluir una consulta para un diseño determinado.</p>
<p>Otro ejemplo de cómo puedes adaptar la existencia de diferentes componentes es comprobar su disponibilidad antes de realizar una operación relacionada con los mismos. Por ejemplo, en la aplicación de ejemplo News Reader, hay un botón que abre un menú, pero ese botón solo aparece en las versiones anteriores a Android 3.0 (porque <PH>{@link android.app.ActionBar}</PH> en el nivel 11 del API y en niveles superiores). Por tanto, para añadir el detector de eventos para este botón, puedes hacer lo siguiente:</p>
<pre class="prettyprint">
Button catButton = (Button) findViewById(R.id.categorybutton);
OnClickListener listener = /* create your listener here */;
if (catButton != null) {
catButton.setOnClickListener(listener);
}
</pre>
<h2 id="TaskReactToLayout">Cómo reaccionar en función del diseño actual</h2>
<p>El resultado de algunas acciones puede variar en función del diseño actual. Por ejemplo, en el ejemplo de News Reader, al hacer clic en un encabezado de la lista se abrirá el artículo del panel situado a la derecha si la interfaz de usuario está en modo de panel dual, pero se iniciará una actividad independiente si esta está en modo de panel único:</p>
<pre>
&#64;Override
public void onHeadlineSelected(int index) {
mArtIndex = index;
if (mIsDualPane) {
/* display article on the right pane */
mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
} else {
/* start a separate activity */
Intent intent = new Intent(this, ArticleActivity.class);
intent.putExtra("catIndex", mCatIndex);
intent.putExtra("artIndex", index);
startActivity(intent);
}
}
</pre>
<p>De igual modo, si la aplicación está en modo de panel dual, debe configurar la barra de acción con pestañas para la navegación, mientras que si la aplicación está en modo de panel único, debe configurar la navegación con un widget giratorio. Por tanto, el código debe comprobar también cuál es el caso adecuado:</p>
<pre>
final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };
public void onCreate(Bundle savedInstanceState) {
....
if (mIsDualPane) {
/* use tabs for navigation */
actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
int i;
for (i = 0; i &lt; CATEGORIES.length; i++) {
actionBar.addTab(actionBar.newTab().setText(
CATEGORIES[i]).setTabListener(handler));
}
actionBar.setSelectedNavigationItem(selTab);
}
else {
/* use list navigation (spinner) */
actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
SpinnerAdapter adap = new ArrayAdapter<String>(this,
R.layout.headline_item, CATEGORIES);
actionBar.setListNavigationCallbacks(adap, handler);
}
}
</pre>
<h2 id="TaskReuseFrag">Cómo volver a utilizar fragmentos en otras actividades</h2>
<p>Un patrón recurrente a la hora de diseñar para distintas pantallas es utilizar una parte de la interfaz que se implementa como un panel en algunas configuraciones de pantalla y como actividad independiente en otras. Por ejemplo, en el ejemplo de News Reader, el texto del artículo de noticias se presenta en el panel de la derecha en las pantallas grandes, pero es una actividad independiente en las pantallas más pequeñas.</p>
<p>En otros casos similares, puedes evitar la duplicación de código reutilizando la misma <PH>{@link android.app.Fragment}</PH> en distintas actividades. Por ejemplo, <code>ArticleFragment</code> se utiliza en el diseño de panel dual:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
<p>A continuación, se vuelve a utilizar (sin diseño) en el diseño de actividad para pantallas más pequeñas (<code>ArticleActivity</code>):</p>
<pre>
ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
</pre>
<p>Evidentemente, esto tiene el mismo efecto que declarar el fragmento en un diseño XML. Sin embargo, en este caso, un diseño XML sería un trabajo innecesario porque el fragmento del artículo es el único componente de esta actividad.</p>
<p>Un punto muy importante que debes tener en cuenta al diseñar tus fragmentos es no crear un acoplamiento fuerte para una actividad determinada. Para ello, normalmente puedes definir una interfaz que resuma todas las formas en las que tiene que interactuar el fragmento con su actividad principal y, a continuación, la actividad principal implementa esa interfaz:</p>
<p>Por ejemplo, ese es precisamente el objetivo del <code>HeadlinesFragment</code> de la aplicación News Reader:</p>
<pre>
public class HeadlinesFragment extends ListFragment {
...
OnHeadlineSelectedListener mHeadlineSelectedListener = null;
/* Must be implemented by host activity */
public interface OnHeadlineSelectedListener {
public void onHeadlineSelected(int index);
}
...
public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
mHeadlineSelectedListener = listener;
}
}
</pre>
<p>A continuación, cuando el usuario selecciona un encabezado, el fragmento notifica el detector especificado por la actividad principal (en lugar de notificar una actividad predefinida específica):</p>
<pre>
public class HeadlinesFragment extends ListFragment {
...
&#64;Override
public void onItemClick(AdapterView&lt;?&gt; parent,
View view, int position, long id) {
if (null != mHeadlineSelectedListener) {
mHeadlineSelectedListener.onHeadlineSelected(position);
}
}
...
}
</pre>
<p>Si quieres obtener más información sobre esta técnica, puedes consultar la guía sobre <a
href="{@docRoot}guide/practices/tablets-and-handsets.html">Cómo admitir tablets y dispositivos móviles</a>.</p>
<h2 id="TaskHandleConfigChanges">Cómo gestionar los cambios en la configuración de la pantalla</h2>
<p>Si utilizas actividades independientes para implementar partes individuales de tu interfaz, debes tener en cuenta que es posible que tengas que reaccionar ante determinados cambios en la configuración (como un cambio de rotación) para mantener la homogeneidad de tu interfaz.</p>
<p>Por ejemplo, en un tablet de 7" que utilice Android 3.0 o una versión superior, el ejemplo de News Reader utiliza una actividad independiente para mostrar el artículo de noticias en el modo vertical, pero utiliza el diseño de panel dual en el modo horizontal.</p>
<p>Esto significa que cuando el usuario utiliza el modo vertical y está consultando un artículo, tienes que detectar que la orientación ha cambiado al modo horizontal y reaccionar de forma adecuada finalizando la actividad. A continuación, debes volver a la actividad principal para que el contenido pueda mostrarse en el diseño de panel dual:</p>
<pre>
public class ArticleActivity extends FragmentActivity {
int mCatIndex, mArtIndex;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
// If should be in two-pane mode, finish to return to main activity
if (getResources().getBoolean(R.bool.has_two_panes)) {
finish();
return;
}
...
}
</pre>

View File

@@ -1,63 +0,0 @@
page.title=Cómo diseñar aplicaciones para varias pantallas
trainingnavtop=true
startpage=true
next.title=Cómo admitir varios tamaños de pantalla
next.link=screensizes.html
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependencias y requisitos previos</h2>
<ul>
<li>Android 1.6 o superior (Android 2.1 o superior para la aplicación de ejemplo)</li>
<li>Conocimiento básico de <a
href="http://developer.android.com/guide/components/activities.html">Actividades</a> y <a href="http://developer.android.com/guide/components/fragments.html">Fragmentos</a></li>
<li>Experiencia en el desarrollo de una <a
href="http://developer.android.com/guide/topics/ui/index.html">Interfaz de usuario</a> de Android</li>
<li>Algunas funciones requieren el uso de la <a
href="{@docRoot}tools/support-library/index.html">biblioteca de compatibilidad</a></li>
</ul>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Cómo admitir varias pantallas</a></li>
</ul>
<h2>¡Pruébalo!</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Descargar la aplicación de ejemplo</a>
<p class="filename">NewsReader.zip</p>
</div>
</div>
</div>
<p>Android se utiliza en cientos de dispositivos con diferentes tamaños de pantalla, desde pequeños teléfonos hasta enormes televisores. Por ello, es importante que diseñes tu aplicación para que sea compatible con todos los tamaños de pantalla y esté disponible para el mayor número de usuarios posible.</p>
<p>Sin embargo, no es suficiente con que tu aplicación sea compatible con diferentes dispositivos. Cada tamaño de pantalla ofrece diferentes posibilidades y retos para la interacción del usuario. Por ello, para satisfacer completamente a tus usuarios e impresionarlos, tu aplicación debe ir más allá de simplemente <em>admitir</em> varias pantallas: debe <em>optimizar</em> la experiencia de usuario para cada configuración de pantalla.</p>
<p>En esta sección se explica cómo implementar una interfaz de usuario que esté optimizada para diferentes configuraciones de pantalla.</p>
<p>El código que aparece en cada sección se ha extraído de una aplicación de ejemplo para explicar las prácticas recomendadas a la hora de optimizar tu aplicación para varias pantallas. Puedes descargar el ejemplo (situado a la derecha) y utilizarlo como fuente de código reutilizable para tu propia aplicación.</p>
<p class="note"><strong>Nota:</strong> en esta sección y en el ejemplo correspondiente, se utiliza la <a
href="{@docRoot}tools/support-library/index.html">biblioteca de compatibilidad</a> para poder usar las API de <PH>{@link android.app.Fragment}</PH> en versiones anteriores a Android 3.0. Debes descargar y la biblioteca y añadirla a tu aplicación para poder utilizar todas las API que se indican en esta sección.</p>
<h2>Secciones</h2>
<dl>
<dt><b><a href="screensizes.html">Cómo admitir varios tamaños de pantalla</a></b></dt>
<dd>En esta sección se explica cómo crear diseños que se adapten a diferentes tamaños de pantalla (mediante dimensiones flexibles para vistas, <PH>{@link android.widget.RelativeLayout}</PH>, calificadores de orientación y tamaño de pantalla, filtros de alias y mapas de bits de la clase NinePatch).</dd>
<dt><b><a href="screendensities.html">Cómo admitir varias densidades de pantalla</a></b></dt>
<dd>En esta sección se explica cómo admitir pantallas con diferentes densidades de píxeles (mediante píxeles independientes de la densidad y mapas de bits adecuados a cada densidad).</dd>
<dt><b><a href="adaptui.html">Cómo implementar interfaces de usuario adaptables</a></b></dt>
<dd>En esta sección se explica cómo implementar tu interfaz de usuario para que se adapte a varias combinaciones de densidad o de tamaño de pantalla (detección de tiempo de ejecución del diseño activo, cómo reaccionar en función del diseño actual y cómo administrar los cambios en la configuración de la pantalla).</dd>
</dl>

View File

@@ -1,100 +0,0 @@
page.title=Cómo admitir varias densidades de pantalla
parent.title=Cómo diseñar aplicaciones para varias pantallas
parent.link=index.html
trainingnavtop=true
previous.title=Cómo admitir varios tamaños de pantalla
previous.link=screensizes.html
next.title=Cómo implementar interfaces de usuario adaptables
next.link=adaptui.html
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#TaskUseDP">Cómo utilizar píxeles independientes de la densidad</a></li>
<li><a href="#TaskProvideAltBmp">Cómo proporcionar mapas de bits alternativos</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Cómo admitir varias pantallas</a></li>
<li><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Directrices para diseñar iconos</a></li>
</ul>
<h2>¡Pruébalo!</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Descargar la aplicación de ejemplo</a>
<p class="filename">NewsReader.zip</p>
</div>
</div>
</div>
<p>En esta sección se explica cómo proporcionar diferentes recursos y utilizar unidades de medida de resolución independiente para admitir diferentes densidades de pantalla.</p>
<h2 id="TaskUseDP">Cómo utilizar píxeles independientes de la densidad</h2>
<p>Un error común que debes evitar al crear tus diseños es utilizar píxeles absolutos para definir distancias o tamaños. Definir dimensiones de diseño mediante píxeles es problemático porque cada pantalla tiene densidades de píxeles diferentes, por lo que es posible que el mismo número de píxeles corresponda a varios tamaños físicos en distintos dispositivos. Por tanto, al especificar dimensiones, debes utilizar siempre unidades <code>dp</code> o <code>sp</code>. <code>dp</code> es un píxel independiente de la densidad que corresponde al tamaño físico de un píxel a 160 dpi. <code>sp</code> es la misma unidad de base, pero aumentada en función del tamaño de letra preferido por el usuario (se trata de un píxel independiente de la escala). Por tanto, debes utilizar esta unidad de medida para definir el tamaño de letra (pero no para tamaños de diseños).</p>
<p>Por ejemplo, al especificar un espacio entre dos vistas, debes utilizar <code>dp</code> en lugar de <code>px</code>:</p>
<pre>
&lt;Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/clickme"
android:layout_marginTop="20dp" /&gt;
</pre>
<p>Al especificar el tamaño de letra, debes usar siempre <code>sp</code>:</p>
<pre>
&lt;TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp" /&gt;
</pre>
<h2 id="TaskProvideAltBmp">Cómo proporcionar mapas de bits alternativos</h2>
<p>Dado que Android se ejecuta en dispositivos con diferentes densidades de pantalla, siempre debes proporcionar tus recursos de mapas de bits adaptados a los conjuntos de densidades generalizados: baja, media, alta y muy alta. De este modo, podrás conseguir un rendimiento y una calidad gráfica óptimos en todas las densidades de pantalla.</p>
<p>Para generar estas imágenes, debes empezar con tu recurso genérico en formato vectorial y generar las imágenes para cada densidad con la siguiente escala de tamaños:</p>
<p><ul>
<li><code>xhdpi</code>: 2,0
<li><code>hdpi</code>: 1,5
<li><code>mdpi</code>: 1.0 (base)
<li><code>ldpi</code>: 0,75
</ul></p>
<p>Esto significa que si generas una imagen de 200 x 200 para dispositivos <code>xhdpi</code>, debes generar el mismo recurso en 150 x 150 para <code>hdpi</code>, en 100 x 100 para <code>mdpi</code> y, por último, una imagen de 75 x 75 para dispositivos <code>ldpi</code>.</p>
<p>A continuación, sitúa los archivos de imagen generados en el subdirectorio adecuado en <code>res/</code> y el sistema seleccionará el archivo correspondiente automáticamente en función de la densidad de la pantalla del dispositivo en el que se esté ejecutando la aplicación:</p>
<pre class="classic no-pretty-print">
MyProject/
res/
drawable-xhdpi/
awesomeimage.png
drawable-hdpi/
awesomeimage.png
drawable-mdpi/
awesomeimage.png
drawable-ldpi/
awesomeimage.png
</pre>
<p>Por tanto, cada vez que hagas referencia a <code>&#64;drawable/awesomeimage</code>, el sistema seleccionará el mapa de bits adecuado en función de los puntos por pulgada de la pantalla.</p>
<p>Para consultar más sugerencias y directrices sobre cómo crear recursos de iconos para tu aplicación, consulta la sección <a
href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Directrices para diseñar iconos</a>.</p>

View File

@@ -1,279 +0,0 @@
page.title=Cómo admitir varios tamaños de pantalla
parent.title=Cómo diseñar aplicaciones para varias pantallas
parent.link=index.html
trainingnavtop=true
next.title=Cómo admitir varias densidades de pantalla
next.link=screendensities.html
@jd:body
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
<h2>En esta sección puedes aprender:</h2>
<ol>
<li><a href="#TaskUseWrapMatchPar">Cómo utilizar los valores "wrap_content" y "match_parent"</a></li>
<li><a href="#TaskUseRelativeLayout">Cómo utilizar RelativeLayout</a></li>
<li><a href="#TaskUseSizeQuali">Cómo utilizar calificadores de tamaño</a></li>
<li><a href="#TaskUseSWQuali">Cómo utilizar el calificador de ancho más pequeño</a></li>
<li><a href="#TaskUseAliasFilters">Cómo utilizar alias de diseño</a></li>
<li><a href="#TaskUseOriQuali">Cómo utilizar calificadores de orientación</a></li>
<li><a href="#TaskUse9Patch">Cómo utilizar mapas de bits de la clase NinePatch</a></li>
</ol>
<h2>También puedes consultar:</h2>
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Cómo admitir varias pantallas</a></li>
</ul>
<h2>¡Pruébalo!</h2>
<div class="download-box">
<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Descargar la aplicación de ejemplo</a>
<p class="filename">NewsReader.zip</p>
</div>
</div>
</div>
<p>En esta sección se explica cómo admitir varios tamaños de pantalla. Para ello, sigue estos pasos:</p>
<ul>
<li>Asegúrate de que el diseño se haya ajustado correctamente al tamaño de la pantalla.</li>
<li>Configura la pantalla con el diseño de interfaz adecuado.</li>
<li>Asegúrate de aplicar el diseño adecuado a la pantalla correspondiente.</li>
<li>Utiliza el mapa de bits con la escala adecuada.</li>
</ul>
<h2 id="TaskUseWrapMatchPar">Cómo utilizar los valores "wrap_content" y "match_parent"</h2>
<p>Para garantizar que el diseño es flexible y que se adapta a varios tamaños de pantalla, debes utilizar los valores <code>"wrap_content"</code> y <code>"match_parent"</code> para la altura y el ancho de algunos componentes de la vista. Si utilizas <code>"wrap_content"</code>, el ancho o la altura de la vista se establece en el tamaño mínimo necesario para adaptar el contenido a esta vista, mientras que <code>"match_parent"</code> (también conocido como <code>"fill_parent"</code> antes del nivel 8 del API) provoca que el componente se amplíe hasta coincidir con el tamaño de la vista principal.</p>
<p>Al utilizar los valores de tamaño <code>"wrap_content"</code> y <code>"match_parent"</code> en lugar de los tamaños predefinidos, las vistas pueden utilizar únicamente el espacio requerido para esa vista o ampliarse hasta rellenar el espacio disponible respectivamente. Por ejemplo:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
<p>Observa cómo se utilizan en el ejemplo los valores <code>"wrap_content"</code> y <code>"match_parent"</code> para los tamaños de los componentes en lugar de dimensiones específicas. Esto permite que el diseño se adapte correctamente a diferentes tamaños y orientaciones de la pantalla.</p>
<p>Por ejemplo, esta es la apariencia del diseño en modo horizontal y vertical. Ten en cuenta que los tamaños de los componentes se adaptan automáticamente a la altura y al ancho:</p>
<img src="{@docRoot}images/training/layout-hvga.png" />
<p class="img-caption"><strong>Figura 1.</strong> La aplicación de ejemplo News Reader en modo vertical (izquierda) y horizontal (derecha)</p>
<h2 id="TaskUseRelativeLayout">Cómo utilizar RelativeLayout</h2>
<p>Puedes crear diseños de un cierto nivel de complejidad con instancias anidadas de <PH>{@link android.widget.LinearLayout}</PH> y combinaciones de los valores de tamaño <code>"wrap_content"</code> y <code>"match_parent"</code>. Sin embargo, <PH>{@link android.widget.LinearLayout}</PH> no te permite controlar con precisión las relaciones espaciales de las vistas secundarias; las vistas de <PH>{@link android.widget.LinearLayout}</PH> simplemente se alinean en paralelo. Si quieres orientar las vistas secundarias de una forma que no sea una línea recta, a menudo la mejor solución es utilizar <PH>{@link android.widget.RelativeLayout}</PH>que te permite especificar el diseño según las relaciones espaciales entre los componentes. Por ejemplo, puedes alinear una vista secundaria en el lateral izquierdo y otra vista en el lateral derecho de la pantalla.</p>
<p>Por ejemplo:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"&gt;
&lt;TextView
android:id="&#64;+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type here:"/&gt;
&lt;EditText
android:id="&#64;+id/entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="&#64;id/label"/&gt;
&lt;Button
android:id="&#64;+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="&#64;id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="OK" /&gt;
&lt;Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="&#64;id/ok"
android:layout_alignTop="&#64;id/ok"
android:text="Cancel" /&gt;
&lt;/RelativeLayout&gt;
</pre>
<p>La figura 2 indica cómo se muestra este diseño en una pantalla QVGA.</p>
<img src="{@docRoot}images/training/relativelayout1.png" />
<p class="img-caption"><strong>Figura 2.</strong> Captura de pantalla de una pantalla QVGA (pantalla pequeña)</p>
<p>La figura 3 indica cómo se muestra este diseño en una pantalla más grande.</p>
<img src="{@docRoot}images/training/relativelayout2.png" />
<p class="img-caption"><strong>Figura 3.</strong> Captura de pantalla de una pantalla WSVGA (pantalla grande)</p>
<p>Ten en cuenta que aunque el tamaño de los componentes es diferente, las relaciones espaciales se mantienen según se ha especificado con <PH>{@link android.widget.RelativeLayout.LayoutParams}</PH>.</p>
<h2 id="TaskUseSizeQuali">Cómo utilizar calificadores de tamaño</h2>
<p>Hay mucha diferencia entre un diseño flexible y un diseño relativo como el que se ha utilizado en las secciones anteriores. Aunque ambos diseños se adaptan a diferentes pantalla estirando el espacio dentro de los componentes y alrededor de los mismos, puede que no ofrezcan la mejor experiencia de usuario para cada tamaño de pantalla. Por tanto, tu aplicación no solo debe implementar los diseños flexibles, sino que también debe ofrecer varios diseños alternativos para diferentes configuraciones de pantalla. Para ello, se utilizan <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">calificadores de configuración</a>, que permiten que el tiempo de ejecución seleccione el recurso adecuado en función de la configuración actual del dispositivo (por ejemplo, un diseño diferente para diferentes tamaños de pantalla).</p>
<p>Por ejemplo, muchas aplicaciones implementan el patrón de "panel dual" para pantallas grandes (la aplicación mostraría una lista de elementos en un panel y el contenido en otro panel). Aunque los tablets y las televisiones son lo suficientemente grandes como para que los dos paneles aparezcan simultáneamente en la pantalla, las pantallas de los teléfonos tienen que mostrarlos por separado. Para implementar estos diseños, puedes utilizar los siguientes archivos:</p>
<ul>
<li><code>res/layout/main.xml</code>, diseño de panel único (predeterminado):
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
</li>
<li><code>res/layout-large/main.xml</code>, diseño de panel dual:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
</li>
</ul>
<p>Observa el calificador <code>large</code> en el nombre de directorio del segundo diseño. Este diseño se seleccionará en dispositivos con pantallas clasificadas como grandes (por ejemplo, tablets de 7" y superiores). El otro diseño (sin calificadores) se seleccionará en el caso de dispositivos más pequeños.</p>
<h2 id="TaskUseSWQuali">Cómo utilizar el calificador de ancho mínimo</h2>
<p>Una de las dificultades a las que se enfrentaron los desarrolladores con los dispositivos Android anteriores a la versión 3.2 fue el contenedor de tamaño de pantalla "grande". Algunos ejemplos de este tipo de dispositivo son el tablet Dell Streak, el tablet Galaxy Tab original y los tablets de 7" en general. Sin embargo, es posible que muchas aplicaciones quieran mostrar varios diseños para diferentes dispositivos de esta categoría (por ejemplo, para dispositivos de 5" y de 7"), aunque todos estos dispositivos se consideren de pantalla grande. Por esta razón, Android introdujo el calificador de "ancho mínimo" (entre otros) en Android 3.2.</p>
<p>Este calificador te permite mostrar contenido en pantallas que tengan un ancho mínimo determinado en píxeles independientes de la densidad. Por ejemplo, el tablet típico de 7" tiene un ancho mínimo de 600 dp, por lo que si quieres que la interfaz de usuario sea de panel dual en esta pantalla (y una única lista en pantallas más pequeñas), puedes utilizar los mismos dos diseños de la sección anterior para los diseños de panel único y de panel dual, solo que en lugar de utilizar el calificador de tamaño <code>large</code>, debes utilizar <code>sw600dp</code> para indicar que el diseño de panel dual se utiliza con las pantallas cuyo ancho mínimo sea de 600 dp:</p>
<ul>
<li><code>res/layout/main.xml</code>, diseño de panel único (predeterminado):
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
</li>
<li><code>res/layout-sw600dp/main.xml</code>, diseño de panel dual:
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
</li>
</ul>
<p>Esto significa que los dispositivos cuyo ancho mínimo sea igual o superior a 600 dp utilizarán el diseño <code>layout-sw600dp/main.xml</code> (panel dual), mientras que las pantallas más pequeñas utilizarán el diseño <code>layout/main.xml</code> (panel único).</p>
<p>No obstante, esto no funcionará en los dispositivos anteriores a Android 3.2 porque no reconocen <code>sw600dp</code> como calificador de tamaño, por lo que también tendrás que seguir utilizando el calificador <code>large</code>. Por tanto, debes tener un archivo con el nombre <code>res/layout-large/main.xml</code> idéntico a <code>res/layout-sw600dp/main.xml</code>. En la siguiente sección, obtendrás información sobre una técnica que te permite evitar que se dupliquen los archivos de diseños.</p>
<h2 id="TaskUseAliasFilters">Cómo utilizar alias de diseño</h2>
<p>El calificador de ancho mínimo solo está disponible en Android 3.2 o superior. Por tanto, tendrás que seguir utilizando los contenedores de tamaño abstractos (pequeño, normal, grande y extragrande) para que sean compatibles con versiones anteriores. Por ejemplo, si quieres que tu interfaz de usuario sea de panel único en teléfonos pero multipanel en tablets de 7", televisiones y otros dispositivos grandes, tendrás que utilizar los siguientes archivos:</p>
<p><ul>
<li><code>res/layout/main.xml:</code> diseño de panel único,</li>
<li><code>res/layout-large:</code> diseño multipanel,</li>
<li><code>res/layout-sw600dp:</code> diseño multipanel.</li>
</ul></p>
<p>Los dos últimos archivos son idénticos porque uno de ellos se utilizará con dispositivos Android 3.2 y el otro con tablets y televisiones que utilicen versiones anteriores de Android.</p>
<p>Para evitar la duplicación del mismo archivo para tablets y televisiones (así como todos los problemas que esto conlleva), puedes utilizar archivos alias. Por ejemplo, puedes establecer los siguientes diseños:</p>
<ul>
<li><code>res/layout/main.xml</code>: diseño de panel único,</li>
<li><code>res/layout/main_twopanes.xml</code>: diseño de panel dual.</li>
</ul>
<p>Añade estos dos archivos:</p>
<p><ul>
<li><code>res/values-large/layout.xml</code>:
<pre>
&lt;resources>
&lt;item name="main" type="layout">&#64;layout/main_twopanes&lt;/item>
&lt;/resources>
</pre>
</li>
<li><code>res/values-sw600dp/layout.xml</code>:
<pre>
&lt;resources>
&lt;item name="main" type="layout">&#64;layout/main_twopanes&lt;/item>
&lt;/resources>
</pre>
</li>
</ul></p>
<p>Estos dos últimos archivos tienen el mismo contenido, pero en realidad no definen el diseño. Solo configuran <PH>{@code main}</PH> para que sea un alias de <PH>{@code main_twopanes}</PH>. Como los archivos tienen selectores <code>large</code> y <code>sw600dp</code>, se aplican a tablets y a televisiones independientemente de la versión de Android (las televisiones y los tablets anteriores a la versión 3.2 utilizarán
<PH>{@code large}</PH>y las televisiones y los tablets posteriores a la versión 3.2 utilizarán <code>sw600dp</code>).</p>
<h2 id="TaskUseOriQuali">Cómo utilizar calificadores de orientación</h2>
<p>Aunque algunos diseños se pueden utilizar tanto en modo horizontal como vertical, la mayoría de ellos pueden beneficiarse de los ajustes. A continuación, se indica cómo se comporta el diseño según cada tamaño y orientación de la pantalla en la aplicación de ejemplo News Reader:</p>
<p><ul>
<li><b>pantalla pequeña, vertical:</b> panel único con logotipo,</li>
<li><b>pantalla pequeña, horizontal:</b> panel único con logotipo,</li>
<li><b>tablet de 7", vertical:</b> panel único con barra de acciones,</li>
<li><b>tablet de 7", horizontal:</b> panel dual ancho con barra de acciones,</li>
<li><b>tablet de 10", vertical:</b> panel dual estrecho con barra de acciones,</li>
<li><b>tablet de 10", horizontal:</b> panel dual ancho con barra de acciones,</li>
<li><b>televisión, horizontal:</b> panel dual ancho con barra de acciones.</li>
</ul></p>
<p>Cada uno de estos diseños se establecen en un archivo XML en el directorio <code>res/layout/</code>. Para definir posteriormente las diferentes configuraciones de pantalla, la aplicación utiliza alias de diseño para asignarlos a cada configuración:</p>
<p><code>res/layout/onepane.xml:</code></p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all}
<p><code>res/layout/onepane_with_bar.xml:</code></p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all}
<p><code>res/layout/twopanes.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all}
<p><code>res/layout/twopanes_narrow.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all}
<p>Una vez que se hayan definido todos los diseños posibles, solo se debe asignar el diseño adecuado a cada configuración a través de calificadores de configuración. Ahora ya puedes utilizar la técnica de los alias de diseño:</p>
<p><code>res/values/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all}
<p><code>res/values-sw600dp-land/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml
all}
<p><code>res/values-sw600dp-port/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml
all}
<p><code>res/values-large-land/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all}
<p><code>res/values-large-port/layouts.xml</code>:</p>
{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all}
<h2 id="TaskUse9Patch">Cómo utilizar mapas de bits de la clase NinePatch</h2>
<p>Admitir diferentes tamaños de pantalla normalmente implica que las fuentes de imagen también deben poder adaptarse a varios tamaños. Por ejemplo, un fondo de botón debe adaptarse a cualquier forma de botón a la que se aplique.</p>
<p>Si utilizas imágenes sencillas en componentes que pueden cambiar de tamaño, observarás rápidamente que los resultados no es que sean precisamente impresionantes, ya que las imágenes se estirarán o estrecharán. La solución es utilizar mapas de bits de la clase NinePatch, que son archivos PNG con un formato especial que indican las áreas que se pueden y no se pueden estirar.</p>
<p>Por tanto, al diseñar mapas de bits que se vayan a utilizar en componentes con tamaño variable, utiliza siempre mapas de bits de la clase NinePatch. Para convertir un mapa de bits en uno de la clase NinePatch, puedes empezar con una imagen normal (consulta la figura 4, que se ha ampliado cuatro veces para obtener una mayor claridad).</p>
<img src="{@docRoot}images/training/button.png" />
<p class="img-caption"><strong>Figura 4.</strong> <code>button.png</code></p>
<p>A continuación, puedes pasar a la utilidad <ode
href="{@docRoot}tools/help/draw9patch.html"><code>draw9patch</code></a> del SDK (que se localiza en el directorio <code>tools/</code>) en la que puedes marcar las áreas que se deben estirar dibujando píxeles a lo largo de los bordes superior e izquierdo. También puedes marcar el área que debe incluir el contenido dibujando píxeles a lo largo de los bordes inferior y derecho, como se muestra en la figura 5.</p>
<img src="{@docRoot}images/training/button_with_marks.png" />
<p class="img-caption"><strong>Figura 5.</strong> <code>button.9.png</code></p>
<p>Observa los píxeles de color negro situados junto a los bordes. Los que aparecen en los bordes superior e izquierdo indican los lugares en los que se puede estirar la imagen, mientras que los que aparecen en los bordes inferior y derecho indican dónde se debe situar el contenido.</p>
<p>Además, observa la extensión <code>.9.png</code>. Debes utilizar esta extensión, ya que, de este modo, el marco detecta que se trata de una imagen de la clase NinePatch, en lugar de una imagen PNG normal.</p>
<p>Cuando aplicas este fondo a un componente (definiendo <code>android:background="&#64;drawable/button"</code>), el marco estira la imagen de forma adecuada para adaptarla al botón, como se muestra en varios tamaños de la figura 6.</p>
<img src="{@docRoot}images/training/buttons_stretched.png" />
<p class="img-caption"><strong>Figura 6.</strong> Botón que utiliza la clase NinePatch <code>button.9.png</code> en varios tamaños</p>

View File

@@ -1,213 +0,0 @@
page.title=Modo Picture-in-picture
page.keywords=preview,sdk,PIP,Picture-in-picture
page.tags=androidn
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#declaring">Declarar que la actividad permite
el modo Picture-in-Picture</a></li>
<li><a href="#pip_button">Cambiar la actividad al modo Picture-in-picture</a>
</li>
<li><a href="#handling_ui">Gestionar las IU durante el modo Picture-in-picture</a>
</li>
<li><a href="#continuing_playback">Continuar la reproducción de video durante
el modo Picture-in-picture</a></li>
<li><a href="#single_playback">Usar una única actividad de reproducción para
el modo Picture-in-picture</a></li>
<li><a href="#best">Prácticas recomendadas</a></li>
</ol>
<h2>Consulta también</h2>
<ol>
<li><a href="{@docRoot}preview/features/multi-window.html">Compatibilidad con
ventanas múltiples</a></li>
</ol>
</div>
</div>
<p>Con Android N, los usuarios de Android TV ahora pueden ver un video
en una ventana fija que se ubica en una esquina de la pantalla mientras navegan dentro de
aplicaciones. El modo picture-in-picture (PIP) permite que las aplicaciones reproduzcan un video
en una ventana fija mientras se lleva a cabo otra actividad
en el fondo. La ventana de PIP les permite a los usuarios realizar múltiples tareas mientras usan tu aplicación, lo cual les permite
ser más productivos.</p>
<p>Tu aplicación puede decidir cuándo activar el modo PIP. Aquí te mostramos algunos ejemplos de
situaciones en las que se podría usar el modo PIP:</p>
<ul>
<li>Tu aplicación puede pasar un video al modo PIP cuando el usuario retrocede
en la navegación desde el video para explorar otro contenido.</li>
<li>También puede hacerlo mientras el usuario está viendo el final
de un episodio de contenido. La pantalla principal muestra información promocional
o de resumen sobre el próximo capítulo de la serie.</li>
<li>Tu aplicación puede brindarles a los usuarios una forma de poner en cola otro contenido mientras
miran un video. El video continúa reproduciéndose en modo PIP mientras la pantalla
principal muestra una actividad de selección de contenido.</li>
</ul>
<p>La ventana de PIP es de 240x135 dp y se muestra en la capa delantera en una de las
cuatro esquinas de la pantalla que el sistema elige. El usuario puede acceder a un menú de
PIP que le permite activar o desactivar la ventana de PIP a pantalla completa o cerrarla
presionando el botón <b>Home</b> en el control remoto. Si se comienza a reproducir
otro video en la pantalla principal, la ventana de PIP se cierra
automáticamente. Los usuarios también pueden cerrar la ventana de PIP desde Recents.</p>
<img src="{@docRoot}images/android-7.0/pip-active.png" />
<p class="img-caption"><strong>Imagen 1.</strong> Un video picture-in-picture
visible en una esquina de la pantalla mientras el usuario explora contenido
en la pantalla principal.</p>
<p>El modo PIP aprovecha las API de ventanas múltiples disponibles en Android N para
brindar la ventana superpuesta fija de video. Para agregarle el modo PIP a tu aplicación, debes
registrar las actividades que permitan este modo, cambiar la actividad al modo PIP según
sea necesario y asegurarte de que los elementos de IU se oculten y que la reproducción de video continúe mientras
la actividad se encuentra en modo PIP.</p>
<h2 id="declaring">Declarar que la actividad permite el modo picture-in-picture</h2>
<p>De forma predeterminada, el sistema no permite el modo PIP para aplicaciones automáticamente.
Si deseas permitir este modo en tu aplicaciones, registra la actividad
de video en tu manifiesto configurando
<code>android:supportsPictureInPicture</code> y
<code>android:resizeableActivity</code> en <code>true</code>. Además, debes especificar
que tu actividad gestiona los cambios de configuración de la presentación para que la actividad
no se reinicie cuando ocurran cambios de presentación durante las transiciones en el modo PIP.</p>
<pre>
&lt;activity android:name="VideoActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...
</pre>
<p>Cuando registres la actividad, ten en cuenta que, en el modo PIP, la
actividad se muestra en una ventana superpuesta pequeña en una pantalla de TV. Las actividades de reproducción
de videos con IU mínimas brindan la mejor experiencia de usuario. Las actividades que
incluyen elementos de IU pequeños podrían no brindar una buena experiencia de usuario
cuando se cambian al modo PIP, porque los usuarios no podrán ver los detalles de los elementos de IU
en la ventana PIP.</p>
<h2 id="pip_button">Cambiar la actividad al modo Picture-in-picture</h2>
Cuando necesites cambiar la actividad al modo PIP, llama a
<code>Activity.enterPictureInPictureMode()</code>. En el siguiente ejemplo, se
cambia al modo PIP cuando el usuario selecciona un botón PIP especial en una barra
de control de medios:</p>
<pre>
&#64;Override
public void onActionClicked(Action action) {
if (action.getId() == R.id.lb_control_picture_in_picture) {
getActivity().enterPictureInPictureMode();
return;
}
...
</pre>
<p>Agregar un botón PIP a la barra de control de medios le permite al usuario cambiar
fácilmente al modo PIP y seguir controlando la reproducción de video.</p>
<img src="{@docRoot}images/android-7.0/pip-button.png" />
<p class="img-caption"><strong>Imagen 1.</strong> Un botón
PIP en una barra de control de medios.</p>
<p>Android N incluye una nueva clase
<code>PlaybackControlsRow.PictureInPictureAction</code> que define
las acciones de PIP de la barra de control y usa el ícono PIP.</p>
<h2 id="handling_ui">Gestionar las IU durante el modo picture-in-picture</h2>
<p>Cuando la actividad ingresa al modo PIP, esta solo debería mostrar la reproducción
de video. Debes quitar los elementos de IU antes de que la actividad ingrese al modo PIP
y volver a mostrarlos cuando la actividad vuelva al modo de pantalla completa.
Anula <code>Activity.onPictureInPictureModeChanged()</code> o
<code>Fragment.onPictureInPictureModeChanged()</code> y habilita
o inhabilita los elementos de IU según sea necesario, por ejemplo:</p>
<pre>
&#64;Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
if (isInPictureInPictureMode) {
// Hide the controls in picture-in-picture mode.
...
} else {
// Restore the playback UI based on the playback status.
...
}
}
</pre>
<h2 id="continuing_playback">Continuar la reproducción de video durante
el modo Picture-in-picture</h2>
<p>Cuando la actividad cambia al modo PIP, el sistema considera que se encuentra en
pausa y llama al método <code>onPause()</code> de la actividad. La reproducción
de video no debería pausarse y debería continuar si la actividad se
pausa debido al modo PIP. Busca el modo PIP en el método
<code>onPause()</code> de la actividad y controla la reproducción según corresponda, por
ejemplo:</p>
<pre>
&#64;Override
public void onPause() {
// If called while in PIP mode, do not pause playback
if (isInPictureInPictureMode()) {
// Continue playback
...
}
// If paused but not in PIP, pause playback if necessary
...
}
</pre>
<p>Cuando la actividad sale del modo PIP y vuelve al modo de pantalla completa, el
sistema reinicia la actividad y llama al método <code>onResume()</code>.</p>
<h2 id="single_playback">Usar una única actividad de reproducción para
el modo Picture-in-picture</h2>
<p>En tu aplicación, un usuario puede seleccionar un nuevo video cuando busca contenido en la
pantalla principal, mientras una actividad de reproducción de video está en modo PIP. Reproduce el nuevo
video en la actividad de reproducción actual en modo de pantalla completa, en lugar de
iniciar una nueva actividad que podría confundir al usuario.</p>
<p>A fin de garantizar que se utilice una única actividad para las solicitudes de reproducción de video y que esta
ingrese en el modo PIP o salga de este cuando sea necesario, configura el
<code>android:launchMode</code> de la actividad en <code>singleTask</code>, en el manifiesto:
</p>
<pre>
&lt;activity android:name="VideoActivity"
...
android:supportsPictureInPicture="true"
android:launchMode="singleTask"
...
</pre>
<p>En tu actividad, anula {@link android.app.Activity#onNewIntent
Activity.onNewIntent()} y administra el nuevo video, deteniendo cualquier reproducción
de video actual si es necesario.</p>
<h2 id="best">Prácticas recomendadas</h2>
<p>El modo PIP está diseñado para actividades que reproducen un video en pantalla completa. Cuando cambies la
actividad al modo PIP, evita que se muestre cualquier elemento que no sea el contenido del video.
Rastrea el cambio a modo PIP de la actividad y oculta los elementos de IU, como se explica
en la sección <a href="#handling_ui">Gestionar las IU durante el modo picture-in-picture</a>.</p>
<p>Debido a que la ventana de PIP se muestra como una ventana flotante en una
esquina de la pantalla, debes evitar mostrar información importante en la pantalla principal
en cualquier área que pueda quedar oculta detrás de la ventana de PIP.</p>
<p>Cuando una actividad se encuentra en modo PIP, de forma predeterminada, no tiene focalización en las entradas. Para
recibir eventos de entradas durante este modo, usa
<code>MediaSession.setMediaButtonReceiver()</code>.</p>

View File

@@ -1,142 +0,0 @@
page.title=Grabación de TV
page.keywords=preview,sdk,tv,recording
page.tags=androidn
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>En este documento</h2>
<ol>
<li><a href="#supporting">Indicar la compatibilidad para la grabación</a></li>
<li><a href="#recording">Grabar una sesión</a></li>
<li><a href="#errors">Gestionar los errores de grabación</a></li>
<li><a href="#sessions">Gestionar las sesiones grabadas</a></li>
<li><a href="#best">Prácticas recomendadas</a></li>
</ol>
</div>
</div>
<p>Los servicios de entrada de TV le permiten al usuario pausar y reanudar la reproducción de canales
mediante API de time-shifting. Android N expande la función de time-shifting
permitiéndoles a los usuarios guardar múltiples sesiones grabadas.</p>
<p>Los usuarios pueden programar las grabaciones por adelantado o comenzar a grabar a la vez
que miran un programa. Una vez que el sistema haya guardado una grabación, el usuario puede explorar, gestionar
y reproducir las grabaciones usando la aplicación del sistema de TV.</p>
<p>Si deseas brindar funcionalidades de grabación a tu servicio de entrada de TV,
debes indicarle al sistema que tu aplicación permite la grabación, implementar
la habilidad para grabar programas, gestionar y comunicar los errores que ocurren
durante la grabación y gestionar las sesiones grabadas.</p>
<p class="note"><strong>Nota:</strong> La aplicación Live Channels todavía no
permite que los usuarios creen grabaciones ni accedan a estas. Hasta que se realicen
cambios en la aplicación Live Channels, es posible que sea difícil probar completamente la
experiencia de grabación para tu servicio de entrada de TV.</p>
<h2 id="supporting">Indicar la compatibilidad para la grabación</h2>
<p>Para comunicarle al sistema que tu servicio de entrada de TV permite la grabación, configura el
atributo <code>android:canRecord</code> de tu archivo XML de metadatos de servicio
en <code>true</code>:
</p>
<pre>
&lt;tv-input xmlns:android="http://schemas.android.com/apk/res/android"
<b>android:canRecord="true"</b>
android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" /&gt;
</pre>
<p>Para obtener más información sobre el archivo de metadatos de servicio, consulta
<a href="{@docRoot}training/tv/tif/tvinput.html#manifest">Declarar el servicio de entrada
de TV en el manifiesto</a>.
</p>
<p>De forma alternativa, puedes indicar la compatibilidad para la grabación en tu código; para ello, sigue
estos pasos:</p>
<ol>
<li>En el método <code>TvInputService.onCreate()</code>, crea un nuevo
objeto <code>TvInputInfo</code> usando la clase <code>TvInputInfo.Builder</code>.
</li>
<li>Cuando crees el nuevo objeto <code>TvInputInfo</code>, llama a
<code>setCanRecord(true)</code> antes de llamar a <code>build()</code> para
indicar que tu servicio permite la grabación.</li>
<li>Registra tu objeto <code>TvInputInfo</code> con el sistema llamando a
<code>TvInputManager.updateTvInputInfo()</code>.</li>
</ol>
<h2 id="recording">Grabar una sesión</h2>
<p>Luego de que el servicio de entrada de TV registra la compatibilidad
con la funcionalidad de grabación, el sistema llama a tu
<code>TvInputService.onCreateRecordingSession()</code> cuando necesita acceder
a la implementación de grabación de tu aplicación. Implementa tu propia subclase
<code>TvInputService.RecordingSession</code> y devuélvela
cuando el callback de <code>onCreateRecordingSession()</code>
se dispare. Esta subclase es responsable de cambiar a los datos del canal correcto,
de grabar los datos solicitados y de comunicar el estado y los errores de grabación al
sistema.</p>
<p>Cuando el sistema llama a <code>RecordingSession.onTune()</code>, pasando en un
URI de canal, sintoniza el canal que el URI especifica. Notifícale al sistema que tu
aplicación se ha sintonizado al canal deseado llamando a <code>notifyTuned()</code>
o, si tu aplicación no pudo sintonizarse al canal correcto, llama a
<code>notifyError()</code>.</p>
<p>El sistema invoca, a continuación, el callback <code>RecordingSession.onStartRecording()</code>.
Tu aplicación debe comenzar a grabar inmediatamente. Cuando el sistema invoca
este callback, puede brindar un URI que contiene información sobre el programa
que se está por grabar. Cuando finaliza la grabación, debes copiar estos
datos a la tabla de datos <code>RecordedPrograms</code>.</p>
<p>Finalmente, el sistema llama a <code>RecordingSession.onStopRecording()</code>.
En este momento, tu aplicación debe dejar de grabar inmediatamente. También debes crear
una entrada en la tabla <code>RecordedPrograms</code>. Esta entrada debe
incluir el URI de datos de la sesión grabada en la columna
<code>RecordedPrograms.COLUMN_RECORDING_DATA_URI</code> y cualquier información
del programa que el sistema haya brindado en la llamada inicial a
<code>onStartRecording()</code>.</p>
<p>Para obtener más información sobre cómo acceder a la tabla <code>RecordedPrograms</code>
, consulta <a href="#sessions">Gestionar las sesiones grabadas</a>.</p>
<h2 id="errors">Gestionar los errores de grabación</h2>
<p>Si ocurre un error durante la grabación que hace que los datos grabados no se puedan usar,
notifica al sistema llamando a<code>RecordingSession.notifyError()</code>.
De forma similar, puedes llamar a <code>notifyError()</code> después de que se cree una sesión de grabación
para que el sistema sepa que la aplicación ya no puede grabar sesiones.</p>
<p>Si ocurre un error durante la grabación, pero deseas brindarle al usuario una grabación
parcial usable para su reproducción, llama a
<code>RecordingSession.notifyRecordingStopped()</code> para permitir que el sistema
use la sesión parcial.</p>
<h2 id="sessions">Gestionar las sesiones grabadas</h2>
<p>El sistema mantiene información de todas las sesiones grabadas de todas
las aplicaciones de canal con funcionalidad de grabación en la tabla de proveedor de contenido <code>TvContract.RecordedPrograms</code>
. Esta información se accede mediante el URI de contenido
<code>RecordedPrograms.Uri</code>. Usa API de proveedor de contenido para
leer, agregar y borrar entradas de esta tabla.</p>
<p>Para obtener más información sobre cómo trabajar con datos del proveedor de contenido, consulta
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Conceptos básicos sobre el proveedor de contenido</a>.</p>
<h2 id="best">Prácticas recomendadas</h2>
<p>Los dispositivos de TV tienen un almacenamiento limitado, de modo que debes ser cuidadoso a la hora
de asignar el almacenamiento para guardar las sesiones grabadas. Usa
<code>RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE)</code> cuando
no haya espacio suficiente para guardar una sesión grabada.</p>
<p>Cuando el usuario inicie la grabación, el registro de datos debe comenzar
lo antes posible. Para facilitar este proceso, completa cualquier tarea anterior demandante,
como acceder al espacio de almacenamiento y asignarlo, cuando el sistema invoque el
callback <code>onCreateRecordingSession()</code>. Hacerlo te permite comenzar
a grabar inmediatamente cuando el callback <code>onStartRecording()</code>
se dispare.</p>

View File

@@ -1,190 +0,0 @@
page.title=Panduan Pengujian
page.image=images/cards/card-n-guide_2x.png
meta.tags="preview", "testing"
page.tags="preview", "developer preview"
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#runtime-permissions">Izin Pengujian</a></li>
<li><a href="#doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</a></li>
<li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
</ol>
</div>
</div>
<p>
Android N memberi Anda kesempatan untuk memastikan aplikasi bekerja pada
platform versi berikutnya. Pratinjau ini berisi beberapa API dan perubahan perilaku yang bisa
memengaruhi aplikasi Anda, sebagaimana dijelaskan dalam <a href="{@docRoot}preview/api-overview.html">Ringkasan
API</a> dan <a href="{@docRoot}preview/behavior-changes.html">Perubahan Perilaku</a>. Dalam menguji
aplikasi dengan pratinjau, ada beberapa perubahan sistem spesifik yang harus Anda fokuskan untuk
memastikan pengguna mendapatkan pengalaman yang bagus.
</p>
<p>
Panduan ini menjelaskan apa dan bagaimana menguji fitur pratinjau dengan aplikasi Anda. Anda harus
mengutamakan pengujian fitur pratinjau spesifik ini, dikarenakan pengaruhnya yang besar pada
perilaku aplikasi Anda:
</p>
<ul>
<li><a href="#runtime-permissions">Izin</a>
</li>
<li><a href="#doze-standby">Istirahatkan dan Aplikasi Siaga</a>
</li>
<li><a href="#ids">Pencadangan Otomatis dan Identifier Perangkat</a></li>
</ul>
<p>
Untuk informasi selengkapnya tentang cara menyiapkan perangkat atau perangkat maya dengan citra sistem pratinjau
untuk pengujian, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan
Android N SDK</a>.
</p>
<h2 id="runtime-permissions">Izin Pengujian</h2>
<p>
Model <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a> yang baru
mengubah cara alokasi izin untuk aplikasi Anda oleh pengguna. Sebagai ganti memberi semua
izin selama prosedur pemasangan, aplikasi Anda harus meminta izin kepada pengguna secara individual
pada waktu proses. Bagi pengguna, perilaku ini memberi kontrol yang lebih detail atas setiap aktivitas aplikasi, dan
juga konteks yang lebih untuk memahami sebab aplikasi meminta izin tertentu. Pengguna
bisa memberi atau mencabut izin yang diberikan pada suatu aplikasi secara individual kapan saja. Fitur
pratinjau ini kemungkinan besar memengaruhi perilaku aplikasi Anda dan mungkin menghambat fungsi beberapa
fitur aplikasi Anda, atau mengurangi kualitas kerjanya.
</p>
<p class="caution">
Perubahan ini memengaruhi semua aplikasi yang berjalan di platform baru, bahkan aplikasi yang tidak menargetkan versi
platform baru. Platform ini memberikan perilaku kompatibilitas terbatas untuk aplikasi lawas, namun Anda
harus mulai merencanakan migrasi aplikasi ke model izin baru sekarang juga, dengan tujuan
mempublikasikan versi terbaru aplikasi Anda saat peluncuran platform secara resmi.
</p>
<h3 id="permission-test-tips">Tip pengujian</h3>
<p>
Gunakan tip berikut untuk membantu Anda merencanakan dan menjalankan pengujian aplikasi dengan
perilaku izin yang baru.
</p>
<ul>
<li>Identifikasi izin aplikasi Anda saat ini dan jalur kode terkait.</li>
<li>Uji alur pengguna pada semua layanan dan data yang dilindungi izin.</li>
<li>Uji dengan berbagai kombinasi izin yang diberikan/dicabut.</li>
<li>Gunakan alat bantu {@code adb} untuk mengelola izin dari baris perintah:
<ul>
<li>Cantumkan daftar izin dan status berdasarkan kelompok:
<pre>adb shell pm list permissions -d -g</pre>
</li>
<li>Beri atau cabut satu atau beberapa izin menggunakan sintaks berikut:<br>
<pre>adb shell pm [grant|revoke] &lt;permission.name&gt; ...</pre>
</li>
</ul>
</li>
<li>Analisis aplikasi Anda untuk layanan yang menggunakan izin.</li>
</ul>
<h3 id="permission-test-strategy">Strategi pengujian</h3>
<p>
Perubahan izin memengaruhi struktur dan desain aplikasi Anda, begitu juga
pengalaman pengguna dan alur yang Anda sediakan untuk pengguna. Anda harus menilai penggunaan izin
aplikasi saat ini dan mulai merencanakan alur baru yang ingin ditawarkan. Rilis platform
resmi menyediakan perilaku kompatibilitas, namun Anda harus merencanakan pembaruan aplikasi dan tidak
bergantung pada perilaku ini.
</p>
<p>
Identifikasi izin yang sebenarnya diperlukan dan digunakan aplikasi Anda, kemudian temukan berbagai
jalur kode yang menggunakan layanan yang dilindungi izin. Anda bisa melakukan ini melalui kombinasi
pengujian pada platform baru dan analisis kode. Dalam pengujian, Anda harus fokus pada pemilihan
izin waktu proses dengan mengubah {@code targetSdkVersion} aplikasi ke versi pratinjau. Untuk
informasi selengkapnya, lihat <a href="{@docRoot}preview/setup-sdk.html#">Menyiapkan
Android N SDK</a>.
</p>
<p>
Uji dengan berbagai kombinasi izin yang dicabut dan ditambahkan, untuk menyoroti alur pengguna yang
bergantung pada izin. Jika dependensi tidak jelas atau logis, Anda harus mempertimbangkan
optimalisasi atau kompartementalisasi alur tersebut untuk mengeliminasi dependensi atau menjelaskan alasan
diperlukannya izin.
</p>
<p>
Untuk informasi selengkapnya tentang perilaku izin waktu proses, pengujian, dan praktik terbaik, lihat
halaman pratinjau <a href="{@docRoot}preview/features/runtime-permissions.html">Izin</a>
pengembang.
</p>
<h2 id="doze-standby">Menguji Istirahatkan dan Aplikasi Siaga</h2>
<p>
Fitur penghematan daya Istirahatkan dan Aplikasi Siaga membatasi jumlah pemrosesan latar belakang yang
bisa dikerjakan aplikasi Anda saat perangkat dalam keadaan diam atau saat aplikasi Anda sedang tidak fokus. Pembatasan
yang dapat diberlakukan oleh sistem pada aplikasi termasuk akses jaringan terbatas atau tidak ada,
tugas latar belakang yang ditangguhkan, Pemberitahuan yang ditangguhkan, permintaan membangunkan yang diabaikan, serta alarm. Untuk memastikan
aplikasi Anda berperilaku dengan benar pada optimalisasi penghematan daya ini, Anda harus menguji aplikasi dengan
menyimulasikan keadaan baterai yang sedang tinggal sedikit ini.
</p>
<h4 id="doze">Menguji aplikasi Anda dengan Istirahatkan</h4>
<p>Untuk menguji Istirahatkan dengan aplikasi Anda:</p>
<ol>
<li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
<li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
<li>Jalankan aplikasi Anda dan biarkan aktif.</li>
<li>Simulasikan perangkat yang sedang masuk ke dalam mode Istirahatkan dengan menjalankan perintah berikut:
<pre>
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
$ adb shell dumpsys deviceidle -h
</pre>
</li>
<li>Amati perilaku aplikasi Anda saat perangkat diaktifkan kembali. Pastikan aplikasi
pulih dengan baik saat perangkat keluar dari Istirahatkan.</li>
</ol>
<h4 id="standby">Menguji aplikasi dengan Aplikasi Siaga</h4>
<p>Untuk menguji mode Aplikasi Siaga dengan aplikasi Anda:</p>
<ol>
<li>Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.</li>
<li>Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.</li>
<li>Jalankan aplikasi Anda dan biarkan aktif.</li>
<li>Simulasikan aplikasi yang sedang masuk ke dalam mode siaga dengan menjalankan perintah berikut:
<pre>
$ adb shell am broadcast -a android.os.action.DISCHARGING
$ adb shell am set-idle &lt;packageName&gt; true
</pre>
</li>
<li>Simulasikan membangunkan aplikasi Anda menggunakan perintah berikut:
<pre>$ adb shell am set-idle &lt;packageName&gt; false</pre>
</li>
<li>Amati perilaku aplikasi Anda saat dibangunkan. Pastikan aplikasi pulih dengan baik
dari mode siaga. Secara khusus, Anda harus memeriksa apakah Pemberitahuan aplikasi dan pekerjaan latar belakang
tetap berjalan sebagaimana yang diharapkan.</li>
</ol>
<h2 id="ids">Auto Backup for Apps dan Identifier Perangkat Spesifik</h2>
<p>Jika aplikasi Anda mempertahankan identifier perangkat spesifik, seperti ID pendaftaran Google
Cloud Messaging, dalam penyimpanan internal,
pastikan Anda mengikuti praktik terbaik untuk mengecualikan lokasi
penyimpanan dari pencadangan otomatis, seperti dijelaskan dalam <a href="{@docRoot}preview/backup/index.html">Auto
Backup for Apps</a>. </p>

View File

@@ -1,610 +0,0 @@
page.title=Perubahan Perilaku
page.keywords=pratinjau,sdk,kompatibilitas
meta.tags="preview", "compatibility"
page.tags="preview", "developer preview"
page.image=images/cards/card-n-changes_2x.png
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#perf">Peningkatan Kinerja</a>
<ol>
<li><a href="#doze">Istirahatkan</a></li>
<li><a href="#bg-opt">Optimalisasi Latar Belakang</a></li>
</ol>
</li>
<li><a href="#perm">Perubahan Izin</a>
</li>
<li><a href="#sharing-files">Berbagi File Antar Aplikasi</a></li>
<li><a href="#accessibility">Peningkatan Aksesibilitas</a>
<ol>
<li><a href="#screen-zoom">Perbesaran Layar</a></li>
<li><a href="#vision-settings">Vision Settings di Setup Wizard</a></li>
</ol>
</li>
<li><a href="#ndk">Penautan Aplikasi NDK ke Pustaka Platform</a></li>
<li><a href="#afw">Android for Work</a></li>
<li><a href="#annotations">Retensi Anotasi</a></li>
<li><a href="#other">Poin Penting Lainnya</a></li>
</ol>
<h2>Lihat Juga</h2>
<ol>
<li><a href="{@docRoot}preview/api-overview.html">
Ringkasan Android N API</a></li>
</ol>
</div>
</div>
<p>
Bersama fitur dan kemampuan baru, Android N
menyertakan berbagai macam perubahan sistem dan perubahan perilaku API. Dokumen ini
menyoroti beberapa perubahan utama yang harus dipahami dan diperhitungkan
dalam aplikasi Anda.
</p>
<p>
Jika Anda sebelumnya telah mempublikasikan aplikasi untuk Android, ketahuilah bahwa aplikasi Anda
mungkin dipengaruhi oleh perubahan dalam platform.
</p>
<h2 id="perf">Baterai dan Memori</h2>
<p>
Android N menyertakan perubahan perilaku sistem yang bertujuan untuk meningkatkan daya tahan baterai
perangkat dan mengurangi penggunaan RAM. Perubahan ini bisa memengaruhi akses aplikasi Anda ke
sumber daya sistem, termasuk cara aplikasi Anda berinteraksi dengan aplikasi lain melalui
intent implisit tertentu.
</p>
<h3 id="doze">Istirahatkan</h3>
<p>
Diperkenalkan dalam Android 6.0 (API level 23), Istirahatkan meningkatkan daya tahan baterai dengan
menangguhkan aktivitas CPU dan jaringan bila pengguna tidak mencabut perangkat,
tidak bergerak, dan layar dinonaktifkan. Android N lebih
menyempurnakan Istirahatkan dengan menerapkan subset CPU dan pembatasan jaringan
bila perangkat dicabut dan layar dinonaktifkan, namun tidak harus
diam, misalnya, bila handset dibawa bepergian di saku pengguna.
</p>
<img src="{@docRoot}images/android-7.0/doze-diagram-1.png" alt="" height="251px" id="figure1" />
<p class="img-caption">
<strong>Gambar 1.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
aktivitas sistem level pertama untuk meningkatkan daya tahan baterai.
</p>
<p>
Bila perangkat sedang menggunakan daya baterai, dan layar telah nonaktif selama jangka waktu
tertentu, perangkat akan memasuki Istirahatkan dan menerapkan subset pembatasan pertama: Perangkat
akan menutup akses jaringan aplikasi, serta menangguhkan pekerjaan dan sinkronisasi. Jika perangkat sedang
diam selama jangka waktu tertentu setelah memasuki Istirahatkan, sistem akan menerapkan
pembatasan Istirahatkan selebihnya terhadap alarm {@link android.os.PowerManager.WakeLock},
{@link android.app.AlarmManager}, GPS, dan pemindaian Wi-Fi. Tidak peduli
apakah sebagian atau semua pembatasan Istirahatkan diterapkan, sistem akan membangunkan
perangkat selama jeda pemeliharaan singkat, dan selama itu aplikasi diizinkan
mengakses jaringan dan bisa mengeksekusi semua pekerjaan/sinkronisasi yang telah ditangguhkan.
</p>
<img src="{@docRoot}images/android-7.0/doze-diagram-2.png" alt="" id="figure2" />
<p class="img-caption">
<strong>Gambar 2.</strong> Ilustrasi tentang cara Istirahatkan menerapkan pembatasan
aktivitas sistem level kedua setelah perangkat diam selama jangka waktu tertentu.
</p>
<p>
Perhatikan, mengaktifkan layar atau mencolokkan steker perangkat akan mengeluarkan dari Istirahatkan
dan membuang pembatasan pemrosesan ini. Perilaku tambahan ini tidak
memengaruhi rekomendasi dan praktik terbaik dalam menyesuaikan aplikasi Anda dengan versi
Istirahatkan sebelumnya yang diperkenalkan dalam Android 6.0 (API level 23), seperti yang dibahas di
<a href="{@docRoot}training/monitoring-device-state/doze-standby.html">
Mengoptimalkan untuk Istirahatkan dan Aplikasi Siaga</a>. Anda tetap harus
mengikuti rekomendasi itu, seperti menggunakan Google Cloud Messaging (GCM) untuk
mengirim dan menerima pesan, serta mulai merencanakan pembaruan
untuk mengakomodasi perilaku Istirahatkan tambahan.
</p>
<h3 id="bg-opt">Project Svelte: Optimalisasi Latar Belakang</h3>
<p>
Android N membuang tiga siaran implisit untuk membantu mengoptimalkan
penggunaan memori dan konsumsi daya. Perubahan ini penting karena siaran
implisit sering memulai aplikasi yang telah didaftarkan untuk mendengarkannya di
latar belakang. Membuang siaran ini bisa sangat menguntungkan
kinerja perangkat dan pengalaman pengguna.
</p>
<p>
Perangkat seluler seringkali mengalami perubahan konektivitas, seperti saat berpindah
antara Wi-Fi dan data seluler. Saat ini, aplikasi bisa memantau perubahan dalam
konektivitas dengan mendaftarkan suatu penerima untuk siaran implisit {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION} dalam manifes
mereka. Karena banyak aplikasi yang didaftarkan untuk menerima siaran ini, switch jaringan tunggal
bisa menyebabkan semuanya aktif dan memproses siaran tersebut
secara bersamaan.
</p>
<p>
Demikian pula, dalam Android versi sebelumnya, aplikasi bisa mendaftar untuk menerima siaran implisit {@link
android.hardware.Camera#ACTION_NEW_PICTURE} dan {@link
android.hardware.Camera#ACTION_NEW_VIDEO} dari aplikasi lain, seperti
Kamera. Bila pengguna mengambil gambar dengan aplikasi Kamera, semua aplikasi ini akan aktif
untuk memproses siaran.
</p>
<p>
Untuk meminimalkan masalah ini, Android N menerapkan optimalisasi
berikut:
</p>
<ul>
<li>Aplikasi yang menargetkan Android N tidak menerima siaran {@link
android.net.ConnectivityManager#CONNECTIVITY_ACTION}, sekalipun
memiliki entri manifes untuk meminta pemberitahuan mengenai kejadian ini. Aplikasi
yang berjalan tetap bisa mendengarkan {@code CONNECTIVITY_CHANGE} pada thread utama
jika mereka meminta pemberitahuan dengan {@link android.content.BroadcastReceiver}.
</li>
<li>Aplikasi tidak bisa mengirim atau menerima siaran {@link
android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link
android.hardware.Camera#ACTION_NEW_VIDEO}. Optimalisasi ini
memengaruhi semua aplikasi, bukan hanya aplikasi yang menargetkan Android N.
</li>
</ul>
<p>Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya
secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar.
Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan
siaran implisit ini. Misalnya, {@link
android.app.job.JobScheduler} API menyediakan mekanisme yang tangguh untuk menjadwalkan
operasi jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan
berbiaya tetap, terpenuhi. Anda juga dapat menggunakan {@link
android.app.job.JobScheduler} untuk bereaksi terhadap perubahan pada penyedia materi.
</p>
<p>
Untuk informasi selengkapnya tentang optimalisasi latar belakang di N dan cara menyesuaikan aplikasi Anda,
lihat <a href="{@docRoot}preview/features/background-optimization.html">Optimalisasi
Latar Belakang</a>.
</p>
<h2 id="perm">Perubahan Izin</h2>
<p>
Android N menyertakan perubahan pada izin yang bisa memengaruhi aplikasi Anda.
</p>
<h3 id="permfilesys">Perubahan izin sistem file</h3>
<p>
Guna meningkatkan keamanan file privat, direktori privat
aplikasi yang menargetkan Android N atau yang lebih tinggi memiliki akses terbatas (<code>0700</code>).
Pengaturan ini mencegah kebocoran metadata dari file privat, seperti ukuran
atau eksistensi. Perubahan izin ini memiliki beberapa efek samping:
</p>
<ul>
<li>
Izin file privat tidak boleh dianggap remeh oleh pemilik,
dan usaha untuk melakukannya menggunakan
{@link android.content.Context#MODE_WORLD_READABLE} dan/atau
{@link android.content.Context#MODE_WORLD_WRITEABLE}, akan memicu sebuah
{@link java.lang.SecurityException}.
<p class="note">
<strong>Catatan:</strong> Seperti sebelumnya, pembatasan ini tidak sepenuhnya diterapkan.
Aplikasi mungkin masih memodifikasi izin ke direktori privat mereka menggunakan
API asal atau {@link java.io.File File} API. Akan tetapi, kami sangat
tidak menyarankan Anda meremehkan izin direktori privat.
</p>
</li>
<li>
Meneruskan URI <code>file://</code> di luar domain paket dapat meninggalkan
penerima dengan jalur yang tidak bisa di akses. Karena itu, upaya untuk meneruskan URI
<code>file://</code> akan memicu
<code>FileUriExposedException</code>. Cara yang disarankan adalah
materi file privat menggunakan {@link
android.support.v4.content.FileProvider}.
</li>
<li>
{@link android.app.DownloadManager} tidak bisa lagi berbagi
file yang tersimpan secara privat berdasarkan nama file. Aplikasi lawas dapat mengakibatkan
jalur yang tidak dapat diakses saat mengakses {@link
android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. Aplikasi yang menargetkan
Android N atau yang lebih tinggi akan memicu {@link java.lang.SecurityException} saat
berupaya mengakses
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}.
Aplikasi lawas yang menyetel lokasi unduhan ke lokasi publik dengan
menggunakan
{@link
android.app.DownloadManager.Request#setDestinationInExternalFilesDir
DownloadManager.Request.setDestinationInExternalFilesDir()} atau
{@link
android.app.DownloadManager.Request#setDestinationInExternalPublicDir
DownloadManager.Request.setDestinationInExternalPublicDir()}
tetap bisa mengakses jalur tersebut di
{@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}, akan tetapi,
metode ini sangat tidak disarankan. Cara yang disarankan untuk mengakses file
yang diekspos oleh {@link android.app.DownloadManager} adalah menggunakan
{@link android.content.ContentResolver#openFileDescriptor
ContentResolver.openFileDescriptor()}.
</li>
</ul>
<h2 id="sharing-files">Berbagi File Antar Aplikasi</h2>
<p>
Untuk aplikasi yang menargetkan Android N, kerangka kerja Android menerapkan
kebijakan {@link android.os.StrictMode} API yang melarang mengekspos URI {@code file://}
di luar aplikasi Anda. Jika sebuah intent berisi URI file meninggalkan aplikasi Anda, aplikasi tersebut akan gagal
dengan pengecualian {@code FileUriExposedException}.
</p>
<p>
Untuk berbagi file antar aplikasi, Anda harus mengirim URI {@code content://}
dan memberikan izin akses sementara pada URI. Cara termudah untuk memberikan izin ini adalah dengan
menggunakan kelas {@link android.support.v4.content.FileProvider}. Untuk informasi selengkapnya
mengenai izin dan berbagi file,
lihat <a href="{@docRoot}training/secure-file-sharing/index.html">Berbagi File</a>.
</p>
<h2 id="accessibility">Peningkatan Aksesibilitas</h2>
<p>
Android N menyertakan perubahan yang bertujuan meningkatkan kegunaan
platform untuk pengguna dengan penglihatan yang rendah atau lemah. Perubahan ini umumnya tidak
memerlukan perubahan kode dalam aplikasi Anda, akan tetapi Anda harus memeriksa
fitur ini dan mengujinya dengan aplikasi untuk menilai kemungkinan dampaknya terhadap pengalaman
pengguna.
</p>
<h3 id="screen-zoom">Perbesaran Layar</h3>
<p>
Android N memungkinkan pengguna menyetel <strong>Display size</strong> yang akan memperbesar
atau memperkecil semua elemen pada layar, sehingga meningkatkan aksesibilitas perangkat
bagi pengguna yang kurang melihat. Pengguna tidak bisa memperbesar layar melewati lebar layar
minimum <a href="http://developer.android.com/guide/topics/resources/providing-resources.html">
sw320dp</a>, yang merupakan lebar Nexus 4, yakni ponsel ukuran sedang pada umumnya.
</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}images/android-7.0/screen-zoom-1.png" alt="" height="XXX" id="figure1" />
</div>
<div class="col-6">
<img src="{@docRoot}images/android-7.0/screen-zoom-2.png" alt="" height="XXX" id="figure1" />
</div>
</div> <!-- end cols -->
<p class="img-caption">
<strong>Gambar 3.</strong> Layar di sebelah kanan menampilkan efek
penambahan Display size perangkat yang menjalankan citra sistem Android N.
</p>
<p>
Bila kepadatan perangkat berubah, sistem akan memberi tahu aplikasi yang sedang berjalan dengan
cara berikut:
</p>
<ul>
<li>Jika aplikasi menargetkan API level 23 atau yang lebih rendah, sistem secara otomatis akan mematikan
semua proses latar belakang. Artinya, jika pengguna beralih dari
aplikasi tersebut untuk membuka layar <em>Settings</em> dan mengubah
setelan <strong>Display size</strong>, maka sistem akan mematikan aplikasi tersebut dengan cara yang
sama dengan saat memori tinggal sedikit. Jika aplikasi memiliki beberapa proses
latar depan, sistem akan memberi tahu proses tersebut mengenai perubahan konfigurasi seperti
dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
Waktu Proses</a>, seolah-olah orientasi perangkat telah berubah.
</li>
<li>Jika sebuah aplikasi menargetkan Android N, semua prosesnya
(latar depan dan latar belakang) akan diberi tahu mengenai perubahan konfigurasi seperti
dijelaskan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
Waktu Proses</a>.
</li>
</ul>
<p>
Sebagian besar aplikasi tidak perlu melakukan perubahan untuk mendukung fitur ini, asalkan
aplikasi tersebut mengikuti praktik terbaik Android. Hal-hal tertentu yang harus diperiksa:
</p>
<ul>
<li>Uji aplikasi Anda pada perangkat dengan lebar layar <code><a href=
"{@docRoot}guide/topics/resources/providing-resources.html">sw320dp</a></code>
dan pastikan aplikasi berjalan dengan semestinya.
</li>
<li>Bila konfigurasi perangkat berubah, perbarui informasi cache
yang bergantung pada kepadatan, seperti bitmap di cache atau sumber daya yang dimuat dari
jaringan. Periksa perubahan konfigurasi bila aplikasi melanjutkan dari status dihentikan
sementara.
<p class="note">
<strong>Catatan:</strong> Catatan: Jika Anda meng-cache data yang bergantung pada konfigurasi, ada
baiknya untuk menyertakan metadata yang relevan seperti ukuran layar
atau kepadatan piksel yang sesuai untuk data tersebut. Menyimpan metadata ini memungkinkan Anda untuk
memutuskan apakah Anda perlu segarkan data cache setelah perubahan
konfigurasi.
</p>
</li>
<li>Hindari menetapkan dimensi dengan satuan px, karena satuan ini tidak diskalakan dengan
kepadatan layar. Sebagai gantinya, tetapkan dimensi dengan satuan <a href="{@docRoot}guide/practices/screens_support.html">piksel yang tidak bergantung kepadatan
</a> (<code>dp</code>).
</li>
</ul>
<h3 id="vision-settings">Vision Settings di Setup Wizard</h3>
<p>
Android N menyertakan Vision Settings di layar Sambutan, di mana pengguna bisa
menyiapkan setelan aksesibilitas berikut pada perangkat baru:
<strong>Magnification gesture</strong>, <strong>Font size</strong>,
<strong>Display size</strong> dan <strong>TalkBack</strong>. Perubahan ini
meningkatkan visibilitas bug terkait dengan setelan layar yang berbeda. Untuk
mengurangi dampak fitur ini, Anda harus menguji aplikasi dengan setelan ini
diaktifkan. Anda bisa menemukannya pada <strong>Settings &gt;
Accessibility</strong>.
</p>
<h2 id="ndk">Penautan Aplikasi NDK ke Pustaka Platform</h2>
<p>
Android N menyertakan perubahan ruang nama untuk mencegah pemuatan API non-publik.
Jika menggunakan NDK, Anda hanya boleh menggunakan API publik dari platform
Android. Menggunakan API non-publik dalam rilis Android resmi berikutnya
bisa menyebabkan aplikasi mogok.
</p>
<p>
Untuk memberi tahu Anda agar menggunakan API non-publik, aplikasi yang berjalan pada perangkat
Android N akan menghasilkan kesalahan dalam keluaran logcat bila aplikasi memanggil API non-publik.
Kesalahan ini juga ditampilkan di layar perangkat berupa pesan untuk membantu
meningkatkan kepedulian terhadap situasi ini. Anda harus memeriksa kode aplikasi untuk
membuang penggunaan API platform non-publik dan secara saksama menguji aplikasi Anda menggunakan
perangkat pratinjau atau emulator.
</p>
<p>
Jika aplikasi Anda bergantung pada pustaka platform, lihat dokumentasi NDK untuk
perbaikan tipikal guna menggantikan API privat umum dengan padanan API publik.
Anda mungkin juga menautkan ke pustaka platform tanpa menyadarinya,
terutama jika aplikasi Anda menggunakan pustaka yang merupakan bagian dari platform ini (seperti
<code>libpng</code>), namun bukan bagian dari NDK. Dalam hal itu, pastikan
APK Anda berisi semua file .so yang ingin ditautkan.
</p>
<p class="caution">
<strong>Perhatian:</strong> Beberapa pustaka pihak ketiga mungkin menautkan ke API
non-publik. Jika menggunakan pustaka ini, aplikasi Anda bisa mogok saat dijalankan
pada rilis resmi Android berikutnya.
</p>
<p>
Aplikasi tidak boleh bergantung pada atau menggunakan pustaka bawaan yang tidak disertakan dalam
NDK, karena bisa mengalami perubahan, atau dipindahkan dari satu rilis Android ke
rilis lainnya. Peralihan dari OpenSSL ke BoringSSL merupakan satu contoh dari perubahan semacam ini.
Selain itu, perangkat yang berbeda bisa menawarkan tingkat kompatibilitas yang berbeda, karena
tidak ada persyaratan kompatibilitas untuk pustaka platform yang tidak disertakan
dalam NDK. Jika Anda harus mengakses pustaka non-NDK pada perangkat yang lebih lama, jadikan
pemuatan bergantung pada level Android API.
</p>
<p>
Untuk membantu Anda mendiagnosis tipe masalah ini ada beberapa contoh kesalahan Java dan NDK
yang mungkin Anda temui saat berusaha membangun aplikasi dengan Android N:
</p>
<p>Contoh kesalahan Java:</p>
<pre class="no-pretty-print">
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
is not accessible for the namespace "classloader-namespace"
</pre>
<p>Contoh kesalahan NDK:</p>
<pre class="no-pretty-print">
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
</pre>
<p>
Inilah beberapa perbaikan tipikal untuk aplikasi yang mengalami tipe kesalahan ini:
</p>
<ul>
<li>Penggunaan getJavaVM dan getJNIEnv dari libandroid_runtime.so bisa diganti
dengan fungsi JNI standar:
<pre class="no-pretty-print">
AndroidRuntime::getJavaVM -&gt; GetJavaVM from &lt;jni.h&gt;
AndroidRuntime::getJNIEnv -&gt; JavaVM::GetEnv or
JavaVM::AttachCurrentThread from &lt;jni.h&gt;.
</pre>
</li>
<li>Penggunaan simbol {@code property_get} dari {@code libcutils.so} bisa
diganti dengan {@code alternative __system_property_get} publik.
Caranya, gunakan {@code __system_property_get} dengan menyertakan yang berikut:
<pre>
#include &lt;sys/system_properties.h&gt;
</pre>
</li>
<li>Penggunaan simbol {@code SSL_ctrl} dari {@code libcrypto.so} harus
diganti dengan aplikasi versi lokal. Misalnya, Anda harus menautkan
{@code libcyrpto.a} secara statis dalam file {@code .so} atau menyertakan
{@code libcrypto.so} Anda sendiri secara dinamis dari BoringSSL atau OpenSSL dalam aplikasi Anda.
</li>
</ul>
<h2 id="afw">Android for Work</h2>
<p>
Android N berisi perubahan untuk aplikasi yang menargetkan Android for Work, termasuk
perubahan pada pemasangan sertifikat, penyetelan ulang sandi, manajemen pengguna
tambahan, dan akses ke identifier perangkat. Jika Anda membangun aplikasi untuk
lingkungan Android for Work, Anda harus meninjau perubahan ini dan memodifikasi
aplikasi sebagaimana mestinya.
</p>
<ul>
<li>Anda harus pasang pemasang sertifikat yang didelegasikan sebelum DPC bisa
menyetelnya. Untuk aplikasi profil dan aplikasi pemilik perangkat yang menargetkan N SDK, Anda harus
pasang pemasang sertifikat yang didelegasikan sebelum pengontrol kebijakan
perangkat (DPC) memanggil
<code>DevicePolicyManager.setCertInstallerPackage()</code>. Jika pemasang
belum dipasang, sistem akan melontarkan
<code>IllegalArgumentException</code>.
</li>
<li>Pembatasan sandi penyetelan ulang untuk admin perangkat sekarang diterapkan ke pemilik
profil. Admin perangkat tidak bisa lagi menggunakan
{@code DevicePolicyManager.resetPassword()} untuk menghapus sandi atau mengubah
sandi yang sudah disetel. Admin perangkat tetap bisa menyetel sandi, namun hanya
bila perangkat belum memiliki sandi, PIN, atau pola.
</li>
<li>Pemilik perangkat dan profil bisa mengelola akun meskipun pembatasan
telah disetel. Pemilik perangkat dan pemilik profil bisa memanggil Account Management API
sekalipun pembatasan pengguna <code>DISALLOW_MODIFY_ACCOUNTS</code> diberlakukan.
</li>
<li>Pemilik perangkat bisa mengelola pengguna tambahan lebih mudah. Bila perangkat
berjalan dalam mode pemilik perangkat, maka pembatasan <code>DISALLOW_ADD_USER</code>
secara otomatis akan ditetapkan. Ini mencegah pengguna membuat pengguna tambahan yang
tidak terkelola. Selain itu, <code>CreateUser()</code> dan
<code>createAndInitializeUser()</code> metode tidak digunakan lagi; metode
<code>DevicePolicyManager.createAndManageUser()</code> telah menggantikannya.
</li>
<li>Pemilik perangkat bisa mengakses identifier perangkat. Pemilik perangkat bisa mengakses
alamat MAC Wi-Fi dari perangkat, menggunakan
<code>DevicePolicyManagewr.getWifiMacAddress()</code>. Jika Wi-Fi belum pernah
diaktifkan pada perangkat tersebut, metode ini akan mengembalikan nilai {@code null}.
</li>
<li>Setelan Mode Kerja mengontrol akses ke aplikasi kerja. Bila mode kerja tidak aktif, peluncur sistem
akan menunjukkan aplikasi kerja tidak tersedia dengan membuat warnanya jadi abu-abu. Mengaktifkan kembali
mode kerja akan memulihkan perilaku normal.
</ul>
<p>
Untuk informasi selengkapnya tentang perubahan Android for Work di Android N, lihat
<a href="{@docRoot}preview/features/afw.html">Pembaruan Android for Work</a>.
</p>
<h2 id="annotations">Retensi Anotasi</h2>
<p>
Android N memperbaiki bug dengan visibilitas anotasi diabaikan.
Masalah ini mengaktifkan waktu proses untuk mengakses anotasi yang seharusnya tidak bisa
dilakukan. Anotasi ini termasuk:
</p>
<ul>
<li>{@code VISIBILITY_BUILD}: Dimaksudkan agar hanya bisa terlihat pada waktu pembuatan.</li>
<li>{@code VISIBILITY_SYSTEM}: Dimaksud agar bisa terlihat pada waktu proses, namun hanya pada
sistem yang mendasarinya.</li>
</ul>
<p>
Jika aplikasi Anda mengandalkan perilaku ini, tambahkan kebijakan retensi untuk anotasi yang harus
tersedia di waktu proses. Caranya dengan menggunakan {@code @Retention(RetentionPolicy.RUNTIME)}.
</p>
<h2 id="other">Poin Penting Lainnya</h2>
<ul>
<li>Bila aplikasi berjalan pada Android N, namun menargetkan level API yang lebih rendah,
dan pengguna mengubah ukuran tampilan, proses aplikasi akan dimatikan. Aplikasi
harus dapat menangani skenario ini dengan lancar. Jika tidak, maka akan mogok
bila pengguna memulihkannya dari Recents.
<p>
Anda harus menguji aplikasi untuk memastikan
perilaku ini tidak terjadi.
Anda bisa melakukannya dengan menyebabkan suatu mogok yang identik
saat mematikan aplikasi secara manual melalui DDMS.
</p>
<p>
Aplikasi yang menargetkan N dan yang di atasnya tidak secara otomatis dimatikan saat perubahan kepadatan;
akan tetapi, aplikasi tersebut mungkin tetap merespons perubahan konfigurasi dengan buruk.
</p>
</li>
<li>
Aplikasi pada Android N harus mampu menangani perubahan konfigurasi dengan lancar,
dan tidak boleh mengalami mogok pada start selanjutnya. Anda bisa memverifikasi perilaku aplikasi
dengan mengubah ukuran font (<strong>Setting</strong> &gt;
<strong>Display</strong> &gt; <strong>Font size</strong>), kemudian memulihkan
aplikasi dari Recents.
</li>
<li>
Dikarenakan adanya bug di versi Android sebelumnya, sistem tidak menandai penulisan
ke soket TCP di thread utama sebagai pelanggaran mode-ketat. Android N memperbaiki bug ini.
Aplikasi yang menunjukkan perilaku ini kini melontarkan sebuah {@code android.os.NetworkOnMainThreadException}.
Secara umum, melakukan operasi jaringan di thread utama tidak baik karena operasi ini
biasanya memiliki latensi tinggi yang menyebabkan ANR dan jank.
</li>
<li>
Kelompok metode {@code Debug.startMethodTracing()} kini default ke
keluaran penyimpanan di direktori paket tertentu di penyimpanan bersama,
sebagai ganti di level teratas
kartu SD. Berarti aplikasi tidak perlu lagi meminta izin {@code WRITE_EXTERNAL_STORAGE} untuk menggunakan API ini.
</li>
<li>
Banyak platform API yang kini mulai memeriksa beban besar yang dikirim
ke seluruh transaksi {@link android.os.Binder}, dan sistem
kini melontarkan kembali {@code TransactionTooLargeExceptions}
sebagai {@code RuntimeExceptions}, sebagai ganti logging secara diam-diam atau menyembunyikannya. Satu contoh
umum adalah menyimpan terlalu banyak data di
{@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()},
yang menyebabkan {@code ActivityThread.StopInfo} melontarkan
{@code RuntimeException} bila aplikasi Anda menargetkan Android N.
</li>
<li>
Jika sebuah aplikasi mengeposkan tugas {@link java.lang.Runnable} ke{@link android.view.View}, dan
{@link android.view.View}
tidak terpasang ke jendela, sistem
akan mengantrekan tugas {@link java.lang.Runnable} dengan {@link android.view.View};
tugas {@link java.lang.Runnable} tidak akan dieksekusi hingga
{@link android.view.View} terpasang
ke jendela. Perilaku ini mengatasi bug berikut:
<ul>
<li>Jika sebuah aplikasi mengeposkan ke {@link android.view.View} dari thread selain thread UI jendela yang dimaksud,
maka {@link java.lang.Runnable} mungkin akan menjalankan thread yang salah.
</li>
<li>Jika tugas {@link java.lang.Runnable} diposkan dari thread selain
looper-thread, aplikasi bisa mengekspos tugas {@link java.lang.Runnable}.</li>
</ul>
</li>
<li>
Jika sebuah aplikasi di Android N dengan
izin{@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES}
mencoba menghapus sebuah paket, namun sebuah aplikasi berbeda telah memasang paket itu,
sistem akan memerlukan konfirmasi pengguna. Dalam skenario ini, aplikasi harus mengharapkan
{@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION}
sebagai status kembalian bila memanggil
{@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}.
</li>
</ul>

View File

@@ -1,85 +0,0 @@
page.title=Contoh
page.tags="preview", "samples", "android"
page.image=images/cards/card-n-samples_2x.png
@jd:body
<p>
Contoh kode berikut disediakan untuk Android N. Untuk
mengunduh contoh di Android Studio, pilih opsi menu <b>File &gt; Import
Samples</b>.
</p>
<p class="note">
<strong>Catatan:</strong> Proyek yang bisa diunduh ini didesain
untuk digunakan bersama Gradle dan Android Studio.
</p>
<h3 id="mw">Playground Multi-Jendela</h3>
<img src="{@docRoot}images/android-7.0/sample-multiwindow.png" style="float: left; padding-right: 0.5em" height="250" width="156" />
<p>
Contoh ini memperagakan cara memanfaatkan antarmuka pengguna
multi-jendela bersama aplikasi Anda.
</p>
<p>
<a href="https://github.com/googlesamples/android-MultiWindowPlayground">
Dapatkan di GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="an">Pemberitahuan Aktif</h3>
<img src="{@docRoot}images/android-7.0/sample-activenotifications.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
Ini adalah contoh yang sudah ada sebelumnya, menampilkan layanan sederhana yang mengirimkan
pemberitahuan menggunakan NotificationCompat. Setiap percakapan yang belum dibaca dari pengguna
dikirimkan sebagai pemberitahuan berbeda.
</p>
<p>
Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
yang tersedia di Android N.
</p>
<p>
<a href="https://github.com/googlesamples/android-ActiveNotifications">
Dapatkan di GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="ms">Layanan Perpesanan</h3>
<img src="{@docRoot}images/android-7.0/sample-messagingservice.png" style="float: left; padding-right: 0.5em" height="250" width="150" />
<p>
Ini adalah contoh yang telah ada sebelumnya yang memperagakan cara menggunakan
NotificationManager untuk memberi tahu jumlah pemberitahuan yang saat ini ditampilkan
oleh aplikasi.
</p>
<p>
Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru
yang tersedia di Android N.
</p>
<p>
<a href="https://github.com/googlesamples/android-MessagingService">
Dapatkan di GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="fbe">Direct Boot</h3>
<img src="{@docRoot}images/android-7.0/sample-directboot.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
Contoh ini memperagakan cara menyimpan dan mengakses data dalam penyimpanan yang dienkripsi
dengan perangkat yang selalu tersedia saat perangkat booting.
</p>
<p>
<a href="https://github.com/googlesamples/android-DirectBoot">
Dapatkan di GitHub</a>
</p>
<div style="clear: both;"></div>
<h3 id="sda">Scoped Directory Access</h3>
<img src="{@docRoot}images/android-7.0/sample-scopeddirectoryaccess.png" style="float: left; padding-right: 0.5em" height="250" width="141" />
<p>
Contoh ini memperagakan cara membaca dan menulis data dari direktori
spesifik, sekaligus meminta izin lebih sedikit.
</p>
<p>
<a href="https://github.com/googlesamples/android-ScopedDirectoryAccess">
Dapatkan di GitHub</a>
</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +0,0 @@
page.title=Android 7.0 Nougat
page.tags="androidn","versions"
meta.tags="android n", "nougat", "android 7.0"
fullpage=true
forcelocalnav=true
header.hide=1
footer.hide=1
@jd:body
<section class="dac-expand dac-hero dac-light">
<div class="wrap" style="max-width:1100px;margin-top:0">
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
<div class="cols dac-hero-content" style="padding-bottom:1em;">
<div class="col-7of16 col-push-8of16" style="padding-left:2em">
<h1 class="dac-hero-title">Android 7.0 Nougat</h1>
<p class="dac-hero-description">
Bersiaplah menyambut Android Nougat!
<strong>Uji aplikasi Anda</strong> pada perangkat Nexus dan perangkat lainnya. Dukung perilaku sistem
baru untuk <strong>menghemat daya dan memori</strong>.
Tambah aplikasi Anda dengan <strong>UI multi-jendela</strong>,
<strong>pemberitahuan balasan langsung</strong> dan lainnya.
</p>
<a class="dac-hero-cta" href="{@docRoot}about/versions/nougat/android-7.0.html">
<span class="dac-sprite dac-auto-chevron"></span>
Mulai
</a>
</div>
<div class="col-7of16 col-pull-6of16 dac-hero-figure" style="margin-top:1.5em;padding-right:1.5em;">
<a href="{@docRoot}about/versions/nougat/android-7.0.html">
<img class="dac-hero-image" src="{@docRoot}images/home/n-preview-hero.png"
srcset="{@docRoot}images/home/n-preview-hero.png 1x,
{@docRoot}images/home/n-preview-hero_2x.png 2x" />
</a>
</div>
</div></a>
<div class="dac-section dac-small">
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/resources"
data-cardSizes="6x2"
data-maxResults="3"></div>
</div>
</div>
</section>
<div class="dac-section dac-slim dac-gray dac-expand">
<div class="wrap dac-offset-parent">
<a class="dac-fab dac-scroll-button" data-scroll-button href="#latest">
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
<ul class="dac-actions">
<li class="dac-action">
<a class="dac-action-link" href="https://source.android.com/source/report-bugs.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Laporkan masalah
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}preview/dev-community">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Bergabunglah dengan komunitas pengembang
</a>
</li>
</ul>
</div><!-- end .wrap -->
</div><!-- end .dac-actions -->
<section class="dac-section dac-light dac-small" id="latest"><div class="wrap">
<h2 class="norule">Terbaru</h2>
<div class="resource-widget resource-flow-layout col-16"
data-query="type:blog+tag:androidn+tag:featured, type:youtube+tag:androidn+tag:featured"
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="3"></div>
</div></section>
<section class="dac-section dac-gray" id="videos"><div class="wrap">
<h1 class="dac-section-title">Videos</h1>
<div class="dac-section-subtitle">
New Android capabilities and the right way to use them in your apps.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/videos/first,type:youtube+tag:androidn"
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="3">
</div>
</div></section>
<section class="dac-section dac-light" id="resources"><div class="wrap">
<h1 class="dac-section-title">Sumber Daya</h1>
<div class="dac-section-subtitle">
Informasi penting guna membantu mempersiapkan aplikasi untuk Android Nougat.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:nougat/landing/more"
data-cardSizes="6x6"
data-items-per-page="6"
data-maxResults="15"
data-initial-results="6"></div>
</div>
</section>

View File

@@ -1,307 +0,0 @@
page.title=Prinsip Desain Android
@jd:body
<p>Prinsip desain ini dikembangkan oleh dan untuk Tim Pengalaman Pengguna
Android agar selalu mempertimbangkan kepentingan pengguna.
Untuk pengembang dan desainer Android, mereka terus
meletakkan dasar pedoman desain yang lebih detail untuk beragam tipe
perangkat.</p>
<p>
Perhatikan prinsip-prinsip ini saat Anda menerapkan
kreativitas dan pemikiran desain sendiri. Menyimpang dengan sengaja.
</p>
<h2 id="enchant-me">Pikat Saya</h2>
<div class="cols">
<div class="col-7">
<h4 id="delight-me">Senangkan saya dengan cara yang mengejutkan</h4>
<p>Permukaan yang cantik, animasi yang ditempatkan dengan hati-hati, atau efek suara di saat yang tepat sungguh menyenangkan untuk
dinikmati. Efek yang lembut menimbulkan perasaan serba mudah dan kesadaran bahwa kekuatan yang
bisa diandalkan ada dalam genggaman.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="real-objects-more-fun">Objek sungguhan lebih menyenangkan daripada tombol dan menu</h4>
<p>Biarkan orang langsung menyentuh dan memanipulasi objek dalam aplikasi Anda. Ini mengurangi upaya kognitif
yang diperlukan untuk menjalankan tugas sekaligus membuatnya lebih memuaskan secara emosional.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-it-mine">Biarkan saya memilikinya</h4>
<p>Orang suka menambahkan sentuhan pribadi karena membantu mereka merasa betah dan memegang kendali. Memberikan
default yang pantas dan indah, tetapi juga mempertimbangkan penyesuaian opsional yang menyenangkan, yang tidak mengganggu
tugas utama.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="get-to-know-me">Kenali saya</h4>
<p>Pelajari preferensi orang dari waktu ke waktu. Daripada meminta mereka untuk membuat pilihan yang sama
berulang-ulang, tempatkan pilihan sebelumnya agar mudah dijangkau.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
</div>
</div>
<h2 id="simplify-my-life">Sederhanakan Hidup Saya</h2>
<div class="cols">
<div class="col-7">
<h4 id="keep-it-brief">Persingkat</h4>
<p>Gunakan frasa pendek dengan kata-kata sederhana. Orang cenderung melewatkan kalimat-kalimat panjang.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="pictures-faster-than-words">Gambar lebih cepat dibanding kata-kata</h4>
<p>Pertimbangkan menggunakan gambar untuk menjelaskan gagasan. Gambar menarik perhatian orang dan bisa jauh lebih efisien
dibanding kata-kata.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="decide-for-me">Putuskan untuk saya tetapi biarkan saya yang menentukan</h4>
<p>Gunakan tebakan terbaik Anda dan bertindaklah daripada meminta terlebih dahulu. Terlalu banyak pilihan dan keputusan membuat orang
tidak suka. Untuk berjaga-jaga jika Anda salah, izinkan 'pembatalan'.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="only-show-when-i-need-it">Cukup tunjukkan yang saya perlukan ketika saya memerlukannya</h4>
<p>Orang merasa kewalahan ketika melihat terlalu banyak hal sekaligus. Uraikan tugas dan informasi menjadi potongan-potongan
kecil yang mudah dicerna. Sembunyikan opsi yang tidak perlu pada saat ini, dan ajari orang sambil jalan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="always-know-where-i-am">Saya harus selalu tahu di mana saya berada</h4>
<p>Beri orang kepercayaan diri bahwa mereka tahu di mana berada. Buat agar tempat-tempat dalam aplikasi Anda terlihat berbeda dan
gunakan transisi untuk menunjukkan hubungan antar layar. Berikan umpan balik tentang tugas yang sedang berlangsung.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="never-lose-my-stuff">Jangan sekali-kali menghilangkan milik saya</h4>
<p>Simpan apa yang telah susah-payah dibuat orang dan biarkan mereka mengaksesnya dari mana saja. Ingat pengaturan,
sentuhan pribadi, dan kreasi lintas ponsel, tablet, dan komputer. Itu membuat pemutakhiran menjadi
hal termudah di dunia.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="looks-same-should-act-same">Jika terlihat sama, seharusnya fungsinya sama</h4>
<p>Bantu orang merasakan perbedaan fungsional dengan membuat mereka terlihat berbeda daripada mirip.
Hindari mode, yaitu tempat yang terlihat mirip tetapi berbeda fungsinya pada input yang sama.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="interrupt-only-if-important">Sela saya jika penting saja</h4>
<p>Layaknya asisten pribadi yang baik, lindungi orang dari detail yang tidak penting. Orang ingin tetap
fokus, dan kecuali jika memang penting dan sensitif waktu, interupsi bisa melelahkan dan menjengkelkan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
</div>
</div>
<h2 id="make-me-amazing">Buat Saya Terpesona</h2>
<div class="cols">
<div class="col-7">
<h4 id="give-me-tricks">Beri saya trik yang efektif di mana saja</h4>
<p>Orang merasa senang ketika mereka memahami sendiri sesuatu. Jadikan aplikasi Anda lebih mudah dipelajari dengan
memanfaatkan pola visual dan memori otot dari aplikasi Android lainnya. Misalnya, gerakan menggeser
dapat menjadi pintasan navigasi yang bagus.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="its-not-my-fault">Bukan salah saya</h4>
<p>Bersikap ramahlah dalam meminta orang untuk melakukan koreksi. Mereka ingin merasa pintar ketika menggunakan
aplikasi Anda. Jika terjadi kesalahan, berikan petunjuk perbaikan yang jelas tetapi lepaskan mereka dari detail teknis.
Jika Anda dapat memperbaikinya secara diam-diam, tentu lebih baik.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="sprinkle-encouragement">Berikan dorongan</h4>
<p>Uraikan tugas-tugas rumit menjadi langkah-langkah kecil yang dapat dilakukan dengan mudah. Beri umpan balik tentang tindakan,
meskipun hanya sesuatu yang sederhana.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="do-heavy-lifting-for-me">Lakukan pekerjaan yang sulit untuk saya</h4>
<p>Buatlah pemula merasa seperti ahli dengan memungkinkan mereka untuk melakukan hal-hal yang mereka pikir tidak akan bisa.
Misalnya, pintasan yang menggabungkan beberapa efek foto dapat membuat foto amatir terlihat mengagumkan hanya
dalam beberapa langkah.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-important-things-fast">Percepat hal penting</h4>
<p>Tidak semua tindakan itu sama. Putuskan apa yang terpenting dalam aplikasi Anda dan permudah untuk menemukannya serta
cepat untuk digunakan, seperti tombol rana pada kamera, atau tombol jeda pada pemutar musik.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">
</div>
</div>

View File

@@ -1,186 +0,0 @@
page.title=Material Design for Android
page.tags=Material,design
page.type=design
page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
<!-- developer docs box -->
<a class="notice-developers right" href="{@docRoot}training/material/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Membuat Aplikasi dengan Desain Bahan</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=p4gmvHyuZzw">
<div>
<h3>Video</h3>
<p>Pengantar Desain Bahan</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
<div>
<h3>Video</h3>
<p>Kertas dan Tinta: Bahan Penting</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=XOcCOBe8PTc">
<div>
<h3>Video</h3>
<p>Desain Bahan di Aplikasi Google I/O</p>
</div>
</a>
<p itemprop="description">Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan
interaksi lintas platform dan perangkat. Android kini menyertakan dukungan untuk
aplikasi desain bahan. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan yang didefinisikan
dalam <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a> dan gunakan
komponen dan fungsionalitas baru yang tersedia di Android 5.0 (API level 21) ke atas.</p>
<p>Android menyediakan elemen berikut untuk membangun aplikasi desain bahan:</p>
<ul>
<li>Tema baru</li>
<li>Widget baru untuk tampilan yang kompleks</li>
<li>API baru untuk animasi dan bayangan custom</li>
</ul>
<p>Untuk informasi selengkapnya tentang mengimplementasikan desain bahan pada Android, lihat
<a href="{@docRoot}training/material/index.html">Membuat Aplikasi dengan Desain Bahan</a>.</p>
<h3>Tema Bahan</h3>
<p>Tema bahan menyediakan gaya baru untuk aplikasi Anda, widget sistem yang memungkinkan Anda mengatur
palet warnanya, dan animasi default untuk umpan balik sentuh dan transisi aktivitas.</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema bahan gelap</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema bahan terang</p>
</div>
</div>
<br style="clear:left"/>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/theme.html">Menggunakan Tema
Bahan</a>.</p>
<h3>Daftar dan Kartu</h3>
<p>Android menyediakan dua widget baru untuk menampilkan kartu dan daftar dengan gaya desain bahan
dan animasi:</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
<p>Widget <code>RecyclerView</code> baru adalah versi <code>ListView</code>
yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.</p>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
<p>Widget <code>CardView</code> baru memungkinkan Anda menampilkan potongan informasi penting dalam
kartu yang memiliki tampilan dan cara kerja yang konsisten.</p>
</div>
<br style="clear:left"/>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
dan Kartu</a>.</p>
<h3>Bayangan Tampilan</h3>
<p>Selain properti X dan Y, tampilan di Android kini memiliki
properti Z. Properti baru ini mewakili ketinggian tampilan, yang menentukan:</p>
<ul>
<li>Ukuran bayangan: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar.</li>
<li>Urutan penggambaran: tampilan dengan nilai Z lebih tinggi muncul di atas tampilan lainnya.</li>
</ul>
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay>
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4"/>
<source src="{@docRoot}design/videos/ContactsAnim.webm"/>
<source src="{@docRoot}design/videos/ContactsAnim.ogv"/>
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<em>Untuk memutar ulang film, klik layar perangkat</em>
</div>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
Bayangan dan Memangkas Tampilan</a>.</p>
<h3>Animasi</h3>
<p>API animasi baru memungkinkan Anda membuat animasi custom untuk umpan balik sentuh dalam kontrol UI,
perubahan status tampilan, dan transisi aktivitas.</p>
<p>API ini memungkinkan Anda:</p>
<ul>
<li style="margin-bottom:15px">
Merespons kejadian sentuh dalam tampilan Anda dengan animasi <strong>umpan balik sentuh</strong>.
</li>
<li style="margin-bottom:15px">
Menyembunyikan dan memperlihatkan tampilan dengan animasi <strong>membuka melingkar</strong>.
</li>
<li style="margin-bottom:15px">
Peralihan antar aktivitas dengan animasi <strong>transisi aktivitas</strong> custom.
</li>
<li style="margin-bottom:15px">
Membuat animasi yang lebih alami dengan <strong>gerak melengkung</strong>.
</li>
<li style="margin-bottom:15px">
Menganimasikan perubahan dalam satu atau beberapa properti tampilan dengan animasi <strong>perubahan status tampilan</strong>.
</li>
<li style="margin-bottom:15px">
Menampilkan animasi di <strong>drawable daftar status</strong> di antara perubahan status tampilan.
</li>
</ul>
<p>Animasi umpan balik sentuh dimasukkan ke dalam beberapa tampilan standar, misalnya tombol. API baru
ini memungkinkan Anda menyesuaikan animasi ini dan menambahkannya ke tampilan custom Anda.</p>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi
Custom</a>.</p>
<h3>Drawable</h3>
<p>Kemampuan baru untuk drawable ini membantu Anda mengimplementasikan aplikasi desain bahan:</p>
<ul>
<li><strong>Drawable vektor</strong> bisa diubah skalanya tanpa kehilangan definisi dan cocok
untuk ikon satu-warna dalam-aplikasi.</li>
<li><strong>Pewarnaan drawable</strong> memungkinkan Anda mendefinisikan bitmap sebagai alpha-mask dan mewarnainya
saat runtime.</li>
<li><strong>Ekstraksi warna</strong> memungkinkan Anda mengekstrak warna mencolok secara otomatis dari
gambar bitmap.</li>
</ul>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/drawables.html">Bekerja dengan
Drawable</a>.</p>

View File

@@ -1,70 +0,0 @@
page.title=Kompatibilitas Mundur
page.tags="support"
page.metaDescription=Catatan tentang bagaimana Android 4.x menyesuaikan UI yang didesain untuk perangkat keras dan versi OS yang lebih lama.
@jd:body
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Mendukung Perangkat Berbeda</p>
</div>
</a>
<p>Perubahan signifikan dalam Android 3.0 meliputi:</p>
<ul>
<li>Dihilangkannya tombol perangkat keras navigasi (Back, Menu, Search, Home) untuk membantu menangani navigasi
melalui kontrol maya (Back, Home, Recents).</li>
<li>Pola yang tangguh untuk penggunaan menu pada action-bar.</li>
</ul>
<p>Android 4.0 membawa perubahan ini untuk tablet dengan platform ponsel.</p>
<h2 id="older-hardware">Menyesuaikan Android 4.0 dengan Perangkat Keras dan Aplikasi yang Lebih Lama</h2>
<div class="cols">
<div class="col-6">
<h4>Ponsel dengan kontrol navigasi virtual</h4>
<p>Aplikasi Android yang ditulis untuk Android 3.0 dan yang lebih baru menampilkan tindakan dalam action-bar. Tindakan yang tidak
muat dalam action-bar atau tidak cukup penting untuk ditampilkan di tingkat atas akan muncul dalam
action-overflow.</p>
<p>Pengguna mengakses action-overflow dengan menyentuhnya dalam action-bar.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Ponsel dengan tombol navigasi fisik</h4>
<p>Ponsel Android dengan tombol perangkat keras navigasi biasa tidak menampilkan baris navigasi virtual di
bagian bawah layar. Sebagai gantinya, action-overflow tersedia dari tombol perangkat keras menu. Popup
tindakan yang dihasilkan memiliki gaya yang sama dengan contoh sebelumnya, tetapi ditampilkan di bagian bawah layar.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Aplikasi lama pada ponsel dengan kontrol navigasi virtual</h4>
<p>Bila Anda menjalankan aplikasi yang dibuat untuk Android 2.3 atau yang lebih lama pada ponsel
dengan kontrol navigasi virtual, sebuah kontrol action-overflow akan muncul di sebelah kanan baris navigasi virtual. Anda
dapat menyentuh kontrol itu untuk menampilkan tindakan aplikasi dalam gaya menu Android biasa.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
</div>
</div>

View File

@@ -1,70 +0,0 @@
page.title=Mengonfirmasi &amp; Mengakui
page.tags=dialog,toast,notification
@jd:body
<p>Dalam beberapa situasi, bila pengguna memanggil suatu tindakan dalam aplikasi Anda, ada baiknya <em>mengonfirmasi</em> atau <em>mengakui</em> tindakan itu melalui teks.</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>Mengonfirmasi</strong> adalah meminta pengguna untuk memverifikasi bahwa mereka benar-benar ingin melanjutkan tindakan yang baru saja mereka panggil. Dalam beberapa kasus, konfirmasi ditampilkan bersama-sama dengan peringatan atau informasi penting yang terkait dengan tindakan yang perlu mereka pertimbangkan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p><strong>Mengakui</strong> adalah menampilkan teks untuk memberi tahu pengguna bahwa tindakan yang baru mereka panggil sudah dilakukan. Ini menghilangkan ketidakpastian tentang operasi implisit yang dilakukan sistem. Dalam beberapa kasus, pengakuan ditampilkan bersama dengan opsi untuk membatalkan tindakan.</p>
</div>
</div>
<p>Berkomunikasi pada pengguna dengan cara ini bisa membantu mengurangi ketidakpastian tentang hal-hal yang sudah atau akan terjadi. Mengonfirmasi atau mengakui juga dapat mencegah pengguna melakukan kesalahan yang akan mereka sesali.</p>
<h2>Kapan Harus Mengonfirmasi atau Mengakui Tindakan Pengguna</h2>
<p>Tidak semua tindakan memerlukan konfirmasi atau pengakuan. Gunakan bagan alur ini untuk memandu keputusan desain Anda.</p>
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>Mengonfirmasi</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: Google Play Books</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>Dalam contoh ini, pengguna telah meminta untuk menghapus sebuah buku dari perpustakaan Google Play mereka. Sebuah <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">peringatan</a> muncul untuk mengonfirmasi tindakan ini karena perlu dipahami bahwa buku tersebut tidak akan tersedia lagi dari perangkat apa pun.</p>
<p>Saat membuat dialog konfirmasi, buat judul bermakna dengan mencerminkan tindakan yang diminta.</p>
</div>
<div class="col-7">
<h4>Contoh: Android Beam</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>Konfirmasi tidak harus ditampilkan dalam peringatan dengan dua tombol. Setelah menjalankan Android Beam, pengguna diminta untuk menyentuh konten yang akan dibagikan (dalam contoh ini, sebuah foto). Jika mereka memutuskan untuk tidak melanjutkan, mereka tinggal memindahkan ponsel.</p>
</div>
</div>
<h2>Mengakui</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: Draf Gmail batal yang disimpan</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>Dalam contoh ini, jika pengguna menyusuri ke belakang atau ke atas dari layar pembuatan email di Gmail, sesuatu yang tak diharapkan bisa terjadi: draf saat itu akan disimpan secara otomatis. Pengakuan dalam bentuk pemberitahuan akan lebih jelas. Ini menghilang setelah beberapa detik.</p>
<p>Pembatalan tidak cocok di sini karena penyimpanan dilakukan oleh aplikasi, bukan pengguna. Cepat dan mudah untuk melanjutkan penulisan pesan dengan menyusuri daftar draf.</p>
</div>
<div class="col-6">
<h4>Contoh: Percakapan Gmail dihapus</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>Setelah pengguna menghapus percakapan dari daftar dalam Gmail, sebuah pengakuan muncul tanpa opsi pembatalan. Pengakuan tetap ada sampai pengguna melakukan tindakan yang tidak berkaitan, seperti menggulir daftar.</p>
</div>
</div>
<h2>Tidak ada Konfirmasi atau Pengakuan</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: memberikan +1</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>Konfirmasi tidak diperlukan</strong>. Jika pengguna telah memberikan +1 secara tidak sengaja, tidak masalah. Mereka cukup menyentuh kembali tombol itu untuk membatalkan tindakan.</p>
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan melihat tombol +1 memantul dan berubah merah. Itu tanda yang sangat jelas.</p>
</div>
<div class="col-7">
<h4>Contoh: Menghapus aplikasi dari Layar Beranda</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>Konfirmasi tidak diperlukan</strong>. Ini adalah tindakan yang disengaja: pengguna harus menyeret dan meletakkan sebuah item di atas target yang relatif besar dan terpisah. Karena itu, kecil kemungkinan terjadi ketidaksengajaan. Tetapi jika pengguna menyesali keputusan itu, maka hanya perlu beberapa detik untuk mengembalikannya lagi.</p>
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan mengetahui bahwa aplikasi itu tidak ada di Layar Beranda karena mereka menghilangkannya dengan cara menyeretnya.</p>
</div>
</div>

View File

@@ -1,213 +0,0 @@
page.title=Navigasi dengan Back dan Up
page.tags="navigation","activity","task","up navigation","back navigation"
page.image=/design/media/navigation_between_siblings_gmail.png
@jd:body
<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Mengimplementasikan Navigasi yang Efektif</p>
</div>
</a>
<p itemprop="description">Navigasi yang konsisten merupakan komponen penting dari keseluruhan pengalaman pengguna. Hampir tidak ada yang lebih membingungkan
pengguna selain navigasi dasar yang perilakunya tidak konsisten dan tidak sesuai harapan. Android 3.0
memperkenalkan perubahan besar dalam perilaku navigasi global. Mengikuti dengan saksama
panduan untuk Back dan Up akan membuat navigasi aplikasi Anda dapat diprediksi dan dapat diandalkan pengguna.</p>
<p>Android 2.3 dan versi sebelumnya mengandalkan tombol <em>Back</em> sistem untuk mendukung navigasi dalam
aplikasi. Dengan diperkenalkannya action-bar dalam Android 3.0, mekanisme navigasi kedua muncul:
tombol <em>Up</em>, yang terdiri dari ikon aplikasi dan tanda panah yang menunjuk ke kiri.</p>
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
<h2 id="up-vs-back">Up vs. Back</h2>
<p>Tombol Up digunakan untuk berpindah dalam aplikasi berdasarkan hubungan hierarki
antar layar. Misalnya, jika layar A menampilkan daftar item, dan memilih sebuah item akan membuka
layar B (yang menampilkan item tersebut secara lebih detail), maka layar B akan menawarkan tombol Up untuk
kembali ke layar A.</p>
<p>Jika suatu layar merupakan yang teratas dalam aplikasi (yaitu layar Home aplikasi), maka tidak perlu menampilkan tombol
Up.</p>
<p>Tombol Back sistem digunakan untuk berpindah, dalam urutan kronologis terbalik, melalui riwayat
layar yang baru dibuka oleh pengguna. Biasanya ini berdasarkan hubungan sementara
antar layar, dan bukan hierarki aplikasi.</p>
<p>Bila layar yang dilihat sebelumnya juga merupakan induk hierarki dari layar yang sekarang, menekan tombol
Back akan sama hasilnya dengan menekan tombol Up&mdash;ini adalah kejadian
biasa. Akan tetapi, berbeda dengan tombol Up, yang memastikan pengguna tetap berada dalam aplikasi Anda, tombol Back
dapat mengembalikan pengguna ke layar Home, atau bahkan ke aplikasi lain.</p>
<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
<p>Tombol Back juga mendukung beberapa perilaku yang tidak terkait langsung dengan navigasi antar layar:
</p>
<ul>
<li>Menghilangkan jendela mengambang (dialog, popup)</li>
<li>Menghilangkan action-bar kontekstual, dan menghapus sorotan dari item yang dipilih</li>
<li>Menyembunyikan keyboard di layar (IME)</li>
</ul>
<h2 id="within-app">Navigasi Dalam Aplikasi Anda</h2>
<h4>Berpindah ke layar yang memiliki beberapa titik masuk</h4>
<p>Kadang-kadang layar tidak memiliki posisi pasti dalam hierarki aplikasi, dan bisa dimasuki
dari berbagai titik masuk&mdash;seperti layar pengaturan yang dapat dibuka dari layar lain
dalam aplikasi Anda. Dalam hal ini, tombol Up akan memilih untuk kembali ke layar pengarah, yang cara kerjanya
sama dengan tombol Back.</p>
<h4>Mengubah tampilan dalam layar</h4>
<p>Mengubah opsi tampilan untuk layar tidak mengubah perilaku Up atau Back: layar tetap
berada di tempat yang sama dalam hierarki aplikasi, dan tidak dibuat riwayat navigasi yang baru.</p>
<p>Contoh perubahan tampilan tersebut adalah:</p>
<ul>
<li>Mengganti tampilan menggunakan tab dan/atau geser kiri dan kanan</li>
<li>Mengubah tampilan menggunakan tarik-turun (alias tab turun)</li>
<li>Memfilter daftar</li>
<li>Menyortir daftar</li>
<li>Mengubah karakteristik tampilan (seperti zoom)</li>
</ul>
<h4>Berpindah antar layar yang seinduk</h4>
<p>Bila aplikasi Anda mendukung navigasi dari daftar item ke tampilan detail salah satu item tersebut, aplikasi
juga sering diharapkan mendukung navigasi langsung dari item itu ke item sebelumnya atau
sesudahnya dalam daftar. Misalnya, dalam Gmail, begitu mudah untuk bergeser ke kiri atau kanan dari sebuah percakapan
untuk melihat percakapan yang lebih baru atau lebih lama dalam Inbox yang sama. Sama seperti saat mengubah tampilan dalam layar, navigasi
ini tidak mengubah perilaku Up atau Back.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
<p>Akan tetapi, pengecualian khusus terhadap hal ini terjadi saat menjelajah di antara tampilan detail terkait yang tidak disatukan
oleh daftar yang merujuknya&mdash;misalnya, saat menjelajahi Play Store di antara aplikasi dari
pengembang yang sama, atau album dari artis yang sama. Dalam hal ini, mengikuti setiap tautan akan membuat
riwayat, sehingga tombol Back akan menyusuri setiap layar yang dilihat sebelumnya. Tombol Up akan terus
melewatkan semua layar terkait ini dan berpindah ke layar kontainer yang terakhir dilihat.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
<p>Anda dapat menjadikan perilaku tombol Up lebih cerdas lagi berdasarkan pengetahuan Anda tentang tampilan
detail. Dengan memperluas contoh Play Store dari atas, bayangkan pengguna yang telah berpindah dari Buku
terakhir yang dilihat ke detail untuk adaptasi Film. Dalam hal itu, tombol Up dapat kembali ke kontainer
(Movies) yang sebelumnya belum dilalui pengguna.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
<h2 id="into-your-app">Navigasi ke Aplikasi Anda melalui Widget dan Pemberitahuan Layar Home</h2>
<p>Anda bisa menggunakan widget atau pemberitahuan layar Home untuk membantu pengguna berpindah langsung ke layar
jauh dalam hierarki aplikasi Anda. Misalnya, widget Inbox dan pemberitahuan pesan baru di Gmail dapat
melewatkan layar Inbox, dan membawa pengguna langsung ke tampilan percakapan.</p>
<p>Untuk kedua kasus ini, tangani tombol Up sebagai berikut:</p>
<ul>
<li><em>Jika layar tujuan biasanya dicapai dari satu layar tertentu dalam aplikasi
Anda</em>, tombol Up akan mengarahkannya ke layar itu.</li>
<li><em>Jika tidak</em>, tombol Up akan mengarahkan ke layar teratas ("Home") dari aplikasi Anda.</li>
</ul>
<p>Dalam hal tombol Back, Anda harus membuat navigasi lebih bisa diprediksi dengan menyisipkan ke dalam
back-stack tugas path navigasi naik lengkap menuju layar teratas aplikasi. Ini memungkinkan pengguna
yang lupa cara masuk ke aplikasi Anda untuk berpindah ke layar teratas aplikasi sebelum
keluar.</p>
<p>Sebagai contoh, widget layar Home di Gmail memiliki tombol untuk menuju langsung ke layar
Compose. Tombol Up atau Back dari layar Compose akan membawa pengguna ke Inbox, dan dari sana tombol
Back berlanjut ke Home.</p>
<img src="{@docRoot}design/media/navigation_from_outside_back.png">
<h4>Pemberitahuan tidak langsung</h4>
<p>Jika aplikasi Anda perlu menampilkan informasi tentang beberapa kejadian sekaligus, aplikasi dapat menggunakan
pemberitahuan tunggal yang mengarahkan pengguna ke layar antara. Layar ini merangkum semua
kejadian tersebut, dan menyediakan path bagi pengguna untuk menjelajah ke dalam aplikasi. Pemberitahuan dengan gaya seperti ini
disebut <em>pemberitahuan tidak langsung</em>.</p>
<p>Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari
layar antara pada pemberitahuan tidak langsung akan mengembalikan pengguna ke titik pemicu pemberitahuan tersebut&mdash;tidak ada
layar tambahan yang disisipkan ke dalam back-stack. Setelah pengguna melanjutkan ke dalam aplikasi dari
layar antara, tombol Up dan Back akan berperilaku seperti pada pemberitahuan standar, sebagaimana dijelaskan di atas:
menyusuri ke dalam aplikasi dan bukan kembali ke layar antara.</p>
<p>Misalnya, anggaplah seorang pengguna di Gmail menerima pemberitahuan tidak langsung dari Kalender. Menyentuh
pemberitahuan ini akan membuka layar antara, yang menampilkan pengingat beberapa macam
kejadian. Menyentuh Back dari layar antara akan mengembalikan pengguna ke Gmail. Menyentuh kejadian
tertentu akan membawa pengguna dari layar antara ke aplikasi Kalender lengkap untuk menampilkan detail
kejadian. Dari detail kejadian, tombol Up dan Back akan mengarahkan ke tampilan Kalender tingkat atas.</p>
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
<h4>Pemberitahuan pop-up</h4>
<p><em>Pemberitahuan pop-up</em> akan melewatkan laci pemberitahuan, bukan muncul secara langsung di
hadapan pengguna. Ini jarang digunakan, dan <strong>harus dicadangkan untuk peristiwa yang memerlukan respons tepat waktu
dan diperlukan interupsi dari konteks pengguna</strong>. Misalnya,
Talk menggunakan gaya ini untuk memberi tahu pengguna tentang ajakan dari teman untuk bergabung dalam chatting video, karena
ajakan ini akan kedaluwarsa secara otomatis setelah beberapa detik.</p>
<p>Dalam hal perilaku navigasi, pemberitahuan pop-up sangat mirip perilaku pemberitahuan
tidak langsung pada layar antara. Tombol Back akan menghilangkan pemberitahuan pop-up. Jika pengguna berpindah
dari pop-up ke aplikasi yang memberi tahu, tombol Up dan Back akan mengikuti aturan pemberitahuan standar,
berpindah dalam aplikasi.</p>
<img src="{@docRoot}design/media/navigation_popup_notification.png">
<h2 id="between-apps">Navigasi Antar Aplikasi</h2>
<p>Salah satu kekuatan dasar sistem Android adalah kemampuan aplikasi untuk saling
mengaktifkan, sehingga pengguna dapat berpindah langsung dari satu aplikasi ke aplikasi lainnya. Misalnya, sebuah
aplikasi yang perlu mengambil foto dapat mengaktifkan aplikasi Kamera, yang akan mengembalikan foto
ke aplikasi perujuk. Ini sangat menguntungkan pengembang, yang bisa dengan mudah memanfaatkan
kode dari aplikasi lain, maupun pengguna, yang menikmati pengalaman konsisten untuk tindakan yang biasa
dilakukan.</p>
<p>Untuk memahami navigasi antar aplikasi, maka perlu memahami perilaku kerangka kerja Android
yang akan dibahas di bawah ini.</p>
<h4>Aktivitas, tugas, dan intent</h4>
<p>Dalam Android, <strong>aktivitas</strong> adalah komponen aplikasi yang mendefinisikan layar
informasi dan semua tindakan terkait yang dapat dilakukan pengguna. Aplikasi Anda adalah kumpulan
aktivitas, yang terdiri dari aktivitas yang Anda buat dan aktivitas yang Anda gunakan ulang dari aplikasi lain.</p>
<p><strong>Tugas</strong> adalah urutan aktivitas yang diikuti pengguna untuk mencapai tujuan.
Tugas tunggal dapat memanfaatkan aktivitas dari satu aplikasi saja, atau dapat memanfaatkan aktivitas dari sejumlah
aplikasi berbeda.</p>
<p><strong>Intent</strong> adalah mekanisme bagi satu aplikasi untuk memberi isyarat minta bantuan
aplikasi lain dalam menjalankan suatu tindakan. Aktivitas aplikasi dapat menunjukkan intent
apa saja yang dapat diresponsnya. Untuk intent umum seperti "Share", pengguna mungkin telah menginstal beberapa aplikasi
yang dapat memenuhi permintaan itu.</p>
<h4>Contoh: berpindah antar aplikasi untuk mendukung berbagi</h4>
<p>Untuk memahami cara kerja sama aktivitas, tugas, dan intent, perhatikan bagaimana sebuah aplikasi memungkinkan pengguna
untuk berbagi konten dengan menggunakan aplikasi lain. Misalnya, membuka aplikasi Play Store dari Home akan memulai
Task A baru (lihat gambar di bawah). Setelah menyusuri Play Store dan menyentuh buku yang dipromosikan
untuk melihat detailnya, pengguna tetap berada dalam tugas yang sama, memperluasnya dengan menambahkan aktivitas. Memicu
tindakan Share akan memberi tahu pengguna dengan dialog berisi daftar aktivitas (dari aplikasi berbeda)
yang telah terdaftar untuk menangani intent Share.</p>
<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
<p>Bila pengguna memilih untuk berbagi melalui Gmail, aktivitas penulisan di Gmail akan ditambahkan sebagai kelanjutan dari
Task A&mdash;tidak ada tugas baru yang dibuat. Jika Gmail sedang menjalankan tugasnya di latar belakang, maka
tidak akan terpengaruh.</p>
<p>Dari aktivitas penulisan, mengirim pesan atau menyentuh tombol Back akan mengembalikan pengguna ke
aktivitas detail buku tersebut. Penyentuhan tombol Back berikutnya akan terus mengarahkan kembali melalui Play
Store, sampai akhirnya tiba di Home.</p>
<img src="{@docRoot}design/media/navigation_between_apps_back.png">
<p>Akan tetapi, dengan menyentuh tombol Up dari aktivitas penulisan, pengguna menunjukkan keinginan untuk tetap berada di
Gmail. Aktivitas daftar percakapan Gmail muncul, Task B yang baru akan dibuat untuk itu. Tugas baru
selalu terkait ke Home, maka menyentuh tombol Back dari daftar percakapan akan mengembalikan ke sana.</p>
<img src="{@docRoot}design/media/navigation_between_apps_up.png">
<p>Task A tetap berjalan di latar belakang, dan pengguna nanti dapat kembali ke sana (misalnya, melalui layar
Recents). Jika Gmail sedang menjalankan tugasnya di latar belakang, maka itu akan digantikan
dengan Task B&mdash;konteks sebelumnya akan diabaikan demi tujuan baru pengguna.</p>
<p>Jika register aplikasi Anda menangani intent dengan aktivitas yang jauh di dalam hierarki aplikasi,
lihat <a href="#into-your-app">Navigasi Aplikasi Anda melalui Widget Layar Home dan
Pemberitahuan</a> untuk panduan mengenai cara menetapkan navigasi Up.</p>

View File

@@ -1,756 +0,0 @@
page.title=Aktivitas
page.tags=aktivitas,intent
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Creating">Membuat Aktivitas</a>
<ol>
<li><a href="#UI">Mengimplementasikan antarmuka pengguna</a></li>
<li><a href="#Declaring">Mendeklarasikan aktivitas dalam manifes</a></li>
</ol>
</li>
<li><a href="#StartingAnActivity">Memulai Aktivitas</a>
<ol>
<li><a href="#StartingAnActivityForResult">Memulai aktivitas agar berhasil</a></li>
</ol>
</li>
<li><a href="#ShuttingDown">Mematikan Aktivitas</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>
<ol>
<li><a href="#ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
<li><a href="#SavingActivityState">Menyimpan status aktivitas</a></li>
<li><a href="#ConfigurationChanges">Menangani perubahan konfigurasi</a></li>
<li><a href="#CoordinatingActivities">Mengoordinasikan aktivitas</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Activity}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan
Back-Stack</a></li>
</ol>
</div>
</div>
<p>{@link android.app.Activity} adalah sebuah komponen aplikasi yang menyediakan layar yang digunakan
pengguna untuk berinteraksi guna melakukan sesuatu, misalnya memilih nomor telepon, mengambil foto, mengirim email, atau
menampilkan peta. Tiap aktivitas diberi sebuah jendela untuk menggambar antarmuka penggunanya. Jendela ini
biasanya mengisi layar, namun mungkin lebih kecil daripada layar dan mengambang di atas
jendela lain.</p>
<p> Sebuah aplikasi biasanya terdiri atas beberapa aktivitas yang terikat secara longgar
satu sama lain. Biasanya, satu aktivitas dalam aplikasi ditetapkan sebagai aktivitas "utama", yang
ditampilkan kepada pengguna saat membuka aplikasi untuk pertama kali. Tiap
aktivitas kemudian bisa memulai aktivitas lain untuk melakukan berbagai tindakan. Tiap kali
aktivitas baru dimulai, aktivitas sebelumnya akan dihentikan, namun sistem mempertahankan aktivitas
dalam sebuah tumpukan ("back-stack"). Bila sebuah aktivitas baru dimulai, aktivitas itu akan didorong ke atas back-stack dan
mengambil fokus pengguna. Back-stack mematuhi mekanisme dasar tumpukan "masuk terakhir, keluar pertama",
jadi, bila pengguna selesai dengan aktivitas saat ini dan menekan tombol <em>Back</em>, aktivitas
akan dikeluarkan dari tumpukan (dan dimusnahkan) dan aktivitas sebelumnya akan dilanjutkan. (Back-stack
dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas
dan Back-Stack</a>.)</p>
<p>Bila aktivitas dihentikan karena ada aktivitas baru yang dimulai, aktivitas lama akan diberi tahu tentang perubahan status ini
melalui metode callback daur hidupnya.
Ada beberapa metode callback yang mungkin diterima aktivitas, karena sebuah perubahan dalam
statusnya&mdash;apakah sistem sedang membuatnya, menghentikannya, melanjutkannya, atau menghapuskannya&mdash;dan
masing-masing callback memberi Anda kesempatan melakukan pekerjaan tertentu yang
sesuai untuk perubahan status itu. Misalnya, bila dihentikan, aktivitas Anda harus melepas
objek besar, seperti koneksi jaringan atau database. Bila aktivitas dilanjutkan, Anda bisa
memperoleh kembali sumber daya yang diperlukan dan melanjutkan tindakan yang terputus. Transisi status ini
semuanya bagian dari daur hidup aktivitas.</p>
<p>Bagian selebihnya dari dokumen ini membahas dasar-dasar cara membuat dan menggunakan aktivitas,
yang meliputi satu pembahasan lengkap tentang cara kerja daur hidup aktivitas, sehingga Anda bisa dengan benar mengelola
transisi di antara berbagai status aktivitas.</p>
<h2 id="Creating">Membuat Aktivitas</h2>
<p>Untuk membuat sebuah aktivitas, Anda harus membuat subkelas {@link android.app.Activity} (atau
subkelasnya yang ada). Dalam subkelas itu, Anda perlu mengimplementasikan metode-metode callback yang
dipanggil sistem saat aktivitas bertransisi di antara berbagai status daur hidupnya, misalnya saat
aktivitas sedang dibuat, dihentikan, dilanjutkan, atau dimusnahkan. Dua metode callback
terpenting adalah:</p>
<dl>
<dt>{@link android.app.Activity#onCreate onCreate()}</dt>
<dd>Anda harus mengimplementasikan metode ini. Sistem memanggilnya saat membuat
aktivitas Anda. Dalam implementasi, Anda harus menginisialisasi komponen-komponen esensial
aktivitas.
Yang terpenting, inilah tempat Anda harus memanggil {@link android.app.Activity#setContentView
setContentView()} untuk mendefinisikan layout untuk antarmuka pengguna aktivitas.</dd>
<dt>{@link android.app.Activity#onPause onPause()}</dt>
<dd>Sistem memanggil metode ini sebagai pertanda pertama bahwa pengguna sedang meninggalkan
aktivitas Anda (walau itu tidak selalu berarti aktivitas sedang dimusnahkan). Inilah biasanya tempat Anda
harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
pengguna mungkin tidak kembali).</dd>
</dl>
<p>Ada beberapa metode callback daur hidup lainnya yang harus Anda gunakan untuk memberikan
pengalaman pengguna yang mengalir di antara aktivitas dan menangani interupsi tidak terduga yang menyebabkan aktivitas Anda
dihentikan dan bahkan dimusnahkan. Semua metode callback daur hidup akan dibahas nanti, di
bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>.</p>
<h3 id="UI">Mengimplementasikan antarmuka pengguna</h3>
<p> Antarmuka pengguna aktivitas disediakan oleh hierarki objek&mdash;tampilan yang diturunkan
dari kelas {@link android.view.View}. Tiap tampilan mengontrol sebuah ruang persegi panjang tertentu
dalam jendela aktivitas dan bisa merespons interaksi pengguna. Misalnya, sebuah tampilan mungkin berupa sebuah
tombol yang mengawali suatu tindakan bila pengguna menyentuhnya.</p>
<p>Android menyediakan sejumlah tampilan siap-dibuat yang bisa Anda gunakan untuk mendesain dan mengatur
layout. "Widget" adalah tampilan yang menyediakan elemen-elemen visual (dan interaktif) untuk layar,
misalnya tombol, bidang teks, kotak cek, atau sekadar sebuah gambar. "Layout" adalah tampilan yang diturunkan dari {@link
android.view.ViewGroup} yang memberikan sebuah model layout unik untuk tampilan anaknya, misalnya
layout linier, layout grid, atau layout relatif. Anda juga bisa mensubkelaskan kelas-kelas {@link android.view.View} dan
{@link android.view.ViewGroup} (atau subkelas yang ada) untuk membuat widget dan
layout Anda sendiri dan menerapkannya ke layout aktivitas Anda.</p>
<p>Cara paling umum untuk mendefinisikan layout dengan menggunakan tampilan adalah dengan file layout XML yang disimpan dalam
sumber daya aplikasi Anda. Dengan cara ini, Anda bisa memelihara desain antarmuka pengguna Anda secara terpisah dari
kode yang mendefinisikan perilaku aktivitas. Anda bisa mengatur layout sebagai UI
aktivitas Anda dengan {@link android.app.Activity#setContentView(int) setContentView()}, dengan meneruskan
ID sumber daya untuk layout itu. Akan tetapi, Anda juga bisa membuat {@link android.view.View} baru dalam
kode aktivitas dan membuat hierarki tampilan dengan menyisipkan {@link
android.view.View} baru ke dalam {@link android.view.ViewGroup}, kemudian menggunakan layout itu dengan meneruskan akar
{@link android.view.ViewGroup} ke {@link android.app.Activity#setContentView(View)
setContentView()}.</p>
<p>Untuk informasi tentang cara membuat antarmuka pengguna, lihat dokumentasi <a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
<h3 id="Declaring">Mendeklarasikan aktivitas dalam manifes</h3>
<p>Anda harus mendeklarasikan aktivitas dalam file manifes agar file itu
bisa diakses oleh sistem. Untuk mendeklarasikan aktivitas, bukalah file manifes Anda dan tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
sebagai anak elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
. Misalnya:</p>
<pre>
&lt;manifest ... &gt;
&lt;application ... &gt;
&lt;activity android:name=".ExampleActivity" /&gt;
...
&lt;/application ... &gt;
...
&lt;/manifest &gt;
</pre>
<p>Ada beberapa atribut lain yang bisa Anda sertakan dalam elemen ini, untuk mendefinisikan properti
misalnya label untuk aktivitas, ikon untuk aktivitas, atau tema untuk memberi gaya ke
UI aktivitas. Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a>
adalah satu-satunya atribut yang diperlukan&mdash;atribut ini menetapkan nama kelas aktivitas. Setelah
Anda mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
sebagian fungsionalitas, misalnya pintasan aplikasi (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
That Cannot Change</a>).</p>
<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
untuk informasi selengkapnya tentang cara mendeklarasikan aktivitas Anda dalam manifes.</p>
<h4>Menggunakan filter intent</h4>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a> juga bisa menetapkan berbagai filter intent&mdash;dengan menggunakan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> &mdash;untuk mendeklarasikan cara komponen aplikasi lain
mengaktifkannya.</p>
<p>Bila Anda membuat aplikasi baru dengan Android SDK Tools, aktivitas stub
yang dibuat untuk Anda secara otomatis menyertakan filter intent yang mendeklarasikan respons
aktivitas pada tindakan "main" (utama) dan harus diletakkan dalam kategori "launcher"). Filter intent
terlihat seperti ini:</p>
<pre>
&lt;activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> menetapkan bahwa ini adalah titik masuk "main" ke aplikasi. Elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> menetapkan bahwa aktivitas ini harus tercantum dalam launcher aplikasi
sistem (untuk memungkinkan pengguna meluncurkan aktivitas ini).</p>
<p>Jika Anda bermaksud agar aplikasi dimuat dengan sendirinya dan tidak memperbolehkan aplikasi lain
mengaktifkan aktivitasnya, maka Anda tidak memerlukan filter intent lain. Hanya satu aktivitas yang boleh
memiliki tindakan "main" dan kategori "launcher", seperti dalam contoh sebelumnya. Aktivitas yang
tidak ingin Anda sediakan untuk aplikasi lain tidak boleh memiliki filter intent dan Anda bisa
memulai sendiri aktivitas dengan menggunakan intent secara eksplisit (seperti dibahas di bagian berikut).</p>
<p>Akan tetapi, jika ingin aktivitas Anda merespons intent implisit yang dikirim dari
aplikasi lain (dan aplikasi Anda sendiri), maka Anda harus mendefinisikan filter intent tambahan untuk
aktivitas. Untuk masing-masing tipe intent yang ingin direspons, Anda harus menyertakan sebuah <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> yang menyertakan elemen
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> dan, opsional, sebuah elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> dan/atau elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data&gt;}</a>. Elemen-elemen ini menetapkan tipe intent yang bisa
direspons oleh aktivitas Anda.</p>
<p>Untuk informasi selengkapnya tentang cara aktivitas Anda merespons intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
</p>
<h2 id="StartingAnActivity">Memulai Aktivitas</h2>
<p>Anda bisa memulai aktivitas lain dengan memanggil {@link android.app.Activity#startActivity
startActivity()}, dengan meneruskan sebuah {@link android.content.Intent} yang menjelaskan aktivitas
yang ingin Anda mulai. Intent menetapkan aktivitas persis yang ingin Anda mulai atau menjelaskan
tipe tindakan yang ingin Anda lakukan (dan sistem akan memilih aktivitas yang sesuai untuk Anda,
yang bahkan
bisa berasal dari aplikasi berbeda). Intent juga bisa membawa sejumlah kecil data untuk
digunakan oleh aktivitas yang dimulai.</p>
<p>Saat bekerja dalam aplikasi sendiri, Anda nanti akan sering meluncurkan aktivitas yang dikenal saja.
Anda bisa melakukannya dengan membuat intent yang mendefinisikan secara eksplisit aktivitas yang ingin Anda mulai,
dengan menggunakan nama kelas. Misalnya, beginilah cara satu aktivitas memulai aktivitas lain bernama {@code
SignInActivity}:</p>
<pre>
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
</pre>
<p>Akan tetapi, aplikasi Anda mungkin juga perlu melakukan beberapa tindakan, misalnya mengirim email,
pesan teks, atau pembaruan status, dengan menggunakan data dari aktivitas Anda. Dalam hal ini, aplikasi Anda mungkin
tidak memiliki aktivitasnya sendiri untuk melakukan tindakan tersebut, sehingga Anda bisa memanfaatkan aktivitas
yang disediakan oleh aplikasi lain pada perangkat, yang bisa melakukan tindakan itu untuk Anda. Inilah saatnya
intent benar-benar berharga&mdash;Anda bisa membuat intent yang menjelaskan tindakan yang ingin
dilakukan dan sistem
akan meluncurkan aktivitas yang tepat dari aplikasi lain. Jika ada
beberapa aktivitas yang bisa menangani intent itu, pengguna bisa memilih aktivitas yang akan digunakan. Misalnya,
jika Anda ingin memperbolehkan pengguna mengirim pesan email, Anda bisa membuat
intent berikut:</p>
<pre>
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
</pre>
<p>Ekstra {@link android.content.Intent#EXTRA_EMAIL} yang ditambahkan ke intent adalah sebuah larik string
alamat email yang menjadi tujuan pengiriman email. Bila aplikasi email merespons intent ini,
aplikasi itu akan membaca larik string yang disediakan dalam ekstra dan meletakkannya dalam bidang "to"
pada formulir penulisan email. Dalam situasi ini, aktivitas aplikasi email dimulai dan bila
pengguna selesai, aktivitas Anda akan dilanjutkan.</p>
<h3 id="StartingAnActivityForResult">Memulai aktivitas agar berhasil</h3>
<p>Kadang-kadang, Anda mungkin ingin menerima hasil dari aktivitas yang Anda mulai. Dalam hal itu,
mulailah aktivitas dengan memanggil {@link android.app.Activity#startActivityForResult
startActivityForResult()} (sebagai ganti {@link android.app.Activity#startActivity
startActivity()}). Untuk menerima hasil dari
aktivitas selanjutnya nanti, implementasikan metode callback {@link android.app.Activity#onActivityResult onActivityResult()}
. Bila aktivitas selanjutnya selesai, aktivitas akan mengembalikan hasil dalam {@link
android.content.Intent} kepada metode {@link android.app.Activity#onActivityResult onActivityResult()}
Anda.</p>
<p>Misalnya, mungkin Anda ingin pengguna mengambil salah satu kontaknya, sehingga aktivitas Anda bisa
melakukan sesuatu dengan informasi dalam kontak itu. Begini caranya membuat intent tersebut dan
menangani hasilnya:</p>
<pre>
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
&#64;Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK &amp;&amp; requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}
</pre>
<p>Contoh ini menunjukkan logika dasar yang harus Anda gunakan dalam metode {@link
android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani
hasil aktivitas. Syarat pertama memeriksa apakah permintaan berhasil&mdash;jika ya, maka
{@code resultCode} akan berupa {@link android.app.Activity#RESULT_OK}&mdash;dan apakah permintaan
yang direspons hasil ini dikenal&mdash;dalam hal ini, {@code requestCode} cocok dengan
parameter kedua yang dikirim dengan {@link android.app.Activity#startActivityForResult
startActivityForResult()}. Dari sana, kode akan menangani hasil aktivitas dengan membuat query
data yang dihasilkan dalam{@link android.content.Intent} (parameter {@code data}).</p>
<p>Yang terjadi adalah {@link
android.content.ContentResolver} melakukan query terhadap penyedia konten, yang menghasilkan
{@link android.database.Cursor} yang memperbolehkan data query dibaca. Untuk informasi selengkapnya, lihat dokumen
<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
Intent</a>.</p>
<h2 id="ShuttingDown">Mematikan Aktivitas</h2>
<p>Anda bisa mematikan aktivitas dengan memanggil metode {@link android.app.Activity#finish
finish()}-nya. Anda juga bisa mematikan aktivitas terpisah yang sebelumnya Anda mulai dengan memanggil
{@link android.app.Activity#finishActivity finishActivity()}.</p>
<p class="note"><strong>Catatan:</strong> Pada umumnya, Anda tidak boleh secara eksplisit mengakhiri aktivitas
dengan menggunakan metode-metode ini. Seperti yang dibahas di bagian berikut tentang daur hidup aktivitas,
sistem Android mengelola hidup aktivitas untuk Anda, sehingga Anda tidak perlu menyelesaikan sendiri
aktivitas tersebut. Memanggil metode-metode ini bisa berpengaruh negatif pada pengalaman
pengguna yang diharapkan dan hanya boleh digunakan bila Anda benar-benar tidak ingin pengguna kembali ke
instance aktivitas ini.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Aktivitas</h2>
<p>Mengelola daur hidup aktivitas dengan mengimplementasikan metode-metode callback sangat
penting untuk mengembangkan
aplikasi yang kuat dan fleksibel. Daur hidup aktivitas dipengaruhi langsung oleh kaitannya dengan
aktivitas lain, tugasnya, serta back-stack.</p>
<p>Pada dasarnya, sebuah aktivitas bisa berada dalam tiga status:</p>
<dl>
<dt><i>Dilanjutkan</i></dt>
<dd>Aktivitas berada di latar depan layar dan mendapatkan fokus pengguna. (Status ini
kadang-kadang disebut juga dengan "running" (berjalan).)</dd>
<dt><i>Dihentikan sementara</i></dt>
<dd>Aktivitas lain berada di latar depan dan mendapat fokus, namun aktivitas ini masih terlihat. Yakni,
aktivitas lain terlihat di atas aplikasi ini dan aktivitas itu setengah transparan atau tidak
menuutpi seluruh layar. Aktivitas yang dihentikan sementara adalah benar-benar hidup (objek {@link android.app.Activity}
dipertahankan dalam memori, objek itu memelihara semua informasi status dan anggota, dan tetap dikaitkan dengan
window manager), namun bisa dimatikan oleh sistem dalam situasi memori sangat rendah.</dd>
<dt><i>Dihentikan</i></dt>
<dd>Aktivitas ditutupi sepenuhnya oleh aktivitas lain (aktivitas sekarang berada di
"latar belakang"). Aktivitas yang dihentikan juga masih hidup (objek {@link android.app.Activity}
dipertahankan dalam memori, objek itu menjaga semua informasi status dan anggota, namun <em>tidak</em>
dikaitkan dengan window manager). Akan tetapi, aktivitas tidak lagi terlihat bagi pengguna dan
bisa dimatikan oleh sistem bila memori diperlukan di lain.</dd>
</dl>
<p>Jika aktivitas dihentikan sementara atau dihentikan, sistem bisa mengeluarkannya dari memori baik dengan memintanya agar
diakhiri (memanggil metode {@link android.app.Activity#finish finish()}-nya), atau sekadar mematikan
prosesnya. Bila dibuka lagi (setelah diakhiri atau dimatikan), aktivitas harus dibuat dari
awal.</p>
<h3 id="ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
<p>Saat bertransisi ke dalam dan ke luar berbagai status yang dijelaskan di atas, aktivitas diberi tahu
melalui berbagai metode callback. Semua metode callback adalah sangkutan yang
bisa Anda kesampingkan untuk melakukan pekerjaan yang sesuai saat status aktivitas Anda berubah. Aktivitas skeleton
berikut menyertakan setiap metode daur hidup mendasar:</p>
<pre>
public class ExampleActivity extends Activity {
&#64;Override
public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
&#64;Override
protected void {@link android.app.Activity#onStart onStart()} {
super.onStart();
// The activity is about to become visible.
}
&#64;Override
protected void {@link android.app.Activity#onResume onResume()} {
super.onResume();
// The activity has become visible (it is now "resumed").
}
&#64;Override
protected void {@link android.app.Activity#onPause onPause()} {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
&#64;Override
protected void {@link android.app.Activity#onStop onStop()} {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
&#64;Override
protected void {@link android.app.Activity#onDestroy onDestroy()} {
super.onDestroy();
// The activity is about to be destroyed.
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Implementasi Anda terhadap metode-metode daur hidup ini harus
selalu memanggil implementasi superkelas sebelum melakukan pekerjaan apa pun, seperti yang ditampilkan dalam contoh-contoh di atas.</p>
<p>Bersama-sama, semua metode ini mendefinisikan seluruh daur hidup sebuah aktivitas. Dengan mengimplementasikan
metode-metode ini, Anda bisa memantau tiga loop tersarang (nested loop) dalam daur hidup aktivitas: </p>
<ul>
<li><b>Seluruh masa hidup</b> aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onCreate onCreate()} dan panggilan ke {@link
android.app.Activity#onDestroy}. Aktivitas Anda harus melakukan penyiapan
status "global" (misalnya mendefinisikan layout) dalam {@link android.app.Activity#onCreate onCreate()}, dan
melepas semua sisa sumber daya dalam {@link android.app.Activity#onDestroy}. Misalnya, jika
aktivitas Anda memiliki sebuah thread yang berjalan di latar belakang untuk mengunduh data dari jaringan, aktivitas itu bisa membuat
thread itu dalam {@link android.app.Activity#onCreate onCreate()} kemudian menghentikan thread dalam {@link
android.app.Activity#onDestroy}.</li>
<li><p><b>Masa pakai terlihat</b> (visible lifetime) aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onStart onStart()} dan panggilan ke {@link
android.app.Activity#onStop onStop()}. Selama ini, pengguna bisa melihat aktivitas
pada layar dan berinteraksi dengannya. Misalnya, {@link android.app.Activity#onStop onStop()} dipanggil
bila sebuah aktivitas baru dimulai dan aktivitas ini tidak lagi terlihat. Di antara dua metode ini, Anda bisa
memelihara sumber daya yang diperlukan untuk menampilkan aktivitas kepada pengguna. Misalnya, Anda bisa mendaftarkan sebuah
{@link android.content.BroadcastReceiver} dalam {@link
android.app.Activity#onStart onStart()} untuk memantau perubahan yang berdampak pada UI Anda, dan mencabut pendaftarannya
dalam {@link android.app.Activity#onStop onStop()} bila pengguna tidak bisa lagi melihat apa yang sedang Anda
tampilkan. Sistem bisa memanggil {@link android.app.Activity#onStart onStart()} dan {@link
android.app.Activity#onStop onStop()} beberapa kali selama masa pakai aktivitas, sambil
aktivitas berganti-ganti antara terlihat dan tersembunyi bagi pengguna.</p></li>
<li><p><b>Masa pakai latar depan</b> aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onResume onResume()} dan panggilan ke {@link android.app.Activity#onPause
onPause()}. Selama waktu ini, aktivitas berada di depan semua aktivitas lain pada layar dan mendapatkan
fokus input pengguna. Aktivitas bisa sering bertransisi ke dalam dan ke luar latar depan&mdash;misalnya,
{@link android.app.Activity#onPause onPause()} dipanggil bila perangkat masuk ke mode tidur atau
bila dialog muncul. Karena status ini bisa sering bertransisi, kode dalam dua metode ini harus
cukup ringan untuk menghindari transisi lamban yang membuat pengguna menunggu.</p></li>
</ul>
<p>Gambar 1 mengilustrasikan loop dan path yang mungkin diambil sebuah aktivitas di antara status-status.
Persegi panjang mewakili metode callback yang bisa Anda implementasikan untuk melakukan operasi saat
aktivitas bertransisi di antara status. <p>
<img src="{@docRoot}images/activity_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup aktivitas.</p>
<p>Metode-metode callback daur hidup yang sama tercantum dalam tabel 1, yang menjelaskan setiap metode callback
secara lebih detail dan menentukan lokasinya masing-masing dalam
daur hidup aktivitas keseluruhan, termasuk apakah sistem bisa mematikan aktivitas setelah
metode callback selesai.</p>
<p class="table-caption"><strong>Tabel 1.</strong> Rangkuman metode callback
daur hidup aktivitas.</p>
<table border="2" width="85%" frame="hsides" rules="rows">
<colgroup align="left" span="3"></colgroup>
<colgroup align="left"></colgroup>
<colgroup align="center"></colgroup>
<colgroup align="center"></colgroup>
<thead>
<tr><th colspan="3">Metode</th> <th>Keterangan</th> <th>Bisa dimatikan setelahnya?</th> <th>Berikutnya</th></tr>
</thead>
<tbody>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
<td>Dipanggil saat aktivitas pertama kali dibuat.
Di sinilah Anda harus melakukan semua persiapan statis normal &mdash;
membuat tampilan, mengikat data ke daftar, dan sebagainya. Metode ini diberi
sebuah objek Bundle yang berisi status aktivitas sebelumnya, jika
status itu tertangkap (lihat <a href="#actstate">Menyimpan Status Aktivitas</a>,
nanti).
<p>Selalu diikuti oleh {@code onStart()}.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td colspan="2" align="left"><code>{@link android.app.Activity#onRestart
onRestart()}</code></td>
<td>Dipanggil setelah aktivitas dihentikan, tepat sebelum
dimulai lagi.
<p>Selalu diikuti oleh {@code onStart()}</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
<td>Dipanggil tepat sebelum aktivitas menjadi terlihat bagi pengguna.
<p>Diikuti oleh {@code onResume()} jika aktivitas maju
ke latar depan, atau {@code onStop()} jika menjadi tersembunyi.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
</tr>
<tr>
<td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
<td>Dipanggil tepat sebelum aktivitas mulai
berinteraksi dengan pengguna. Pada titik ini, aktivitas berada di
puncak tumpukan aktivitas, dengan input pengguna menuju kepadanya.
<p>Selalu diikuti oleh {@code onPause()}.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onPause()}</td>
</tr>
<tr>
<td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
<td>Dipanggil bila sistem akan memulai pelanjutan
aktivitas lain. Metode ini biasanya digunakan untuk menerapkan (commit) perubahan yang tidak tersimpan pada
data persisten, menghentikan animasi dan hal-hal lain yang mungkin menghabiskan
CPU, dan sebagainya. Metode ini harus melakukan apa saja yang dilakukannya dengan sangat cepat, karena
aktivitas berikutnya tidak akan dilanjutkan hingga aktivitas ini kembali.
<p>Diikuti oleh {@code onResume()} jika aktivitas
kembali ke depan, atau oleh {@code onStop()} jika menjadi
tidak terlihat bagi pengguna.</td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
<td>Dipanggil bila aktivitas tidak lagi terlihat bagi pengguna. Hal ini
bisa terjadi karena aktivitas sedang dimusnahkan, atau karena aktivitas lain
(aktivitas yang ada atau yang baru) telah dilanjutkan dan sedang menutupinya.
<p>Diikuti oleh {@code onRestart()} jika
aktivitas kembali untuk berinteraksi dengan pengguna, atau oleh
{@code onDestroy()} jika aktivitas ini akan menghilang.</p></td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center">{@code onRestart()} <br/>atau<br/> {@code onDestroy()}</td>
</tr>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy
onDestroy()}</code></td>
<td>Dipanggil sebelum aktivitas dimusnahkan. Inilah panggilan terakhir
yang akan diterima aktivitas. Metode ini bisa dipanggil karena
aktivitas selesai (seseorang memanggil <code>{@link android.app.Activity#finish
finish()}</code> padanya), atau karena sistem memusnahkan sementara
instance aktivitas ini untuk menghemat tempat. Anda bisa membedakan
kedua skenario ini dengan metode <code>{@link
android.app.Activity#isFinishing isFinishing()}</code>.</td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center"><em>tidak ada</em></td>
</tr>
</tbody>
</table>
<p>Kolom berlabel "Bisa dimatikan setelahnya?" menunjukkan apakah sistem bisa
atau tidak mematikan proses yang menjadi host aktivitas kapan saja <em>setelah metode kembali</em>, tanpa
menjalankan baris lain pada kode aktivitas. Tiga metode ini ditandai "ya": ({@link
android.app.Activity#onPause
onPause()}, {@link android.app.Activity#onStop onStop()}, dan {@link android.app.Activity#onDestroy
onDestroy()}). Karena {@link android.app.Activity#onPause onPause()} adalah yang pertama
dari tiga, begitu aktivitas dibuat, {@link android.app.Activity#onPause onPause()} adalah
metode terakhir yang dipastikan akan dipanggil sebelum proses <em>bisa</em> dimatikan&mdash;jika
sistem harus memulihkan memori dalam keadaan darurat, maka {@link
android.app.Activity#onStop onStop()} dan {@link android.app.Activity#onDestroy onDestroy()} mungkin
tidak dipanggil. Karena itu, Anda harus menggunakan {@link android.app.Activity#onPause onPause()} untuk menulis
data persisten yang penting (misalnya hasil edit pengguna) ke penyimpanan. Akan tetapi, Anda harus selektif dalam hal
informasi yang harus dipertahankan selama {@link android.app.Activity#onPause onPause()}, karena setiap
prosedur pemblokiran dalam metode ini akan memblokir transisi ke aktivitas berikutnya dan memperlambat
pengalaman pengguna.</p>
<p> Metode-metode yang ditandai "Tidak" dalam kolom <b>Bisa dimatikan</b> melindungi proses yang menjadi host
aktivitas dari dimatikan sejak saat metode dipanggil. Jadi, aktivitas bisa dimatikan
sejak {@link android.app.Activity#onPause onPause()} kembali hingga waktu
{@link android.app.Activity#onResume onResume()} dipanggil. Aktivitas tidak akan lagi bisa dimatikan hingga
{@link android.app.Activity#onPause onPause()} dipanggil lagi dan kembali. </p>
<p class="note"><strong>Catatan:</strong> Aktivitas yang tidak "bisa dimatikan" secara teknis oleh
definisi dalam tabel 1 masih bisa dimatikan oleh sistem&mdash;namun itu hany terjadi dalam
situasi ekstrem bila tidak ada jalan lain. Kapan aktivitas bisa dimatikan
akan dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan
Threading</a>.</p>
<h3 id="SavingActivityState">Menyimpan status aktivitas</h3>
<p>Pengantar untuk <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a> secara ringkas menyebutkan
bahwa
bila aktivitas dihentikan sementara atau dihentikan, status aktivitas akan dipertahankan. Hal itu terjadi karena
objek {@link android.app.Activity} masih ditahan dalam memori saat aktivitas dihentikan sementara atau
dihentikan&mdash;semua informasi tentang anggota dan statusnya saat ini masih hidup. Jadi, setiap perubahan
yang dibuat pengguna dalam aktivitas akan dipertahankan sehingga bila aktivitas kembali ke
latar depan (bila "dilanjutkan"), perubahan itu masih ada.</p>
<p>Akan tetapi, bila sistem memusnahkan aktivitas untuk memulihkan memori, objek {@link
android.app.Activity} akan dimusnahkan, sehingga sistem tidak bisa sekadar melanjutkan aktivitas dengan status
tidak berubah. Sebagai gantinya, sistem harus membuat ulang objek {@link android.app.Activity} jika pengguna
menyusuri kembali ke aktivitas tersebut. Namun, pengguna tidak menyadari
bahwa sistem memusnahkan aktivitas dan membuatnya kembali dan, karena itu, mungkin
mengharapkan aktivitas untuk sama persis dengan sebelumnya. Dalam situasi ini, Anda bisa memastikan bahwa
informasi penting tentang status aktivitas tetap terjaga dengan mengimplementasikan
metode callback tambahan yang memungkinkan Anda menyimpan informasi tentang status aktivitas: {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p>
<p>Sistem memanggil {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
sebelum membuat aktivitas rawan terhadap pemusnahan. Sistem meneruskan ke metode ini
sebuah {@link android.os.Bundle} tempat Anda bisa menyimpan
informasi status tentang aktivitas sebagai pasangan nama-nilai, dengan menggunakan metode-metode misalnya {@link
android.os.Bundle#putString putString()} dan {@link
android.os.Bundle#putInt putInt()}. Kemudian, jika sistem mematikan proses aplikasi Anda
dan pengguna menyusuri kembali ke aktivitas tersebut, sistem akan membuat kembali aktivitas dan meneruskan
{@link android.os.Bundle} ke {@link android.app.Activity#onCreate onCreate()} maupun {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. Dengan menggunakan salah satu
metode ini, Anda bisa mengekstrak status tersimpan dari {@link android.os.Bundle} dan memulihkan
status aktivitas. Jika tidak ada informasi status untuk dipulihkan, maka {@link
android.os.Bundle} yang diteruskan kepada adalah Anda null (yang akan terjadi bila aktivitas dibuat untuk
pertama kali).</p>
<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Ada dua cara yang bisa digunakan aktivitas untuk kembali ke fokus pengguna
dengan status tetap: aktivitas dimusnahkan, kemudian dibuat kembali, dan aktivitas harus memulihkan
status yang disimpan sebelumnya, atau aktivitas dihentikan, kemudian dilanjutkan dengan status aktivitas
tetap.</p>
<p class="note"><strong>Catatan:</strong> Tidak ada jaminan bahwa {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} akan dipanggil sebelum
aktivitas Anda dimusnahkan, karena bisa saja terjadi aktivitas tidak perlu menyimpan status
(misalnya saat pengguna meninggalkan aktivitas Anda dengan menggunakan tombol <em>Back</em>, karena pengguna menutup aktivitas
secara eksplisit
). Jika sistem memanggil {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()}, ini akan dilakukan sebelum {@link
android.app.Activity#onStop onStop()} dan mungkin sebelum {@link android.app.Activity#onPause
onPause()}.</p>
<p>Akan tetapi, sekalipun Anda tidak melakukan apa-apa dan tidak mengimplementasikan {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()}, beberapa status aktivitas
akan dipulihkan oleh implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} dalam kelas {@link android.app.Activity}. Khususnya,
implementasi default akan memanggil metode {@link
android.view.View#onSaveInstanceState onSaveInstanceState()} yang sesuai untuk setiap {@link
android.view.View} dalam layout, yang memungkinkan setiap tampilan untuk memberi informasi tentang dirinya
yang harus disimpan. Hampir setiap widget dalam kerangka kerja Android mengimplementasikan metode ini
sebagaimana mestinya, sehingga setiap perubahan yang terlihat pada UI akan disimpan dan dipulihkan secara otomatis bila
aktivitas Anda dibuat kembali. Misalnya, widget {@link android.widget.EditText} menyimpan teks apa saja
yang dimasukkan oleh pengguna dan widget {@link android.widget.CheckBox} menyimpan baik teks itu diperiksa maupun
tidak. Satu-satunya pekerjaan yang Anda perlukan adalah memberikan ID unik (dengan atribut <a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>
) untuk masing-masing widget yang ingin disimpan statusnya. Jika widget tidak memiliki ID, maka sistem
tidak bisa menyimpan statusnya.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>Anda juga bisa menghentikan secara eksplisit sebuah tampilan dalam layout Anda agar tidak menyimpan statusnya dengan mengatur atribut
{@link android.R.attr#saveEnabled android:saveEnabled} ke {@code "false"} atau dengan memanggil
metode {@link android.view.View#setSaveEnabled setSaveEnabled()}. Biasanya, Anda tidak boleh
menonaktifkannya, namun Anda boleh melakukannya jika ingin memulihkan status UI aktivitas secara berbeda.</p>
</div>
</div>
<p>Walaupun implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} menyimpan informasi yang berguna tentang
UI aktivitas, Anda mungkin masih perlu mengesampingkannya untuk menyimpan informasi tambahan.
Misalnya, Anda mungkin perlu menyimpan nilai-nilai anggota yang berubah selama masa pakai aktivitas (yang
mungkin berkorelasi dengan nilai-nilai yang dipulihkan dalam UI, namun anggota-anggota yang menyimpan nilai-nilai UI itu tidak
dipulihkan, secara default).</p>
<p>Karena implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} membantu menyimpan status UI, jika
Anda mengesampingkan metode ini untuk menyimpan informasi tambahan status, Anda harus selalu memanggil
implementasi superkelas {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
sebelum melakukan pekerjaan apa pun. Demikian pula, Anda juga harus memanggil implementasi superkelas {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} jika Anda mengesampingkannya, sehingga
implementasi default bisa memulihkan status tampilan.</p>
<p class="note"><strong>Catatan:</strong> Karena {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()} tidak dijamin
akan dipanggil, Anda harus menggunakannya hanya untuk mencatat status aktivitas sementara (transient) (status
UI)&mdash;Anda tidak boleh menggunakannya untuk menyimpan data persisten. Sebagai gantinya, Anda harus menggunakan {@link
android.app.Activity#onPause onPause()} untuk menyimpan data persisten (misalnya data yang harus disimpan
ke database) saat pengguna meninggalkan aktivitas.</p>
<p>Salah satu cara yang baik untuk menguji kemampuan aplikasi dalam memulihkan statusnya adalah cukup dengan memutar
perangkat sehingga orientasi layarnya berubah. Bila orientasi layar berubah, sistem
akan memusnahkan dan membuat kembali aktivitas untuk menerapkan sumber daya alternatif yang mungkin tersedia
untuk konfigurasi layar baru. Karena alasan ini saja, sangat penting bahwa aktivitas Anda
memulihkan statusnya secara lengkap saat dibuat kembali, karena pengguna memutar layar secara rutin saat
menggunakan aplikasi.</p>
<h3 id="ConfigurationChanges">Menangani perubahan konfigurasi</h3>
<p>Sebagian konfigurasi perangkat bisa berubah saat runtime (misalnya orientasi layar, ketersediaan keyboard
, dan bahasa). Bila terjadi perubahan demikian, Android akan membuat kembali aktivitas yang berjalan
(sistem akan memanggil {@link android.app.Activity#onDestroy}, kemudian segera memanggil {@link
android.app.Activity#onCreate onCreate()}). Perilaku ini
didesain untuk membantu aplikasi Anda menyesuaikan diri dengan konfigurasi baru dengan cara memuat ulang
aplikasi Anda secara otomatis dengan sumber daya alternatif yang telah Anda sediakan (misalnya layout yang berbeda untuk
layar orientasi dan ukuran yang berbeda).</p>
<p>Jika Anda mendesain aktivitas dengan benar untuk menangani restart karena perubahan orientasi layar dan
memulihkan status aktivitas seperti yang dijelaskan di atas, aplikasi Anda akan lebih tahan terhadap
kejadian tidak terduga lainnya dalam daur hidup aktivitas.</p>
<p>Cara terbaik menangani restart tersebut adalah
menyimpan dan memulihkan status aktivitas Anda dengan menggunakan {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} dan {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (atau {@link
android.app.Activity#onCreate onCreate()}), seperti yang dibahas di bagian sebelumnya.</p>
<p>Untuk informasi selengkapnya tentang konfigurasi perubahan yang terjadi saat program berjalan dan cara menanganinya
, bacalah panduan untuk <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani
Perubahan Runtime</a>.</p>
<h3 id="CoordinatingActivities">Mengoordinasikan aktivitas</h3>
<p>Bila suatu aktivitas memulai aktivitas lain, keduanya akan mengalami transisi daur hidup. Aktivitas pertama
akan berhenti sementara dan berhenti sama sekali (walau tidak akan berhenti jika masih terlihat di latar belakang), saat
aktivitas lain dibuat. Jika aktivitas-aktivitas ini berbagi data yang disimpan ke disk atau di tempat lain, Anda perlu
memahami bahwa aktivitas pertama tidak dihentikan sepenuhnya sebelum aktivitas kedua dibuat.
Sebagai gantinya, proses akan memulai aktivitas kedua secara tumpang tindih dengan proses penghentian
aktivitas pertama.</p>
<p>Urutan callback daur hidup didefinisikan dengan baik, khususnya bila kedua aktivitas berada dalam
proses yang sama dan salah satunya memulai yang lain. Berikut ini adalah urutan operasi yang terjadi bila Aktivitas
A memulai Aktivitas B: </p>
<ol>
<li>Metode {@link android.app.Activity#onPause onPause()} Aktivitas A berjalan.</li>
<li>Metode-metode {@link android.app.Activity#onCreate onCreate()}, {@link
android.app.Activity#onStart onStart()}, dan {@link android.app.Activity#onResume onResume()}
Aktivitas B berjalan secara berurutan. (Aktivitas B sekarang mendapatkan fokus pengguna.)</li>
<li>Kemudian, jika Aktivitas A tidak lagi terlihat di layar, metode {@link
android.app.Activity#onStop onStop()}-nya akan dijalankan.</li>
</ol>
<p>Urutan callback daur hidup yang bisa diramalkan ini memungkinkan Anda mengelola transisi
informasi dari satu aktivitas ke aktivitas lainnya. Misalnya, jika Anda harus menulis ke database saat
aktivitas pertama berhenti agar aktivitas berikutnya bisa membacanya, maka Anda harus menulis ke
database selama {@link android.app.Activity#onPause onPause()} sebagai ganti selama {@link
android.app.Activity#onStop onStop()}.</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how Android maintains a history of activities and
enables user multitasking, continue with the <b><a
href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back
Stack</a></b> document.</p>
-->

View File

@@ -1,658 +0,0 @@
page.title=Layanan Terikat
parent.title=Layanan
parent.link=services.html
@jd:body
<div id="qv-wrapper">
<ol id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Basics">Dasar-Dasar</a></li>
<li><a href="#Creating">Membuat Layanan Terikat</a>
<ol>
<li><a href="#Binder">Memperluas kelas Binder</a></li>
<li><a href="#Messenger">Menggunakan Messenger</a></li>
</ol>
</li>
<li><a href="#Binding">Mengikat ke Layanan</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan Terikat</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Service}</li>
<li>{@link android.content.ServiceConnection}</li>
<li>{@link android.os.IBinder}</li>
</ol>
<h2>Contoh</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
RemoteService}</a></li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService}</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/services.html">Layanan</a></li>
</ol>
</div>
<p>Layanan terikat adalah server di antarmuka klien-server. Layanan terikat memungkinkan komponen-komponen
(seperti aktivitas) untuk diikat ke layanan, mengirim permintaan, menerima respons, dan bahkan melakukan
komunikasi antarproses (IPC). Layanan terikat biasanya hidup hanya saat melayani
komponen aplikasi lain dan tidak berjalan di latar belakang terus-menerus.</p>
<p>Dokumen ini menampilkan cara membuat layanan terikat, termasuk cara mengikat
ke layanan dari komponen aplikasi lain. Akan tetapi, Anda juga harus mengacu dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a> untuk
informasi tambahan tentang layanan secara umum, seperti cara menyampaikan pemberitahuan dari layanan, mengatur
layanan agar berjalan di latar depan, dan lain-lain.</p>
<h2 id="Basics">Dasar-Dasar</h2>
<p>Layanan terikat adalah implementasi kelas {@link android.app.Service} yang memungkinkan
aplikasi lain diikat padanya dan berinteraksi dengannya. Untuk menyediakan pengikatan bagi sebuah
layanan, Anda harus mengimplementasikan metode callback {@link android.app.Service#onBind onBind()}. Metode ini
menghasilkan objek {@link android.os.IBinder} yang mendefinisikan antarmuka pemprograman yang
bisa digunakan klien untuk berinteraksi dengan layanan.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Mengikat ke Layanan yang Sudah Dimulai</h3>
<p>Seperti dibahas dalam dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a>
, Anda bisa membuat layanan yang dimulai sekaligus diikat. Yakni, layanan bisa
dimulai dengan memanggil {@link android.content.Context#startService startService()}, yang memungkinkan
layanan berjalan terus-menerus, dan juga membolehkan klien untuk mengikat ke layanan dengan memanggil {@link
android.content.Context#bindService bindService()}.
<p>Jika Anda mengizinkan layanan dimulai dan diikat, lalu ketika layanan telah
dimulai, sistem <em>tidak</em> menghapus layanan ketika semua klien melepas ikatan. Sebagai gantinya, Anda harus
menghentikan layanan secara eksplisit, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}.</p>
<p>Walaupun Anda biasanya harus mengimplementasikan {@link android.app.Service#onBind onBind()}
<em>atau</em> {@link android.app.Service#onStartCommand onStartCommand()}, kadang-kadang perlu
mengimplementasikan keduanya. Misalnya, sebuah pemutar musik bisa merasakan manfaatnya karena layanannya boleh berjalan
terus-menerus dan juga menyediakan pengikatan. Dengan cara ini, sebuah aktivitas bisa memulai layanan untuk memutar beberapa
lagu dan musik terus dimainkan sekalipun pengguna meninggalkan aplikasi. Lalu, bila pengguna
kembali ke aplikasi, aktivitas bisa mengikat ke layanan untuk mendapatkan kembali kontrol atas pemutaran.</p>
<p>Pastikan membaca bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan
Terikat</a>, untuk informasi selengkapnya tentang daur hidup layanan saat menambahkan pengikatan ke
layanan yang sudah dimulai.</p>
</div>
</div>
<p>Klien bisa mengikat ke layanan dengan memanggil {@link android.content.Context#bindService
bindService()}. Bila itu dilakukan, klien harus menyediakan implementasi {@link
android.content.ServiceConnection}, yang memantau koneksi dengan layanan. Metode {@link
android.content.Context#bindService bindService()} kembali dengan serta-merta tanpa sebuah nilai, namun
bila sistem Android membuat koneksi antara klien
dan layanan, sistem akan memanggil {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()} pada {@link
android.content.ServiceConnection} untuk mengirim {@link android.os.IBinder} yang
bisa digunakan klien untuk berkomunikasi dengan layanan.</p>
<p>Beberapa klien bisa terhubung ke layanan dengan serentak. Akan tetapi, sistem akan memanggil metode
{@link android.app.Service#onBind onBind()} layanan Anda untuk mengambil {@link android.os.IBinder} hanya
bila klien pertama mengikat. Sistem lalu memberikan {@link android.os.IBinder} yang sama ke setiap
klien tambahan yang mengikat, tanpa memanggil {@link android.app.Service#onBind onBind()} lagi.</p>
<p>Bila klien terakhir melepas ikatan dari layanan, sistem akan menghapus layanan (kecuali jika
layanan juga dimulai oleh {@link android.content.Context#startService startService()}).</p>
<p>Bila Anda mengimplementasikan layanan terikat, yang terpenting adalah mendefinisikan antarmuka
yang dihasilkan metode callback {@link android.app.Service#onBind onBind()} Anda. Ada sedikit
cara mendefinisikan antarmuka {@link android.os.IBinder} layanan Anda dan bagian berikut
akan membahas masing-masing teknik.</p>
<h2 id="Creating">Membuat Layanan Terikat</h2>
<p>Saat membuat layanan yang menyediakan pengikatan, Anda harus menyediakan {@link android.os.IBinder}
yang menyediakan antarmuka pemrograman yang bisa digunakan klien untuk berinteraksi dengan layanan. Ada
tiga cara untuk mendefinisikan antarmuka:</p>
<dl>
<dt><a href="#Binder">Memperluas kelas Binder</a></dt>
<dd>Jika layanan Anda bersifat privat untuk aplikasi Anda sendiri dan berjalan dalam proses yang sama dengan klien
(biasanya), Anda harus membuat antarmuka dengan memperluas kelas {@link android.os.Binder}
dan menghasilkan instance dari
{@link android.app.Service#onBind onBind()}. Klien akan menerima {@link android.os.Binder} dan
bisa menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasi {@link android.os.Binder}
atau bahkan {@link android.app.Service}.
<p>Inilah teknik yang lebih disukai bila layanan Anda sekadar pekerja latar belakang untuk aplikasi Anda
sendiri. Satu-satunya alasan tidak membuat antarmuka dengan cara ini adalah karena
layanan Anda akan digunakan oleh aplikasi lain atau pada proses-proses terpisah.</dd>
<dt><a href="#Messenger">Menggunakan Messenger</a></dt>
<dd>Jika antarmuka Anda perlu bekerja lintas proses, Anda bisa membuat
antarmuka untuk layanan dengan {@link android.os.Messenger}. Dengan cara ini, layanan
mendefinisikan {@link android.os.Handler} yang akan merespons aneka tipe objek {@link
android.os.Message}. {@link android.os.Handler}
ini adalah dasar bagi {@link android.os.Messenger} yang nanti bisa berbagi {@link android.os.IBinder}
dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objek {@link
android.os.Message}. Selain itu, klien bisa mendefinisikan sendiri {@link android.os.Messenger}
sehingga layanan bisa mengirim balik pesan.
<p>Inilah cara termudah melakukan komunikasi antarproses (IPC), karena {@link
android.os.Messenger} akan mengantre semua permintaan ke dalam satu thread sehingga Anda tidak perlu mendesain
layanan agar thread-safe.</p>
</dd>
<dt>Menggunakan AIDL</dt>
<dd>AIDL (Android Interface Definition Language) melakukan semua pekerjaan untuk mengurai objek menjadi
primitif yang bisa dipahami dan diarahkan oleh sistem operasi ke berbagai proses untuk melakukan
IPC. Teknik sebelumnya, dengan menggunakan {@link android.os.Messenger}, sebenarnya berdasarkan AIDL sebagai
struktur yang mendasarinya. Seperti disebutkan di atas, {@link android.os.Messenger} membuat antrean
semua permintaan klien dalam satu thread, sehingga layanan akan menerima permintaan satu per satu. Akan tetapi,
jika ingin layanan Anda menangani beberapa permintaan sekaligus, Anda bisa menggunakan AIDL
secara langsung. Dalam hal ini, layanan Anda harus mampu multi-thread dan dibuat thread-safe.
<p>Untuk menggunakan AIDL secara langsung, Anda harus
membuat file {@code .aidl} yang mendefinisikan antarmuka pemrograman. Alat Android SDK menggunakan
file ini untuk menghasilkan kelas abstrak yang mengimplementasikan antarmuka dan menangani IPC, yang nanti
bisa Anda perluas dalam layanan.</p>
</dd>
</dl>
<p class="note"><strong>Catatan:</strong> Umumnya aplikasi <strong>tidak boleh</strong> menggunakan AIDL untuk
membuat layanan terikat, karena hal itu mungkin memerlukan kemampuan multi-thread dan
bisa mengakibatkan implementasi yang lebih rumit. Dengan demikian, AIDL tidak cocok untuk sebagian besar aplikasi
dan dokumen ini tidak membahas cara menggunakannya untuk layanan Anda. Jika Anda yakin perlu
menggunakan AIDL secara langsung, lihat dokumen <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
.</p>
<h3 id="Binder">Memperluas kelas Binder</h3>
<p>Jika layanan Anda hanya digunakan oleh aplikasi lokal dan tidak perlu bekerja lintas proses,
maka Anda bisa mengimplementasikan kelas {@link android.os.Binder} Anda sendiri yang memberi klien Anda
akses langsung ke metode publik dalam layanan.</p>
<p class="note"><strong>Catatan:</strong> Hal ini hanya berhasil jika klien dan layanan berada dalam
aplikasi dan proses yang sama, suatu kondisi yang paling umum. Misalnya, cara ini sangat cocok untuk sebuah aplikasi musik
yang perlu mengikat aktivitas ke layanannya sendiri, yakni memutar musik di
latar belakang.</p>
<p>Berikut cara menyiapkannya:</p>
<ol>
<li>Dalam layanan Anda, buat sebuah instance {@link android.os.Binder} yang:
<ul>
<li>berisi metode publik yang bisa dipanggil klien</li>
<li>menghasilkan instance {@link android.app.Service} saat ini, yang memiliki metode publik yang
bisa dipanggil klien</li>
<li>atau, menghasilkan instance kelas lain yang host-nya di layanan dengan metode publik yang
bisa dipanggil klien</li>
</ul>
<li>Hasilkan instance {@link android.os.Binder} ini dari metode callback {@link
android.app.Service#onBind onBind()}.</li>
<li>Di klien, terima {@link android.os.Binder} dari metode callback {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()} dan
buat panggilan ke layanan terikat dengan menggunakan metode yang disediakan.</li>
</ol>
<p class="note"><strong>Catatan:</strong> Alasan layanan dan klien harus berada dalam aplikasi yang sama
adalah agar klien bisa mengkonversi objek yang dihasilkan dan memanggil API-nya dengan benar. Layanan
dan klien juga harus berada dalam proses yang sama, karena teknik ini tidak melakukan
pengarahan (marshalling) apa pun untuk lintas proses.</p>
<p>Misalnya, berikut ini adalah layanan yang memberi klien akses ke metode-metode dalam layanan melalui
implementasi {@link android.os.Binder}:</p>
<pre>
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
&#64;Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
</pre>
<p>{@code LocalBinder} menyediakan {@code getService()} metode bagi klien untuk mengambil
instance {@code LocalService} saat ini. Cara ini memungkinkan klien memanggil metode publik dalam
layanan. Misalnya, klien bisa memanggil {@code getRandomNumber()} dari layanan.</p>
<p>Berikut ini adalah aktivitas yang mengikat ke {@code LocalService} dan memanggil {@code getRandomNumber()}
bila tombol diklik:</p>
<pre>
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
&#64;Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
&#64;Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
&#64;Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
&#64;Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
</pre>
<p>Contoh di atas menampilkan cara klien mengikat ke layanan dengan menggunakan implementasi
{@link android.content.ServiceConnection} dan callback {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()}. Bagian
berikut menyediakan informasi selengkapnya tentang proses pengikatan ke layanan.</p>
<p class="note"><strong>Catatan:</strong> Contoh di atas tidak secara eksplisit melepas ikatan dari layanan,
namun semua klien harus melepas ikatan pada waktu yang tepat (seperti saat aktivitas sedang jeda).</p>
<p>Untuk contoh kode selengkapnya, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService.java}</a> dan kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
LocalServiceActivities.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
<h3 id="Messenger">Menggunakan Messenger</h3>
<div class="sidebox-wrapper">
<div class="sidebox">
<h4>Dibandingkan dengan AIDL</h4>
<p>Bila Anda perlu melakukan IPC, menggunakan {@link android.os.Messenger} untuk antarmuka
lebih sederhana daripada mengimplementasikannya dengan AIDL, karena {@link android.os.Messenger} mengantre
semua panggilan ke layanan, sementara antarmuka AIDL murni mengirim permintaan serentak ke
layanan, yang nanti harus menangani multi-threading.</p>
<p>Untuk sebagian besar aplikasi, layanan tidak perlu melakukan multi-threading, jadi dengan menggunakan {@link
android.os.Messenger} memungkinkan layanan menangani panggilan satu per satu. Jika
layanan harus multi-thread, Anda harus menggunakan <a href="{@docRoot}guide/components/aidl.html">AIDL</a> untuk mendefinisikan antarmuka.</p>
</div>
</div>
<p>Jika layanan perlu berkomunikasi dengan proses jauh, Anda bisa menggunakan
{@link android.os.Messenger} untuk menyediakan antarmuka bagi layanan Anda. Teknik ini memungkinkan
Anda melakukan komunikasi antarproses (IPC) tanpa harus menggunakan AIDL.</p>
<p>Berikut ini rangkuman cara menggunakan {@link android.os.Messenger}:</p>
<ul>
<li>Layanan mengimplementasikan {@link android.os.Handler} yang menerima callback untuk tiap
panggilan dari klien.</li>
<li>{@link android.os.Handler} digunakan untuk membuat objek {@link android.os.Messenger}
(yang merupakan acuan ke {@link android.os.Handler}).</li>
<li>{@link android.os.Messenger} membuat {@link android.os.IBinder} yang
dikembalikan layanan ke klien dari {@link android.app.Service#onBind onBind()}.</li>
<li>Klien menggunakan {@link android.os.IBinder} untuk membuat instance {@link android.os.Messenger}
(yang mengacu {@link android.os.Handler} layanan), yang digunakan klien untuk mengirim
objek {@link android.os.Message} ke layanan.</li>
<li>Layanan menerima setiap {@link android.os.Message} dalam {@link
android.os.Handler}&mdash;secara spesifik, dalam metode {@link android.os.Handler#handleMessage
handleMessage()}.</li>
</ul>
<p>Dengan cara ini, tidak ada "metode" untuk dipanggil klien pada layanan. Sebagai gantinya,
klien mengirim "pesan" (objek-objek {@link android.os.Message}) yang diterima layanan dalam
{@link android.os.Handler}-nya.</p>
<p>Berikut ini contoh layanan sederhana yang menggunakan antarmuka {@link android.os.Messenger}:</p>
<pre>
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
&#64;Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
&#64;Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
</pre>
<p>Perhatikan bahwa metode {@link android.os.Handler#handleMessage handleMessage()} dalam
{@link android.os.Handler} adalah tempat layanan menerima {@link android.os.Message}
yang masuk dan memutuskan aksi yang harus dilakukan, berdasarkan anggota {@link android.os.Message#what}.</p>
<p>Klien tinggal membuat {@link android.os.Messenger} berdasarkan {@link
android.os.IBinder} yang dihasilkan layanan dan mengirim pesan menggunakan {@link
android.os.Messenger#send send()}. Misalnya, berikut ini adalah aktivitas sederhana yang mengikat ke
layanan dan mengirim pesan {@code MSG_SAY_HELLO} ke layanan:</p>
<pre>
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
&#64;Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
&#64;Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
</pre>
<p>Perhatikan bahwa contoh ini tidak menampilkan cara layanan merespons klien. Jika ingin
layanan merespons, Anda juga perlu membuat {@link android.os.Messenger} di klien. Lalu
saat menerima callback {@link android.content.ServiceConnection#onServiceConnected
onServiceConnected()}, klien akan mengirim {@link android.os.Message} ke layanan yang berisi
{@link android.os.Messenger} klien dalam parameter {@link android.os.Message#replyTo}
metode {@link android.os.Messenger#send send()}.</p>
<p>Anda bisa melihat contoh cara menyediakan pertukaran pesan dua arah dalam contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
MessengerService.java}</a> (layanan) dan <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
MessengerServiceActivities.java}</a> (klien).</p>
<h2 id="Binding">Mengikat ke Layanan</h2>
<p>Komponen-komponen aplikasi (klien) bisa mengikat ke layanan dengan memanggil
{@link android.content.Context#bindService bindService()}. Sistem Android
lalu memanggil metode {@link android.app.Service#onBind
onBind()} layanan, yang menghasilkan {@link android.os.IBinder} untuk berinteraksi dengan layanan.</p>
<p>Pengikatan ini bersifat asinkron. {@link android.content.Context#bindService
bindService()} segera kembali dan <em>tidak</em> mengembalikan {@link android.os.IBinder} ke
klien. Untuk menerima {@link android.os.IBinder}, klien harus membuat instance {@link
android.content.ServiceConnection} dan meneruskannya ke {@link android.content.Context#bindService
bindService()}. {@link android.content.ServiceConnection} berisi metode callback yang
dipanggil sistem untuk mengirim {@link android.os.IBinder}.</p>
<p class="note"><strong>Catatan:</strong> Hanya aktivitas, layanan, dan penyedia konten yang bisa mengikat
ke layanan yang&mdash;Anda <strong>tidak bisa</strong> ikat ke layanan dari penerima siaran.</p>
<p>Jadi, untuk mengikat ke layanan dari klien, Anda harus: </p>
<ol>
<li>Mengimplementasikan {@link android.content.ServiceConnection}.
<p>Implementasi Anda harus mengesampingkan dua metode callback:</p>
<dl>
<dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
<dd>Sistem memanggil ini untuk mengirim {@link android.os.IBinder} yang dihasilkan oleh
metode {@link android.app.Service#onBind onBind()} layanan.</dd>
<dt>{@link android.content.ServiceConnection#onServiceDisconnected
onServiceDisconnected()}</dt>
<dd>Sistem Android memanggil ini bila koneksi ke layanan putus
tanpa terduga, seperti ketika layanan mengalami crash atau dimatikan. Ini <em>tidak</em> dipanggil ketika
klien melepas ikatan.</dd>
</dl>
</li>
<li>Panggil {@link
android.content.Context#bindService bindService()}, dengan meneruskan implementasi {@link
android.content.ServiceConnection}. </li>
<li>Bila sistem memanggil metode callback {@link android.content.ServiceConnection#onServiceConnected
onServiceConnected()}, Anda bisa mulai membuat panggilan ke layanan, dengan menggunakan
metode yang didefinisikan oleh antarmuka.</li>
<li>Untuk memutus koneksi dari layanan, panggil {@link
android.content.Context#unbindService unbindService()}.
<p>Bila telah dimusnahkan (destroyed), klien Anda akan melepas ikatan dari layanan, namun Anda harus selalu melepas ikatan
bila sudah selesai berinteraksi dengan layanan atau bila aktivitas Anda sedang jeda sehingga layanan bisa
dimatikan saat tidak sedang digunakan. (Waktu yang tepat untuk mengikat dan melepas ikatan dibahas
selengkapnya di bawah ini.)</p>
</li>
</ol>
<p>Misalnya, cuplikan berikut menghubungkan klien ke layanan yang dibuat di atas dengan
<a href="#Binder">memperluas kelas Binder</a>, sehingga tinggal mengkonversi
{@link android.os.IBinder} yang dihasilkan ke kelas {@code LocalService} dan meminta instance {@code
LocalService}:</p>
<pre>
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};
</pre>
<p>Dengan {@link android.content.ServiceConnection} ini, klien bisa mengikat ke layanan dengan meneruskannya
ke {@link android.content.Context#bindService bindService()}. Misalnya:</p>
<pre>
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
</pre>
<ul>
<li>Parameter pertama {@link android.content.Context#bindService bindService()} adalah sebuah
{@link android.content.Intent} yang secara eksplisit menyebutkan layanan yang akan diikat (walaupun intent
boleh implisit).</li>
<li>Parameter kedua adalah objek {@link android.content.ServiceConnection}.</li>
<li>Parameter ketiga adalah tanda (flag) yang menunjukkan opsi pengikatan. Tanda ini biasanya harus {@link
android.content.Context#BIND_AUTO_CREATE} agar dapat membuat layanan jika belum hidup.
Nilai-nilai lain yang memungkinkan adalah {@link android.content.Context#BIND_DEBUG_UNBIND}
dan {@link android.content.Context#BIND_NOT_FOREGROUND}, atau {@code 0} untuk tidak satu pun.</li>
</ul>
<h3>Catatan tambahan</h3>
<p>Berikut ini beberapa catatan penting tentang mengikat ke layanan:</p>
<ul>
<li>Anda harus selalu menjebak eksepsi {@link android.os.DeadObjectException}, yang dilontarkan
bila koneksi terputus. Inilah satu-satunya eksepsi yang dilontarkan oleh metode jauh.</li>
<li>Objek adalah acuan yang dihitung lintas proses. </li>
<li>Anda biasanya harus memasangkan pengikatan dan pelepasan ikatan selama
memasangkan momen membuat dan menghapus daur hidup klien. Misalnya:
<ul>
<li>Jika Anda hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda
harus mengikat selama {@link android.app.Activity#onStart onStart()} dan melepas ikatan selama {@link
android.app.Activity#onStop onStop()}.</li>
<li>Jika Anda ingin aktivitas menerima tanggapan bahkan saat dihentikan di
latar belakang, Anda bisa mengikat selama {@link android.app.Activity#onCreate onCreate()} dan melepas ikatan
selama {@link android.app.Activity#onDestroy onDestroy()}. Berhati-hatilah karena hal ini menyiratkan aktivitas
Anda perlu menggunakan layanan selama dijalankan (sekalipun di latar belakang), jadi jika
layanan berada dalam proses lain, Anda meningkatkan bobot proses dan semakin besar
kemungkinan sistem akan mematikannya.</li>
</ul>
<p class="note"><strong>Catatan:</strong> Anda biasanya <strong>tidak</strong> boleh mengikat dan melepas ikatan
selama {@link android.app.Activity#onResume onResume()} aktivitas Anda dan {@link
android.app.Activity#onPause onPause()}, karena callback ini terjadi pada setiap transisi daur hidup
dan Anda harus menjaga pemrosesan yang terjadi pada transisi ini tetap minim. Juga, jika
banyak aktivitas dalam aplikasi Anda mengikat ke layanan yang sama dan ada transisi antara
dua aktivitas, layanan bisa dimusnahkan dan dibuat lagi sambil aktivitas saat ini melepas ikatan
(selama jeda) sebelum aktivitas berikutnya mengikat (selama lanjutkan). (Transisi aktivitas ini untuk cara
aktivitas mengoordinasikan daur hidupnya dijelaskan dalam dokumen <a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Aktivitas</a>
.)</p>
</ul>
<p>Untuk contoh kode selengkapnya, yang menampilkan cara mengikat ke layanan, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
RemoteService.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Layanan Terikat</h2>
<p>Bila layanan dilepas ikatannya dari semua klien, sistem Android akan menghapusnya (kecuali jika layanan juga
dimulai dengan {@link android.app.Service#onStartCommand onStartCommand()}). Dengan demikian, Anda tidak harus
mengelola daur hidup layanan jika layanan itu murni sebuah layanan
terikat&mdash;yang dikelola sistem Android untuk Anda berdasarkan apakah layanan terikat ke klien atau tidak.</p>
<p>Akan tetapi, Jika Anda memilih untuk mengimplementasikan metode callback {@link android.app.Service#onStartCommand
onStartCommand()}, maka Anda harus menghentikan layanan secara eksplisit, karena layanan
sekarang dianggap telah <em>dimulai</em>. Dalam hal ini, layanan akan berjalan hingga layanan
menghentikan dirinya sendiri dengan {@link android.app.Service#stopSelf()} atau panggilan komponen lain {@link
android.content.Context#stopService stopService()}, terlepas dari apakah layanan terikat ke
klien atau tidak.</p>
<p>Selain itu, jika layanan Anda telah dimulai dan menerima pengikatan, maka saat sistem memanggil
metode {@link android.app.Service#onUnbind onUnbind()}, Anda bisa memilih untuk mengembalikan
{@code true} jika ingin menerima panggilan ke {@link android.app.Service#onRebind
onRebind()} bila nanti klien mengikat ke layanan (sebagai ganti menerima panggilan ke {@link
android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind
onRebind()} akan menghasilkan void, namun klien tetap menerima {@link android.os.IBinder} dalam callback
{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}.
Di bawah ini adalah gambar 1 yang mengilustrasikan logika untuk jenis daur hidup ini.</p>
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup untuk layanan yang dimulai
dan juga memungkinkan pengikatan.</p>
<p>Untuk informasi selengkapnya tentang daur hidup layanan yang telah dimulai, lihat dokumen <a href="{@docRoot}guide/components/services.html#Lifecycle">Layanan</a>.</p>

View File

@@ -1,812 +0,0 @@
page.title=Fragmen
parent.title=Aktivitas
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Design">Filosofi Desain</a></li>
<li><a href="#Creating">Membuat Fragmen</a>
<ol>
<li><a href="#UI">Menambahkan antarmuka pengguna</a></li>
<li><a href="#Adding">Menambahkan fragmen ke aktivitas</a></li>
</ol>
</li>
<li><a href="#Managing">Mengelola Fragmen</a></li>
<li><a href="#Transactions">Melakukan Transaksi Fragmen</a></li>
<li><a href="#CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</a>
<ol>
<li><a href="#EventCallbacks">Membuat callback kejadian pada aktivitas</a></li>
<li><a href="#ActionBar">Menambahkan item ke Action-Bar</a></li>
</ol>
</li>
<li><a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>
<ol>
<li><a href="#CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</a></li>
</ol>
</li>
<li><a href="#Example">Contoh</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Fragment}</li>
<li>{@link android.app.FragmentManager}</li>
<li>{@link android.app.FragmentTransaction}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/fragments/index.html">Membangun UI Dinamis dengan Fragmen</a></li>
<li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet
dan Handset</a></li>
</ol>
</div>
</div>
<p>{@link android.app.Fragment} mewakili perilaku atau bagian dari antarmuka pengguna dalam
{@link android.app.Activity}. Anda bisa mengombinasikan beberapa fragmen dalam satu aktivitas untuk membangun UI
multipanel dan menggunakan kembali sebuah fragmen dalam beberapa aktivitas. Anda bisa menganggap fragmen sebagai bagian
modular dari aktivitas, yang memiliki daur hidup sendiri, menerima kejadian input sendiri, dan
yang bisa Anda tambahkan atau hapus saat aktivitas berjalan (semacam "sub aktivitas" yang
bisa digunakan kembali dalam aktivitas berbeda).</p>
<p>Fragmen harus selalu tertanam dalam aktivitas dan daur hidup fragmen secara langsung
dipengaruhi oleh daur hidup aktivitas host-nya. Misalnya, saat aktivitas dihentikan sementara,
semua fragmen di dalamnya juga dihentikan sementara, dan bila aktivitas dimusnahkan, semua fragmen juga demikian. Akan tetapi, saat
aktivitas berjalan (dalam <a href="{@docRoot}guide/components/activities.html#Lifecycle">status daur hidup</a> <em>dilanjutkan</em>, Anda bisa
memanipulasi setiap fragmen secara terpisah, seperti menambah atau menghapusnya. Saat melakukan transaksi
fragmen, Anda juga bisa menambahkannya ke back-stack yang dikelola oleh aktivitas
&mdash;setiap entri back-stack merupakan record transaksi fragmen yang
terjadi. Dengan back-stack pengguna dapat membalikkan transaksi fragmen (mengarah mundur),
dengan menekan tombol <em>Back</em>.</p>
<p>Bila Anda menambahkan fragmen sebagai bagian dari layout aktivitas, fragmen itu berada dalam {@link
android.view.ViewGroup} di hierarki tampilan aktivitas tersebut dan fragmen mendefinisikan
layout
tampilannya sendiri. Anda bisa menyisipkan fragmen ke dalam layout aktivitas dengan mendeklarasikan fragmen dalam file layout aktivitas
, sebagai elemen {@code &lt;fragment&gt;}, atau dari kode aplikasi dengan menambahkannya ke
{@link android.view.ViewGroup} yang ada. Akan tetapi, fragmen tidak harus menjadi bagian dari
layout aktivitas; Anda juga bisa menggunakan fragmen tanpa UI-nya sendiri sebagai pekerja tak terlihat untuk
aktivitas tersebut.</p>
<p>Dokumen ini menjelaskan cara membangun aplikasi menggunakan fragmen, termasuk
cara fragmen mempertahankan statusnya bila ditambahkan ke back-stack aktivitas, berbagi
kejadian dengan aktivitas, dan fragmen lain dalam aktivitas, berkontribusi pada action-bar
aktivitas, dan lainnya.</p>
<h2 id="Design">Filosofi Desain</h2>
<p>Android memperkenalkan fragmen di Android 3.0 (API level 11), terutama untuk mendukung desain UI yang lebih
dinamis dan fleksibel pada layar besar, seperti tablet. Karena
layar tablet jauh lebih besar daripada layar handset, maka lebih banyak ruang untuk mengombinasikan dan
bertukar komponen UI. Fragmen memungkinkan desain seperti itu tanpa perlu mengelola perubahan
kompleks pada hierarki tampilan. Dengan membagi layout aktivitas menjadi beberapa fragmen, Anda bisa
mengubah penampilan aktivitas saat runtime dan mempertahankan perubahan itu di back-stack
yang dikelola oleh aktivitas.</p>
<p>Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di
sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan&mdash;kedua fragmen ini muncul di satu
aktivitas, berdampingan, dan masing-masing fragmen memiliki serangkaian metode callback daur hidup dan menangani kejadian input
penggunanya sendiri. Sehingga, sebagai ganti menggunakan satu aktivitas untuk memilih
artikel dan aktivitas lainnya untuk membaca artikel, pengguna bisa memilih artikel dan membaca semuanya dalam
aktivitas yang sama, sebagaimana diilustrasikan dalam layout tablet pada gambar 1.</p>
<p>Anda harus mendesain masing-masing fragmen sebagai komponen aktivitas modular dan bisa digunakan kembali. Yakni, karena
setiap fragmen mendefinisikan layoutnya dan perilakunya dengan callback daur hidupnya sendiri, Anda bisa memasukkan
satu fragmen dalam banyak aktivitas, sehingga Anda harus mendesainnya untuk digunakan kembali dan mencegah
memanipulasi satu fragmen dari fragmen lain secara langsung. Ini terutama penting karena dengan
fragmen modular Anda bisa mengubah kombinasi fragmen untuk ukuran layar berbeda. Saat mendesain aplikasi
untuk mendukung tablet maupun handset, Anda bisa menggunakan kembali fragmen dalam
konfigurasi layout berbeda untuk mengoptimalkan pengalaman pengguna berdasarkan ruang layar yang tersedia. Misalnya
, pada handset, fragmen mungkin perlu dipisahkan untuk menyediakan UI panel tunggal
bila lebih dari satu yang tidak cocok dalam aktivitas yang sama.</p>
<img src="{@docRoot}images/fundamentals/fragments.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Contoh cara dua modul UI yang didefinisikan oleh
fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk
desain handset.</p>
<p>Misalnya&mdash;untuk melanjutkan contoh aplikasi berita&mdash; aplikasi bisa menanamkan
dua fragmen dalam <em>Aktivitas A</em>, saat berjalan pada perangkat berukuran tablet. Akan tetapi, pada
layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga <em>Aktivitas A</em> hanya
menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel,
<em>Aktivitas B</em> akan dimulai, termasuk fragmen kedua untuk membaca artikel. Sehingga, aplikasi mendukung
tablet dan handset dengan menggunakan kembali fragmen dalam kombinasi berbeda, seperti diilustrasikan dalam
gambar 1.</p>
<p>Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda
untuk konfigurasi layar berbeda, lihat panduan untuk <a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet dan Handset</a>.</p>
<h2 id="Creating">Membuat Fragmen</h2>
<div class="figure" style="width:327px">
<img src="{@docRoot}images/fragment_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup fragmen (saat
aktivitasnya berjalan).</p>
</div>
<p>Untuk membuat fragmen, Anda harus membuat subkelas {@link android.app.Fragment} (atau
subkelasnya yang ada). Kelas {@link android.app.Fragment} memiliki kode yang mirip seperti
{@link android.app.Activity}. Kelas ini memiliki metode callback yang serupa dengan aktivitas, seperti
{@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()},
{@link android.app.Fragment#onPause onPause()}, dan {@link android.app.Fragment#onStop onStop()}. Sebenarnya
, jika Anda mengkonversi aplikasi Android saat ini untuk menggunakan fragmen, Anda mungkin cukup memindahkan
kode dari metode callback aktivitas ke masing-masing metode callback
fragmen.</p>
<p>Biasanya, Anda harus mengimplementasikan setidaknya metode daur hidup berikut ini:</p>
<dl>
<dt>{@link android.app.Fragment#onCreate onCreate()}</dt>
<dd>Sistem akan memanggilnya saat membuat fragmen. Dalam implementasi, Anda harus
menginisialisasi komponen penting dari fragmen yang ingin dipertahankan saat fragmen
dihentikan sementara atau dihentikan, kemudian dilanjutkan.</dd>
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
<dd>Sistem akan memanggilnya saat fragmen menggambar antarmuka penggunanya
untuk yang pertama kali. Untuk menggambar UI fragmen, Anda harus mengembalikan {@link android.view.View} dari metode
ini yang menjadi akar layout fragmen. Hasil yang dikembalikan bisa berupa null jika
fragmen tidak menyediakan UI.</dd>
<dt>{@link android.app.Activity#onPause onPause()}</dt>
<dd>Sistem akan memanggil metode ini sebagai indikasi pertama bahwa pengguna sedang meninggalkan
fragmen Anda (walau itu tidak selalu berarti fragmen sedang dimusnahkan). Inilah biasanya tempat Anda
harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
pengguna mungkin tidak kembali).</dd>
</dl>
<p>Kebanyakan aplikasi harus mengimplementasikan setidaknya tiga metode ini untuk setiap fragmen, namun ada
beberapa metode callback lain yang juga harus Anda gunakan untuk menangani berbagai tahap
daur hidup fragmen. Semua metode callback daur hidup akan dibahas secara lebih detail, di bagian
tentang <a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>.</p>
<p>Ada juga beberapa subkelas yang mungkin ingin diperpanjang, sebagai ganti kelas basis {@link
android.app.Fragment}:</p>
<dl>
<dt>{@link android.app.DialogFragment}</dt>
<dd>Menampilkan dialog mengambang. Penggunaan kelas ini untuk membuat dialog merupakan alternatif yang baik dari
penggunaan metode helper dialog di kelas {@link android.app.Activity}, karena Anda bisa
menyatukan dialog fragmen ke dalam back-stack fragmen yang dikelola oleh aktivitas,
sehingga pengguna bisa kembali ke fragmen yang ditinggalkan.</dd>
<dt>{@link android.app.ListFragment}</dt>
<dd>Menampilkan daftar item yang dikelola oleh adaptor (seperti {@link
android.widget.SimpleCursorAdapter}), serupa dengan {@link android.app.ListActivity}. Menampilkan
beberapa metode pengelolaan daftar tampilan seperti callback {@link
android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} untuk
menangani kejadian klik.</dd>
<dt>{@link android.preference.PreferenceFragment}</dt>
<dd>Menampilkan hierarki objek {@link android.preference.Preference} sebagai daftar, serupa dengan
{@link android.preference.PreferenceActivity}. Hal ini berguna saat membuat aktivitas
"pengaturan" untuk aplikasi Anda.</dd>
</dl>
<h3 id="UI">Menambahkan antarmuka pengguna</h3>
<p>Fragmen biasanya digunakan sebagai bagian dari antarmuka pengguna aktivitas dan menyumbangkan
layoutnya sendiri ke aktivitas.</p>
<p>Untuk menyediakan layout fragmen, Anda harus mengimplementasikan metode callback {@link
android.app.Fragment#onCreateView onCreateView()}, yang dipanggil sistem Android
bila tiba saatnya fragmen menggambar layoutnya. Implementasi Anda atas metode ini harus mengembalikan
{@link android.view.View} yang menjadi akar layout fragmen.</p>
<p class="note"><strong>Catatan:</strong> Jika fragmen adalah subkelas {@link
android.app.ListFragment}, implementasi default akan mengembalikan {@link android.widget.ListView} dari
{@link android.app.Fragment#onCreateView onCreateView()}, sehingga Anda tidak perlu mengimplementasikannya.</p>
<p>Untuk mengembalikan layout dari {@link
android.app.Fragment#onCreateView onCreateView()}, Anda bisa memekarkannya dari <a href="{@docRoot}guide/topics/resources/layout-resource.html">sumber daya layout</a> yang didefinisikan di XML. Untuk
membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek
{@link android.view.LayoutInflater}.</p>
<p>Misalnya, ini adalah subkelas {@link android.app.Fragment} yang memuat layout dari file
{@code example_fragment.xml}:</p>
<pre>
public static class ExampleFragment extends Fragment {
&#64;Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
</pre>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Membuat layout</h3>
<p>Dalam contoh di atas, {@code R.layout.example_fragment} merupakan acuan ke sumber daya layout
bernama {@code example_fragment.xml} yang tersimpan dalam sumber daya aplikasi. Untuk informasi tentang cara
membuat layout di XML, lihat dokumentasi
<a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
</div>
</div>
<p>Parameter {@code container} yang diteruskan ke {@link android.app.Fragment#onCreateView
onCreateView()} adalah induk {@link android.view.ViewGroup} (dari layout aktivitas) tempat
layout fragmen
akan disisipkan. Parameter {@code savedInstanceState} adalah {@link android.os.Bundle} yang
menyediakan data tentang instance fragmen sebelumnya, jika fragmen dilanjutkan
(status pemulihan dibahas selengkapnya di bagian tentang <a href="#Lifecycle">Menangani
Daur Hidup Fragmen</a>).</p>
<p>Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan
tiga argumen:</p>
<ul>
<li>ID sumber daya layout yang ingin dimekarkan.</li>
<li>{@link android.view.ViewGroup} akan menjadi induk dari layout yang dimekarkan. {@code
container} perlu diteruskan agar sistem menerapkan parameter layout ke tampilan akar layout
yang dimekarkan, yang ditetapkan dalam tampilan induk yang akan dituju.</li>
<li>Boolean yang menunjukkan apakah layout akan dimekarkan harus ditempelkan pada {@link
android.view.ViewGroup} (parameter kedua) selama pemekaran. (Dalam hal ini, ini
salah karena sistem sudah memasukkan layout yang dimekarkan ke dalam {@code
container}&mdash;meneruskan benar akan membuat tampilan grup yang berlebihan dalam layout akhir.)</li>
</ul>
<p>Anda kini telah melihat cara membuat fragmen yang menyediakan layout. Berikutnya, Anda perlu menambahkan
fragmen ke aktivitas.</p>
<h3 id="Adding">Menambahkan fragmen ke aktivitas</h3>
<p>Biasanya, fragmen berkontribusi pada sebagian UI ke aktivitas host, yang ditanamkan sebagai
bagian dari hierarki tampilan keseluruhan aktivitas. Ada dua cara untuk menambahkan fragmen ke layout
aktivitas:</p>
<ul>
<li><b>Deklarasikan fragmen dalam file layout aktivitas.</b>
<p>Dalam hal ini, Anda bisa
menetapkan properti layout fragmen seakan-akan sebuah tampilan. Misalnya, berikut ini adalah file
layout untuk aktivitas dengan dua fragmen:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"&gt;
&lt;fragment android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;fragment android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>Atribut {@code android:name} dalam {@code &lt;fragment&gt;} menetapkan kelas {@link
android.app.Fragment} untuk dibuat instance-nya dalam layout.</p>
<p>Saat sistem membuat layout aktivitas, sistem membuat instance setiap fragmen sebagaimana yang ditetapkan dalam layout
dan memanggil metode {@link android.app.Fragment#onCreateView onCreateView()} masing-masing,
untuk mengambil setiap fragmen. Sistem akan menyisipkan {@link android.view.View} yang dikembalikan langsung oleh fragmen,
menggantikan elemen {@code &lt;fragment&gt;}.</p>
<div class="note">
<p><strong>Catatan:</strong> Setiap fragmen memerlukan identifier
unik yang bisa digunakan sistem untuk memulihkan fragmen jika aktivitas dimulai kembali (dan identifier yang bisa digunakan menangkap
fragmen untuk melakukan transaksi, seperti menghapusnya). Ada tiga cara untuk memberikan
ID bagi fragmen:</p>
<ul>
<li>Memberikan atribut {@code android:id} bersama ID unik.</li>
<li>Memberikan atribut {@code android:tag} bersama string unik.</li>
<li>Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID
tampilan kontainer.</li>
</ul>
</div>
</li>
<li><b>Atau, secara programatis tambahkan fragmen ke {@link android.view.ViewGroup} yang ada.</b>
<p>Kapan saja saat aktivitas berjalan, Anda bisa menambahkan fragmen ke layout aktivitas. Anda
cukup menetapkan {@link
android.view.ViewGroup} di tempat memasukkan fragmen.</p>
<p>Untuk membuat transaksi fragmen dalam aktivitas (seperti menambah, menghapus, atau mengganti
fragmen), Anda harus menggunakan API dari {@link android.app.FragmentTransaction}. Anda bisa mengambil instance
{@link android.app.FragmentTransaction} dari {@link android.app.Activity} seperti ini:</p>
<pre>
FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}
FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
</pre>
<p>Selanjutnya Anda bisa menambahkan fragmen menggunakan metode {@link
android.app.FragmentTransaction#add(int,Fragment) add()}, dengan menetapkan fragmen yang akan ditambahkan dan
tampilan tempat menyisipkannya. Misalnya:</p>
<pre>
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
</pre>
<p>Argumen pertama yang diteruskan ke {@link android.app.FragmentTransaction#add(int,Fragment) add()}
adalah {@link android.view.ViewGroup} tempat fragmen harus dimasukkan, yang ditetapkan oleh
ID sumber daya, dan parameter kedua merupakan fragmen yang akan ditambahkan.</p>
<p>Setelah membuat perubahan dengan
{@link android.app.FragmentTransaction}, Anda harus
memanggil {@link android.app.FragmentTransaction#commit} untuk menerapkan perubahan.</p>
</li>
</ul>
<h4 id="AddingWithoutUI">Menambahkan fragmen tanpa UI</h4>
<p>Contoh di atas menampilkan cara menambahkan fragmen ke aktivitas untuk menyediakan UI. Akan tetapi,
Anda juga bisa menggunakan fragmen untuk menyediakan perilaku latar belakang bagi aktivitas tanpa menampilkan UI
tambahan.</p>
<p>Untuk menambahkan fragmen tanpa UI, tambahkan fragmen dari aktivitas menggunakan {@link
android.app.FragmentTransaction#add(Fragment,String)} (dengan menyediakan string unik "tag" untuk fragmen
, bukan ID tampilan). Ini akan menambahkan fragmen, namun, karena tidak dikaitkan dengan tampilan
dalam layout aktivitas, ini tidak akan menerima panggilan ke {@link
android.app.Fragment#onCreateView onCreateView()}. Jadi Anda tidak perlu mengimplementasikan metode itu.</p>
<p>Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI&mdash;Anda juga bisa
menyediakan tag string untuk fragmen yang memiliki UI&mdash;namun jika fragmen tidak memiliki UI
, maka tag string adalah satu-satunya cara untuk mengidentifikasinya. Jika Anda ingin mendapatkan fragmen dari
aktivitas nantinya, Anda perlu menggunakan {@link android.app.FragmentManager#findFragmentByTag
findFragmentByTag()}.</p>
<p>Untuk contoh aktivitas yang menggunakan fragmen sebagai pekerja latar belakang, tanpa UI, lihat sampel {@code
FragmentRetainInstance.java}, yang disertakan dalam sampel SDK (tersedia melalui
Android SDK Manager) dan terletak di sistem Anda sebagai
<code>&lt;sdk_root&gt;/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java</code>.</p>
<h2 id="Managing">Mengelola Fragmen</h2>
<p>Untuk mengelola fragmen dalam aktivitas, Anda perlu menggunakan {@link android.app.FragmentManager}. Untuk
mendapatkannya, panggil {@link android.app.Activity#getFragmentManager()} dari aktivitas Anda.</p>
<p>Beberapa hal yang dapat Anda lakukan dengan {@link android.app.FragmentManager} antara lain:</p>
<ul>
<li>Dapatkan fragmen yang ada di aktivitas dengan {@link
android.app.FragmentManager#findFragmentById findFragmentById()} (untuk fragmen yang menyediakan UI dalam
layout aktivitas) atau {@link android.app.FragmentManager#findFragmentByTag
findFragmentByTag()} (untuk fragmen yang menyediakan atau tidak menyediakan UI).</li>
<li>Tarik fragmen dari back-stack, dengan {@link
android.app.FragmentManager#popBackStack()} (mensimulasikan perintah <em>Back</em> oleh pengguna).</li>
<li>Daftarkan listener untuk perubahan pada back-stack, dengan {@link
android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li>
</ul>
<p>Untuk informasi selengkapnya tentang metode ini dan hal lainnya, lihat dokumentasi kelas {@link
android.app.FragmentManager}.</p>
<p>Seperti yang ditunjukkan di bagian sebelumnya, Anda juga bisa menggunakan {@link android.app.FragmentManager}
untuk membuka {@link android.app.FragmentTransaction}, sehingga Anda bisa melakukan transaksi, seperti
menambah dan menghapus fragmen.</p>
<h2 id="Transactions">Melakukan Transaksi Fragmen</h2>
<p>Fitur menarik terkait penggunaan fragmen di aktivitas adalah kemampuan menambah, menghapus, mengganti,
dan melakukan tindakan lain dengannya, sebagai respons atas interaksi pengguna. Setiap set perubahan
yang Anda lakukan untuk aktivitas disebut transaksi dan Anda bisa melakukan transaksi menggunakan API di {@link
android.app.FragmentTransaction}. Anda juga bisa menyimpan setiap transaksi ke back-stack yang dikelola
aktivitas, sehingga pengguna bisa mengarah mundur melalui perubahan fragmen (mirip mengarah
mundur melalui aktivitas).</p>
<p>Anda bisa mengambil instance {@link android.app.FragmentTransaction} dari {@link
android.app.FragmentManager} seperti ini:</p>
<pre>
FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()};
FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
</pre>
<p>Setiap transaksi merupakan serangkaian perubahan yang ingin dilakukan pada waktu yang sama. Anda bisa
mengatur semua perubahan yang ingin dilakukan untuk transaksi mana saja menggunakan metode seperti {@link
android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()},
dan {@link android.app.FragmentTransaction#replace replace()}. Kemudian, untuk menerapkan transaksi
pada aktivitas, Anda harus memanggil {@link android.app.FragmentTransaction#commit()}.</p>
</dl>
<p>Akan tetapi, sebelum memanggil {@link
android.app.FragmentTransaction#commit()}, Anda mungkin perlu memanggil {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, untuk menambahkan transaksi
ke back-stack dari transaksi fragmen. Back-stack ini dikelola oleh aktivitas dan memungkinkan
pengguna kembali ke status fragmen sebelumnya, dengan menekan tombol <em>Back</em>.</p>
<p>Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan
status sebelumnya di back-stack:</p>
<pre>
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
</pre>
<p>Dalam contoh ini, {@code newFragment} menggantikan fragmen apa saja (jika ada) yang saat ini berada dalam
kontainer layout yang diidentifikasi oleh ID {@code R.id.fragment_container}. Dengan memanggil @link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, transaksi yang diganti
disimpan ke back-stack sehingga pengguna bisa membalikkan transaksi dan mengembalikan fragmen
sebelumnya dengan menekan tombol <em>Back</em>.</p>
<p>Jika Anda menambahkan beberapa perubahan pada transaksi (seperti {@link
android.app.FragmentTransaction#add add()} atau {@link android.app.FragmentTransaction#remove
remove()}) dan panggil {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, maka semua perubahan akan diterapkan
sebelum Anda memanggil {@link android.app.FragmentTransaction#commit commit()} akan ditambahkan ke
back-stack sebagai satu transaksi dan tombol <em>Back</em> akan membalikannya semua.</p>
<p>Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh,
kecuali:</p>
<ul>
<li>Anda harus memanggil {@link android.app.FragmentTransaction#commit()} paling akhir</li>
<li>Jika Anda menambahkan beberapa fragmen ke kontainer yang sama, maka
urutan penambahannya akan menentukan urutan munculnya dalam hierarki tampilan</li>
</ul>
<p>Jika Anda tidak memanggil {@link android.app.FragmentTransaction#addToBackStack(String)
addToBackStack()} saat melakukan transaksi yang menghapus fragmen, maka fragmen itu
akan dimusnahkan bila transaksi diikat dan pengguna tidak bisa mengarah kembali ke sana. Sedangkan, jika
Anda memanggil {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} saat
menghapus fragmen, maka fragmen itu akan <em>dihentikan</em> dan akan dilanjutkan jika pengguna mengarah
kembali.</p>
<p class="note"><strong>Tip:</strong> Untuk setiap transaksi fragmen, Anda bisa menerapkan animasi
transisi, dengan memanggil {@link android.app.FragmentTransaction#setTransition setTransition()} sebelum
mengikatnya.</p>
<p>Memanggil {@link android.app.FragmentTransaction#commit()} tidak akan langsung menjalankan
transaksi. Namun sebuah jadwal akan dibuat untuk dijalankan pada thread UI aktivitas (thread "utama")
begitu thread bisa melakukannya. Akan tetapi, jika perlu Anda bisa memanggil {@link
android.app.FragmentManager#executePendingTransactions()} dari thread UI untuk segera
mengeksekusi transaksi yang diserahkan oleh {@link android.app.FragmentTransaction#commit()}. Hal itu
biasanya tidak perlu kecuali jika transaksi merupakan dependensi bagi pekerjaan dalam thread lain.</p>
<p class="caution"><strong>Perhatian:</strong> Anda bisa mengikat transaksi menggunakan {@link
android.app.FragmentTransaction#commit commit()} hanya sebelum aktivitas <a href="{@docRoot}guide/components/activities.html#SavingActivityState">menyimpan
statusnya</a> (saat pengguna meninggalkan aktivitas). Jika Anda mencoba mengikatnya setelah itu,
eksepsi akan dilontarkan. Ini karena status setelah pengikatan bisa hilang jika aktivitas
perlu dipulihkan. Untuk situasi yang memperbolehkan Anda meniadakan pengikatan (commit), gunakan {@link
android.app.FragmentTransaction#commitAllowingStateLoss()}.</p>
<h2 id="CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</h2>
<p>Meskipun {@link android.app.Fragment} diimplementasikan sebagai objek yang tidak bergantung pada
{@link android.app.Activity} dan bisa digunakan dalam banyak aktivitas, instance tertentu
dari fragmen secara langsung terkait dengan aktivitas yang dimuatnya.</p>
<p>Khususnya, fragmen bisa mengakses instance {@link android.app.Activity} dengan {@link
android.app.Fragment#getActivity()} dan dengan mudah melakukan tugas-tugas seperti mencari tampilan dalam
layout aktivitas:</p>
<pre>
View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
</pre>
<p>Demikian pula, aktivitas Anda bisa memanggil metode di fragmen dengan meminta acuan ke
{@link android.app.Fragment} dari {@link android.app.FragmentManager}, menggunakan {@link
android.app.FragmentManager#findFragmentById findFragmentById()} atau {@link
android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. Misalnya:</p>
<pre>
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
</pre>
<h3 id="EventCallbacks">Membuat callback kejadian pada aktivitas</h3>
<p>Dalam beberapa kasus, Anda mungkin perlu fragmen untuk berbagi kejadian dengan aktivitas. Cara yang baik untuk melakukannya
adalah mendefinisikan antarmuka callback di dalam fragmen dan mengharuskan aktivitas host
mengimplementasikannya. Saat aktivitas menerima callback melalui antarmuka, aktivitas akan bisa berbagi informasi itu
dengan fragmen lain dalam layout jika perlu.</p>
<p>Misalnya, jika sebuah aplikasi berita memiliki dua fragmen dalam aktivitas&mdash;satu untuk menampilkan daftar
artikel (fragmen A) dan satu lagi untuk menampilkan artikel (fragmen B)&mdash;maka fragmen A harus
memberi tahu aktivitas bila item daftar dipilih sehingga aktivitas bisa memberi tahu fragmen B untuk menampilkan artikel. Dalam
hal ini, antarmuka {@code OnArticleSelectedListener} dideklarasikan di dalam fragmen A:</p>
<pre>
public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}
</pre>
<p>Selanjutnya aktivitas yang menjadi host fragmen akan mengimplementasikan antarmuka {@code OnArticleSelectedListener}
dan
mengesampingkan {@code onArticleSelected()} untuk memberi tahu fragmen B mengenai kejadian dari fragmen A. Untuk memastikan
bahwa aktivitas host mengimplementasikan antarmuka ini, metode callback fragmen A {@link
android.app.Fragment#onAttach onAttach()} (yang dipanggil sistem saat menambahkan
fragmen ke aktivitas) membuat instance {@code OnArticleSelectedListener} dengan
membuat {@link android.app.Activity} yang diteruskan ke {@link android.app.Fragment#onAttach
onAttach()}:</p>
<pre>
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
&#64;Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
...
}
</pre>
<p>Jika aktivitas belum mengimplementasikan antarmuka, maka fragmen akan melontarkan
{@link java.lang.ClassCastException}.
Jika berhasil, anggota {@code mListener} yang menyimpan acuan ke implementasi aktivitas
{@code OnArticleSelectedListener}, sehingga fragmen A bisa berbagi kejadian dengan aktivitas, dengan memanggil metode
yang didefinisikan oleh antarmuka {@code OnArticleSelectedListener}. Misalnya, jika fragmen A adalah
ekstensi dari {@link android.app.ListFragment}, maka setiap kali
pengguna mengklik item daftar, sistem akan memanggil {@link android.app.ListFragment#onListItemClick
onListItemClick()} di fragmen, yang selanjutnya memanggil {@code onArticleSelected()} untuk berbagi
kejadian dengan aktivitas:</p>
<pre>
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
&#64;Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}
</pre>
<p>Parameter {@code id} yang diteruskan ke {@link
android.app.ListFragment#onListItemClick onListItemClick()} merupakan ID baris dari item yang diklik,
yang digunakan aktivitas (atau fragmen lain) untuk mengambil artikel dari {@link
android.content.ContentProvider} aplikasi.</p>
<p><!--To see a complete implementation of this kind of callback interface, see the <a
href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->Informasi selengkapnya tentang
menggunakan penyedia konten tersedia dalam dokumen <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<h3 id="ActionBar">Menambahkan item ke Action-Bar</h3>
<p>Fragmen Anda bisa menyumbangkan item menu ke <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menu Opsi</a> aktivitas (dan, konsekuensinya, <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>) dengan mengimplementasikan
{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Agar
metode ini bisa menerima panggilan, Anda harus memanggil {@link
android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} selama {@link
android.app.Fragment#onCreate(Bundle) onCreate()}, untuk menunjukkan bahwa fragmen
ingin menambahkan item ke Menu Opsi (jika tidak, fragmen tidak akan menerima panggilan ke
{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p>
<p>Setiap item yang selanjutnya Anda tambahkan ke Menu Opsi dari fragmen akan ditambahkan ke item menu
yang ada. Fragmen juga menerima callback ke {@link
android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} bila item menu
dipilih.</p>
<p>Anda juga bisa mendaftarkan tampilan dalam layout fragmen untuk menyediakan menu konteks dengan memanggil {@link
android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. Bila pengguna
membuka menu konteks, fragmen akan menerima panggilan ke {@link
android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo)
onCreateContextMenu()}. Bila pengguna memilih item, fragmen akan menerima panggilan ke @link
android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
<p class="note"><strong>Catatan:</strong> Walaupun fragmen menerima callback pada item yang dipilih
untuk setiap item menu yang ditambahkannya, aktivitaslah yang pertama kali menerima masing-masing callback saat pengguna
memilih item menu. Jika implementasi aktivitas dari callback bila-item-dipilih,
tidak menangani item yang dipilih, maka kejadian akan diteruskan ke callback fragmen. Ini berlaku
untuk Menu Opsi dan menu konteks.</p>
<p>Untuk informasi selengkapnya tentang menu, lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html">Menu</a> dan <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>.</p>
<h2 id="Lifecycle">Menangani Daur Hidup Fragmen</h2>
<div class="figure" style="width:350px">
<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 3.</strong> Efek daur hidup aktivitas pada daur hidup
fragmen.</p>
</div>
<p>Mengelola daur hidup fragmen mirip sekali dengan mengelola daur hidup aktivitas. Seperti
aktivitas, fragmen bisa berada dalam tiga status:</p>
<dl>
<dt><i>Dilanjutkan</i></dt>
<dd>Fragmen terlihat dalam aktivitas yang berjalan.</dd>
<dt><i>Dihentikan sementara</i></dt>
<dd>Aktivitas lain berada di latar depan dan memiliki fokus, namun aktivitas tempat fragmen berada
masih terlihat (aktivitas latar depan sebagian terlihat atau tidak menutupi
seluruh layar).</dd>
<dt><i>Dihentikan</i></dt>
<dd>Fragmen tidak terlihat. Aktivitas host telah dihentikan atau
fragmen telah dihapus dari aktivitas namun ditambahkan ke back-stack. Fragmen yang dihentikan
masih hidup (semua status dan informasi anggota masih disimpan oleh sistem). Akan tetapi, fragmen
tidak terlihat lagi oleh pengguna dan akan dimatikan jika aktivitas dimatikan.</dd>
</dl>
<p>Seperti halnya aktivitas, Anda bisa mempertahankan status fragmen menggunakan {@link
android.os.Bundle}, jika proses aktivitas dimatikan dan Anda harus memulihkan status
fragmen bila aktivitas dibuat kembali. Anda bisa menyimpan status selama callback {@link
android.app.Fragment#onSaveInstanceState onSaveInstanceState()} fragmen dan memulihkannya selama
{@link android.app.Fragment#onCreate onCreate()}, {@link
android.app.Fragment#onCreateView onCreateView()}, atau {@link
android.app.Fragment#onActivityCreated onActivityCreated()}. Untuk informasi selengkapnya tentang menyimpan
status, lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
.</p>
<p>Perbedaan paling signifikan dalam daur hidup antara aktivitas dan fragmen ada
pada cara penyimpanannya dalam back-stack masing-masing. Aktivitas ditempatkan ke back-stack aktivitas
yang dikelola oleh sistem saat dihentikan, secara default (sehingga pengguna bisa mengarah kembali
ke aktivitas dengan tombol <em>Back</em>, seperti yang dibahas dalam <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan Back-Stack</a>).
Akan tetapi, fragmen yang ditempatkan ke back-stack dikelola oleh aktivitas host hanya saat
Anda secara eksplisit meminta agar instance disimpan dengan memanggil {@link
android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} selama transaksi yang
menghapus fragmen.</p>
<p>Jika tidak, pengelolaan daur hidup fragmen mirip sekali dengan mengelola daur hidup
aktivitas. Jadi, praktik yang sama untuk <a href="{@docRoot}guide/components/activities.html#Lifecycle">mengelola daur hidup
aktivitas</a> juga berlaku untuk fragmen. Namun yang perlu juga Anda pahami adalah bagaimana hidup
aktivitas memengaruhi hidup fragmen.</p>
<p class="caution"><strong>Perhatian:</strong> Jika Anda memerlukan objek {@link android.content.Context}
dalam {@link android.app.Fragment}, Anda bisa memanggil {@link android.app.Fragment#getActivity()}.
Akan tetapi, berhati-hatilah memanggil {@link android.app.Fragment#getActivity()} hanya bila fragmen
terkait dengan aktivitas. Bila fragmen belum terkait, atau terlepas selama akhir daur
hidupnya, {@link android.app.Fragment#getActivity()} akan kembali nol.</p>
<h3 id="CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</h3>
<p>Daur hidup aktivitas tempat fragmen berada akan memengaruhi langsung siklus hidup
fragmen sedemikian rupa sehingga setiap callback daur hidup aktivitas menghasilkan callback yang sama untuk masing-masing
fragmen. Misalnya, bila aktivitas menerima {@link android.app.Activity#onPause}, masing-masing
fragmen dalam aktivitas akan menerima {@link android.app.Fragment#onPause}.</p>
<p>Namun fragmen memiliki beberapa callback daur hidup ekstra, yang menangani interaksi
unik dengan aktivitas untuk melakukan tindakan seperti membangun dan memusnahkan UI fragmen. Metode callback
tambahan ini adalah:</p>
<dl>
<dt>{@link android.app.Fragment#onAttach onAttach()}</dt>
<dd>Dipanggil bila fragmen telah dikaitkan dengan aktivitas ({@link
android.app.Activity} diteruskan di sini).</dd>
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
<dd>Dipanggil untuk membuat hierarki tampilan yang dikaitkan dengan fragmen.</dd>
<dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt>
<dd>Dipanggil bila metode {@link android.app.Activity#onCreate
onCreate()} aktivitas telah dikembalikan.</dd>
<dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt>
<dd>Dipanggil bila hierarki tampilan yang terkait dengan fragmen dihapus.</dd>
<dt>{@link android.app.Fragment#onDetach onDetach()}</dt>
<dd>Dipanggil bila fragmen diputuskan dari aktivitas.</dd>
</dl>
<p>Aliran daur hidup fragmen, karena dipengaruhi oleh aktivitas host-nya, diilustrasikan oleh
gambar 3. Dalam gambar ini, Anda bisa melihat bagaimana setiap status aktivitas menentukan
metode callback mana yang mungkin diterima fragmen. Misalnya, saat aktivitas menerima call back {@link
android.app.Activity#onCreate onCreate()}, fragmen dalam aktivitas akan menerima tidak lebih
dari callback {@link android.app.Fragment#onActivityCreated onActivityCreated()}.</p>
<p>Setelah status aktivitas diteruskan kembali, Anda bisa bebas menambah dan menghapus fragmen untuk
aktivitas tersebut. Sehingga, hanya saat aktivitas berada dalam status dilanjutkan, daur hidup fragmen bisa
berubah secara independen.</p>
<p>Akan tetapi, saat aktivitas meninggalkan status dilanjutkan, fragmen akan kembali didorong
melalui daur hidupnya oleh aktivitas.</p>
<h2 id="Example">Contoh</h2>
<p>Untuk merangkum semua yang telah dibahas dalam dokumen ini, berikut ini contoh aktivitas
yang menggunakan dua fragmen untuk membuat layout dua panel. Aktivitas di bawah ini menyertakan satu fragmen untuk
menampilkan daftar putar Shakespeare dan fragmen lainnya menampilkan rangkuman pemutaran bila dipilih dari
daftar. Aktivitas ini juga menunjukkan cara menyediakan konfigurasi fragmen berbeda,
berdasarkan konfigurasi layar.</p>
<p class="note"><strong>Catatan:</strong> Kode sumber lengkap untuk aktivitas ini tersedia di
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
FragmentLayout.java}</a>.</p>
<p>Aktivitas utama akan menerapkan layout seperti biasa, selama {@link
android.app.Activity#onCreate onCreate()}:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main}
<p>Layout yang diterapkan adalah {@code fragment_layout.xml}:</p>
{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
<p>Dengan layout ini, sistem akan membuat instance {@code TitlesFragment} (yang mencantumkan
judul) segera setelah aktivitas memuat layout, sementara {@link android.widget.FrameLayout}
(lokasi penempatan fragmen untuk menampilkan rangkuman pemutaran) menempati ruang di sisi kanan
layar, namun pada awalnya masih kosong. Seperti yang akan Anda lihat di bawah ini, sampai pengguna memilih item
dari daftar maka fragmen baru akan ditempatkan ke dalam {@link android.widget.FrameLayout}.</p>
<p>Akan tetapi, tidak semua konfigurasi layar cukup lebar untuk menampilkan
daftar putar dan rangkuman secara berdampingan. Sehingga, layout di atas hanya digunakan untuk konfigurasi
layar mendatar, dengan menyimpannya di {@code res/layout-land/fragment_layout.xml}.</p>
<p>Sehingga, bila layar berada dalam orientasi tegak, sistem akan menerapkan layout berikut, yang
tersimpan di {@code res/layout/fragment_layout.xml}:</p>
{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
<p>Layout ini hanya menyertakan {@code TitlesFragment}. Ini artinya saat perangkat berada dalam
orientasi tegak, hanya judul daftar putar yang terlihat. Jadi, saat pengguna mengklik item
daftar dalam konfigurasi ini, aplikasi akan memulai aktivitas baru untuk menampilkan rangkuman,
sebagai ganti pemuatan fragmen kedua.</p>
<p>Berikutnya, Anda bisa melihat bagaimana hal ini dilakukan dalam kelas fragmen. Pertama adalah {@code
TitlesFragment}, yang menampilkan judul daftar putar Shakespeare. Fragmen ini membuat ekstensi {@link
android.app.ListFragment} dan mengandalkannya itu untuk menangani sebagian besar pekerjaan tampilan daftar.</p>
<p>Saat Anda memeriksa kode ini, perhatikan bahwa ada dua kemungkinan perilaku saat pengguna mengklik
item daftar: bergantung pada layout mana yang aktif, bisa membuat dan menampilkan fragmen
baru untuk menampilkan detail dalam aktivitas yang sama (menambahkan fragmen ke {@link
android.widget.FrameLayout}), atau memulai aktivitas baru (tempat fragmen ditampilkan).</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles}
<p>Fragmen kedua, {@code DetailsFragment} menampilkan rangkuman pemutaran untuk item yang dipilih dari
daftar dari {@code TitlesFragment}:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}
<p>Ingatlah dari kelas {@code TitlesFragment}, bahwa, jika pengguna mengklik item daftar dan
layout saat ini <em>tidak</em> menyertakan tampilan {@code R.id.details} (yaitu tempat
{@code DetailsFragment} berada), maka aplikasi memulai aktivitas {@code DetailsActivity}
untuk menampilkan konten item.</p>
<p>Berikut ini adalah {@code DetailsActivity}, yang hanya menanamkan {@code DetailsFragment} untuk menampilkan rangkuman pemutaran
yang dipilih saat layar dalam orientasi tegak:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
details_activity}
<p>Perhatikan bahwa aktivitas ini selesai sendiri jika konfigurasi mendatar, sehingga aktivitas utama
bisa mengambil alih dan menampilkan {@code DetailsFragment} bersama {@code TitlesFragment}.
Ini bisa terjadi jika pengguna memulai {@code DetailsActivity} saat dalam orientasi tegak, namun kemudian
memutarnya menjadi mendatar (yang akan memulai lagi aktivitas saat ini).</p>
<p>Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini),
lihat aplikasi contoh Demo API yang tersedia di <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">
ApiDemos</a> (bisa diunduh dari <a href="{@docRoot}resources/samples/get.html">Komponen contoh SDK</a>).</p>

View File

@@ -1,480 +0,0 @@
page.title=Dasar-Dasar Aplikasi
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Components">Komponen Aplikasi</a>
<ol>
<li><a href="#ActivatingComponents">Mengaktifkan komponen</a></li>
</ol>
</li>
<li><a href="#Manifest">File Manifes</a>
<ol>
<li><a href="#DeclaringComponents">Mendeklarasikan komponen</a></li>
<li><a href="#DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</a></li>
</ol>
</li>
<li><a href="#Resources">Sumber Daya Aplikasi</a></li>
</ol>
</div>
</div>
<p>Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi
kode Anda&mdash;bersama data dan file sumber daya &mdash;ke dalam APK: <i>Paket Android</i>,
yaitu file arsip berekstensi {@code .apk}. Satu file APK berisi semua konten
aplikasi Android dan merupakan file yang digunakan perangkat berbasis Android untuk menginstal aplikasi.</p>
<p>Setelah diinstal di perangkat, setiap aplikasi Android tinggal di sandbox keamanannya sendiri: </p>
<ul>
<li>Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap
aplikasi adalah pengguna berbeda.</li>
<li>Secara default, sistem menetapkan ID pengguna Linux unik kepada setiap aplikasi (ID ini hanya
digunakan oleh sistem dan tidak diketahui aplikasi). Sistem menetapkan izin
bagi semua file dalam aplikasi sehingga hanya ID pengguna yang diizinkan yang bisa mengaksesnya. </li>
<li>Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari
aplikasi lainnya.</li>
<li>Secara default, setiap aplikasi berjalan dalam proses Linux-nya sendiri. Android memulai proses
bila ada komponen aplikasi yang perlu dijalankan, kemudian mematikan proses bila tidak lagi diperlukan
atau bila sistem harus memulihkan memori untuk digunakan aplikasi lain.</li>
</ul>
<p>Dengan cara ini, sistem Android mengimplementasikan <em>prinsip privilese minim</em>. Ini berarti,
secara default aplikasi hanya memiliki akses ke komponen yang diperlukannya untuk melakukan pekerjaannya dan
tidak lebih dari itu. Hal ini menghasilkan lingkungan yang sangat aman sehingga aplikasi tidak bisa mengakses bagian
sistem bila tidak diberi izin.</p>
<p>Akan tetapi, ada beberapa cara bagi aplikasi untuk berbagi data dengan aplikasi lain dan bagi aplikasi
untuk mengakses layanan sistem:</p>
<ul>
<li>Dua aplikasi bisa diatur untuk menggunakan ID pengguna Linux yang sama,
dalam hal ini keduanya bisa saling mengakses file masing-masing. Untuk menghemat sumber daya sistem, aplikasi dengan ID
pengguna yang sama juga bisa diatur agar berjalan dalam proses Linux yang sama dan menggunakan VM yang sama (
aplikasi juga harus ditandatangani dengan sertifikat yang sama).</li>
<li>Aplikasi bisa meminta izin akses ke data perangkat seperti kontak
pengguna, pesan SMS, penyimpanan lepas-pasang (kartu SD), kamera, Bluetooth, dan lainnya. Semua
izin aplikasi harus diberikan oleh pengguna saat menginstal.</li>
</ul>
<p>Hal tersebut mencakup dasar-dasar tentang cara aplikasi Android berada di dalam sistem. Bagian dokumen
selanjutnya memperkenalkan Anda pada:</p>
<ul>
<li>Komponen kerangka kerja inti yang mendefinisikan aplikasi.</li>
<li>File manifes tempat Anda mendeklarasikan komponen dan fitur yang diperlukan perangkat
untuk aplikasi.</li>
<li>Sumber daya yang terpisah dari kode aplikasi dan memungkinkan
aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.</li>
</ul>
<h2 id="Components">Komponen Aplikasi</h2>
<p>Komponen aplikasi adalah blok pembangun penting dari aplikasi Android.
Setiap komponen merupakan titik berbeda yang digunakan sistem untuk memasuki aplikasi. Tidak semua komponen
merupakan titik masuk sebenarnya bagi pengguna dan sebagian saling bergantung, namun masing-masing komponen tersedia
sebagai kesatuan sendiri dan memainkan peran tertentu&mdash;masing-masing merupakan
blok pembangun unik yang mendefinisikan perilaku aplikasi secara keseluruhan.</p>
<p>Ada empat macam tipe komponen aplikasi. Setiap tipe memiliki kegunaan tersendiri
dan daur hidupnya sendiri yang mendefinisikan cara komponen dibuat dan dimusnahkan.</p>
<p>Berikut ini empat tipe komponen aplikasi:</p>
<dl>
<dt><b>Aktivitas</b></dt>
<dd>Sebuah <i>aktivitas</i> mewakili satu layar dengan antarmuka pengguna. Misalnya,
aplikasi email mungkin memiliki satu aktivitas yang menampilkan daftar email
baru, aktivitas lain untuk menulis email, dan aktivitas satunya lagi untuk membaca email. Walaupun
semua aktivitas bekerja sama untuk membentuk pengalaman pengguna yang kohesif dalam aplikasi email,
masing-masing tidak saling bergantung. Karenanya, aplikasi berbeda bisa memulai
salah satu aktivitas ini (jika aplikasi email mengizinkannya). Misalnya, aplikasi kamera bisa memulai
aktivitas dalam aplikasi email yang membuat email baru agar pengguna bisa berbagi gambar.
<p>Aktivitas diimplementasikan sebagai subkelas {@link android.app.Activity} dan Anda bisa mengetahui selengkapnya
tentang hal ini dalam panduan pengembang <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
.</p>
</dd>
<dt><b>Layanan</b></dt>
<dd>Sebuah <i>layanan</i> adalah komponen yang berjalan di latar belakang untuk melakukan
operasi yang berjalan lama atau untuk melakukan pekerjaan bagi proses jarak jauh. Layanan
tidak menyediakan antarmuka pengguna. Misalnya, sebuah layanan bisa memutar musik di latar belakang sementara
pengguna berada dalam aplikasi lain, atau layanan bisa menarik data lewat jaringan tanpa
memblokir interaksi pengguna dengan aktivitas. Komponen lain, seperti aktivitas, bisa memulai
layanan dan membiarkannya berjalan atau mengikat layanan untuk berinteraksi dengannya.
<p>Layanan diimplementasikan sebagai subkelas {@link android.app.Service} dan Anda bisa mengetahui selengkapnya
tentang hal ini dalam panduan
pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
</dd>
<dt><b>Penyedia konten</b></dt>
<dd>Sebuah <i>penyedia konten</i> mengelola seperangkat data-bersama aplikasi. Anda bisa menyimpan data
dalam sistem file, database SQLite, di web, atau lokasi penyimpanan permanen lainnya
yang bisa diakses aplikasi. Melalui penyedia konten, aplikasi lain bisa melakukan query atau bahkan
memodifikasi data (jika penyedia konten mengizinkannya). Misalnya, sistem Android menyediakan penyedia
konten yang mengelola informasi kontak pengguna. Karenanya, setiap aplikasi
dengan izin yang sesuai bisa melakukan query mengenai bagian dari penyedia konten (seperti {@link
android.provider.ContactsContract.Data}) untuk membaca dan menulis informasi tentang orang tertentu.
<p>Penyedia konten juga berguna untuk membaca dan menulis data privat ke aplikasi Anda
dan tidak dibagikan. Misalnya, aplikasi contoh <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> menggunakan
penyedia konten untuk menyimpan catatan.</p>
<p>Penyedia konten diimplementasikan sebagai subkelas {@link android.content.ContentProvider}
dan harus mengimplementasikan seperangkat standar API yang memungkinkan aplikasi
lain melakukan transaksi. Untuk informasi selengkapnya, lihat panduan pengembang
<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
</dd>
<dt><b>Penerima siaran</b></dt>
<dd>Sebuah <i>penerima siaran</i> adalah komponen yang merespons pengumuman siaran dalam lingkup
sistem. Banyak siaran yang berasal dari sistem&mdash;misalnya, siaran yang mengumumkan bahwa
layar telah dimatikan, baterai lemah, atau gambar telah direkam.
Aplikasi juga bisa memulai siaran&mdash;misalnya untuk menginformasikan ke
aplikasi lain bahwa sebagian data telah diunduh ke perangkat dan bisa digunakan aplikasi lain tersebut. Walaupun penerima
siaran tidak menampilkan antarmuka pengguna, penerima bisa <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">membuat pemberitahuan baris status</a>
untuk memberi tahu pengguna kapan kejadian siaran dilakukan. Meskipun penerima siaran umumnya cuma menjadi
"gerbang" untuk komponen lain dan dimaksudkan untuk melakukan pekerjaan dalam jumlah sangat minim. Misalnya
, penerima siaran bisa menjalankan layanan untuk melakukan beberapa pekerjaan berdasarkan kejadian.
<p>Penerima siaran diimplementasikan sebagai subkelas {@link android.content.BroadcastReceiver}
dan setiap siaran dikirim sebagai objek {@link android.content.Intent}. Untuk informasi selengkapnya,
lihat kelas {@link android.content.BroadcastReceiver}.</p>
</dd>
</dl>
<p>Aspek unik dari desain sistem Android adalah aplikasi mana pun bisa memulai
komponen aplikasi lain. Misalnya, jika Anda menginginkan pengguna mengambil
foto dengan kamera perangkat, bisa saja aplikasi lain yang melakukannya dan aplikasi
Anda bisa menggunakannya, sebagai ganti mengembangkan aktivitas sendiri untuk mengambil foto. Anda tidak
harus menyatukan atau bahkan menautkan ke kode dari aplikasi kamera.
Sebagai gantinya, Anda tinggal memulai aktivitas di aplikasi kamera yang akan mengambil
foto. Bila selesai, foto akan dikembalikan ke aplikasi sehingga Anda bisa menggunakannya. Bagi pengguna,
kamera seakan menjadi bagian dari aplikasi Anda.</p>
<p>Saat sistem memulai komponen, sistem akan memulai proses untuk aplikasi itu (jika
belum berjalan) dan membuat instance kelas yang diperlukan untuk komponen. Misalnya, jika aplikasi Anda
memulai aktivitas dalam aplikasi kamera yang mengambil foto, aktivitas itu akan
berjalan dalam proses yang dimiliki oleh aplikasi kamera, bukan dalam proses aplikasi Anda.
Karenanya, tidak seperti aplikasi di sebagian besar sistem lain, aplikasi Android tidak memiliki titik
masuk tunggal (misalnya tidak ada fungsi {@code main()}).</p>
<p>Karena sistem menjalankan setiap aplikasi dalam proses terpisah dengan izin file yang
membatasi akses ke aplikasi lain, aplikasi Anda tidak bisa langsung mengaktifkan komponen dari aplikasi lain. Akan tetapi, sistem
Android bisa melakukannya. Jadi, untuk mengaktifkan
komponen dalam aplikasi lain, Anda harus mengirim pesan ke sistem yang menetapkan <em>intent</em> Anda untuk memulai
komponen tertentu. Selanjutnya sistem akan mengaktifkan komponen untuk Anda.</p>
<h3 id="ActivatingComponents">Mengaktifkan Komponen</h3>
<p>Tiga dari empat tipe komponen&mdash;aktivitas, layanan, dan
penerima siaran&mdash;diaktifkan oleh pesan asinkron yang disebut <em>intent</em>.
Intent saling mengikat setiap komponen saat runtime (Anda bisa menganggapnya
sebagai pembawa pesan yang meminta tindakan dari komponen lain), baik komponen itu milik aplikasi Anda
atau milik aplikasi lain.</p>
<p>Intent dibuat dengan objek {@link android.content.Intent}, yang mendefinisikan pesan untuk
mengaktifkan komponen tertentu atau komponen <em>tipe</em> komponen tertentu&mdash;masing-masing intent
bisa eksplisit atau implisit.</p>
<p>Untuk aktivitas dan layanan, intent mendefinisikan tindakan yang akan dilakukan (misalnya, untuk "melihat" atau
"mengirim" sesuatu) dan mungkin menetapkan URI data untuk ditindaklanjuti (salah satu hal yang mungkin perlu diketahui
oleh komponen yang akan dimulai). Misalnya, intent mungkin menyampaikan permintaan suatu
aktivitas untuk menampilkan gambar atau membuka halaman web. Dalam beberapa kasus, Anda bisa memulai
aktivitas untuk menerima hasil, dalam hal ini, aktivitas juga akan mengembalikan hasil
dalam {@link android.content.Intent} (misalnya Anda bisa mengeluarkan intent agar
pengguna bisa memilih kontak pribadi dan memintanya dikembalikan kepada Anda&mdash;intent yang dikembalikan menyertakan URI yang
menunjuk ke kontak yang dipilih).</p>
<p>Untuk penerima siaran, intent hanya mendefinisikan
pengumuman yang sedang disiarkan (misalnya, siaran untuk menunjukkan baterai perangkat hampir habis
hanya menyertakan string tindakan yang menunjukkan "baterai hampir habis").</p>
<p>Tipe komponen lainnya dan penyedia konten, tidak diaktifkan oleh intent. Melainkan
diaktifkan saat ditargetkan oleh permintaan dari {@link android.content.ContentResolver}. Resolver
konten menangani semua transaksi langsung dengan penyedia konten sehingga komponen yang melakukan
transaksi dengan penyedia tidak perlu dan sebagai gantinya memanggil metode pada objek {@link
android.content.ContentResolver}. Ini membuat lapisan abstraksi antara penyedia
konten dan komponen yang meminta informasi (demi keamanan).</p>
<p>Ada beberapa metode terpisah untuk mengaktifkan masing-masing tipe komponen:</p>
<ul>
<li>Anda bisa memulai aktivitas (atau memberinya pekerjaan baru) dengan
meneruskan {@link android.content.Intent} ke {@link android.content.Context#startActivity
startActivity()} atau {@link android.app.Activity#startActivityForResult startActivityForResult()}
(bila Anda ingin aktivitas mengembalikan hasil).</li>
<li>Anda bisa memulai layanan (atau memberikan instruksi baru ke layanan yang sedang berlangsung) dengan
meneruskan {@link android.content.Intent} ke {@link android.content.Context#startService
startService()}. Atau Anda bisa mengikat ke layanan dengan meneruskan {@link android.content.Intent} ke
{@link android.content.Context#bindService bindService()}.</li>
<li>Anda bisa memulai siaran dengan meneruskan {@link android.content.Intent} ke metode seperti
{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, atau {@link
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
<li>Anda bisa melakukan query ke penyedia konten dengan memanggil {@link
android.content.ContentProvider#query query()} pada {@link android.content.ContentResolver}.</li>
</ul>
<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
Intent</a>. Informasi selengkapnya tentang mengaktifkan komponen
tertentu juga tersedia dalam dokumen berikut: <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>, <a href="{@docRoot}guide/components/services.html">Layanan</a>, {@link
android.content.BroadcastReceiver} dan <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<h2 id="Manifest">File Manifes</h2>
<p>Sebelum sistem Android bisa memulai komponen aplikasi, sistem harus mengetahui
keberadaan komponen dengan membaca file {@code AndroidManifest.xml} aplikasi (file
"manifes"). Aplikasi Anda harus mendeklarasikan semua komponennya dalam file ini, yang harus menjadi akar
dari direktori proyek aplikasi.</p>
<p>Manifes melakukan banyak hal selain mendeklarasikan komponen aplikasi,
seperti:</p>
<ul>
<li>Mengidentifikasi izin pengguna yang diperlukan aplikasi, seperti akses Internet atau
akses-baca ke kontak pengguna.</li>
<li>Mendeklarasikan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a>
minimum yang diperlukan aplikasi, berdasarkan API yang digunakan aplikasi.</li>
<li>Mendeklarasikan fitur perangkat keras dan perangkat lunak yang diperlukan aplikasi, seperti kamera,
layanan Bluetooth, atau layar multisentuh.</li>
<li>Pustaka API aplikasi perlu ditautkan (selain
API kerangka kerja Android), seperti pustaka
<a href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps.</a></li>
<li>Dan lainnya</li>
</ul>
<h3 id="DeclaringComponents">Mendeklarasikan komponen</h3>
<p>Tugas utama manifes adalah menginformasikan komponen aplikasi pada sistem. Misalnya,
file manifes bisa mendeklarasikan aktivitas sebagai berikut: </p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest ... &gt;
&lt;application android:icon="@drawable/app_icon.png" ... &gt;
&lt;activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... &gt;
&lt;/activity&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>Dalam elemen <code><a
href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
, atribut {@code android:icon} menunjuk ke sumber daya untuk ikon yang mengidentifikasi
aplikasi.</p>
<p>Dalam elemen <code><a
href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
atribut {@code android:name} menetapkan nama kelas yang sepenuhnya memenuhi syarat subkelas {@link
android.app.Activity} dan atribut {@code android:label} menetapkan string yang akan
digunakan sebagai label yang terlihat oleh pengguna untuk aktivitas tersebut.</p>
<p>Anda harus mendeklarasikan semua komponen aplikasi dengan cara ini:</p>
<ul>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> untuk
aktivitas</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code> untuk
layanan</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code> untuk
penerima siaran</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> untuk
penyedia konten</li>
</ul>
<p>Aktivitas, layanan, dan penyedia konten yang Anda sertakan dalam kode sumber, namun tidak
dideklarasikan dalam manifes, tidak akan terlihat pada sistem dan, akibatnya, tidak pernah bisa berjalan. Akan tetapi,
penerima siaran
bisa dideklarasikan dalam manifes atau dibuat secara dinamis dalam kode (sebagai objek
{@link android.content.BroadcastReceiver}) dan didaftarkan pada sistem dengan memanggil
{@link android.content.Context#registerReceiver registerReceiver()}.</p>
<p>Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda,
lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">File AndroidManifest.xml</a>. </p>
<h3 id="DeclaringComponentCapabilities">Mendeklarasikan kemampuan komponen</h3>
<p>Seperti telah dibahas di atas, dalam <a href="#ActivatingComponents">Mengaktifkan Komponen</a>, Anda bisa menggunakan
{@link android.content.Intent} untuk memulai aktivitas, layanan, dan penerima siaran. Anda bisa
melakukannya dengan menamai komponen sasaran secara eksplisit (menggunakan nama kelas komponen) dalam intent. Akan tetapi,
kemampuan intent sebenarnya ada pada konsep <em>intent implisit</em>. Intent implisit
cuma menjelaskan tipe tindakan yang akan dilakukan (dan, secara opsional, data tempat Anda ingin
melakukan tindakan) dan memungkinkan sistem untuk menemukan komponen pada perangkat yang bisa melakukan
tindakan tersebut dan memulainya. Jika ada banyak komponen yang bisa melakukan tindakan yang dijelaskan oleh intent,
maka pengguna bisa memilih komponen yang akan digunakan.</p>
<p>Cara sistem mengidentifikasi komponen yang bisa merespons intent adalah dengan membandingkan
intent yang diterima dengan <i>filter intent</i> yang disediakan dalam file manifes aplikasi lainnya pada
perangkat.</p>
<p>Bila mendeklarasikan aktivitas dalam manifes aplikasi, secara opsional Anda bisa menyertakan
filter intent yang mendeklarasikan kemampuan aktivitas agar bisa merespons intent dari
aplikasi lain. Anda bisa mendeklarasikan filter intent untuk komponen dengan
menambahkan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> sebagai anak elemen deklarasi komponen.</p>
<p>Misalnya, jika Anda telah membangun aplikasi email dengan aktivitas untuk menulis email baru, Anda bisa
mendeklarasikan filter intent untuk merespons intent "kirim" (untuk mengirim email baru) seperti ini:</p>
<pre>
&lt;manifest ... >
...
&lt;application ... &gt;
&lt;activity android:name="com.example.project.ComposeEmailActivity">
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND" />
&lt;data android:type="*/*" />
&lt;category android:name="android.intent.category.DEFAULT" />
&lt;/intent-filter>
&lt;/activity>
&lt;/application&gt;
&lt;/manifest>
</pre>
<p>Kemudian, jika aplikasi lain membuat intent dengan tindakan {@link
android.content.Intent#ACTION_SEND} dan meneruskannya ke {@link android.app.Activity#startActivity
startActivity()}, sistem bisa memulai aktivitas Anda agar pengguna bisa menulis draf dan mengirim
email.</p>
<p>Untuk informasi selengkapnya tentang membuat filter intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
</p>
<h3 id="DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</h3>
<p>Ada berbagai macam perangkat yang didukung oleh Android dan tidak
semuanya menyediakan fitur dan kemampuan yang sama. Agar aplikasi Anda tidak dihapus pada perangkat yang tidak memiliki
fitur yang diperlukan aplikasi, Anda harus jelas mendefinisikan profil mengenai
tipe perangkat yang didukung aplikasi dengan mendeklarasikan kebutuhan perangkat dan perangkat lunak dalam file
manifes. Kebanyakan deklarasi ini hanya bersifat informasi dan sistem tidak
membacanya, namun layanan eksternal seperti Google Play akan membacanya untuk menyediakan
penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.</p>
<p>Misalnya, jika aplikasi memerlukan kamera dan menggunakan API yang disediakan dalam Android 2.1 (<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7)
, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:</p>
<pre>
&lt;manifest ... >
&lt;uses-feature android:name="android.hardware.camera.any"
android:required="true" />
&lt;uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
...
&lt;/manifest>
</pre>
<p>Sekarang, perangkat yang <em>tidak</em> memiliki kamera dan menggunakan
Android versi <em>lebih rendah</em> dari 2.1 tidak bisa menginstal aplikasi Anda dari Google Play.</p>
<p>Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak
<em>mengharuskannya</em>. Dalam hal itu, aplikasi Anda harus mengatur atribut <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
ke {@code "false"} dan memeriksa saat runtime apakah
perangkat memiliki kamera dan menonaktifkan setiap fitur kamera yang sesuai.</p>
<p>Informasi selengkapnya tentang cara mengelola kompatibilitas aplikasi dengan
perangkat yang berbeda disediakan dalam dokumen
<a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>.</p>
<h2 id="Resources">Sumber Daya Aplikasi</h2>
<p>Aplikasi Android tidak hanya terdiri dari kode&mdash;Aplikasi memerlukan sumber daya yang
terpisah dari kode sumber, seperti gambar, file audio, dan apa saja yang berkaitan dengan
presentasi visual dari aplikasi. Misalnya, Anda harus mendefinisikan animasi, menu, gaya, warna,
dan layout antarmuka pengguna aktivitas dengan file XML. Penggunaan sumber daya aplikasi
mempermudah pembaruan berbagai karakteristik aplikasi Anda tanpa memodifikasi kode dan&mdash;dengan menyediakan
seperangkat sumber daya alternatif&mdash;memungkinkan Anda mengoptimalkan aplikasi untuk berbagai konfigurasi
perangkat berbeda (seperti bahasa dan ukuran layar yang berbeda).</p>
<p>Untuk setiap sumber daya yang Anda sertakan dalam proyek Android, alat bawaan SDK akan mendefinisikan ID integer
unik, yang bisa Anda gunakan untuk mengacu sumber daya dari kode aplikasi atau dari sumber daya lainnya yang
didefinisikan dalam XML. Misalnya, jika aplikasi berisi file gambar bernama {@code
logo.png} (disimpan dalam direktori {@code res/drawable/}), alat SDK akan menghasilkan ID sumber daya
bernama {@code R.drawable.logo}, yang bisa Anda gunakan untuk mengacu gambar dan memasukkannya dalam
antarmuka pengguna.</p>
<p>Salah satu aspek paling penting dari penyediaan sumber daya yang terpisah dari
kode sumber adalah kemampuan Anda menyediakan sumber daya alternatif untuk konfigurasi perangkat
yang berbeda. Misalnya, dengan mendefinisikan string UI dalam XML, Anda bisa menerjemahkan string ke dalam
bahasa lain dan menyimpan string itu dalam file terpisah. Kemudian, berdasarkan <em>qualifier</em>
bahasa yang ditambahkan ke nama direktori sumber daya (seperti {@code res/values-fr/} untuk nilai
string Prancis) dan pengaturan bahasa pengguna, sistem Android akan menerapkan string bahasa yang sesuai
untuk UI Anda.</p>
<p>Android mendukung banyak <em>qualifier</em> berbeda untuk sumber daya alternatif Anda. Qualifier
adalah string pendek yang Anda sertakan dalam nama direktori sumber
daya untuk mendefinisikan konfigurasi perangkat yang harus digunakan sumber daya tersebut. Contoh lainnya,
Anda harus sering membuat layout berbeda untuk aktivitas, bergantung pada
orientasi layar dan ukuran perangkat. Misalnya, saat layar perangkat dalam orientasi
tegak, Anda mungkin ingin layout tombolnya vertikal, tetapi saat layar dalam orientasi
mendatar, tombolnya harus sejajar horizontal. Untuk mengubah layout
sesuai orientasi, Anda bisa mendefinisikan dua layout berbeda dan menerapkan qualifier yang
tepat untuk setiap nama direktori layout. Kemudian, sistem secara otomatis menerapkan
layout yang tepat sesuai dengan orientasi perangkat saat ini.</p>
<p>Untuk informasi selengkapnya tentang berbagai jenis sumber daya yang bisa disertakan dalam aplikasi dan cara
membuat sumber daya alternatif untuk konfigurasi perangkat berbeda, bacalah <a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a>.</p>
<div class="next-docs">
<div class="col-6">
<h2 class="norule">Teruskan membaca tentang:</h2>
<dl>
<dt><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
</dt>
<dd>Informasi tentang cara menggunakan API {@link android.content.Intent} untuk
mengaktifkan komponen aplikasi, seperti aktivitas dan layanan, dan cara menyediakan komponen aplikasi
untuk digunakan oleh aplikasi lain.</dd>
<dt><a href="{@docRoot}guide/components/activities.html">Aktivitas</a></dt>
<dd>Informasi tentang cara membuat instance kelas {@link android.app.Activity},
yang menyediakan layar tersendiri dalam aplikasi bersama antarmuka pengguna.</dd>
<dt><a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a></dt>
<dd>Informasi tentang cara aplikasi Android disusun untuk memisahkan sumber daya aplikasi dari
kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk
konfigurasi perangkat tertentu.
</dd>
</dl>
</div>
<div class="col-6">
<h2 class="norule">Anda juga mungkin tertarik dengan:</h2>
<dl>
<dt><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a></dt>
<dd>Informasi tentang cara kerja Android pada berbagai tipe perangkat dan
pengenalan mengenai cara mengoptimalkan aplikasi untuk setiap perangkat atau membatasi ketersediaan aplikasi Anda untuk
perangkat berbeda.</dd>
<dt><a href="{@docRoot}guide/topics/security/permissions.html">Izin Sistem</a></dt>
<dd>Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin
yang mengharuskan persetujuan pengguna agar aplikasi dapat menggunakan API tersebut.</dd>
</dl>
</div>
</div>

View File

@@ -1,57 +0,0 @@
page.title=Komponen Aplikasi
page.landing=true
page.landing.intro=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
page.metaDescription=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
page.landing.image=images/develop/app_components.png
page.image=images/develop/app_components.png
@jd:body
<div class="landing-docs">
<div class="col-6">
<h3>Artikel Blog</h3>
<a href="http://android-developers.blogspot.com/2012/05/using-dialogfragments.html">
<h4>Menggunakan DialogFragments</h4>
<p>Dalam posting ini, saya akan menunjukkan cara menggunakan DialogFragments dengan pustaka dukungan v4 (untuk kompatibilitas mundur pada perangkat sebelum Honeycomb) untuk menunjukkan dialog edit sederhana dan mengembalikan hasil ke Aktivitas pemanggil menggunakan antarmuka.</p>
</a>
<a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">
<h4>Fragmen Untuk Semua</h4>
<p>Hari ini kami telah merilis pustaka statis yang memperlihatkan API Fragment yang sama (serta LoaderManager baru dan beberapa kelas lain) agar aplikasi yang kompatibel dengan Android 1.6 atau yang lebih baru bisa menggunakan fragmen untuk membuat antarmuka pengguna yang kompatibel dengan tablet. </p>
</a>
<a href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html">
<h4>Multithreading untuk Kinerja</h4>
<p>Praktik yang baik dalam membuat aplikasi yang responsif adalah memastikan thread UI utama Anda
melakukan pekerjaan minimum. Setiap tugas yang berpotensi lama dan dapat membuat aplikasi mogok harus
ditangani di thread berbeda.</p>
</a>
</div>
<div class="col-6">
<h3>Pelatihan</h3>
<a href="http://developer.android.com/training/basics/activity-lifecycle/index.html">
<h4>Mengelola Daur Hidup Aktivitas</h4>
<p>Bagian ini menjelaskan pentingnya metode callback daur hidup yang diterima setiap instance Aktivitas
dan cara menggunakannya sehingga aktivitas Anda melakukan yang diharapkan pengguna dan tidak menghabiskan sumber daya sistem
saat aktivitas tidak membutuhkannya.</p>
</a>
<a href="http://developer.android.com/training/basics/fragments/index.html">
<h4>Membangun UI Dinamis dengan Fragmen</h4>
<p>Bagian ini menunjukkan kepada Anda cara membuat pengalaman pengguna yang dinamis dengan fragmen dan mengoptimalkan
pengalaman pengguna aplikasi Anda dengan berbagai ukuran layar, sekaligus terus mendukung
perangkat yang menjalankan versi sebelumnya, sesudah versi Android 1.6.</p>
</a>
<a href="http://developer.android.com/training/sharing/index.html">
<h4>Berbagi Konten</h4>
<p>Bagian ini membahas beberapa cara umum untuk mengirim dan menerima konten antar
aplikasi menggunakan API Intent dan objek ActionProvider.</p>
</a>
</div>
</div>

View File

@@ -1,899 +0,0 @@
page.title=Intent dan Filter Intent
page.tags="IntentFilter"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Types">Tipe Intent</a></li>
<li><a href="#Building">Membangun Intent</a>
<ol>
<li><a href="#ExampleExplicit">Contoh intent eksplisit</a></li>
<li><a href="#ExampleSend">Contoh intent implisit</a></li>
<li><a href="#ForceChooser">Memaksakan pemilih aplikasi</a></li>
</ol>
</li>
<li><a href="#Receiving">Menerima Intent Implisit</a>
<ol>
<li><a href="#ExampleFilters">Contoh filter</a></li>
</ol>
</li>
<li><a href="#PendingIntent">Menggunakan Intent Tertunda</a></li>
<li><a href="#Resolution">Resolusi Intent</a>
<ol>
<li><a href="#ActionTest">Pengujian tindakan</a></li>
<li><a href="#CategoryTest">Pengujian kategori</a></li>
<li><a href="#DataTest">Pengujian data</a></li>
<li><a href="#imatch">Pencocokan intent</a></li>
</ol>
</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/intents/index.html">Berinteraksi dengan Aplikasi Lain</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Berbagi Konten</a></li>
</ol>
</div>
</div>
<p>{@link android.content.Intent} merupakan objek pertukaran pesan yang bisa Anda gunakan untuk meminta tindakan
dari <a href="{@docRoot}guide/components/fundamentals.html#Components">komponen aplikasi</a> lain.
Walaupun intent memudahkan komunikasi antarkomponen dalam beberapa cara, ada tiga
kasus-penggunaan dasar:</p>
<ul>
<li><b>Untuk memulai aktivitas:</b>
<p>{@link android.app.Activity} menyatakan satu layar dalam aplikasi. Anda bisa memulai instance
baru {@link android.app.Activity} dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#startActivity startActivity()}. {@link android.content.Intent}
menjelaskan aktivitas yang akan dimulai dan membawa data yang diperlukan.</p>
<p>Jika Anda ingin menerima hasil dari aktivitas bila selesai,
panggil {@link android.app.Activity#startActivityForResult
startActivityForResult()}. Aktivitas Anda menerima hasil
sebagai objek {@link android.content.Intent} terpisah dalam callback {@link
android.app.Activity#onActivityResult onActivityResult()} aktivitas Anda.
Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>.</p></li>
<li><b>Untuk memulai layanan:</b>
<p>{@link android.app.Service} adalah komponen yang melakukan operasi di latar belakang
tanpa antarmuka pengguna. Anda bisa memulai layanan untuk melakukan operasi satu-kali
(misalnya mengunduh file) dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#startService startService()}. {@link android.content.Intent}
menjelaskan layanan yang akan dimulai dan membawa data yang diperlukan.</p>
<p>Jika layanan didesain dengan antarmuka pengguna klien-server, Anda bisa mengikat ke layanan
dari komponen lain dengan meneruskan {@link android.content.Intent} ke {@link
android.content.Context#bindService bindService()}</code>. Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p></li>
<li><b>Untuk mengirim siaran:</b>
<p>Siaran adalah pesan yang bisa diterima aplikasi apa saja. Sistem menyampaikan beragam siaran
untuk kejadian sistem, misalnya saat sistem booting atau saat perangkat mulai mengisi daya.
Anda bisa mengirim siaran ke aplikasi lain dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()},
{@link android.content.Context#sendOrderedBroadcast(Intent, String)
sendOrderedBroadcast()}, atau {@link
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
</li>
</ul>
<h2 id="Types">Tipe Intent</h2>
<p>Ada dua tipe intent:</p>
<ul>
<li><b>Intent eksplisit</b> menetapkan komponen untuk memulai dengan nama (
nama kelas yang sepenuhnya memenuhi syarat). Anda biasanya akan menggunakan intent eksplisit untuk memulai sebuah komponen
dalam aplikasi sendiri, karena Anda mengetahui nama kelas dari aktivitas atau layanan yang ingin dimulai.
Misalnya, mulai aktivitas baru sebagai respons terhadap tindakan pengguna atau mulai layanan untuk mengunduh
file di latar belakang.</li>
<li><b>Intent implisit</b> tidak menetapkan komponen tertentu, melainkan mendeklarasikan tindakan umum
yang dilakukan, yang memungkinkan komponen aplikasi lain untuk menanganinya. Misalnya, jika Anda ingin
menampilkan sebuah lokasi di peta pada pengguna, Anda bisa menggunakan intent implisit untuk meminta aplikasi lain
yang mampu untuk menunjukkan lokasi yang telah ditetapkan di peta tersebut.</li>
</ul>
<p>Saat Anda membuat intent eksplisit untuk memulai aktivitas atau layanan, sistem akan segera
memulai komponen aplikasi yang telah ditetapkan dalam objek {@link android.content.Intent}.</p>
<div class="figure" style="width:446px">
<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi yang menggambarkan cara intent implisit
disampaikan melalui sistem untuk memulai aktivitas lain: <b>[1]</b> <em>Aktivitas A</em> membuat sebuah
{@link android.content.Intent} dengan keterangan tindakan dan meneruskannya ke {@link
android.content.Context#startActivity startActivity()}. <b>[2]</b> Sistem Android akan mencari semua
aplikasi untuk filter intent yang cocok dengan intent tersebut. Bila cocok, <b>[3]</b> sistem akan
memulai aktivitas mencocokkan (<em>Aktivitas B</em>) dengan memanggil metode {@link
android.app.Activity#onCreate onCreate()} dan meneruskannya ke {@link android.content.Intent}.
</p>
</div>
<p>Bila Anda membuat intent implisit, sistem Android akan menemukan komponen yang sesuai untuk memulai
dengan membandingkan konten intent dengan <em>filter intent</em> yang dideklarasikan dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> aplikasi lain di
perangkat. Jika intent cocok dengan filter intent, sistem akan memulai komponen tersebut dan mengiriminya
objek {@link android.content.Intent}. Jika banyak filter intent yang kompatibel, sistem
menampilkan dialog sehingga pengguna bisa memilih aplikasi yang akan digunakan.</p>
<p>Filter intent adalah ekspresi dalam file manifes aplikasi yang
menetapkan tipe intent yang akan diterima
komponen. Misalnya, dengan mendeklarasikan intent filter untuk aktivitas,
Anda akan memungkinkan aplikasi lain untuk langsung memulai aktivitas Anda dengan intent tertentu.
Demikian pula, jika Anda <em>tidak</em> mendeklarasikan filter intent untuk suatu aktivitas, maka aktivitas tersebut hanya bisa dimulai
dengan intent eksplisit.</p>
<p class="caution"><strong>Perhatian:</strong> Untuk memastikan aplikasi Anda aman, selalu gunakan intent
eksplisit saat memulai {@link android.app.Service} dan jangan
mendeklarasikan filter intent untuk layanan. Menggunakan intent implisit untuk memulai layanan akan menimbulkan
bahaya keamanan karena Anda tidak bisa memastikan layanan apa yang akan merespons intent,
dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dari Android 5.0 (API level 21), sistem
melontarkan eksepsi jika Anda memanggil {@link android.content.Context#bindService bindService()}
dengan intent implisit.</p>
<h2 id="Building">Membangun Intent</h2>
<p>Objek {@link android.content.Intent} membawa informasi yang digunakan sistem Android
untuk menentukan komponen mana yang akan dimulai (misalnya nama persis dari suatu komponen atau kategori
komponen yang seharusnya menerima intent), ditambah informasi yang digunakan komponen penerima untuk
melakukan tindakan dengan benar (misalnya tindakan yang harus dilakukan dan data yang harus diolah).</p>
<p>Informasi utama yang dimuat dalam {@link android.content.Intent} adalah sebagai berikut:</p>
<dl>
<dt><b>Nama komponen</b></dt>
<dd>Nama komponen yang akan dimulai.
<p>Ini opsional, namun merupakan bagian informasi penting yang membuat intent
menjadi <b>eksplisit</b>, yaitu intent harus dikirim hanya ke komponen aplikasi
yang didefinisikan oleh nama komponen. Tanpa nama komponen, intent menjadi <b>implisit</b> dan
sistem akan memutuskan komponen mana yang harus menerima intent berdasarkan informasi intent lain
(misalnya tindakan, data, dan kategori&mdash;yang dijelaskan di bawah ini). Jadi jika Anda ingin memulai komponen
tertentu dalam aplikasi, Anda harus menetapkan nama komponen tersebut.</p>
<p class="note"><strong>Catatan:</strong> Saat memulai {@link android.app.Service}, Anda harus
<strong>selalu menetapkan nama komponen</strong>. Jika tidak, maka Anda tidak bisa memastikan layanan apa
yang akan merespons intent tersebut, dan pengguna tidak bisa melihat layanan mana yang dimulai.</p>
<p>Bidang {@link android.content.Intent} ini adalah objek
{@link android.content.ComponentName}, yang bisa Anda tetapkan menggunakan
nama kelas yang sepenuhnya memenuhi syarat dari komponen target, termasuk nama paket aplikasi. Misalnya,
{@code com.example.ExampleActivity}. Anda bisa mengatur nama komponen dengan {@link
android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass
setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()}, atau dengan konstruktor
{@link android.content.Intent}.</p>
</dd>
<p><dt><b>Tindakan</b></dt>
<dd>String yang menetapkan tindakan generik untuk dilakukan (misalnya <em>lihat</em> atau <em>pilih</em>).
<p>Dalam hal intent siaran, ini adalah tindakan yang terjadi dan dilaporkan.
Tindakan ini sangat menentukan bagaimana keseluruhan intent disusun&mdash;terutama
apa yang dimuat dalam data dan ekstra.
<p>Anda bisa menetapkan tindakan sendiri yang akan digunakan oleh intent dalam aplikasi Anda (atau digunakan oleh aplikasi
lain untuk memanggil komponen dalam aplikasi Anda), namun Anda harus menggunakan konstanta tindakan
yang didefinisikan oleh kelas {@link android.content.Intent} atau kelas kerangka kerja lain. Berikut ini adalah beberapa
tindakan umum untuk memulai sebuah aktivitas:</p>
<dl>
<dt>{@link android.content.Intent#ACTION_VIEW}</dt>
<dd>Gunakan tindakan ini dalam intent dengan {@link
android.content.Context#startActivity startActivity()} saat Anda memiliki beberapa informasi yang
bisa ditampilkan aktivitas kepada pengguna, misalnya foto yang bisa dilihat dalam aplikasi galeri, atau alamat
yang bisa dilihat dalam aplikasi peta.</dd>
<dt>{@link android.content.Intent#ACTION_SEND}</dt>
<dd>Juga dikenal dengan intent "berbagi", Anda harus menggunakannya dalam intent dengan {@link
android.content.Context#startActivity startActivity()} bila Anda memiliki data yang bisa digunakan pengguna untuk
berbagi melalui aplikasi lain, misalnya aplikasi email atau aplikasi jaringan sosial.</dd>
</dl>
<p>Lihat referensi kelas {@link android.content.Intent} untuk konstanta
selengkapnya yang mendefinisikan tindakan generik. Tindakan lain yang didefinisikan
di tempat lain dalam kerangka kerja Android, misalnya dalam {@link android.provider.Settings} untuk tindakan
yang membuka layar tertentu dalam aplikasi Settings di sistem.</p>
<p>Anda bisa menetapkan tindakan untuk sebuah intent dengan {@link android.content.Intent#setAction
setAction()} atau dengan konstruktor {@link android.content.Intent}.</p>
<p>Jika mendefinisikan tindakan Anda sendiri, pastikan untuk memasukkan nama paket aplikasi Anda
sebagai awalan. Misalnya:</p>
<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre>
</dd>
<dt><b>Data</b></dt>
<dd>URI (objek {@link android.net.Uri}) yang mengacu data untuk diolah dan/atau
tipe MIME dari data tersebut. Tipe data yang disediakan umumnya didikte oleh tindakan intent.
Misalnya, jika tindakan merupakan {@link android.content.Intent#ACTION_EDIT}, data harus berisi
URI dari dokumen untuk diedit.
<p>Saat membuat intent,
seringkali tipe data (tipe MIME-nya) selain URI perlu ditetapkan.
Misalnya, aktivitas yang mampu menampilkan gambar mungkin tidak mampu
memutar file audio, walaupun format URI mungkin serupa.
Jadi menetapkan tipe MIME data Anda akan membantu sistem
Android menemukan komponen terbaik untuk diterima intent.
Akan tetapi, tipe MIME seringkali bisa diambil dari URI&mdash;terutama saat datanya merupakan URI
{@code content:}, yang menunjukkan data tersebut berada di perangkat dan dikontrol oleh
{@link android.content.ContentProvider}, yang membuat data tipe MIME terlihat di sistem.</p>
<p>Untuk mengatur data URI saja, panggil {@link android.content.Intent#setData setData()}.
Untuk mengatur tipe MIME saja, panggil {@link android.content.Intent#setType setType()}. Jika perlu, Anda
bisa mengatur keduanya secara eksplisit dengan {@link
android.content.Intent#setDataAndType setDataAndType()}.</p>
<p class="caution"><strong>Perhatian:</strong> Jika ingin mengatur tipe URI dan MIME,
<strong>jangan</strong> panggil {@link android.content.Intent#setData setData()} dan
{@link android.content.Intent#setType setType()} karena mereka saling menghapuskan nilai satu sama lain.
Selalu gunakan {@link android.content.Intent#setDataAndType setDataAndType()} untuk mengatur
tipe URI maupun MIME.</p>
</dd>
<p><dt><b>Kategori</b></dt>
<dd>String yang berisi informasi tambahan tentang jenis komponen
yang harus menangani intent. Keterangan kategori dalam jumlah berapa pun bisa
dimasukkan dalam intent, namun sebagian besar intent tidak memerlukan kategori.
Berikut ini adalah beberapa kategori umum:
<dl>
<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
<dd>Aktivitas target memungkinkannya dimulai oleh browser web untuk menampilkan data
yang diacu oleh tautan&mdash;misalnya gambar atau pesan e-mail.
</dd>
<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
<dd>Aktivitas tersebut adalah aktivitas awal dari sebuah tugas dan dicantumkan dalam
launcher aplikasi sistem.
</dd>
</dl>
<p>Lihat keterangan kelas {@link android.content.Intent} untuk mengetahui daftar lengkap
kategori.</p>
<p>Anda bisa menetapkan kategori dengan {@link android.content.Intent#addCategory addCategory()}.</p>
</dd>
</dl>
<p>Properti yang tercantum di atas (nama komponen, tindakan, data, dan kategori) menyatakan
karakteristik yang mendefinisikan intent. Dengan membaca properti ini, sistem Android
mampu memutuskan komponen aplikasi yang harus dimulainya.</p>
<p>Akan tetapi, intent bisa membawa informasi tambahan yang tidak memengaruhi
cara intent ditetapkan pada komponen aplikasi. Intent juga bisa menyediakan:</p>
<dl>
<dt><b>Ekstra</b></dt>
<dd>Pasangan nilai-kunci yang membawa informasi yang diperlukan untuk menghasilkan tindakan yang diminta.
Seperti halnya beberapa tindakan menggunakan jenis tertentu URI data, beberapa tindakan juga menggunakan ekstra tertentu.
<p>Anda bisa menambahkan data ekstra dengan beragam metode {@link android.content.Intent#putExtra putExtra()},
masing-masing menerima dua parameter: nama kunci dan nilainya.
Anda juga bisa membuat objek {@link android.os.Bundle} dengan semua data ekstra, kemudian memasukkan
{@link android.os.Bundle} dalam {@link android.content.Intent} dengan {@link
android.content.Intent#putExtras putExtras()}.</p>
<p>Misalnya, saat membuat intent yang akan dikirimkan bersama email
{@link android.content.Intent#ACTION_SEND}, Anda bisa menetapkan penerima "kepada" dengan kunci
{@link android.content.Intent#EXTRA_EMAIL}, dan menetapkan "subjek" dengan kunci
{@link android.content.Intent#EXTRA_SUBJECT}.</p>
<p>Kelas {@link android.content.Intent} menetapkan beberapa konstanta {@code EXTRA_*}
untuk tipe data standar. Jika Anda ingin mendeklarasikan kunci ekstra sendiri (untuk intent yang
diterima aplikasi Anda), pastikan untuk memasukkan nama paket aplikasi
sebagai awalan. Misalnya:</p>
<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre>
</dd>
<dt><b>Flag</b></dt>
<dd>Flag didefinisikan dalam kelas {@link android.content.Intent} yang berfungsi sebagai metadata untuk
intent. Flag menginstruksikan cara meluncurkan aktivitas (misalnya,
<a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> mana yang harus dimiliki suatu aktivitas
) dan cara memperlakukannya setelah diluncurkan (misalnya, apakah aktivitas tersebut masuk ke dalam daftar aktivitas
terbaru) pada sistem Android.
<p>Untuk informasi selengkapnya, lihat metode {@link android.content.Intent#setFlags setFlags()} .</p>
</dd>
</dl>
<h3 id="ExampleExplicit">Contoh intent eksplisit</h3>
<p>Intent eksplisit adalah intent yang Anda gunakan untuk meluncurkan komponen aplikasi tertentu, seperti
aktivitas tertentu atau layanan dalam aplikasi Anda. Untuk membuat intent eksplisit, definisikan
nama komponen untuk objek {@link android.content.Intent} &mdash;semua
properti intent lain bersifat opsional.</p>
<p>Misalnya, jika Anda ingin membangun layanan dalam aplikasi Anda, bernama {@code DownloadService},
yang didesain untuk mengunduh file dari web, Anda bisa memulainya dengan kode berikut ini:</p>
<pre>
// Executed in an Activity, so 'this' is the {@link android.content.Context}
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData({@link android.net.Uri#parse Uri.parse}(fileUrl));
startService(downloadIntent);
</pre>
<p>Konstruktor {@link android.content.Intent#Intent(Context,Class)}
menyediakan {@link android.content.Context} aplikasi dan
objek {@link java.lang.Class} pada komponen. Dengan demikian,
intent ini memulai secara eksplisit kelas {@code DownloadService} dalam aplikasi.</p>
<p>Untuk informasi selengkapnya tentang membangun dan memulai layanan, lihat panduan
<a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
<h3 id="ExampleSend">Contoh intent implisit</h3>
<p>Intent implisit menetapkan tindakan yang bisa memanggil aplikasi pada perangkat yang mampu
melakukan tindakan. Menggunakan intent implisit berguna bila aplikasi Anda tidak bisa melakukan
tindakan, namun aplikasi lain mungkin bisa melakukannya dan Anda ingin pengguna untuk memilih aplikasi mana yang ingin digunakan.</p>
<p>Misalnya, jika memiliki konten yang Anda ingin agar pengguna berbagi konten itu dengan orang lain, buatlah intent
dengan tindakan {@link android.content.Intent#ACTION_SEND}
dan tambahkan ekstra yang menetapkan konten yang akan dibagikan. Bila Anda memanggil
{@link android.content.Context#startActivity startActivity()} dengan intent tersebut, pengguna bisa
memilih aplikasi yang akan digunakan untuk berbagi konten.</p>
<p class="caution"><strong>Perhatian:</strong> Ada kemungkinan pengguna tidak memiliki <em>suatu</em>
aplikasi yang menangani intent implisit yang Anda kirimkan ke {@link android.content.Context#startActivity
startActivity()}. Jika itu terjadi, panggilan akan gagal dan aplikasi Anda akan crash. Untuk memeriksa
apakah aktivitas bisa menerima intent, panggil {@link android.content.Intent#resolveActivity
resolveActivity()} pada objek {@link android.content.Intent} Anda. Jika hasilnya bukan nol,
berarti setidaknya ada satu aplikasi yang bisa menangani intent tersebut dan aman untuk memanggil
{@link android.content.Context#startActivity startActivity()}. Jika hasilnya nol,
Anda tidak boleh menggunakan intent tersebut dan, jika memungkinkan, Anda harus menonaktifkan fitur yang mengeluarkan
intent tersebut.</p>
<pre>
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
</pre>
<p class="note"><strong>Catatan:</strong> Dalam hal ini, URI tidak digunakan, namun tipe data intent
dideklarasikan untuk menetapkan konten yang dibawa oleh ekstra.</p>
<p>Saat {@link android.content.Context#startActivity startActivity()} dipanggil, sistem akan
memeriksa semua aplikasi yang terinstal untuk menentukan aplikasi mana yang bisa menangani intent jenis ini (
intent dengan tindakan {@link android.content.Intent#ACTION_SEND} dan yang membawa data
"teks/polos"). Jika hanya ada satu aplikasi yang bisa menanganinya, aplikasi tersebut akan langsung terbuka dan diberi
intent tersebut. Jika banyak aktivitas menerima intent, sistem akan
menampilkan dialog sehingga pengguna bisa memilih aplikasi mana yang digunakan.</p>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/training/basics/intent-chooser.png" alt="">
<p class="img-caption"><strong>Gambar 2.</strong> Dialog pemilih.</p>
</div>
<h3 id="ForceChooser">Memaksakan pemilih aplikasi</h3>
<p>Bila ada lebih dari satu aplikasi yang merespons intent implisit Anda,
pengguna bisa memilih aplikasi mana yang digunakan dan membuat aplikasi tersebut pilihan default untuk
tindakan tersebut. Ini sangat membantu saat melakukan tindakan di mana pengguna
mungkin ingin menggunakan aplikasi yang sama untuk seterusnya, seperti saat membuka halaman web (pengguna
biasanya memilih hanya satu browser web).</p>
<p>Akan tetapi, jika ada banyak aplikasi yang bisa merespons intent tersebut dan pengguna mungkin ingin menggunakan aplikasi
yang berbeda untuk setiap kalinya, Anda harus menampilkan dialog pemilih secara eksplisit. Dialog pemilih akan meminta
pengguna memilih aplikasi yang akan digunakan untuk tindakan tertentu setiap kali (pengguna tidak bisa memilih aplikasi default untuk
tindakan tersebut). Misalnya, saat aplikasi Anda melakukan "berbagi" dengan tindakan {@link
android.content.Intent#ACTION_SEND}, pengguna mungkin ingin berbagi menggunakan aplikasi berbeda sesuai
dengan situasi mereka saat itu, jadi Anda harus selalu menggunakan dialog pemilih, seperti yang ditampilkan dalam gambar 2.</p>
<p>Untuk menampilkan pemilih, buatlah {@link android.content.Intent} menggunakan {@link
android.content.Intent#createChooser createChooser()} dan teruskan ke {@link
android.app.Activity#startActivity startActivity()}. Misalnya:</p>
<pre>
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
</pre>
<p>Ini menampilkan dialog dengan daftar aplikasi yang merespons intent yang diteruskan ke metode {@link
android.content.Intent#createChooser createChooser()} dan menggunakan teks yang disediakan sebagai
judul dialog.</p>
<h2 id="Receiving">Menerima Intent Implisit</h2>
<p>Untuk mengiklankan intent implisit yang bisa diterima aplikasi Anda, deklarasikan satu atau beberapa filter intent untuk
tiap komponen aplikasi dengan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> Anda.
Tiap filter intent menetapkan tipe intent yang diterimanya berdasarkan tindakan intent,
data, dan kategori. Sistem akan mengirim intent implisit ke komponen aplikasi Anda hanya jika
intent tersebut bisa diteruskan melalui salah satu filter intent.</p>
<p class="note"><strong>Catatan:</strong> Intent eksplisit selalu dikirimkan ke targetnya,
apa pun filter intent yang dideklarasikan komponen.</p>
<p>Komponen aplikasi harus mendeklarasikan filter terpisah untuk setiap pekerjaan unik yang bisa dilakukannya.
Misalnya, satu aktivitas dalam aplikasi galeri gambar bisa memiliki dua filter: satu filter
untuk melihat gambar, dan filter lainnya untuk mengedit gambar. Bila aktivitas dimulai,
aktivitas akan memeriksa {@link android.content.Intent} dan menentukan cara berperilaku berdasarkan informasi
dalam {@link android.content.Intent} (misalnya menampilkan kontrol editor atau tidak).</p>
<p>Tiap filter intent didefinisikan oleh elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
dalam file manifes aplikasi, yang tersarang dalam komponen aplikasi terkait (seperti
elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
). Di dalam <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>,
Anda bisa menetapkan tipe intent yang akan diterima dengan menggunakan salah satu atau beberapa
dari tiga elemen ini:</p>
<dl>
<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a></dt>
<dd>Mendeklarasikan tindakan intent yang diterima, dalam atribut {@code name}. Nilai
haruslah nilai string literal dari tindakan, bukan konstanta kelas.</dd>
<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a></dt>
<dd>Mendeklarasikan tipe data yang diterima, menggunakan salah satu atau beberapa atribut yang menetapkan beragam
aspek URI data (<code>scheme</code>, <code>host</code>, <code>port</code>,
<code>path</code>, dll.) dan tipe MIME.</dd>
<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a></dt>
<dd>Mendeklarasikan kategori intent yang diterima, dalam atribut {@code name}. Nilai
haruslah nilai string literal dari tindakan, bukan konstanta kelas.
<p class="note"><strong>Catatan:</strong> Untuk menerima intent implisit, Anda
<strong>harus menyertakan</strong> kategori
{@link android.content.Intent#CATEGORY_DEFAULT} dalam filter intent. Metode
{@link android.app.Activity#startActivity startActivity()}dan
{@link android.app.Activity#startActivityForResult startActivityForResult()} memperlakukan semua intent
seolah-olah mendeklarasikan kategori {@link android.content.Intent#CATEGORY_DEFAULT}.
Jika tidak mendeklarasikan kategori ini dalam filter intent Anda, tidak ada intent implisit yang ditetapkan untuk
aktivitas Anda.</p>
</dd>
</dl>
<p>Misalnya, ini adalah deklarasi aktivitas dengan filter intent yang diterima intent
{@link android.content.Intent#ACTION_SEND} bila tipe data berupa teks:</p>
<pre>
&lt;activity android:name="ShareActivity">
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="text/plain"/>
&lt;/intent-filter>
&lt;/activity>
</pre>
<p>Anda bisa membuat filter yang menyertakan lebih dari satu instance
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a>,
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>, atau
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a>.
Jika Anda melakukannya, Anda hanya perlu memastikan bahwa komponen bisa menangani semua kombinasi
elemen filter tersebut.</p>
<p>Bila ingin menangani beragam jenis intent, namun hanya dalam kombinasi
tindakan, data, dan tipe kategori tertentu, maka Anda harus membuat banyak filter intent.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Membatasi akses ke komponen</h2>
<p>Menggunakan filter intent bukanlah cara yang aman untuk mencegah aplikasi lain memulai
komponen Anda. Walaupun filter intent membatasi komponen agar hanya merespons
jenis intent implisit tertentu, aplikasi lain bisa saja memulai komponen aplikasi Anda
dengan menggunakan intent eksplisit jika pengembangnya menentukan nama komponen Anda.
Jika perlu <em>hanya aplikasi Anda sendiri</em> yang mampu memulai salah satu komponen,
atur atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#exported">{@code
exported}</a> ke {@code "false"} untuk komponen itu.
</p>
</div>
</div>
<p>Intent implisit diuji terhadap filter dengan membandingkan intent dengan masing-masing
dari ketiga elemen. Agar dikirim ke komponen, intent harus lolos ketiga pengujian tersebut.
Jika intent gagal dalam salah satu pengujian, sistem Android tidak akan mengirim intent ke
komponen. Akan tetapi, karena sebuah komponen dapat memiliki beberapa filter intent, intent yang tidak
lolos melalui salah satu filter komponen mungkin akan lolos di filter lain.
Informasi selengkapnya tentang cara sistem menetapkan intent disediakan dalam bagian di bawah ini
tentang <a href="#Resolution">Resolusi Intent</a>.</p>
<p class="caution"><strong>Perhatian:</strong> Untuk menghindari menjalankan
{@link android.app.Service} aplikasi yang berbeda secara tidak sengaja, selalu gunakan intent eksplisit untuk memulai layanan Anda sendiri dan jangan
deklarasikan filter intent untuk layanan Anda.</p>
<p class="note"><strong>Catatan:</strong>
Untuk semua aktivitas, Anda harus mendeklarasikan filter intent dalam file manifes.
Akan tetapi, filter untuk penerima siaran bisa didaftarkan secara dinamis dengan memanggil
{@link android.content.Context#registerReceiver(BroadcastReceiver, IntentFilter, String,
Handler) registerReceiver()}. Anda nanti bisa mencabut pendaftaran penerima dengan {@link
android.content.Context#unregisterReceiver unregisterReceiver()}. Dengan begitu aplikasi Anda
bisa mendengarkan siaran tertentu hanya selama periode waktu yang telah ditetapkan saat aplikasi Anda
berjalan.</p>
<h3 id="ExampleFilters">Contoh filter</h3>
<p>Untuk lebih memahami beberapa perilaku filter intent, lihatlah cuplikan berikut
dari file manifes aplikasi berbagi di jaringan sosial.</p>
<pre>
&lt;activity android:name="MainActivity">
&lt;!-- This activity is the main entry, should appear in app launcher -->
&lt;intent-filter>
&lt;action android:name="android.intent.action.MAIN" />
&lt;category android:name="android.intent.category.LAUNCHER" />
&lt;/intent-filter>
&lt;/activity>
&lt;activity android:name="ShareActivity">
&lt;!-- This activity handles "SEND" actions with text data -->
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="text/plain"/>
&lt;/intent-filter&gt;
&lt;!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.SEND"/>
&lt;action android:name="android.intent.action.SEND_MULTIPLE"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="application/vnd.google.panorama360+jpg"/>
&lt;data android:mimeType="image/*"/>
&lt;data android:mimeType="video/*"/>
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p>Aktivitas pertama, {@code MainActivity}, merupakan titik masuk utama aplikasi&mdash;aplikasi yang
terbuka saat pengguna meluncurkan aplikasi dengan ikon launcher:</p>
<ul>
<li>Tindakan {@link android.content.Intent#ACTION_MAIN}
menunjukkan ini adalah titik masuk utama dan tidak mengharapkan data intent apa pun.</li>
<li>Kategori {@link android.content.Intent#CATEGORY_LAUNCHER} menunjukjkan bahwa ikon
aktivitas ini harus ditempatkan dalam launcher aplikasi sistem. Jika elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
tidak menetapkan ikon dengan{@code icon}, maka sistem akan menggunakan ikon dari elemen
<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>.</li>
</ul>
<p>Keduanya harus dipasangkan bersama agar aktivitas muncul dalam launcher aplikasi.</p>
<p>Aktivitas kedua, {@code ShareActivity}, dimaksudkan untuk memudahkan berbagi teks dan konten
media. Walaupun pengguna mungkin memasuki aktivitas ini dengan mengarah ke aktivitas dari {@code MainActivity},
pengguna juga bisa memasukkan {@code ShareActivity} secara langsung dari aplikasi lain yang mengeluarkan intent
implisit yang cocok dengan salah satu dari kedua filter intent.</p>
<p class="note"><strong>Catatan:</strong> Tipe MIME,
<a href="https://developers.google.com/panorama/android/">{@code
application/vnd.google.panorama360+jpg}</a>, merupakan tipe data khusus yang menetapkan
foto panorama, yang bisa Anda tangani dengan API <a href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">panorama
Google</a>.</p>
<h2 id="PendingIntent">Menggunakan Intent Tertunda</h2>
<p>Objek {@link android.app.PendingIntent} merupakan pembungkus objek {@link
android.content.Intent}. Tujuan utama {@link android.app.PendingIntent}
adalah memberikan izin pada aplikasi asing
untuk menggunakan {@link android.content.Intent} yang termuat seolah-olah dieksekusi dari
proses aplikasi Anda sendiri.</p>
<p>Kasus penggunaan utama untuk intent tertunda antara lain:</p>
<ul>
<li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan</a>
({@link android.app.NotificationManager}
sistem Android akan mengeksekusi {@link android.content.Intent}) Anda.
<li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan
<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a>
(aplikasi layar Home mengeksekusi {@link android.content.Intent}).
<li>Mendeklarasikan intent untuk dieksekusi di waktu yang telah ditetapkan di masa mendatang
({@link android.app.AlarmManager} sistem Android akan mengeksekusi {@link android.content.Intent}).
</ul>
<p>Karena setiap objek {@link android.content.Intent} didesain untuk ditangani oleh tipe
tertentu dari komponen aplikasi (baik {@link android.app.Activity}, {@link android.app.Service}, maupun
{@link android.content.BroadcastReceiver}), jadi {@link android.app.PendingIntent} harus
dibuat dengan pertimbangan yang sama. Saat menggunakan intent tertunda, aplikasi Anda tidak akan
mengeksekusi intent dengan panggilan seperti {@link android.content.Context#startActivity
startActivity()}. Anda harus mendeklarasikan tipe komponen yang dimaksud saat membuat
{@link android.app.PendingIntent} dengan memanggil metode kreator masing-masing:</p>
<ul>
<li>{@link android.app.PendingIntent#getActivity PendingIntent.getActivity()} untuk
{@link android.content.Intent} yang memulai {@link android.app.Activity}.</li>
<li>{@link android.app.PendingIntent#getService PendingIntent.getService()} untuk
{@link android.content.Intent} yang memulai {@link android.app.Service}.</li>
<li>{@link android.app.PendingIntent#getBroadcast PendingIntent.getBroadcast()} untuk
{@link android.content.Intent} yang memulai {@link android.content.BroadcastReceiver}.</li>
</ul>
<p>Kecuali jika aplikasi Anda <em>menerima</em> intent tertunda dari aplikasi lain,
metode di atas untuk membuat {@link android.app.PendingIntent} menjadi satu-satunya metode
{@link android.app.PendingIntent} yang mungkin Anda butuhkan.</p>
<p>Tiap metode mengambil {@link android.content.Context} aplikasi saat itu,
{@link android.content.Intent} yang ingin Anda bungkus, dan satu atau beberapa flag yang menetapkan
cara penggunaan intent (misalnya apakah intent bisa digunakan lebih dari sekali).</p>
<p>Informasi selengkapnya tentang intent tertunda disediakan pada dokumentasi untuk setiap
kasus penggunaan yang bersangkutan, seperti dalam panduan API <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
dan <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a>.</p>
<h2 id="Resolution">Resolusi Intent</h2>
<p>Saat sistem menerima intent implisit yang memulai suatu aktivitas, sistem tersebut akan mencari
aktivitas terbaik untuk intent dengan membandingkan intent dengan filter intent berdasarkan tiga aspek:</p>
<ul>
<li>Tindakan intent
<li>Data intent (baik URI maupun tipe data)
<li>Kategori intent
</ul>
<p>Bagian berikut menjelaskan cara pencocokan intent dengan komponen yang sesuai
sehubungan dengan cara pendeklarasian filter intent dalam file manifes aplikasi.</p>
<h3 id="ActionTest">Pengujian tindakan</h3>
<p>Untuk menetapkan tindakan intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.EDIT" /&gt;
&lt;action android:name="android.intent.action.VIEW" /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Untuk melewati filter ini, tindakan yang ditetapkan dalam {@link android.content.Intent}
harus sesuai dengan salah satu tindakan yang tercantum dalam filter.</p>
<p>Jika filter tidak mencantumkan tindakan apa pun, maka tidak ada intent
yang dicocokkan, jadi semua intent gagal dalam pengujian. Akan tetapi, jika sebuah {@link android.content.Intent}
tidak menetapkan suatu tindakan, maka akan lolos pengujian (asalkan filter
berisi setidaknya satu tindakan).</p>
<h3 id="CategoryTest">Pengujian kategori</h3>
<p>Untuk menetapkan kategori intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;category android:name="android.intent.category.BROWSABLE" /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Agar intent bisa lolos pengujian kategori, setiap kategori dalam {@link android.content.Intent}
harus sesuai dengan kategori dalam filter. Kebalikannya tidak diperlukan&mdash;filter intent bisa
mendeklarasikan kategori lebih banyak daripada yang ditetapkan dalam {@link android.content.Intent} dan
{@link android.content.Intent} tetap akan lolos. Oleh karena itu, intent tanpa kategori harus
selalu lolos pengujian ini, kategori apa pun yang dideklarasikan dalam filter.</p>
<p class="note"><strong>Catatan:</strong>
Android secara otomatis menerapkan kategori {@link android.content.Intent#CATEGORY_DEFAULT}
untuk semua intent implisit yang diteruskan ke {@link
android.content.Context#startActivity startActivity()} dan {@link
android.app.Activity#startActivityForResult startActivityForResult()}.
Jadi jika ingin aktivitas Anda menerima intent implisit, aktivitas tersebut harus
menyertakan kategori untuk{@code "android.intent.category.DEFAULT"} dalam filter intent (seperti
yang ditampilkan dalam contoh{@code &lt;intent-filter&gt;} sebelumnya.</p>
<h3 id="DataTest">Pengujian data</h3>
<p>Untuk menetapkan data intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:mimeType="video/mpeg" android:scheme="http" ... /&gt;
&lt;data android:mimeType="audio/mpeg" android:scheme="http" ... /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Tiap elemen <code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
bisa menetapkan struktur URI dan tipe data (tipe media MIME). Ada atribut
terpisah &mdash; {@code scheme}, {@code host}, {@code port},
dan {@code path} &mdash; untuk setiap bagian URI:
</p>
<p style="margin-left: 2em">{@code &lt;scheme&gt;://&lt;host&gt;:&lt;port&gt;/&lt;path&gt;}</p>
<p>
Misalnya:
</p>
<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p>
<p>Dalam URI ini, skemanya adalah {@code content}, host-nya adalah {@code com.example.project},
port-nya adalah {@code 200}, dan path-nya adalah {@code folder/subfolder/etc}.
</p>
<p>Tiap atribut bersifat opsional dalam elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>,
namun ada dependensi linear:</p>
<ul>
<li>Jika skema tidak ditetapkan, host akan diabaikan.</li>
<li>Jika host tidak ditetapkan, port akan diabaikan.</li>
<li>Jika skema dan host tidak ditetapkan, path akan diabaikan.</li>
</ul>
<p>Bila URI dalam intent dibandingkan dengan spesifikasi URI dalam filter,
pembandingannya hanya dengan bagian URI yang disertakan dalam filter. Misalnya:</p>
<ul>
<li>Jika sebuah filter menetapkan hanya satu skema, semua URI dengan skema tersebut akan cocok
dengan filter.</li>
<li>Jika sebuah filter menetapkan satu skema dan satu otoritas namun tanpa path, semua URI
dengan skema dan otoritas yang sama akan lolos dari filter, apa pun path-nya.</li>
<li>Jika sebuah filter menetapkan satu skema, otoritas dan path, hanya URI dengan skema,
otoritas, dan path sama yang bisa lolos dari filter.</li>
</ul>
<p class="note"><strong>Catatan:</strong> Spesifikasi path bisa berisi
wildcard bintang (*) untuk hanya mencocokkan nama path secara parsial.</p>
<p>Pengujian data membandingkan URI maupun tipe MIME dalam intent dengan URI
dan tipe MIME yang ditetapkan dalam filter. Aturannya adalah sebagai berikut:
</p>
<ol type="a">
<li>Intent yang tidak berisi URI maupun tipe MIME hanya akan lolos
pengujian jika filter tersebut tidak menetapkan URI atau tipe MIME apa pun.</li>
<li>Intent yang berisi URI namun tidak berisi tipe MIME (baik secara eksplisit maupun tidak langsung dari
URI) hanya akan lolos pengujian jika URI-nya cocok dengan format URI filter
dan filternya juga tidak menetapkan tipe MIME.</li>
<li>Intent yang berisi tipe MIME namun tidak berisi URI hanya akan lolos pengujian
jika filter mencantumkan tipe MIME yang sama dan tidak menetapkan format URI.</li>
<li>Intent yang berisi URI maupun tipe MIME (baik secara eksplisit maupun tidak langsung dari
URI) hanya akan lolos pengujian bagian tipe MIME jika
tipe tersebut cocok dengan tipe yang dicantumkan dalam filter. Ini akan lolos pengujian bagian URI
jika URI-nya cocok dengan URI dalam filter atau memiliki {@code content:}
atau URI {@code file:} dan filter tidak menetapkan URI. Dengan kata lain,
komponen dianggap mendukung data {@code content:} dan {@code file:} jika
filternya <em>hanya</em> mencantumkan tipe MIME.</p></li>
</ol>
<p>
Aturan terakhir ini, aturan (d), mencerminkan harapan
bahwa komponen mampu mendapatkan data lokal dari file atau penyedia konten.
Oleh karena itu, filter mereka mencatumkan tipe data saja dan tidak secara eksplisit
harus menamai skema {@code content:} dan {@code file:}.
Ini adalah kasus umum. Elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
seperti berikut ini, misalnya, memberi tahu Android bahwa komponen bisa mengambil data gambar dari penyedia
konten dan menampilkannya:
</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:mimeType="image/*" /&gt;
...
&lt;/intent-filter&gt;</pre>
<p>
Karena sebagian besar data yang tersedia dikeluarkan oleh penyedia konten, filter yang
menetapkan tipe data namun bukan URI mungkin adalah yang paling umum.
</p>
<p>
Konfigurasi umum yang lain adalah filter dengan skema dan tipe data. Misalnya
, elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
seperti berikut ini akan memberi tahu Android bahwa
komponen bisa mengambil data video dari jaringan untuk melakukan tindakan:
</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:scheme="http" android:type="video/*" /&gt;
...
&lt;/intent-filter&gt;</pre>
<h3 id="imatch">Pencocokan intent</h3>
<p>Intent dicocokkan dengan filter intent selain untuk menemukan komponen
target yang akan diaktifkan, juga untuk menemukan sesuatu tentang rangkaian
komponen pada perangkat. Misalnya, aplikasi Home akan menempatkan launcher aplikasi
dengan mencari semua aktivitas dengan filter intent yang menetapkan tindakan
{@link android.content.Intent#ACTION_MAIN} dan
kategori {@link android.content.Intent#CATEGORY_LAUNCHER}.</p>
<p>Aplikasi Anda bisa menggunakan pencocokan intent dengan cara serupa.
{@link android.content.pm.PackageManager} memiliki seperangkat metode {@code query...()}
yang mengembalikan semua komponen yang bisa menerima intent tertentu, dan
serangkaian metode{@code resolve...()} serupa yang menentukan komponen
terbaik untuk merespons intent. Misalnya,
{@link android.content.pm.PackageManager#queryIntentActivities
queryIntentActivities()} akan mengembalikan daftar semua aktivitas yang bisa melakukan
intent yang diteruskan sebagai argumen, dan {@link
android.content.pm.PackageManager#queryIntentServices
queryIntentServices()} akan mengembalikan daftar layanan serupa.
Tidak ada metode yang akan mengaktifkan komponen; mereka hanya mencantumkan komponen yang
bisa merespons. Ada metode serupa,
{@link android.content.pm.PackageManager#queryBroadcastReceivers
queryBroadcastReceivers()}, untuk penerima siaran.
</p>

View File

@@ -1,494 +0,0 @@
page.title=Aktivitas
parent.title=Loader
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#summary">Rangkuman Loader API</a></li>
<li><a href="#app">Menggunakan Loader dalam Aplikasi</a>
<ol>
<li><a href="#requirements"></a></li>
<li><a href="#starting">Memulai Loader</a></li>
<li><a href="#restarting">Me-restart Loader</a></li>
<li><a href="#callback">Menggunakan Callback LoaderManager</a></li>
</ol>
</li>
<li><a href="#example">Contoh</a>
<ol>
<li><a href="#more_examples">Contoh Selengkapnya</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.LoaderManager}</li>
<li>{@link android.content.Loader}</li>
</ol>
<h2>Contoh-contoh terkait</h2>
<ol>
<li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
LoaderCursor</a></li>
<li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
LoaderThrottle</a></li>
</ol>
</div>
</div>
<p>Diperkenalkan di Android 3.0, loader memudahkan pemuatan data asinkron
dalam aktivitas atau fragmen. Loader memiliki karakteristik ini:</p>
<ul>
<li>Loader tersedia untuk setiap {@link android.app.Activity} dan {@link
android.app.Fragment}.</li>
<li>Loader menyediakan pemuatan data asinkron.</li>
<li>Loader memantau sumber data mereka dan memberikan hasil baru bila
konten berubah.</li>
<li>Loader secara otomatis menghubungkan kembali ke kursor loader lalu saat
dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang
datanya.</li>
</ul>
<h2 id="summary">Rangkuman Loader API</h2>
<p>Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan
loader pada aplikasi. Semuanya dirangkum dalam tabel ini:</p>
<table>
<tr>
<th>Kelas/Antarmuka</th>
<th>Keterangan</th>
</tr>
<tr>
<td>{@link android.app.LoaderManager}</td>
<td>Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau
{@link android.app.Fragment} untuk mengelola satu atau beberapa instance {@link
android.content.Loader}. Ini membantu aplikasi mengelola
operasi berjalan lebih lama bersamaan dengan daur hidup {@link android.app.Activity}
atau {@link android.app.Fragment}; penggunaan paling umumnya adalah dengan
{@link android.content.CursorLoader}, akan tetapi aplikasi bebas menulis loader-nya
sendiri untuk memuat tipe data lainnya.
<br />
<br />
Hanya ada satu {@link android.app.LoaderManager} per aktivitas atau fragmen. Namun {@link android.app.LoaderManager} bisa memiliki
beberapa loader.</td>
</tr>
<tr>
<td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
<td>Antarmuka callback untuk klien berinteraksi dengan {@link
android.app.LoaderManager}. Misalnya, Anda menggunakan metode callback {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
untuk membuat loader baru.</td>
</tr>
<tr>
<td>{@link android.content.Loader}</td>
<td>Kelas abstrak yang melakukan pemuatan data asinkron. Ini
adalah kelas dasar untuk loader. Biasanya Anda akan menggunakan {@link
android.content.CursorLoader}, namun Anda bisa menerapkan subkelas sendiri. Selagi
loader aktif, loader harus memantau sumber datanya dan memberikan hasil
baru bila konten berubah. </td>
</tr>
<tr>
<td>{@link android.content.AsyncTaskLoader}</td>
<td>Loader abstrak yang menyediakan {@link android.os.AsyncTask} untuk melakukan pekerjaan.</td>
</tr>
<tr>
<td>{@link android.content.CursorLoader}</td>
<td>Subkelas {@link android.content.AsyncTaskLoader} yang meng-query
{@link android.content.ContentResolver} dan mengembalikan {@link
android.database.Cursor}. Kelas ini mengimplementasikan protokol {@link
android.content.Loader} dengan cara standar untuk query kursor,
yang dibuat berdasarkan {@link android.content.AsyncTaskLoader} untuk melakukan query kursor
pada thread latar belakang agar tidak memblokir UI aplikasi. Menggunakan loader
ini merupakan cara terbaik untuk memuat data secara asinkron dari {@link
android.content.ContentProvider}, sebagai ganti melakukan query terkelola melalui
fragmen atau API aktivitas.</td>
</tr>
</table>
<p>Kelas dan antarmuka dalam tabel di atas merupakan komponen
esensial yang akan Anda gunakan untuk mengimplementasikan loader dalam aplikasi Anda. Anda tidak memerlukan semuanya
untuk setiap loader yang dibuat, namun Anda akan selalu memerlukan acuan ke {@link
android.app.LoaderManager} untuk memulai loader dan implementasi
kelas {@link android.content.Loader} seperti {@link
android.content.CursorLoader}. Bagian berikut ini menunjukkan kepada Anda cara menggunakan
kelas dan antarmuka ini dalam aplikasi.</p>
<h2 id ="app">Menggunakan Loader dalam Aplikasi</h2>
<p>Bagian ini menjelaskan cara menggunakan loader dalam aplikasi Android. Aplikasi
yang menggunakan loader biasanya berisi yang berikut ini:</p>
<ul>
<li>{@link android.app.Activity} atau {@link android.app.Fragment}.</li>
<li>Instance {@link android.app.LoaderManager}.</li>
<li>{@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link
android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri
dari {@link android.content.Loader} atau {@link android.content.AsyncTaskLoader} untuk
memuat data dari beberapa sumber lain.</li>
<li>Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}.
Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader
yang ada.</li>
<li>Cara menampilkan data loader, seperti {@link
android.widget.SimpleCursorAdapter}.</li>
<li>Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan
{@link android.content.CursorLoader}.</li>
</ul>
<h3 id="starting">Memulai Loader</h3>
<p>{@link android.app.LoaderManager} mengelola satu atau beberapa instance {@link
android.content.Loader} dalam {@link android.app.Activity} atau
{@link android.app.Fragment}. Hanya ada satu {@link
android.app.LoaderManager} per aktivitas atau fragmen.</p>
<p>Anda biasanya
memulai {@link android.content.Loader} dalam metode {@link
android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode
{@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda
melakukannya dengan cara berikut ini:</p>
<pre>// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);</pre>
<p>Metode {@link android.app.LoaderManager#initLoader initLoader()} mengambil
parameter berikut:</p>
<ul>
<li>ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.</li>
<li>Argumen opsional untuk dipasok ke loader
pada saat pembuatan (dalam contoh ini <code>null</code>).</li>
<li>Implementasi {@link android.app.LoaderManager.LoaderCallbacks}, yang
akan dipanggil {@link android.app.LoaderManager} untuk melaporkan kejadian loader. Dalam contoh
ini, kelas lokal mengimplementasikan antarmuka {@link
android.app.LoaderManager.LoaderCallbacks}, sehingga meneruskan acuan
ke dirinya sendiri, {@code this}.</li>
</ul>
<p>Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader
telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:</p>
<ul>
<li>Jika loader yang disebutkan oleh ID sudah ada, loader yang dibuat terakhir akan digunakan
kembali.</li>
<li>Jika loader yang disebutkan oleh ID <em>tidak</em> ada,
{@link android.app.LoaderManager#initLoader initLoader()} akan memicu metode
{@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
Di sinilah Anda mengimplementasikan kode untuk membuat instance dan mengembalikan loader baru.
Untuk diskusi selengkapnya, lihat bagian <a href="#onCreateLoader">onCreateLoader</a>.</li>
</ul>
<p>Dalam hal ini, implementasi {@link android.app.LoaderManager.LoaderCallbacks}
yang ditentukan akan dikaitkan dengan loader, dan akan dipanggil bila
status loader berubah. Jika saat panggilan ini status pemanggil sudah
dimulai, dan loader yang diminta sudah ada dan telah menghasilkan
datanya, maka sistem segera memanggil {@link
android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
(selama {@link android.app.LoaderManager#initLoader initLoader()}),
sehingga Anda harus siap bila hal ini terjadi. Lihat <a href="#onLoadFinished">
onLoadFinished</a> untuk diskusi selengkapnya mengenai callback ini</p>
<p>Perhatikan bahwa metode {@link android.app.LoaderManager#initLoader initLoader()}
mengembalikan {@link android.content.Loader} yang dibuat, namun Anda tidak
perlu menangkap acuan ke sana. {@link android.app.LoaderManager} mengelola
masa hidup loader secara otomatis. {@link android.app.LoaderManager}
memulai dan menghentikan pemuatan jika perlu, dan menjaga status loader
dan konten terkaitnya. Seperti yang tersirat di sini, Anda akan jarang berinteraksi dengan loader
secara langsung (meskipun misalnya menggunakan metode loader untuk menyempurnakan perilaku
loader, lihat contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>).
Anda paling sering akan menggunakan metode {@link
android.app.LoaderManager.LoaderCallbacks} untuk mengintervensi proses
pemuatan saat terjadi kejadian tertentu. Untuk diskusi selengkapnya mengenai topik ini, lihat <a href="#callback">Menggunakan Callback LoaderManager</a>.</p>
<h3 id="restarting">Me-restart Loader</h3>
<p>Bila Anda menggunakan {@link android.app.LoaderManager#initLoader initLoader()}, seperti
ditampilkan di atas, loader yang ada akan digunakan dengan ID yang ditetapkan jika ada.
Jika tidak ada, ID akan dibuat. Namun kadang-kadang Anda perlu membuang data lama
dan mulai dari awal.</p>
<p>Untuk membuang data lama, gunakan {@link
android.app.LoaderManager#restartLoader restartLoader()}. Misalnya, implementasi
{@link android.widget.SearchView.OnQueryTextListener} ini akan me-restart
bila query pengguna berubah. Loader perlu di-restart
agar dapat menggunakan filter pencarian yang telah direvisi untuk melakukan query baru:</p>
<pre>
public boolean onQueryTextChanged(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, this);
return true;
}</pre>
<h3 id="callback">Menggunakan Callback LoaderManager</h3>
<p>{@link android.app.LoaderManager.LoaderCallbacks} adalah antarmuka callback
yang memungkinkan klien berinteraksi dengan {@link android.app.LoaderManager}. </p>
<p>Loader, khususnya {@link android.content.CursorLoader}, diharapkan
mempertahankan datanya setelah dihentikan. Ini memungkinkan aplikasi mempertahankan
datanya di aktivitas atau metode {@link android.app.Activity#onStop
onStop()} fragmen dan {@link android.app.Activity#onStart onStart()}, sehingga
bila pengguna kembali ke aplikasi, mereka tidak harus menunggu data
dimuat kembali. Anda menggunakan metode {@link android.app.LoaderManager.LoaderCallbacks}
untuk mengetahui waktu membuat loader baru, dan memberi tahu aplikasi kapan
berhenti menggunakan data loader.</p>
<p>{@link android.app.LoaderManager.LoaderCallbacks} berisi metode
ini:</p>
<ul>
<li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} —
Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID yang diberikan.
</li></ul>
<ul>
<li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
— Dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
</li></ul>
<ul>
<li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}
— Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
tidak tersedia.
</li>
</ul>
<p>Metode ini dijelaskan lebih detail dalam bagian berikutnya.</p>
<h4 id ="onCreateLoader">onCreateLoader</h4>
<p>Saat Anda mencoba mengakses loader (misalnya, melalui {@link
android.app.LoaderManager#initLoader initLoader()}), ia akan memeriksa untuk mengetahui adanya
loader yang ditetapkan oleh ID. Jika tidak ada, ia akan memicu metode {@link
android.app.LoaderManager.LoaderCallbacks} {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Di
sinilah Anda membuat loader baru. Biasanya ini adalah {@link
android.content.CursorLoader}, namun Anda bisa mengimplementasikan sendiri subkelas {@link
android.content.Loader}. </p>
<p>Dalam contoh ini, metode callback {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
akan membuat {@link android.content.CursorLoader}. Anda harus membuat
{@link android.content.CursorLoader} menggunakan metode konstruktornya, yang
memerlukan set informasi lengkap untuk melakukan query ke {@link
android.content.ContentProvider}. Secara khusus, ia memerlukan:</p>
<ul>
<li><em>uri</em> — URI untuk konten yang akan diambil. </li>
<li><em>projection</em> — Daftar berisi kolom yang akan dikembalikan. Meneruskan
<code>null</code> akan mengembalikan semua kolom, jadi tidak efisien. </li>
<li><em>selection</em> — Filter yang mendeklarasikan baris yang akan dikembalikan,
diformat sebagai klausa SQL WHERE (tidak termasuk WHERE itu sendiri). Meneruskan
<code>null</code> akan mengembalikan semua baris untuk URI yang diberikan. </li>
<li><em>selectionArgs</em> — Anda dapat menyertakan ?s dalam pilihan, yang akan
digantikan dengan nilai dari <em>selectionArgs</em>, agar muncul dalam
pilihan. Nilai-nilai akan diikat sebagai String. </li>
<li><em>sortOrder</em> — Cara menyusun baris, diformat sebagai klausa SQL
ORDER BY (tidak termasuk ORDER BY itu sendiri). Meneruskan <code>null</code> akan
menggunakan urutan sortir default, yang mungkin tidak berurutan.</li>
</ul>
<p>Misalnya:</p>
<pre>
// If non-null, this is the current filter the user has provided.
String mCurFilter;
...
public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created.  This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }
    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
            + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
            + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
}</pre>
<h4 id="onLoadFinished">onLoadFinished</h4>
<p>Metode ini dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
Metode ini dijamin dipanggil sebelum pelepasan data terakhir
yang disediakan untuk loader ini. Di titik ini Anda harus menyingkirkan semua penggunaan
data lama (karena akan segera dilepas), namun jangan melepas sendiri
data tersebut karena loader memilikinya dan akan menanganinya.</p>
<p>Loader akan melepas data setelah mengetahui bahwa aplikasi tidak
lagi menggunakannya. Misalnya, jika data adalah kursor dari {@link
android.content.CursorLoader}, Anda tidak boleh memanggil {@link
android.database.Cursor#close close()} sendiri. Jika kursor ditempatkan
dalam {@link android.widget.CursorAdapter}, Anda harus menggunakan metode {@link
android.widget.SimpleCursorAdapter#swapCursor swapCursor()} agar
{@link android.database.Cursor} lama tidak ditutup. Misalnya:</p>
<pre>
// This is the Adapter being used to display the list's data.<br
/>SimpleCursorAdapter mAdapter;
...
public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
// Swap the new cursor in.  (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}</pre>
<h4 id="onLoaderReset">onLoaderReset</h4>
<p>Metode ini dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
tidak tersedia. Callback ini memungkinkan Anda mengetahui
kapan data akan dilepas sehingga dapat menghapus acuannya ke callback.  </p>
<p>Implementasi ini memanggil
{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}
dengan nilai <code>null</code>:</p>
<pre>
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...
public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed.  We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}</pre>
<h2 id="example">Contoh</h2>
<p>Sebagai contoh, berikut ini adalah implementasi penuh {@link
android.app.Fragment} yang menampilkan {@link android.widget.ListView} berisi
hasil query terhadap penyedia konten kontak. Ia menggunakan {@link
android.content.CursorLoader} untuk mengelola query pada penyedia.</p>
<p>Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini,
manifesnya harus menyertakan izin
{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p>
<pre>
public static class CursorLoaderListFragment extends ListFragment
        implements OnQueryTextListener, LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
// This is the Adapter being used to display the list's data.
    SimpleCursorAdapter mAdapter;
    // If non-null, this is the current filter the user has provided.
    String mCurFilter;
    @Override public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Give some text to display if there is no data.  In a real
        // application this would come from a resource.
        setEmptyText(&quot;No phone numbers&quot;);
        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);
        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_list_item_2, null,
                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
        setListAdapter(mAdapter);
        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }
    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        MenuItem item = menu.add(&quot;Search&quot;);
        item.setIcon(android.R.drawable.ic_menu_search);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        SearchView sv = new SearchView(getActivity());
        sv.setOnQueryTextListener(this);
        item.setActionView(sv);
    }
    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }
    @Override public boolean onQueryTextSubmit(String query) {
        // Don't care about this.
        return true;
    }
    @Override public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
        Log.i(&quot;FragmentComplexList&quot;, &quot;Item clicked: &quot; + id);
    }
    // These are the Contacts rows that we will retrieve.
    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.CONTACT_STATUS,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY,
    };
    public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
                + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
                + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
        return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION, select, null,
                Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
    }
    public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
    }
    public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }
}</pre>
<h3 id="more_examples">Contoh Selengkapnya</h3>
<p>Ada beberapa contoh berbeda dalam <strong>ApiDemos</strong> yang
mengilustrasikan cara menggunakan loader:</p>
<ul>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
LoaderCursor</a> — Versi lengkap dari
cuplikan yang ditampilkan di atas.</li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — Contoh cara penggunaan throttling untuk
mengurangi jumlah query dari penyedia konten saat datanya berubah.</li>
</ul>
<p>Untuk informasi tentang mengunduh dan menginstal contoh SDK, lihat <a href="http://developer.android.com/resources/samples/get.html"> Mendapatkan
Contoh</a>. </p>

View File

@@ -1,411 +0,0 @@
page.title=Proses dan Thread
page.tags=daur hidup,latar belakang
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Processes">Proses</a>
<ol>
<li><a href="#Lifecycle">Daur hidup proses</a></li>
</ol>
</li>
<li><a href="#Threads">Thread</a>
<ol>
<li><a href="#WorkerThreads">Thread pekerja</a></li>
<li><a href="#ThreadSafe">Metode thread-safe</a></li>
</ol>
</li>
<li><a href="#IPC">Komunikasi antarproses</a></li>
</ol>
</div>
</div>
<p>Bila komponen aplikasi dimulai dan tidak ada komponen aplikasi lain yang
berjalan, sistem Android akan memulai proses Linux baru untuk aplikasi dengan satu thread
eksekusi. Secara default, semua komponen aplikasi yang sama berjalan dalam proses dan
thread yang sama (disebut thread "utama"). Jika komponen aplikasi dimulai dan sudah ada
proses untuk aplikasi itu (karena komponen lain dari aplikasi itu sudah ada), maka komponen
akan dimulai dalam proses itu dan menggunakan thread eksekusi yang sama. Akan tetapi, Anda bisa
mengatur komponen berbeda di aplikasi agar berjalan di proses terpisah, dan Anda bisa membuat thread tambahan untuk
setiap proses.</p>
<p>Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.</p>
<h2 id="Processes">Proses</h2>
<p>Secara default, semua komponen aplikasi yang sama berjalan dalam proses yang sama dan kebanyakan
aplikasi tidak boleh mengubah ini. Akan tetapi, jika Anda merasa perlu mengontrol proses milik
komponen tertentu, Anda dapat melakukannya dalam file manifes.</p>
<p>Entri manifes untuk setiap tipe elemen komponen&mdash;<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code
&lt;service&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
&lt;receiver&gt;}</a>, dan <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code
&lt;provider&gt;}</a>&mdash;mendukung atribut {@code android:process} yang bisa menetapkan
dalam proses mana komponen harus dijalankan. Anda bisa mengatur atribut ini agar setiap komponen
berjalan dalam prosesnya sendiri atau agar beberapa komponen menggunakan proses yang sama sementara yang lainnya tidak. Anda juga bisa mengatur
{@code android:process} agar komponen aplikasi yang berbeda berjalan dalam proses yang sama
&mdash;sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani
dengan sertifikat yang sama.</p>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
&lt;application&gt;}</a> juga mendukung atribut {@code android:process}, untuk mengatur
nilai default yang berlaku bagi semua komponen.</p>
<p>Android bisa memutuskan untuk mematikan proses pada waktu tertentu, bila memori tinggal sedikit dan diperlukan oleh
proses lain yang lebih mendesak untuk melayani pengguna. Komponen
aplikasi yang berjalan dalam proses yang dimatikan maka sebagai konsekuensinya juga akan dimusnahkan. Proses dimulai
kembali untuk komponen itu bila ada lagi pekerjaan untuk mereka lakukan.</p>
<p>Saat memutuskan proses yang akan dimatikan, sistem Android akan mempertimbangkan kepentingan relatifnya bagi
pengguna. Misalnya, sistem lebih mudah menghentikan proses yang menjadi host aktivitas yang tidak
lagi terlihat di layar, dibandingkan dengan proses yang menjadi host aktivitas yang terlihat. Karena itu, keputusan
untuk menghentikan proses bergantung pada keadaan komponen yang berjalan dalam proses tersebut. Aturan
yang digunakan untuk menentukan proses yang akan dihentikan dibahas di bawah ini. </p>
<h3 id="Lifecycle">Daur hidup proses</h3>
<p>Sistem Android mencoba mempertahankan proses aplikasi selama mungkin, namun
pada akhirnya perlu menghapus proses lama untuk mengambil kembali memori bagi proses baru atau yang lebih penting. Untuk
menentukan proses yang akan
dipertahankan dan yang harus dimatikan, sistem menempatkan setiap proses ke dalam "hierarki prioritas" berdasarkan
komponen yang berjalan dalam proses dan status komponen tersebut. Proses yang memiliki
prioritas terendah akan dimatikan terlebih dahulu, kemudian yang terendah berikutnya, dan seterusnya, jika perlu
untuk memulihkan sumber daya sistem.</p>
<p>Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa
tipe proses berdasarkan urutan prioritas (proses pertama adalah yang <em>terpenting</em> dan
<em>dimatikan terakhir</em>):</p>
<ol>
<li><b>Proses latar depan</b>
<p>Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna. Proses
dianggap berada di latar depan jika salah satu kondisi berikut terpenuhi:</p>
<ul>
<li>Proses menjadi host {@link android.app.Activity} yang berinteraksi dengan pengguna dengan metode ({@link
android.app.Activity}{@link android.app.Activity#onResume onResume()} telah
dipanggil).</li>
<li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan
pengguna.</li>
<li>Proses menjadi host {@link android.app.Service} yang berjalan "di latar depan"&mdash;
layanan telah memanggil{@link android.app.Service#startForeground startForeground()}.
<li>Proses menjadi host {@link android.app.Service} yang menjalankan salah satu callback
daur hidupnya ({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart
onStart()}, atau {@link android.app.Service#onDestroy onDestroy()}).</li>
<li>Proses menjadi host {@link android.content.BroadcastReceiver} yang menjalankan metode {@link
android.content.BroadcastReceiver#onReceive onReceive()}-nya.</li>
</ul>
<p>Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan. Proses dimatikan hanya sebagai
upaya terakhir&mdash; jika memori hampir habis sehingga semuanya tidak bisa terus berjalan. Pada umumnya, pada
titik itu, perangkat dalam keadaan memory paging, sehingga menghentikan beberapa proses latar depan
diperlukan agar antarmuka pengguna tetap responsif.</p></li>
<li><b>Proses yang terlihat</b>
<p>Proses yang tidak memiliki komponen latar depan, namun masih bisa
memengaruhi apa yang dilihat pengguna di layar. Proses dianggap terlihat jika salah satu kondisi
berikut terpenuhi:</p>
<ul>
<li>Proses ini menjadi host {@link android.app.Activity} yang tidak berada di latar depan, namun masih
terlihat oleh penggunanya (metode {@link android.app.Activity#onPause onPause()} telah dipanggil).
Ini bisa terjadi, misalnya, jika aktivitas latar depan memulai dialog, sehingga
aktivitas sebelumnya terlihat berada di belakangnya.</li>
<li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar
depan)</li>
</ul>
<p>Proses yang terlihat dianggap sangat penting dan tidak akan dimatikan kecuali jika hal itu
diperlukan agar semua proses latar depan tetap berjalan. </p>
</li>
<li><b>Proses layanan</b>
<p>Proses yang menjalankan layanan yang telah dimulai dengan metode {@link
android.content.Context#startService startService()} dan tidak termasuk dalam salah satu dari dua kategori
yang lebih tinggi. Walaupun proses pelayanan tidak langsung terkait dengan semua yang dilihat oleh pengguna, proses ini
umumnya melakukan hal-hal yang dipedulikan pengguna (seperti memutar musik di latar belakang
atau mengunduh data di jaringan), jadi sistem membuat proses tetap berjalan kecuali memori tidak cukup untuk
mempertahankannya bersama semua proses latar depan dan proses yang terlihat. </p>
</li>
<li><b>Proses latar belakang</b>
<p>Proses yang menampung aktivitas yang saat ini tidak terlihat oleh pengguna (metode
{@link android.app.Activity#onStop onStop()} aktivitas telah dipanggil). Proses ini tidak memiliki dampak
langsung pada pengalaman pengguna, dan sistem bisa menghentikannya kapan saja untuk memperoleh kembali memori bagi
proses latar depan, proses yang terlihat,
atau proses layanan. Biasanya ada banyak proses latar belakang yang berjalan, sehingga disimpan
dalam daftar LRU (least recently used atau paling sedikit digunakan) untuk memastikan bahwa proses dengan aktivitas yang paling baru
terlihat oleh pengguna sebagai yang terakhir untuk dimatikan. Jika aktivitas mengimplementasikan metode
daur hidupnya dengan benar, dan menyimpan statusnya saat ini, menghentikan prosesnya tidak akan memiliki efek
yang terlihat pada pengalaman pengguna, karena ketika pengguna kembali ke aktivitas, aktivitas itu memulihkan
semua statusnya yang terlihat. Lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
untuk mendapatkan informasi tentang menyimpan dan memulihkan status.</p>
</li>
<li><b>Proses kosong</b>
<p>Sebuah proses yang tidak berisi komponen aplikasi aktif apa pun. Alasan satu-satunya mempertahankan proses
seperti ini tetap hidup adalah untuk keperluan caching, meningkatkan waktu mulai (startup) bila
nanti komponen perlu dijalankan di dalamnya. Sistem sering menghentikan proses ini untuk menyeimbangkan sumber
daya sistem secara keseluruhan antara proses cache dan cache kernel yang mendasarinya.</p>
</li>
</ol>
<p>Android sebisa mungkin memeringkat proses setinggi
mungkin, berdasarkan prioritas komponen yang sedang aktif dalam proses. Misalnya, jika suatu proses menjadi host sebuah layanan dan
aktivitas yang terlihat, proses akan diperingkat sebagai proses yang terlihat, bukan sebagai proses layanan.</p>
<p>Selain itu, peringkat proses dapat meningkat karena adanya proses lain yang bergantung padanya
&mdash;proses yang melayani proses lain tidak bisa diperingkat lebih rendah daripada proses yang
sedang dilayaninya. Misalnya, jika penyedia konten dalam proses A melayani klien dalam proses B, atau
jika layanan dalam proses A terikat dengan komponen dalam proses B, proses A selalu dipertimbangkan sebagai paling rendah
prioritasnya dibandingkan dengan proses B.</p>
<p>Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang,
aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai <a href="{@docRoot}guide/components/services.html">layanan</a> untuk operasi itu, daripada hanya
membuat thread pekerja&mdash;khususnya jika operasi mungkin akan berlangsung lebih lama daripada aktivitas.
Misalnya, aktivitas yang mengunggah gambar ke situs web harus memulai layanan
untuk mengunggah sehingga unggahan bisa terus berjalan di latar belakang meskipun pengguna meninggalkan aktivitas tersebut.
Menggunakan layanan akan memastikan operasi paling tidak memiliki prioritas "proses layanan",
apa pun yang terjadi pada aktivitas. Ini menjadi alasan yang sama yang membuat penerima siaran harus
menjalankan layanan daripada hanya menempatkan operasi yang menghabiskan waktu di thread.</p>
<h2 id="Threads">Thread</h2>
<p>Bila aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang diberi nama,
"main". Thread ini sangat penting karena bertugas mengirim kejadian ke widget
antarmuka pengguna yang sesuai, termasuk kejadian menggambar. Ini juga merupakan thread yang
membuat aplikasi berinteraksi dengan komponen dari Android UI toolkit (komponen dari paket {@link
android.widget} dan {@link android.view}). Karena itu, thread 'main' juga terkadang
disebut thread UI.</p>
<p>Sistem ini <em>tidak</em> membuat thread terpisah untuk setiap instance komponen. Semua
komponen yang berjalan di proses yang sama akan dibuat instance-nya dalam thread UI, dan sistem akan memanggil
setiap komponen yang dikirim dari thread itu. Akibatnya, metode yang merespons callback sistem
(seperti {@link android.view.View#onKeyDown onKeyDown()} untuk melaporkan tindakan pengguna atau metode callback daur hidup)
selalu berjalan di thread UI proses.</p>
<p>Misalnya saat pengguna menyentuh tombol pada layar, thread UI aplikasi akan mengirim kejadian
sentuh ke widget, yang selanjutnya menetapkan status ditekan dan mengirim permintaan yang tidak divalidasi ke
antrean kejadian. Thread UI akan menghapus antrean permintaan dan memberi tahu widget bahwa widget harus menggambar
dirinya sendiri.</p>
<p>Saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna, model
thread tunggal ini bisa menghasilkan kinerja yang buruk kecuali jika Anda mengimplementasikan aplikasi dengan benar. Khususnya jika
semua terjadi di thread UI, melakukan operasi yang panjang seperti akses ke jaringan atau query
database akan memblokir seluruh UI. Bila thread diblokir, tidak ada kejadian yang bisa dikirim,
termasuk kejadian menggambar. Dari sudut pandang pengguna, aplikasi
tampak mogok (hang). Lebih buruk lagi, jika thread UI diblokir selama lebih dari beberapa detik
(saat ini sekitar 5 detik) pengguna akan ditampilkan dialog "<a href="http://developer.android.com/guide/practices/responsiveness.html">aplikasi tidak
merespons</a>" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi
jika mereka tidak suka.</p>
<p>Selain itu, toolkit Android UI <em>bukan</em> thread-safe. Jadi, Anda tidak harus memanipulasi
UI dari thread pekerja&mdash;Anda harus melakukan semua manipulasi pada antarmuka pengguna dari thread
UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:</p>
<ol>
<li>Jangan memblokir thread UI
<li>Jangan mengakses toolkit Android UI dari luar thread UI
</ol>
<h3 id="WorkerThreads">Thread pekerja</h3>
<p>Karena model thread tunggal yang dijelaskan di atas, Anda dilarang memblokir thread
UI demi daya respons UI aplikasi. Jika memiliki operasi untuk dijalankan
yang tidak seketika, Anda harus memastikan untuk melakukannya di thread terpisah (thread "latar belakang" atau
thread "pekerja").</p>
<p>Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari
thread terpisah dan menampilkannya dalam {@link android.widget.ImageView}:</p>
<pre>
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}
</pre>
<p>Awalnya hal ini tampak bekerja dengan baik, karena menciptakan thread baru untuk menangani
operasi jaringan. Akan tetapi, hal tersebut melanggar aturan kedua model thread tunggal: <em>jangan mengakses
toolkit Android UI dari luar thread UI</em>&mdash;sampel ini memodifikasi {@link
android.widget.ImageView} dari thread pekerja sebagai ganti thread UI. Ini bisa
mengakibatkan perilaku yang tidak terdefinisi dan tidak diharapkan, yang bisa menyulitkan dan menghabiskan waktu untuk melacaknya.</p>
<p>Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari
thread lainnya. Berikut ini daftar metode yang bisa membantu:</p>
<ul>
<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable)
Activity.runOnUiThread(Runnable)}</li>
<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable,
long)}</li>
</ul>
<p>Misalnya, Anda bisa memperbaiki kode di atas dengan menggunakan metode {@link
android.view.View#post(java.lang.Runnable) View.post(Runnable)}:</p>
<pre>
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
</pre>
<p>Kini implementasi ini thread-safe: operasi jaringan dilakukan terpisah dari thread
sementara {@link android.widget.ImageView} dimanipulasi dari thread UI.</p>
<p>Akan tetapi, karena operasi semakin kompleks, jenis kode seperti ini bisa semakin rumit
dan sulit dipertahankan. Untuk menangani interaksi yang lebih kompleks dengan thread pekerja, Anda bisa mempertimbangkan
penggunaan {@link android.os.Handler}di thread pekerja, untuk memproses pesan yang dikirim dari
thread UI. Mungkin solusi terbaiknya adalah memperpanjang kelas {@link android.os.AsyncTask},
yang akan menyederhanakan eksekusi tugas-tugas thread pekerja yang perlu berinteraksi dengan UI.</p>
<h4 id="AsyncTask">Menggunakan AsyncTask</h4>
<p>Dengan {@link android.os.AsyncTask}, Anda bisa melakukan pekerjaan asinkron pada antarmuka
pengguna. AsyncTask memblokir operasi di thread pekerja kemudian mempublikasikan hasilnya
di thread UI, tanpa mengharuskan Anda untuk menangani sendiri thread dan/atau handler sendiri.</p>
<p>Untuk menggunakannya, Anda harus menempatkan {@link android.os.AsyncTask} sebagai subkelas dan mengimplementasikan metode callback {@link
android.os.AsyncTask#doInBackground doInBackground()} yang berjalan di kumpulan
thread latar belakang. Untuk memperbarui UI, Anda harus mengimplementasikan {@link
android.os.AsyncTask#onPostExecute onPostExecute()}, yang memberikan hasil dari {@link
android.os.AsyncTask#doInBackground doInBackground()} dan berjalan di thread UI, jadi Anda bisa
memperbarui UI dengan aman. Selanjutnya Anda bisa menjalankan tugas dengan memanggil {@link android.os.AsyncTask#execute execute()}
dari thread UI.</p>
<p>Misalnya, Anda bisa mengimplementasikan contoh sebelumnya menggunakan {@link android.os.AsyncTask} dengan cara
ini:</p>
<pre>
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
</pre>
<p>Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke
dalam bagian-bagian yang harus dilakukan pada thread pekerja dan thread UI.</p>
<p>Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya
cara menggunakan kelas ini, namun berikut ini ikhtisar singkat cara kerjanya:</p>
<ul>
<li>Anda bisa menetapkan tipe parameter, nilai kemajuan, dan nilai
akhir tugas, dengan menggunakan generik</li>
<li>Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada
thread pekerja</li>
<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link
android.os.AsyncTask#onPostExecute onPostExecute()}, dan {@link
android.os.AsyncTask#onProgressUpdate onProgressUpdate()} semuanya dipanggil pada thread UI</li>
<li>Nilai yang dikembalikan oleh {@link android.os.AsyncTask#doInBackground doInBackground()} akan dikirim ke
{@link android.os.AsyncTask#onPostExecute onPostExecute()}</li>
<li>Anda bisa memangil {@link android.os.AsyncTask#publishProgress publishProgress()} setiap saat di {@link
android.os.AsyncTask#doInBackground doInBackground()} untuk mengeksekusi {@link
android.os.AsyncTask#onProgressUpdate onProgressUpdate()} pada thread UI</li>
<li>Anda bisa membatalkan tugas ini kapan saja, dari thread mana saja</li>
</ul>
<p class="caution"><strong>Perhatian:</strong> Masalah lain yang mungkin Anda temui saat menggunakan
thread pekerja adalah restart tak terduga dalam aktivitas karena <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan konfigurasi runtime</a>
(seperti saat pengguna mengubah orientasi layar), yang bisa memusnahkan thread pekerja. Untuk
melihat cara mempertahankan tugas selama restart ini dan cara membatalkan
tugas dengan benar saat aktivitas dimusnahkan, lihat kode sumber untuk aplikasi sampel <a href="http://code.google.com/p/shelves/">Shelves</a>.</p>
<h3 id="ThreadSafe">Metode thread-safe</h3>
<p> Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread,
dan karena itu harus ditulis agar menjadi thread-safe. </p>
<p>Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh &mdash;seperti metode dalam <a href="{@docRoot}guide/components/bound-services.html">layanan terikat</a>. Bila sebuah panggilan pada
metode yang dijalankan dalam {@link android.os.IBinder} berasal dari proses yang sama di mana
{@link android.os.IBinder IBinder} berjalan, metode ini akan dieksekusi di thread pemanggil.
Akan tetapi, bila panggilan berasal proses lain, metode akan dieksekusi dalam thread yang dipilih dari
kumpulan (pool) thread yang dipertahankan sistem dalam proses yang sama seperti{@link android.os.IBinder
IBinder} (tidak dieksekusi dalam thread UI proses). Misalnya, karena metode
{@link android.app.Service#onBind onBind()} layanan akan dipanggil dari thread UI
proses layanan, metode yang diimplementasikan dalam objek yang dikembalikan {@link android.app.Service#onBind
onBind()} (misalnya, subkelas yang mengimplementasikan metode RPC) akan dipanggil dari thread
di pool. Karena layanan bisa memiliki lebih dari satu klien, maka lebih dari satu pool thread bisa melibatkan
metode {@link android.os.IBinder IBinder} yang sama sekaligus. Metode {@link android.os.IBinder
IBinder} karenanya harus diimplementasikan sebagai thread-safe.</p>
<p> Penyedia konten juga bisa menerima permintaan data yang berasal dalam proses lain.
Meskipun kelas {@link android.content.ContentResolver} dan {@link android.content.ContentProvider}
menyembunyikan detail cara komunikasi antarproses dikelola, metode {@link
android.content.ContentProvider} yang merespons permintaan itu&mdash;metode {@link
android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert
insert()}, {@link android.content.ContentProvider#delete delete()}, {@link
android.content.ContentProvider#update update()}, dan {@link android.content.ContentProvider#getType
getType()}&mdash; dipanggil dari pool thread pada proses penyedia konten, bukan thread UI
untuk proses tersebut. Mengingat metode ini bisa dipanggil dari thread mana pun
sekaligus, metode-metode ini juga harus diimplementasikan sebagai thread-safe. </p>
<h2 id="IPC">Komunikasi Antarproses</h2>
<p>Android menawarkan mekanisme komunikasi antarproses (IPC) menggunakan panggilan prosedur jauh
(RPC), yang mana metode ini dipanggil oleh aktivitas atau komponen aplikasi lain, namun dieksekusi dari
jauh (di proses lain), bersama hasil yang dikembalikan ke
pemanggil. Ini mengharuskan penguraian panggilan metode dan datanya ke tingkat yang bisa
dipahami sistem operasi, mentransmisikannya dari proses lokal dan ruang alamat untuk proses jauh
dan ruang proses, kemudian merakit kembali dan menetapkannya kembali di sana. Nilai-nilai yang dikembalikan
akan ditransmisikan dalam arah berlawanan. Android menyediakan semua kode untuk melakukan transaksi IPC
ini, sehingga Anda bisa fokus pada pendefinisian dan implementasi antarmuka pemrograman RPC. </p>
<p>Untuk melakukan IPC, aplikasi Anda harus diikat ke layanan, dengan menggunakan {@link
android.content.Context#bindService bindService()}. Untuk informasi selengkapnya, lihat panduan pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>For information about how to perform work in the background for an indefinite period of time
(without a user interface), continue with the <b><a
href="{@docRoot}guide/components/services.html">Services</a></b> document.</p>
-->

View File

@@ -1,256 +0,0 @@
page.title=Layar Ikhtisar
page.tags="recents","overview"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#adding">Menambahkan Tugas ke Layar Ikhtisar</a>
<ol>
<li><a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a></li>
<li><a href="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</a></li>
</ol>
</li>
<li><a href="#removing">Menghapus Tugas</a>
<ol>
<li><a href="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</a></li>
<li><a href="#retain-finished">Mempertahankan tugas yang telah selesai</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.ActivityManager.AppTask}</li>
<li>{@link android.content.Intent}</li>
</ol>
<h2>Kode contoh</h2>
<ol>
<li><a href="{@docRoot}samples/DocumentCentricApps/index.html">Aplikasi yang berorientasi dokumen</a></li>
</ol>
</div>
</div>
<p>Layar ikhtisar (juga disebut sebagai layar terbaru, daftar tugas terbaru, atau aplikasi terbaru)
UI tingkat sistem yang mencantumkan <a href="{@docRoot}guide/components/activities.html">
aktivitas</a> dan <a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> yang baru saja diakses. Pengguna
bisa menyusuri daftar ini dan memilih satu tugas untuk dilanjutkan, atau pengguna bisa menghapus tugas dari
daftar dengan gerakan mengusap. Dengan dirilisnya Android 5.0 (API level 21), beberapa instance aktivitas yang
sama yang berisi dokumen berbeda dapat muncul sebagai tugas di layar ikhtisar. Misalnya,
Google Drive mungkin memiliki satu tugas untuk setiap beberapa dokumen Google. Setiap dokumen muncul sebagai
tugas dalam layar ikhtisar.</p>
<img src="{@docRoot}images/components/recents.png" alt="" width="284" />
<p class="img-caption"><strong>Gambar 1.</strong> Layar ikhtisar menampilkan tiga dokumen
Google Drive, masing-masing dinyatakan sebagai tugas terpisah.</p>
<p>Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.
Akan tetapi, aplikasi Anda dapat menentukan cara dan waktu munculnya aktivitas di layar ikhtisar. Kelas
{@link android.app.ActivityManager.AppTask} memungkinkan Anda mengelola tugas, dan flag
aktivitas kelas {@link android.content.Intent} memungkinkan Anda menentukan kapan aktivitas ditambahkan atau dihapus dari
layar ikhtisar. Selain itu, atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
&lt;activity&gt;</a></code> memungkinkan Anda menetapkan perilaku di manifes.</p>
<h2 id="adding">Menambahkan Tugas ke Layar Ikhtisar</h2>
<p>Penggunaan flag kelas {@link android.content.Intent} untuk menambahkan tugas memberi kontrol lebih besar
atas waktu dan cara dokumen dibuka atau dibuka kembali di layar ikhtisar. Bila menggunakan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas
yang ada untuk dokumen tersebut.</p>
<h3 id="flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</h3>
<p>Bila membuat dokumen baru untuk aktivitas, Anda memanggil metode
{@link android.app.ActivityManager.AppTask#startActivity(android.content.Context, android.content.Intent, android.os.Bundle) startActivity()}
dari kelas {@link android.app.ActivityManager.AppTask}, dengan meneruskannya ke intent yang
menjalankan aktivitas tersebut. Untuk menyisipkan jeda logis agar sistem memperlakukan aktivitas Anda sebagai tugas
baru di layar ikhtisar, teruskan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
dalam metode {@link android.content.Intent#addFlags(int) addFlags()} dari {@link android.content.Intent}
yang memulai aktivitas itu.</p>
<p class="note"><strong>Catatan:</strong> Flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET},
yang tidak digunakan lagi pada Android 5.0 (API level 21).</p>
<p>Jika Anda menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} saat membuat
dokumen baru, sistem akan selalu membuat tugas baru dengan aktivitas target sebagai akar.
Dengan pengaturan ini, dokumen yang sama dapat dibuka di lebih dari satu tugas. Kode berikut memperagakan
cara aktivitas utama melakukannya:</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
DocumentCentricActivity.java</a></p>
<pre>
public void createNewDocument(View view) {
final Intent newDocumentIntent = newDocumentIntent();
if (useMultipleTasks) {
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
}
startActivity(newDocumentIntent);
}
private Intent newDocumentIntent() {
boolean useMultipleTasks = mCheckbox.isChecked();
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
private static int incrementAndGet() {
Log.d(TAG, "incrementAndGet(): " + mDocumentCounter);
return mDocumentCounter++;
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Aktivitas yang dimulai dengan flag {@code FLAG_ACTIVITY_NEW_DOCUMENT}
harus telah menetapkan nilai atribut {@code android:launchMode="standard"} (default) dalam
manifes.</p>
<p>Bila aktivitas utama memulai aktivitas baru, sistem akan mencari tugas yang intent
-nya cocok dengan nama komponen intent dalam tugas-tugas yang sudah ada dan mencari aktivitas dalam data Intent. Jika tugas
tidak ditemukan, atau intent ada dalam flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
, tugas baru akan dibuat dengan aktivitas tersebut sebagai akarnya. Jika ditemukan, sistem akan
mengedepankan tugas itu dan meneruskan intent baru ke {@link android.app.Activity#onNewIntent onNewIntent()}.
Aktivitas baru akan mendapatkan intent dan membuat dokumen baru di layar ikhtisar, seperti dalam
contoh berikut:</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
NewDocumentActivity.java</a></p>
<pre>
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_document);
mDocumentCount = getIntent()
.getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
mDocumentCounterTextView = (TextView) findViewById(
R.id.hello_new_document_text_view);
setDocumentCounterText(R.string.hello_new_document_counter);
}
&#64;Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
is reused to create a new document.
*/
setDocumentCounterText(R.string.reusing_document_counter);
}
</pre>
<h3 id="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</h3>
<p>Aktivitas juga dapat menetapkan dalam manifesnya agar selalu dimulai ke dalam tugas baru dengan menggunakan
atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, <a href="{@docRoot}guide/topics/manifest/activity-element.html#dlmode">
{@code android:documentLaunchMode}</a>. Atribut ini memiliki empat nilai yang menghasilkan efek berikut
bila pengguna membuka dokumen dengan aplikasi:</p>
<dl>
<dt>"{@code intoExisting}"</dt>
<dd>Aktivitas menggunakan kembali tugas yang ada untuk dokumen tersebut. Ini sama dengan mengatur flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} <em>tanpa</em> mengatur flag
{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, seperti dijelaskan dalam
<a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a>, di atas.</dd>
<dt>"{@code always}"</dt>
<dd>Aktivitas ini membuat tugas baru untuk dokumen, meski dokumen sudah dibuka. Menggunakan
nilai ini sama dengan menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
maupun {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.</dd>
<dt>"{@code none”}"</dt>
<dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Layar ikhtisar memperlakukan
aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang
dilanjutkan dari aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
<dt>"{@code never}"</dt>
<dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Mengatur nilai ini akan mengesampingkan
perilaku flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
dan {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, jika salah satunya ditetapkan di
intent, dan layar ikhtisar menampilkan satu tugas untuk aplikasi, yang dilanjutkan dari
aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
</dl>
<p class="note"><strong>Catatan:</strong> Untuk nilai selain {@code none} dan {@code never},
aktivitas harus didefinisikan dengan {@code launchMode="standard"}. Jika atribut ini tidak ditetapkan, maka
{@code documentLaunchMode="none"} akan digunakan.</p>
<h2 id="removing">Menghapus Tugas</h2>
<p>Secara default, tugas dokumen secara otomatis dihapus dari layar ikhtisar bila aktivitasnya
selesai. Anda bisa mengesampingkan perilaku ini dengan kelas {@link android.app.ActivityManager.AppTask},
dengan flag {@link android.content.Intent} atau atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
&lt;activity&gt;</a></code>.</p>
<p>Kapan saja Anda bisa mengecualikan tugas dari layar ikhtisar secara keseluruhan dengan menetapkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, <a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">
{@code android:excludeFromRecents}</a> hingga {@code true}.</p>
<p>Anda bisa menetapkan jumlah maksimum tugas yang dapat disertakan aplikasi Anda dalam layar ikhtisar dengan menetapkan
atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<a href="{@docRoot}guide/topics/manifest/activity-element.html#maxrecents">{@code android:maxRecents}
</a> ke satu nilai integer. Nilai default-nya adalah 16. Bila telah mencapai jumlah maksimum, tugas yang terakhir
digunakan akan dihapus dari layar ikhtisar. Nilai maksimum {@code android:maxRecents}
adalah 50 (25 pada perangkat dengan memori sedikit); nilai yang kurang dari 1 tidak berlaku.</p>
<h3 id="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</h3>
<p>Dalam aktivitas yang membuat tugas baru di layar ikhtisar, Anda bisa
menetapkan kapan menghapus tugas dan menyelesaikan semua aktivitas yang terkait dengannya
dengan memanggil metode {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}.</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
NewDocumentActivity.java</a></p>
<pre>
public void onRemoveFromRecents(View view) {
// The document is no longer needed; remove its task.
finishAndRemoveTask();
}
</pre>
<p class="note"><strong>Catatan:</strong> Penggunaan metode
{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}
akan mengesampingkan penggunaan tag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, seperti
dibahas di bawah ini.</p>
<h3 id="#retain-finished">Mempertahankan tugas yang telah selesai</h3>
<p>Jika Anda ingin mempertahankan tugas di layar ikhtisar, sekalipun aktivitas sudah selesai, teruskan
flag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} dalam metode
{@link android.content.Intent#addFlags(int) addFlags()} dari Intent yang memulai aktivitas itu.</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
DocumentCentricActivity.java</a></p>
<pre>
private Intent newDocumentIntent() {
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
</pre>
<p>Untuk memperoleh efek yang sama, tetapkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<a href="{@docRoot}guide/topics/manifest/activity-element.html#autoremrecents">
{@code android:autoRemoveFromRecents}</a> hingga {@code false}. Nilai default-nya adalah {@code true}
untuk aktivitas dokumen, dan {@code false} untuk aktivitas biasa. Penggunaan atribut ini akan mengesampingkan flag
{@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, yang telah dibahas sebelumnya.</p>

View File

@@ -1,813 +0,0 @@
page.title=Layanan
@jd:body
<div id="qv-wrapper">
<ol id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Basics">Dasar-Dasar</a></li>
<ol>
<li><a href="#Declaring">Mendeklarasikan layanan dalam manifes</a></li>
</ol>
<li><a href="#CreatingAService">Membuat Layanan yang Sudah Dimulai</a>
<ol>
<li><a href="#ExtendingIntentService">Memperluas kelas IntentService</a></li>
<li><a href="#ExtendingService">Memperluas kelas Layanan</a></li>
<li><a href="#StartingAService">Memulai layanan</a></li>
<li><a href="#Stopping">Menghentikan layanan</a></li>
</ol>
</li>
<li><a href="#CreatingBoundService">Membuat Layanan Terikat</a></li>
<li><a href="#Notifications">Mengirim Pemberitahuan ke Pengguna</a></li>
<li><a href="#Foreground">Menjalankan Layanan di Latar Depan</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>
<ol>
<li><a href="#LifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Service}</li>
<li>{@link android.app.IntentService}</li>
</ol>
<h2>Contoh</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
ServiceStartArguments}</a></li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService}</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a></li>
</ol>
</div>
<p>{@link android.app.Service} adalah sebuah komponen aplikasi yang bisa melakukan
operasi yang berjalan lama di latar belakang dan tidak menyediakan antarmuka pengguna. Komponen
aplikasi lain bisa memulai layanan dan komponen aplikasi tersebut akan terus berjalan
di latar belakang walaupun pengguna beralih ke aplikasi lain. Selain itu, komponen bisa mengikat ke layanan
untuk berinteraksi dengannya dan bahkan melakukan komunikasi antarproses (IPC). Misalnya, layanan mungkin
menangani transaksi jaringan, memutar musik, melakukan file I/O, atau berinteraksi dengan penyedia konten
dari latar belakang.</p>
<p>Ada dua bentuk dasar layanan:</p>
<dl>
<dt>Sudah Dimulai</dt>
<dd>Layanan "sudah dimulai" bila komponen aplikasi (misalnya aktivitas) memulainya dengan
memanggil {@link android.content.Context#startService startService()}. Sesudah dimulai, layanan
bisa berjalan terus-menerus di latar belakang walaupun komponen yang memulainya telah dimusnahkan. Biasanya,
layanan yang sudah dimulai akan melakukan operasi tunggal dan tidak mengembalikan hasil ke pemanggilnya.
Misalnya, layanan bisa mengunduh atau mengunggah file melalui jaringan. Bila operasi selesai,
layanan seharusnya berhenti sendiri.</dd>
<dt>Terikat</dt>
<dd>Layanan "terikat" bila komponen aplikasi mengikat kepadanya dengan memanggil {@link
android.content.Context#bindService bindService()}. Layanan terikat menawarkan antarmuka
klien-server yang memungkinkan komponen berinteraksi dengan layanan tersebut, mengirim permintaan, mendapatkan hasil dan bahkan
melakukannya pada sejumlah proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama
ada komponen aplikasi lain yang terikat padanya. Sejumlah komponen bisa terikat pada layanan secara bersamaan,
namun bila semuanya melepas ikatan, layanan tersebut akan dimusnahkan.</dd>
</dl>
<p>Walaupun dokumentasi ini secara umum membahas kedua jenis layanan secara terpisah, layanan
Anda bisa menggunakan keduanya&mdash;layanan bisa dimulai (untuk berjalan terus-menerus) sekaligus memungkinkan pengikatan.
Cukup mengimplementasikan dua metode callback: {@link
android.app.Service#onStartCommand onStartCommand()} untuk memungkinkan komponen memulainya dan {@link
android.app.Service#onBind onBind()} untuk memungkinkan pengikatan.</p>
<p>Apakah aplikasi Anda sudah dimulai, terikat, atau keduanya, semua komponen aplikasi
bisa menggunakan layanan (bahkan dari aplikasi terpisah), demikian pula semua komponen bisa menggunakan
suatu aktivitas&mdash;dengan memulainya dengan {@link android.content.Intent}. Akan tetapi, Anda bisa mendeklarasikan
layanan sebagai privat, pada file manifes, dan memblokir akses dari aplikasi lain. Hal ini
dibahas selengkapnya di bagian tentang <a href="#Declaring">Mendeklarasikan layanan dalam
manifes</a>.</p>
<p class="caution"><strong>Perhatian:</strong> Layanan berjalan di
thread utama proses yang menjadi host-nya&mdash;layanan <strong>tidak</strong> membuat thread-nya sendiri
dan <strong>tidak</strong> berjalan pada proses terpisah (kecuali bila Anda tentukan demikian). Artinya,
jika layanan Anda akan melakukan pekerjaan yang membutuhkan tenaga CPU besar atau operasi yang memblokir (seperti
pemutaran MP3 atau jaringan), Anda perlu membuat thread baru dalam layanan untuk melakukan pekerjaan tersebut. Dengan menggunakan
thread terpisah, Anda mengurangi risiko terjadinya kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan
thread utama aplikasi bisa tetap dikhususkan pada interaksi pengguna dengan aktivitas Anda.</p>
<h2 id="Basics">Dasar-Dasar</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Haruskah menggunakan layanan atau thread?</h3>
<p>Layanan sekadar komponen yang bisa berjalan di latar belakang walaupun pengguna sedang tidak
berinteraksi dengan aplikasi Anda. Sehingga, Anda harus membuat layanan bila memang itu
yang dibutuhkan.</p>
<p>Bila Anda perlu melakukan pekerjaan di luar thread utama, namun hanya bila pengguna sedang berinteraksi
dengan aplikasi, maka Anda harus membuat thread baru sebagai ganti layanan baru. Misalnya,
bila Anda ingin memutar musik, namun hanya saat aktivitas Anda berjalan, Anda bisa membuat
thread dalam {@link android.app.Activity#onCreate onCreate()}, mulai menjalankannya di {@link
android.app.Activity#onStart onStart()}, kemudian menghentikannya di {@link android.app.Activity#onStop
onStop()}. Pertimbangkan juga untuk menggunakan {@link android.os.AsyncTask} atau {@link android.os.HandlerThread},
sebagai ganti kelas {@link java.lang.Thread} yang lazim digunakan. Lihat dokumen <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Proses dan
Threading</a> untuk informasi selengkapnya tentang thread.</p>
<p>Ingatlah jika menggunakan layanan, layanan tersebut tetap berjalan di thread utama aplikasi Anda secara
default, jadi Anda harus tetap membuat thread baru dalam layanan bila layanan tersebut melakukan operasi yang intensif
atau operasi yang memblokir.</p>
</div>
</div>
<p>Untuk membuat layanan, Anda harus membuat subkelas {@link android.app.Service} (atau
salah satu dari subkelasnya yang ada). Dalam implementasi, Anda perlu mengesampingkan sebagian metode callback yang
menangani aspek utama daur hidup layanan dan memberikan mekanisme bagi komponen untuk mengikat
pada layanan, bila dibutuhkan. Metode callback terpenting yang perlu Anda kesampingkan adalah:</p>
<dl>
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
<dd>Sistem akan memanggil metode ini bila komponen lain, misalnya aktivitas,
meminta dimulainya layanan, dengan memanggil {@link android.content.Context#startService
startService()}. Setelah metode ini dieksekusi, layanan akan dimulai dan bisa berjalan di
latar belakang terus-menerus. Jika mengimplementasikan ini, Anda bertanggung jawab menghentikan layanan bila
bila pekerjaannya selesai, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}. (Jika hanya ingin menyediakan pengikatan, Anda tidak
perlu mengimplementasikan metode ini.)</dd>
<dt>{@link android.app.Service#onBind onBind()}</dt>
<dd>Sistem akan memanggil metode ini bila komponen lain ingin mengikat pada
layanan (misalnya untuk melakukan RPC), dengan memanggil {@link android.content.Context#bindService
bindService()}. Dalam mengimplementasikan metode ini, Anda harus menyediakan antarmuka yang digunakan
klien untuk berkomunikasi dengan layanan, dengan mengembalikan {@link android.os.IBinder}. Anda harus selalu
mengimplementasikan metode ini, namun jika tidak ingin mengizinkan pengikatan, Anda perlu mengembalikan null.</dd>
<dt>{@link android.app.Service#onCreate()}</dt>
<dd>Sistem memanggil metode ini bila layanan dibuat untuk pertama kalinya, untuk melakukan prosedur
penyiapan satu kali (sebelum memanggil {@link android.app.Service#onStartCommand onStartCommand()} atau
{@link android.app.Service#onBind onBind()}). Bila layanan sudah berjalan, metode ini tidak
dipanggil.</dd>
<dt>{@link android.app.Service#onDestroy()}</dt>
<dd>Sistem memanggil metode ini bila layanan tidak lagi digunakan dan sedang dimusnahkan.
Layanan Anda perlu mengimplementasikannya untuk membersihkan sumber daya seperti thread, listener
terdaftar, penerima, dll. Ini adalah panggilan terakhir yang diterima layanan.</dd>
</dl>
<p>Bila komponen memulai layanan dengan memanggil {@link
android.content.Context#startService startService()} (yang menyebabkan panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()}), maka layanan
terus berjalan hingga terhenti sendiri dengan {@link android.app.Service#stopSelf()} atau bila komponen
lain menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Bila komponen memanggil
{@link android.content.Context#bindService bindService()} untuk membuat layanan (dan {@link
android.app.Service#onStartCommand onStartCommand()} <em>tidak</em> dipanggil), maka layanan hanya berjalan
selama komponen terikat kepadanya. Setelah layanan dilepas ikatannya dari semua klien,
sistem akan menghancurkannya.</p>
<p>Sistem Android akan menghentikan paksa layanan hanya bila memori tinggal sedikit dan sistem harus memulihkan
sumber daya sistem untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat pada suatu aktivitas yang mendapatkan
fokus pengguna, layanan tersebut lebih kecil kemungkinannya untuk dimatikan, dan jika layanan dideklarasikan untuk <a href="#Foreground">berjalan di latar depan</a> (akan dibahas kemudian), maka sudah hampir pasti ia tidak akan dimatikan.
Sebaliknya, bila layanan sudah dimulai dan berjalan lama, maka sistem akan menurunkan posisinya
dalam daftar tugas latar belakang seiring waktu dan layanan akan sangat rentan untuk
dimatikan&mdash;bila layanan Anda dimulai, maka Anda harus mendesainnya agar bisa menangani restart
oleh sistem dengan baik. Jika sistem mematikan layanan Anda, layanan akan dimulai kembali begitu sumber daya
kembali tersedia (tetapi ini juga bergantung pada nilai yang Anda kembalikan dari {@link
android.app.Service#onStartCommand onStartCommand()}, sebagaimana akan dibahas nanti). Untuk informasi selengkapnya
tentang kapan sistem mungkin akan memusnahkan layanan, lihat dokumen
<a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan Threading</a>.</p>
<p>Dalam bagian selanjutnya, Anda akan melihat bagaimana membuat masing-masing tipe layanan dan cara menggunakannya
dari komponen aplikasi lain.</p>
<h3 id="Declaring">Mendeklarasikan layanan dalam manifes</h3>
<p>Sebagaimana aktivitas (dan komponen lainnya), Anda harus mendeklarasikan semua layanan dalam file manifes
aplikasi Anda.</p>
<p>Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
sebagai anak
elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>. Misalnya:</p>
<pre>
&lt;manifest ... &gt;
...
&lt;application ... &gt;
&lt;service android:name=".ExampleService" /&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
untuk informasi selengkapnya tentang cara mendeklarasikan layanan Anda dalam manifes.</p>
<p>Ada atribut lain yang bisa Anda sertakan dalam elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> untuk
mendefinisikan properti seperti izin yang dibutuhkan untuk memulai layanan dan proses
tempat berjalannya layanan. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> adalah satu-satunya atribut yang diperlukan
&mdash;atribut tersebut menetapkan nama kelas layanan. Setelah
mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
kode karena dependensi terhadap intent eksplisit untuk memulai atau mengikat layanan (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
That Cannot Change</a>).
<p>Untuk memastikan aplikasi Anda aman, <strong>selalu gunakan intent eksplisit saat memulai atau mengikat
{@link android.app.Service} Anda</strong> dan jangan mendeklarasikan filter intent untuk layanan. Jika
Anda perlu membiarkan adanya ambiguitas tentang layanan mana yang dimulai, Anda bisa
menyediakan filter intent bagi layanan dan tidak memasukkan nama komponen pada {@link
android.content.Intent}, namun Anda juga harus menyesuaikan paket bagi intent tersebut dengan {@link
android.content.Intent#setPackage setPackage()}, yang memberikan klarifikasi memadai bagi
target layanan.</p>
<p>Anda juga bisa memastikan layanan tersedia hanya bagi aplikasi Anda dengan
menyertakan atribut <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
dan mengaturnya ke {@code "false"}. Hal ini efektif menghentikan aplikasi lain agar tidak memulai
layanan Anda, bahkan saat menggunakan intent eksplisit.</p>
<h2 id="CreatingStartedService">Membuat Layanan yang Sudah Dimulai</h2>
<p>Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil {@link
android.content.Context#startService startService()}, yang menyebabkan panggilan ke metode
{@link android.app.Service#onStartCommand onStartCommand()} layanan.</p>
<p>Bila layanan sudah dimulai, layanan tersebut memiliki daur hidup yang tidak bergantung pada
komponen yang memulainya dan bisa berjalan terus-menerus di latar belakang walaupun
komponen yang memulainya dimusnahkan. Dengan sendirinya, layanan akan berhenti sendiri bila pekerjaannya
selesai dengan memanggil {@link android.app.Service#stopSelf stopSelf()}, atau komponen lain bisa menghentikannya
dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Komponen aplikasi seperti aktivitas bisa memulai layanan dengan memanggil {@link
android.content.Context#startService startService()} dan meneruskan {@link android.content.Intent}
yang menetapkan layanan dan menyertakan data untuk digunakan layanan. Layanan menerima
{@link android.content.Intent} ini dalam metode {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas tersebut bisa
memulai layanan pendamping dan mengiriminya data untuk disimpan dengan meneruskan intent ke {@link
android.content.Context#startService startService()}. Layanan akan menerima intent dalam {@link
android.app.Service#onStartCommand onStartCommand()}, menghubungkan ke Internet dan melakukan
transaksi database. Bila transaksi selesai, layanan akan berhenti sendiri dan
dimusnahkan.</p>
<p class="caution"><strong>Perhatian:</strong> Layanan berjalan dalam proses yang sama dengan aplikasi
tempatnya dideklarasikan dan dalam thread utama aplikasi tersebut, secara default. Jadi, bila layanan Anda
melakukan operasi yang intensif atau operasi pemblokiran saat pengguna berinteraksi dengan aktivitas dari
aplikasi yang sama, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi
kinerja aplikasi, Anda harus memulai thread baru di dalam layanan.</p>
<p>Biasanya, ada dua kelas yang bisa Anda perluas untuk membuat layanan yang sudah dimulai:</p>
<dl>
<dt>{@link android.app.Service}</dt>
<dd>Ini adalah kelas dasar untuk semua layanan. Bila memperluas kelas ini, Anda perlu
membuat thread baru sebagai tempat melaksanakan semua pekerjaan layanan tersebut, karena layanan
menggunakan thread utama aplikasi Anda secara default, dan hal ini bisa memperlambat
kinerja aktivitas yang dijalankan aplikasi Anda.</dd>
<dt>{@link android.app.IntentService}</dt>
<dd>Ini adalah subkelas {@link android.app.Service} yang menggunakan thread pekerja untuk menangani
semua permintaan memulai, satu per satu. Ini adalah pilihan terbaik jika Anda tidak mengharuskan layanan
menangani beberapa permintaan sekaligus. Anda cukup mengimplementasikan {@link
android.app.IntentService#onHandleIntent onHandleIntent()}, yang menerima intent untuk setiap
permintaan memulai agar bisa melakukan pekerjaan latar belakang.</dd>
</dl>
<p>Bagian selanjutnya membahas cara mengimplementasikan layanan Anda menggunakan
salah satu dari kelas-kelas ini.</p>
<h3 id="ExtendingIntentService">Memperluas kelas IntentService</h3>
<p>Mengingat kebanyakan layanan yang sudah dimulai tidak perlu menangani beberapa permintaan
sekaligus (yang bisa berupa skenario multi-threading berbahaya), mungkin Anda sebaiknya mengimplementasikan
layanan menggunakan kelas {@link android.app.IntentService}.</p>
<p>Berikut ini yang dilakukan {@link android.app.IntentService}:</p>
<ul>
<li>Membuat thread pekerja default yang menjalankan semua intent yang disampaikan ke {@link
android.app.Service#onStartCommand onStartCommand()} terpisah dari thread utama aplikasi
Anda.</li>
<li>Membuat antrean pekerjaan yang meneruskan intent satu per satu ke implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()}, sehingga Anda tidak perlu
mengkhawatirkan multi-threading.</li>
<li>Menghentikan layanan setelah semua permintaan memulai telah ditangani, jadi Anda tidak perlu memanggil
{@link android.app.Service#stopSelf}.</li>
<li>Menyediakan implementasi default {@link android.app.IntentService#onBind onBind()} yang
mengembalikan null.</li>
<li>Menyediakan implementasi default {@link android.app.IntentService#onStartCommand
onStartCommand()} yang mengirimkan intent ke antrean pekerjaan kemudian ke implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()} Anda.</li>
</ul>
<p>Oleh karena itu, Anda hanya perlu mengimplementasikan {@link
android.app.IntentService#onHandleIntent onHandleIntent()} untuk melakukan pekerjaan yang diberikan oleh
klien. (Akan tetapi, Anda juga perlu menyediakan konstruktor kecil bagi layanan.)</p>
<p>Berikut ini contoh implementasi {@link android.app.IntentService}:</p>
<pre>
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
&#64;Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
</pre>
<p>Anda hanya memerlukan: konstruktor dan implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
<p>Jika Anda memutuskan untuk juga mengesampingkan metode callback lain, seperti {@link
android.app.IntentService#onCreate onCreate()}, {@link
android.app.IntentService#onStartCommand onStartCommand()}, atau {@link
android.app.IntentService#onDestroy onDestroy()}, pastikan memanggil implementasi super, sehingga
{@link android.app.IntentService} bisa menangani hidup thread pekerja dengan baik.</p>
<p>Misalnya, {@link android.app.IntentService#onStartCommand onStartCommand()} harus mengembalikan
implementasi default (yang merupakan cara penyampaian intent ke {@link
android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
<pre>
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
</pre>
<p>Selain {@link android.app.IntentService#onHandleIntent onHandleIntent()}, satu-satunya metode lain
yang tidak mengharuskan Anda memanggil super kelas adalah {@link android.app.IntentService#onBind
onBind()} (namun Anda hanya perlu mengimplementasikannya bila layanan mengizinkan pengikatan).</p>
<p>Dalam bagian berikutnya, Anda akan melihat bagaimana layanan serupa diimplementasikan saat
memperluas kelas {@link android.app.Service} basis, yang membutuhkan kode lebih banyak lagi, namun mungkin
cocok jika Anda perlu menangani beberapa permintaan memulai sekaligus.</p>
<h3 id="ExtendingService">Memperluas kelas Layanan</h3>
<p>Seperti telah Anda lihat di bagian sebelumnya, menggunakan {@link android.app.IntentService} membuat
implementasi layanan yang sudah dimulai jadi sangat sederhana. Namun, bila Anda mengharuskan layanan untuk
melakukan multi-threading (sebagai ganti memproses permintaan memulai melalui antrean pekerjaan), maka Anda
bisa memperluas kelas {@link android.app.Service} untuk menangani masing-masing intent.</p>
<p>Sebagai perbandingan, contoh kode berikut ini adalah implementasi kelas {@link
android.app.Service} yang melakukan pekerjaan yang persis sama dengan contoh di atas menggunakan {@link
android.app.IntentService}. Artinya, untuk setiap permintaan memulai, kode tersebut akan menggunakan thread pekerja
untuk melakukan pekerjaan dan memproses permintaan satu per satu.</p>
<pre>
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
&#64;Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
&#64;Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
&#64;Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
&#64;Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>Seperti yang bisa Anda lihat, ini membutuhkan lebih banyak pekerjaan daripada menggunakan {@link android.app.IntentService}.</p>
<p>Akan tetapi, karena Anda menangani sendiri setiap panggilan ke {@link android.app.Service#onStartCommand
onStartCommand()}, Anda bisa melakukan beberapa permintaan sekaligus. Itu bukan yang
dilakukan contoh ini, namun jika itu yang diinginkan, Anda bisa membuat thread baru untuk setiap
permintaan dan langsung menjalankannya (sebagai ganti menunggu permintaan sebelumnya selesai).</p>
<p>Perhatikan bahwa metode {@link android.app.Service#onStartCommand onStartCommand()} harus mengembalikan
integer. Integer tersebut merupakan nilai yang menjelaskan cara sistem melanjutkan layanan dalam
kejadian yang dimatikan oleh sistem (sebagaimana dibahas di atas, implementasi default {@link
android.app.IntentService} menangani hal ini untuk Anda, walaupun Anda bisa memodifikasinya). Nilai yang dikembalikan
dari {@link android.app.Service#onStartCommand onStartCommand()} harus berupa salah satu
konstanta berikut ini:</p>
<dl>
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} dikembalikan, <em>jangan</em> membuat lagi layanan tersebut, kecuali jika ada intent
tertunda yang akan disampaikan. Inilah pilihan teraman untuk menghindari menjalankan layanan Anda
bila tidak diperlukan dan bila aplikasi Anda bisa me-restart pekerjaan yang belum selesai.</dd>
<dt>{@link android.app.Service#START_STICKY}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} dikembalikan, buat kembali layanan dan panggil {@link
android.app.Service#onStartCommand onStartCommand()}, namun <em>jangan</em> menyampaikan ulang intent terakhir.
Sebagai gantinya, sistem akan memanggil {@link android.app.Service#onStartCommand onStartCommand()} dengan
intent null, kecuali jika ada intent tertunda untuk memulai layanan, dan dalam hal ini,
intent tersebut disampaikan. Ini cocok bagi pemutar media (atau layanan serupa) yang tidak
mengeksekusi perintah, namun berjalan terus-menerus dan menunggu pekerjaan.</dd>
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} kembali, buat kembali layanan dan panggil {@link
android.app.Service#onStartCommand onStartCommand()} dengan intent terakhir yang disampaikan ke
layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok bagi layanan yang
aktif melakukan pekerjaan yang harus segera dilanjutkan, misalnya mengunduh file.</dd>
</dl>
<p>Untuk detail selengkapnya tentang nilai pengembalian ini, lihat dokumentasi acuan untuk setiap
konstanta.</p>
<h3 id="StartingAService">Memulai Layanan</h3>
<p>Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan meneruskan
{@link android.content.Intent} (yang menetapkan layanan yang akan dimulai) ke {@link
android.content.Context#startService startService()}. Sistem Android akan memanggil metode {@link
android.app.Service#onStartCommand onStartCommand()} layanan dan meneruskan {@link
android.content.Intent} padanya. (Jangan sekali-kali memanggil {@link android.app.Service#onStartCommand
onStartCommand()} secara langsung.)</p>
<p>Misalnya, aktivitas bisa memulai contoh layanan di bagian sebelumnya ({@code
HelloSevice}) menggunakan intent eksplisit dengan {@link android.content.Context#startService
startService()}:</p>
<pre>
Intent intent = new Intent(this, HelloService.class);
startService(intent);
</pre>
<p>Metode {@link android.content.Context#startService startService()} segera kembali dan
sistem Android akan memanggil metode {@link android.app.Service#onStartCommand
onStartCommand()} layanan. Jika layanan belum berjalan, sistem mula-mula memanggil {@link
android.app.Service#onCreate onCreate()}, kemudian memanggil {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Jika layanan juga tidak menyediakan pengikatan, intent yang disampaikan dengan {@link
android.content.Context#startService startService()} adalah satu-satunya mode komunikasi antara
komponen aplikasi dan layanan. Akan tetapi, jika Anda ingin agar layanan mengirimkan hasilnya kembali, maka
klien yang memulai layanan bisa membuat {@link android.app.PendingIntent} untuk siaran
(dengan {@link android.app.PendingIntent#getBroadcast getBroadcast()}) dan menyampaikannya ke layanan
dalam {@link android.content.Intent} yang memulai layanan. Layanan kemudian bisa menggunakan
siaran untuk menyampaikan hasil.</p>
<p>Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan pula ke
{@link android.app.Service#onStartCommand onStartCommand()} layanan. Akan tetapi, hanya satu permintaan untuk menghentikan
layanan (dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}) dibutuhkan untuk menghentikannya.</p>
<h3 id="Stopping">Menghentikan layanan</h3>
<p>Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak menghentikan atau
memusnahkan layanan kecuali jika harus memulihkan memori sistem dan layanan
terus berjalan setelah {@link android.app.Service#onStartCommand onStartCommand()} kembali. Jadi,
layanan tersebut harus berhenti sendiri dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau
komponen lain bisa menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Setelah diminta untuk berhenti dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}, sistem akan menghapus layanan
secepatnya.</p>
<p>Akan tetapi, bila layanan Anda menangani beberapa permintaan ke {@link
android.app.Service#onStartCommand onStartCommand()} sekaligus, Anda tidak boleh menghentikan
layanan bila Anda baru selesai memproses permintaan memulai, karena setelah itu mungkin Anda sudah menerima permintaan memulai
yang baru (berhenti pada permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari
masalah ini, Anda bisa menggunakan {@link android.app.Service#stopSelf(int)} untuk memastikan bahwa permintaan
Anda untuk menghentikan layanan selalu berdasarkan pada permintaan memulai terbaru. Artinya, bila Anda memanggil {@link
android.app.Service#stopSelf(int)}, Anda akan meneruskan ID permintaan memulai (<code>startId</code>
yang disampaikan ke {@link android.app.Service#onStartCommand onStartCommand()}) yang terkait dengan permintaan berhenti
Anda. Kemudian jika layanan menerima permintaan memulai baru sebelum Anda bisa memanggil {@link
android.app.Service#stopSelf(int)}, maka ID tidak akan sesuai dan layanan tidak akan berhenti.</p>
<p class="caution"><strong>Perhatian:</strong> Aplikasi Anda perlu menghentikan layanannya
bila selesai bekerja untuk menghindari pemborosan sumber daya sistem dan tenaga baterai. Jika perlu,
komponen lain bisa menghentikan layanan secara eksplisit dengan memanggil {@link
android.content.Context#stopService stopService()}. Bahkan jika Anda mengaktifkan pengikatan bagi layanan,
Anda harus selalu menghentikan layanan sendiri jika layanan tersebut menerima panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()}.</p>
<p>Untuk informasi selengkapnya tentang daur hidup layanan, lihat bagian di bawah ini tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>.</p>
<h2 id="CreatingBoundService">Membuat Layanan Terikat</h2>
<p>Layanan terikat adalah layanan yang memungkinkan komponen aplikasi untuk mengikatnya dengan memanggil {@link
android.content.Context#bindService bindService()} guna membuat koneksi yang berlangsung lama
(dan umumnya tidak mengizinkan komponen untuk <em>memulainya</em> dengan memanggil {@link
android.content.Context#startService startService()}).</p>
<p>Anda sebaiknya membuat layanan terikat bila ingin berinteraksi dengan layanan dari aktivitas
dan komponen lain dalam aplikasi Anda atau mengeskpos sebagian fungsionalitas aplikasi Anda ke
ke aplikasi lain, melalui komunikasi antarproses (IPC).</p>
<p>Untuk membuat layanan terikat, Anda harus mengimplementasikan metode callback {@link
android.app.Service#onBind onBind()} untuk mengembalikan {@link android.os.IBinder} yang
mendefinisikan antarmuka bagi komunikasi dengan layanan. Komponen aplikasi lain kemudian bisa memanggil
{@link android.content.Context#bindService bindService()} untuk mengambil antarmuka dan
mulai memanggil metode pada layanan. Layanan hanya hidup untuk melayani komponen aplikasi yang
terikat padanya, jadi bila tidak ada komponen yang terikat pada layanan, sistem akan memusnahkannya
(Anda <em>tidak</em> perlu menghentikan layanan terikat seperti halnya bila layanan dimulai
melalui {@link android.app.Service#onStartCommand onStartCommand()}).</p>
<p>Untuk membuat layanan terikat, hal yang perlu dilakukan pertama kali adalah mendefinisikan antarmuka yang menetapkan
cara klien berkomunikasi dengan layanan. Antarmuka antara layanan
dan klien ini harus berupa implementasi {@link android.os.IBinder} dan yang harus dikembalikan
layanan Anda dari metode callback {@link android.app.Service#onBind
onBind()}. Setelah menerima {@link android.os.IBinder}, klien bisa mulai
berinteraksi dengan layanan melalui antarmuka tersebut.</p>
<p>Beberapa klien bisa mengikat ke layanan sekaligus. Bila klien selesai berinteraksi dengan
layanan, klien akan memanggil {@link android.content.Context#unbindService unbindService()} untuk melepas ikatan. Bila
tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.</p>
<p>Ada beberapa cara untuk mengimplementasikan layanan terikat dan implementasinya lebih
rumit daripada layanan yang sudah dimulai, jadi layanan terikat dibahas dalam dokumen
terpisah tentang <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>.</p>
<h2 id="Notifications">Mengirim Pemberitahuan ke Pengguna</h2>
<p>Setelah berjalan, layanan bisa memberi tahu pengguna tentang suatu kejadian menggunakan <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>.</p>
<p>Pemberitahuan Toast adalah pesan yang muncul sebentar pada permukaan jendela saat ini
kemudian menghilang, sementara pemberitahuan baris status memberikan ikon di baris status dengan
pesan yang bisa dipilih oleh pengguna untuk melakukan suatu tindakan (misalnya memulai suatu aktivitas).</p>
<p>Biasanya, pemberitahuan baris status adalah teknik terbaik bila ada pekerjaan latar belakang yang sudah selesai
(misalnya file selesai
diunduh) dan pengguna kini bisa menggunakannya. Bila pengguna memilih pemberitahuan dari
tampilan diperluas, pemberitahuan akan bisa memulai aktivitas (misalnya menampilkan file yang baru diunduh).</p>
<p>Lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>
untuk informasi selengkapnya.</p>
<h2 id="Foreground">Menjalankan Layanan di Latar Depan</h2>
<p>Layanan latar depan adalah layanan yang dianggap sebagai sesuatu yang
diketahui secara aktif oleh pengguna, jadi bukan sesuatu yang akan dihapus oleh sistem bila memori menipis. Sebuah
layanan latar depan harus memberikan pemberitahuan bagi baris status, yang ditempatkan pada
heading "Ongoing" yang artinya pemberitahuan tersebut tidak bisa diabaikan kecuali jika layanan
dihentikan atau dihapus dari latar depan.</p>
<p>Misalnya, pemutar musik yang memutar musik dari suatu layanan harus diatur untuk berjalan di
latar depan, karena pengguna mengetahui operasi tersebut
secara eksplisit. Pemberitahuan di baris status bisa menunjukkan lagu saat ini dan memungkinkan
pengguna untuk menjalankan suatu aktivitas untuk berinteraksi dengan pemutar musik.</p>
<p>Untuk meminta agar layanan Anda berjalan di latar depan, panggil {@link
android.app.Service#startForeground startForeground()}. Metode ini memerlukan dua parameter: sebuah integer
yang mengidentifikasi pemberitahuan secara unik dan {@link
android.app.Notification} untuk baris status. Misalnya:</p>
<pre>
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
</pre>
<p class="caution"><strong>Perhatian:</strong> ID integer yang Anda berikan ke {@link
android.app.Service#startForeground startForeground()} tidak boleh 0.</p>
<p>Untuk menghapus layanan dari latar depan, panggil {@link
android.app.Service#stopForeground stopForeground()}. Metode ini memerlukan boolean, yang menunjukkan
apakah pemberitahuan baris status juga akan dihapus. Metode ini <em>tidak</em> menghentikan
layanan. Akan tetapi, jika Anda menghentikan layanan saat masih berjalan di latar depan
maka pemberitahuan juga akan dihapus.</p>
<p>Untuk informasi selengkapnya tentang pemberitahuan, lihat <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Membuat Pemberitahuan
Baris Status</a>.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Layanan</h2>
<p>Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Akan tetapi, lebih penting lagi adalah
memerhatikan dengan cermat bagaimana layanan Anda dibuat dan dimusnahkan, karena suatu layanan
bisa berjalan di latar belakang tanpa disadari oleh pengguna.</p>
<p>Daur hidup layanan&mdash;dari saat dibuat hingga dimusnahkan&mdash;bisa mengikuti
dua path berbeda:</p>
<ul>
<li>Layanan yang sudah dimulai
<p>Layanan dibuat bila komponen lain memanggil {@link
android.content.Context#startService startService()}. Layanan kemudian berjalan terus-menerus dan harus
berhenti sendiri dengan memanggil {@link
android.app.Service#stopSelf() stopSelf()}. Komponen lain juga bisa menghentikan
layanan dengan memanggil {@link android.content.Context#stopService
stopService()}. Bila layanan dihentikan, sistem akan menghancurkannya.</p></li>
<li>Layanan terikat
<p>Layanan dibuat bila komponen lain (klien) memanggil {@link
android.content.Context#bindService bindService()}. Klien kemudian berkomunikasi dengan layanan
melalui antarmuka {@link android.os.IBinder}. Klien bisa menutup koneksi dengan memanggil
{@link android.content.Context#unbindService unbindService()}. Sejumlah klien bisa mengikat pada
layanan yang sama dan bila semuanya melepas ikatan, sistem akan memusnahkan layanan tersebut. (Layanan
<em>tidak</em> perlu berhenti sendiri.)</p></li>
</ul>
<p>Kedua path tersebut tidak benar-benar terpisah. Artinya, Anda bisa mengikat ke layanan yang sudah
dimulai dengan {@link android.content.Context#startService startService()}. Misalnya, layanan
musik latar belakang bisa dimulai dengan memanggil {@link android.content.Context#startService
startService()} dengan {@link android.content.Intent} yang mengidentifikasi musik yang akan diputar. Kemudian,
mungkin saat pengguna ingin mengontrol pemutar musik atau mendapatkan informasi
tentang lagu yang diputar, aktivitas bisa mengikat ke layanan dengan memanggil {@link
android.content.Context#bindService bindService()}. Dalam kasus seperti ini, {@link
android.content.Context#stopService stopService()} atau {@link android.app.Service#stopSelf
stopSelf()} tidak menghentikan layanan sampai semua klien melepas ikatan. </p>
<h3 id="LifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
<p>Seperti halnya aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan
untuk memantau perubahan status layanan dan melakukan pekerjaan pada waktu yang tepat. Layanan skeleton
berikut memperagakan setiap metode daur hidup:</p>
<pre>
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
&#64;Override
public void {@link android.app.Service#onCreate onCreate}() {
// The service is being created
}
&#64;Override
public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
// The service is starting, due to a call to {@link android.content.Context#startService startService()}
return <em>mStartMode</em>;
}
&#64;Override
public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()}
return <em>mBinder</em>;
}
&#64;Override
public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
// All clients have unbound with {@link android.content.Context#unbindService unbindService()}
return <em>mAllowRebind</em>;
}
&#64;Override
public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()},
// after onUnbind() has already been called
}
&#64;Override
public void {@link android.app.Service#onDestroy onDestroy}() {
// The service is no longer used and is being destroyed
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Tidak seperti metode callback daur hidup aktivitas, Anda
<em>tidak</em> perlu memanggil implementasi superkelas metode callback tersebut.</p>
<img src="{@docRoot}images/service_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup layanan. Diagram di sebelah kiri
menampilkan daur hidup bila layanan dibuat dengan {@link android.content.Context#startService
startService()} dan diagram di sebelah kanan menampilkan daur hidup bila layanan dibuat
dengan {@link android.content.Context#bindService bindService()}.</p>
<p>Dengan mengimplementasikan metode-metode ini, Anda bisa memantau dua loop tersarang (nested loop) daur hidup layanan: </p>
<ul>
<li><strong>Seluruh masa pakai</strong> layanan terjadi antara saat {@link
android.app.Service#onCreate onCreate()} dipanggil dan saat {@link
android.app.Service#onDestroy} kembali. Seperti halnya aktivitas, layanan melakukan penyiapan awal di
{@link android.app.Service#onCreate onCreate()} dan melepaskan semua sisa sumber daya yang ada di {@link
android.app.Service#onDestroy onDestroy()}. Misalnya,
layanan pemutar musik bisa membuat thread tempat musik akan diputar dalam {@link
android.app.Service#onCreate onCreate()}, kemudian menghentikan thread tersebut dalam {@link
android.app.Service#onDestroy onDestroy()}.
<p>Metode {@link android.app.Service#onCreate onCreate()} dan {@link android.app.Service#onDestroy
onDestroy()} diperlukan semua layanan, baik yang
dibuat oleh {@link android.content.Context#startService startService()} maupun {@link
android.content.Context#bindService bindService()}.</p></li>
<li><strong>Masa pakai aktif</strong> layanan dimulai dengan panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()} atau {@link android.app.Service#onBind onBind()}.
Masing-masing metode diberikan {@link
android.content.Intent} yang diteruskan ke {@link android.content.Context#startService
startService()} atau {@link android.content.Context#bindService bindService()}.
<p>Jika layanan telah dimulai, masa pakai aktif akan berakhir pada saat yang sama dengan
berakhirnya seluruh masa pakai (layanan masih aktif bahkan setelah {@link android.app.Service#onStartCommand
onStartCommand()} kembali). Jika layanan tersebut terikat, masa pakai aktifnya akan berakhir bila {@link
android.app.Service#onUnbind onUnbind()} kembali.</p>
</li>
</ul>
<p class="note"><strong>Catatan:</strong> Meskipun layanan yang sudah dimulai dihentikan dengan panggilan ke
{@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}, tidak ada callback tersendiri bagi
layanan tersebut (tidak ada callback {@code onStop()}). Jadi, kecuali jika layanan terikat ke klien,
sistem akan memusnahkannya bila layanan dihentikan&mdash;{@link
android.app.Service#onDestroy onDestroy()} adalah satu-satunya callback yang diterima.</p>
<p>Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Walaupun gambar tersebut memisahkan
layanan yang dibuat oleh {@link android.content.Context#startService startService()} dari layanan
yang dibuat oleh {@link android.content.Context#bindService bindService()}, ingatlah
bahwa suatu layanan, bagaimana pun dimulainya, bisa memungkinkan klien mengikat padanya.
Jadi, suatu layanan yang awalnya dimulai dengan {@link android.app.Service#onStartCommand
onStartCommand()} (oleh klien yang memanggil {@link android.content.Context#startService startService()})
masih bisa menerima panggilan ke {@link android.app.Service#onBind onBind()} (bila klien memanggil
{@link android.content.Context#bindService bindService()}).</p>
<p>Untuk informasi selengkapnya tentang membuat layanan yang menyediakan pengikatan, lihat dokumen <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>,
yang menyertakan informasi selengkapnya tentang metode callback {@link android.app.Service#onRebind onRebind()}
di bagian tentang <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Mengelola Daur Hidup
Layanan Terikat</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>To learn how to query data from the system or other applications (such as contacts or media
stored on the device), continue with the <b><a
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
document.</p>
-->

View File

@@ -1,578 +0,0 @@
page.title=Tugas dan Back-Stack
parent.title=Aktivitas
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#ActivityState">Menyimpan Status Aktivitas</a></li></li>
<li><a href="#ManagingTasks">Mengelola Tugas</a>
<ol>
<li><a href="#TaskLaunchModes">Mendefinisikan mode peluncuran</a></li>
<li><a href="#Affinities">Menangani afinitas</a></li>
<li><a href="#Clearing">Menghapus back-stack</a></li>
<li><a href="#Starting">Memulai tugas</a></li>
</ol>
</li>
</ol>
<h2>Artikel</h2>
<ol>
<li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html">
Multitasking Ala Android</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}design/patterns/navigation.html">Desain Android:
Navigasi</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html">Elemen manifes
{@code &lt;activity&gt;}</a></li>
<li><a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a></li>
</ol>
</div>
</div>
<p>Sebuah aplikasi biasanya berisi beberapa <a href="{@docRoot}guide/components/activities.html">aktivitas</a>. Setiap aktivitas
harus didesain dengan jenis tindakan tertentu yang bisa dilakukan pengguna dan bisa memulai aktivitas
lain. Misalnya, aplikasi email mungkin memiliki satu aktivitas untuk menampilkan daftar pesan baru.
Bila pengguna memilih sebuah pesan, aktivitas baru akan terbuka untuk melihat pesan tersebut.</p>
<p>Aktivitas bahkan bisa memulai aktivitas yang ada dalam aplikasi lain di perangkat. Misalnya
, jika aplikasi Anda ingin mengirim pesan email, Anda bisa mendefinisikan intent untuk melakukan tindakan
"kirim" dan menyertakan sejumlah data, seperti alamat email dan pesan. Aktivitas dari aplikasi
lain yang mendeklarasikan dirinya untuk menangani jenis intent ini akan terbuka. Dalam hal ini, intent
tersebut untuk mengirim email, sehingga aktivitas "menulis" pada aplikasi email akan dimulai (jika beberapa aktivitas
mendukung intent yang sama, maka sistem akan memungkinkan pengguna memilih mana yang akan digunakan). Bila email telah
dikirim, aktivitas Anda akan dilanjutkan dan seolah-olah aktivitas email adalah bagian dari aplikasi Anda. Meskipun
aktivitas mungkin dari aplikasi yang berbeda, Android akan tetap mempertahankan pengalaman pengguna yang mulus
dengan menjalankan kedua aktivitas dalam <em>tugas</em> yang sama.</p>
<p>Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna
saat melakukan pekerjaan tertentu. Aktivitas tersebut diatur dalam tumpukan (<em>back-stack</em>), dalam
urutan membuka setiap aktivitas.</p>
<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Adding fragments to a task's back stack</h3>
<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
other being a layout to display an item from the list (fragment B). When the user selects an item
from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
C.</p>
<p>For more information about using fragments and adding them to the back stack, see the {@link
android.app.Fragment} class documentation.</p>
</div>
</div>
-->
<p>Layar Home perangkat adalah tempat memulai hampir semua tugas. Bila pengguna menyentuh ikon di launcher
aplikasi
(atau pintasan pada layar Home), tugas aplikasi tersebut akan muncul pada latar depan. Jika tidak ada
tugas untuk aplikasi (aplikasi tidak digunakan baru-baru ini), maka tugas baru
akan dibuat dan aktivitas "utama" untuk aplikasi tersebut akan terbuka sebagai aktivitas akar dalam back-stack.</p>
<p>Bila aktivitas saat ini dimulai lagi, aktivitas baru akan didorong ke atas back-stack dan
mengambil fokus. Aktivitas sebelumnya tetap dalam back-stack, namun dihentikan. Bila aktivitas
dihentikan, sistem akan mempertahankan status antarmuka penggunanya saat ini. Bila pengguna menekan tombol
<em>Back</em>
, aktivitas saat ini akan dikeluarkan dari atas back-stack (aktivitas dimusnahkan) dan
aktivitas sebelumnya dilanjutkan (status UI sebelumnya dipulihkan). Aktivitas dalam back-stack
tidak pernah disusun ulang, hanya didorong dan dikeluarkan dari back-stack&mdash;yang didorong ke back-stack saat dimulai oleh
aktivitas saat ini dan dikeluarkan bila pengguna meninggalkannya menggunakan tombol <em>Back</em>. Dengan demikian,
back-stack
beroperasi sebagai struktur objek "masuk terakhir, keluar pertama". Gambar 1 melukiskan perilaku
ini dengan jangka waktu yang menunjukkan kemajuan antar aktivitas beserta
back-stack pada setiap waktu.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Representasi tentang cara setiap aktivitas baru dalam
tugas menambahkan item ke back-stack. Bila pengguna menekan tombol <em>Back</em>, aktivitas
saat ini
akan dimusnahkan dan aktivitas sebelumnya dilanjutkan.</p>
<p>Jika pengguna terus menekan <em>Back</em>, maka setiap aktivitas dalam back-stack akan dikeluarkan untuk
menampilkan
yang sebelumnya, sampai pengguna kembali ke layar Home (atau aktivitas mana pun yang sedang dijalankan saat tugas
dimulai. Bila semua aktivitas telah dihapus dari back-stack, maka tugas tidak akan ada lagi.</p>
<div class="figure" style="width:287px">
<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
class="img-caption"><strong>Gambar 2.</strong> Dua tugas: Tugas B menerima interaksi pengguna
di latar depan, sedangkan Tugas A di latar belakang, menunggu untuk dilanjutkan.</p>
</div>
<div class="figure" style="width:215px">
<img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
class="img-caption"><strong>Gambar 3.</strong> Satu aktivitas dibuat instance-nya beberapa kali.</p>
</div>
<p>Tugas adalah unit kohesif yang bisa dipindahkan ke "latar belakang" bila pengguna memulai tugas baru atau masuk ke
layar Home, melalui tombol<em>Home</em>. Sementara di latar belakang, semua aktivitas dalam
tugas
dihentikan, namun back-stack untuk tugas tidak berubah&mdash;tugas kehilangan fokus saat
tugas lain berlangsung, seperti yang ditampilkan dalam gambar 2. Kemudian, tugas bisa kembali ke "latar depan" agar pengguna
bisa melanjutkan tugas di tempat menghentikannya. Anggaplah, misalnya, tugas saat ini (Tugas A) memiliki tiga
aktivitas dalam back-stack&mdash;dua pada aktivitas saat ini. Pengguna menekan tombol <em>Home</em>
, kemudian
memulai aplikasi baru dari launcher aplikasi. Bila muncul layar Home, Tugas A akan beralih
ke latar belakang. Bila aplikasi baru dimulai, sistem akan memulai tugas untuk aplikasi tersebut
(Tugas B) dengan back-stack aktivitas sendiri. Setelah berinteraksi dengan aplikasi
tersebut, pengguna akan kembali ke Home lagi dan memilih aplikasi yang semula
memulai Tugas A. Sekarang, Tugas A muncul di
latar depan&mdash;ketiga aktivitas dalam back-stack tidak berubah dan aktivitas di atas
back-stack akan dilanjutkan. Pada
titik ini pengguna juga bisa beralih kembali ke Tugas B dengan masuk ke Home dan memilih ikon aplikasi
yang memulai tugas tersebut (atau dengan memilih tugas aplikasi dari
<a href="{@docRoot}guide/components/recents.html">layar ikhtisar</a>).
Ini adalah contoh dari melakukan multitasking di Android.</p>
<p class="note"><strong>Catatan:</strong> Beberapa tugas bisa berlangsung di latar belakang secara bersamaan.
Akan tetapi, jika pengguna menjalankan banyak tugas di latar belakang sekaligus, sistem mungkin mulai
menghapus aktivitas latar belakang untuk memulihkan memori, yang akan menyebabkan status aktivitas hilang.
Lihat bagian berikut tentang <a href="#ActivityState">Status aktivitas</a>.</p>
<p>Karena aktivitas di back-stack tidak pernah diatur ulang, jika aplikasi Anda memungkinkan
pengguna untuk memulai aktivitas tertentu dari lebih dari satu aktivitas, instance baru
aktivitas tersebut akan dibuat dan didorong ke back-stack (bukannya memunculkan instance sebelumnya dari
aktivitas ke atas). Dengan demikian, satu aktivitas pada aplikasi Anda mungkin dibuat beberapa
kali (bahkan dari beberapa tugas), seperti yang ditampilkan dalam gambar 3. Dengan demikian, jika pengguna mengarahkan mundur
menggunakan tombol <em>Back</em>, setiap instance aktivitas ini akan ditampilkan dalam urutan saat
dibuka (masing-masing
dengan status UI sendiri). Akan tetapi, Anda bisa memodifikasi perilaku ini jika tidak ingin aktivitas
dibuat instance-nya lebih dari sekali. Caranya dibahas di bagian selanjutnya tentang <a href="#ManagingTasks">Mengelola Tugas</a>.</p>
<p>Untuk meringkas perilaku default aktivitas dan tugas:</p>
<ul>
<li>Bila Aktivitas A memulai Aktivitas B, Aktivitas A dihentikan, namun sistem mempertahankan statusnya
(seperti posisi gulir dan teks yang dimasukkan ke dalam formulir).
Jika pengguna menekan tombol <em>Back</em> saat dalam Aktivitas B, Aktivitas A akan dilanjutkan dengan status
yang dipulihkan.</li>
<li>Bila pengguna meninggalkan tugas dengan menekan tombol <em>Home</em> aktivitas saat ini akan
dihentikan dan
tugas beralih ke latar belakang. Sistem akan mempertahankan status setiap aktivitas dalam tugas. Jika
nanti pengguna melanjutkan tugas dengan memilih ikon launcher yang memulai tugas, tugas tersebut akan
beralih ke latar depan dan melanjutkan aktivitas di atas back-stack.</li>
<li>Jika pengguna menekan tombol <em>Back</em>, aktivitas saat ini akan dikeluarkan dari back-stack
dan
dimusnahkan. Aktivitas sebelumnya dalam back-stack akan dilanjutkan. Bila suatu aktivitas dimusnahkan, sistem
<em>tidak akan</em>mempertahankan status aktivitas.</li>
<li>Aktivitas bisa dibuat instance-nya beberapa kali, bahkan dari tugas-tugas lainnya.</li>
</ul>
<div class="note design">
<p><strong>Desain Navigasi</strong></p>
<p>Untuk mengetahui selengkapnya tentang cara kerja navigasi aplikasi di Android, baca panduan <a href="{@docRoot}design/patterns/navigation.html">Navigasi</a> Desain Android.</p>
</div>
<h2 id="ActivityState">Menyimpan Status Aktivitas</h2>
<p>Seperti dibahas di atas, perilaku default sistem akan mempertahankan status aktivitas bila
dihentikan. Dengan cara ini, bila pengguna mengarah kembali ke aktivitas sebelumnya, antarmuka pengguna akan muncul
seperti saat ditinggalkan. Akan tetapi, Anda bisa&mdash;dan <strong>harus</strong>&mdash;secara proaktif mempertahankan
status aktivitas menggunakan metode callback, jika aktivitas ini dimusnahkan dan harus
dibuat kembali.</p>
<p>Bila sistem menghentikan salah satu aktivitas (seperti saat aktivitas baru dimulai atau tugas
dipindah ke latar belakang), sistem mungkin memusnahkan aktivitas sepenuhnya jika perlu memulihkan
memori sistem. Bila hal ini terjadi, informasi tentang status aktivitas akan hilang. Jika hal ini terjadi, sistem
masih
mengetahui bahwa aktivitas memiliki tempat di back-stack, namun saat aktivitas tersebut dibawa ke bagian teratas
back-stack, sistem harus membuatnya kembali (bukan melanjutkannya). Untuk
menghindari hilangnya pekerjaan pengguna, Anda harus secara proaktif mempertahankannya dengan menerapkan metode callback
{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
dalam aktivitas.</p>
<p>Untuk informasi selengkapnya tentang cara menyimpan status aktivitas Anda, lihat dokumen
<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>.</p>
<h2 id="ManagingTasks">Mengelola Tugas</h2>
<p>Cara Android mengelola tugas dan back-stack, seperti yang dijelaskan di atas&mdash;dengan menempatkan semua
aktivitas yang dimulai secara berurutan dalam tugas yang sama dan dalam back-stack "masuk terakhir, keluar pertama"&mdash;berfungsi
dengan baik untuk kebanyakan aplikasi dan Anda tidak perlu khawatir tentang cara mengaitkan aktivitas
dengan tugas atau cara penempatannya di back-stack. Akan tetapi, Anda bisa memutuskan apakah ingin menyela
perilaku normal. Mungkin Anda ingin agar suatu aktivitas dalam aplikasi untuk memulai tugas baru bila telah
dimulai (sebagai ganti menempatkannya dalam tugas saat ini); atau, bila memulai aktivitas, Anda ingin
memajukan instance yang ada (sebagai ganti membuat instance
baru pada bagian teratas back-stack); atau, Anda ingin back-stack dihapus dari semua
aktivitas selain untuk aktivitas akar bila pengguna meninggalkan tugas.</p>
<p>Anda bisa melakukan semua ini dan lainnya, dengan atribut dalam elemen manifes
<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
dan dengan flag pada intent yang Anda teruskan ke
{@link android.app.Activity#startActivity startActivity()}.</p>
<p>Dalam hal ini, atribut<a href="{@docRoot}guide/topics/manifest/activity-element.html">
{@code &lt;activity&gt;}</a> utama yang bisa Anda gunakan adalah:</p>
<ul class="nolist">
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">
{@code taskAffinity}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">
{@code launchMode}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">
{@code clearTaskOnLaunch}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">
{@code finishOnTaskLaunch}</a></li>
</ul>
<p>Dan flag intent utama yang bisa Anda gunakan adalah:</p>
<ul class="nolist">
<li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
</ul>
<p>Dalam bagian berikut, Anda akan melihat cara menggunakan beberapa atribut manifes ini dan flag
intent untuk mendefinisikan cara mengaitkan aktivitas dengan tugas dan cara perilakunya di back-stack.</p>
<p>Juga, pertimbangan cara menyatakan dan mengelola tugas dan aktivitas
dibahas secara terpisah di layar ikhtisar. Lihat <a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a>
untuk informasi selengkapnya. Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.</p>
<p class="caution"><strong>Perhatian:</strong> Kebanyakan aplikasi tidak harus menyela perilaku
default untuk aktivitas dan tugas. Jika merasa bahwa aktivitas Anda perlu memodifikasi
perilaku default, lakukan dengan hati-hati dan pastikan menguji kegunaan aktivitas selama
dijalankan dan saat mengarahkan kembali ke sana dari aktivitas dan tugas lain dengan tombol <em>Back</em>.
Pastikan menguji perilaku navigasi yang mungkin bertentangan dengan perilaku yang diharapkan pengguna.</p>
<h3 id="TaskLaunchModes">Mendefinisikan mode peluncuran</h3>
<p>Mode peluncuran memungkinkan Anda mendefinisikan cara mengaitkan instance baru dari suatu aktivitas dengan
tugas saat ini. Anda bisa mendefinisikan beragam mode peluncuran dalam dua cara:</p>
<ul class="nolist">
<li><a href="#ManifestForTasks">Menggunakan file manifes</a>
<p>Bila Anda mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
dengan tugas-tugas saat mulai.</li>
<li><a href="#IntentFlagsForTasks">Menggunakan flag intent</a>
<p>Saat memanggil{@link android.app.Activity#startActivity startActivity()},
Anda bisa menyertakan flag dalam {@link android.content.Intent} yang menyatakan cara (atau
apakah) aktivitas baru tersebut harus dikaitkan dengan tugas saat ini.</p></li>
</ul>
<p>Dengan demikian, jika Aktivitas A memulai Aktivitas B, Aktivitas B bisa mendefinisikan dalam manifesnya cara
mengaitkan dengan tugas saat ini (jika sama sekali) dan Aktivitas A juga bisa meminta cara mengaitkan Aktivitas B
dengan tugas saat ini. Jika kedua aktivitas mendefinisikan cara mengaitkan Aktivitas B
dengan tugas, maka permintaan Aktivitas A (sebagaimana didefinisikan dalam intent) lebih dihargai daripada
permintaan Aktivitas B (sebagaimana didefinisikan dalam manifesnya).</p>
<p class="note"><strong>Catatan:</strong> Beberapa mode peluncuran yang tersedia untuk file manifes
tidak tersedia sebagai flag untuk intent dan, juga, beberapa mode peluncuran yang tersedia sebagai flag
untuk intent tidak bisa didefinisikan dalam manifest.</p>
<h4 id="ManifestForTasks">Menggunakan file manifes</h4>
<p>Saat mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
dengan tugas menggunakan <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
melalui atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> elemen.</p>
<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> menetapkan instruksi tentang cara meluncurkan aktivitas
ke dalam tugas. Ada empat macam mode peluncuran yang bisa Anda tetapkan ke atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>
:</p>
<dl>
<dt>{@code "standard"} (mode default)</dt>
<dd>Default. Sistem membuat instance baru aktivitas dalam tugas yang
akan menjadi tempat memulainya dan mengarahkan intent ke sana. Aktivitas ini bisa dibuat instance-nya beberapa kali,
masing-masing instance bisa dimiliki oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance.</dd>
<dt>{@code "singleTop"}</dt>
<dd>Jika instance aktivitas sudah ada di bagian teratas tugas saat ini, sistem
akan mengarahkan intent ke instance tersebut melalui panggilan ke metode {@link
android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru dari
aktivitas tersebut. Aktivitas bisa dibuat instance-nya beberapa kali, masing-masing instance bisa dimiliki
oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance (namun hanya jika
aktivitas di bagian teratas back-stack <em>bukan</em> instance yang ada dari aktivitas tersebut).
<p>Misalnya, anggaplah back-stack tugas terdiri dari aktivitas A akar dengan aktivitas B, C,
dan D di bagian teratas (back-stack adalah A-B-C-D; D yang teratas). Intent masuk untuk aktivitas tipe D.
Jika D memiliki mode peluncuran {@code "standard"} default, instance baru dari kelas ini akan diluncurkan dan
back-stack menjadi A-B-C-D-D. Namun, jika mode peluncuran D adalah {@code "singleTop"}, instance
yang ada dari D akan menerima intent melalui {@link
android.app.Activity#onNewIntent onNewIntent()}, karena ada di bagian teratas back-stack&mdash;
back-stack tetap A-B-C-D. Akan tetapi, jika intent masuk untuk aktivitas tipe B, maka
instance B baru akan ditambahkan ke back-stack, sekalipun mode peluncuran adalah{@code "singleTop"}.</p>
<p class="note"><strong>Catatan:</strong> Bila instance dari aktivitas baru telah dibuat,
pengguna bisa menekan tombol <em>Back</em> untuk kembali ke aktivitas sebelumnya. Namun bila instance
yang ada dari
aktivitas menangani intent baru, pengguna tidak bisa menekan tombol <em>Back</em> untuk kembali ke
status
aktivitas sebelum intent baru masuk di {@link android.app.Activity#onNewIntent
onNewIntent()}.</p>
</dd>
<dt>{@code "singleTask"}</dt>
<dd>Sistem membuat tugas baru dan membuat instance aktivitas di akar tugas baru.
Akan tetapi, jika instance aktivitas sudah ada dalam tugas terpisah, sistem akan mengarahkan
intent ke instance yang ada melalui panggilan ke metode {@link
android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru. Hanya
boleh ada satu instance aktivitas untuk setiap kalinya.
<p class="note"><strong>Catatan:</strong> Meskipun aktivitas dimulai di tugas baru, tombol
<em>Back</em> tetap akan mengembalikan pengguna ke aktivitas sebelumnya.</p></dd>
<dt>{@code "singleInstance"}.</dt>
<dd>Sama seperti {@code "singleTask"}, namun sistem tidak meluncurkan aktivitas lain ke
tugas yang menyimpan instance. Aktivitas selalu satu dan satu-satunya anggota dari tugasnya;
aktivitas apa pun yang dimulai dengan ini akan dibuka di tugas yang terpisah.</dd>
</dl>
<p>Sebagai contoh lainnya, aplikasi Browser Android mendeklarasikan bahwa aktivitas browser web harus
selalu dibuka dalam tugasnya sendiri&mdash;dengan menetapkan mode pembuka {@code singleTask} dalam elemen<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.
Ini berarti bahwa jika aplikasi Anda mengeluarkan
intent untuk membuka Browser Android, aktivitasnya <em>tidak</em> akan ditempatkan dalam tugas
yang sama seperti aplikasi Anda. Sebagai gantinya, tugas baru akan dimulai untuk Browser atau, jika Browser
sudah memiliki tugas yang berjalan di latar belakang, tugas tersebut akan dimajukan untuk menangani intent
baru.</p>
<p>Baik aktivitas dimulai dalam tugas baru atau maupun dalam tugas yang sama seperti aktivitas yang memulainya, tombol
<em>Back</em> selalu membawa pengguna ke aktivitas sebelumnya. Akan tetapi, jika
Anda memulai aktivitas yang menetapkan mode pembuka {@code singleTask}, maka jika instance
aktivitas tersebut ada dalam tugas latar belakang, seluruh tugas tersebut akan dibawa ke latar depan. Pada titik
ini, back-stack sekarang menyertakan semua aktivitas dari tugas yang dimajukan, di atas
back-stack. Gambar 4 mengilustrasikan tipe skenario ini.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
<p class="img-caption"><strong>Gambar 4.</strong> Representasi tentang cara aktivitas dengan
mode pembuka "singleTask" ditambahkan ke back-stack. Jika aktivitas tersebut sudah menjadi bagian dari
tugas latar belakang dengan back-stack sendiri, maka seluruh back-stack juga
dimajukan, di atas tugas saat ini.</p>
<p>Untuk informasi selengkapnya tentang menggunakan mode pembuka dalam file manifes, lihat dokumentasi elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, di mana atribut {@code launchMode} dan nilai-nilai yang diterima
akan dibahas selengkapnya.</p>
<p class="note"><strong>Catatan:</strong> Perilaku yang Anda tentukan untuk aktivitas dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
bisa dikesampingkan dengan flag yang disertakan bersama intent yang memulai aktivitas Anda, seperti dibahas dalam
bagian berikutnya.</p>
<h4 id="#IntentFlagsForTasks">Menggunakan flag Intent</h4>
<p>Saat memulai aktivitas, Anda bisa memodifikasi asosiasi default aktivitas pada tugasnya
dengan menyertakan flag dalam intent yang Anda kirimkan ke {@link
android.app.Activity#startActivity startActivity()}. Flag yang bisa Anda gunakan untuk memodifikasi perilaku default
adalah:</p>
<p>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
<dd>Memulai aktivitas dalam tugas baru. Jika tugas sudah dijalankan untuk aktivitas yang sekarang
Anda mulai, tugas tersebut akan dibawa ke latar depan dengan status terakhir yang dipulihkan dan aktivitas
akan menerima intent baru dalam {@link android.app.Activity#onNewIntent onNewIntent()}.
<p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang dibahas di bagian sebelumnya.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
<dd>Jika aktivitas yang dimulai adalah aktivitas saat ini (di bagian teratas back-stack), maka
instance yang ada akan menerima panggilan ke {@link android.app.Activity#onNewIntent onNewIntent()}
sebagai ganti membuat instance baru aktivitas.
<p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang dibahas di bagian sebelumnya.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
<dd>Jika aktivitas yang dimulai sudah berjalan dalam tugas saat ini, maka sebagai
ganti meluncurkan instance baru aktivitas tersebut, semua kegiatan lain di atasnya akan
dimusnahkan dan intent ini akan disampaikan ke instance aktivitas yang dilanjutkan (sekarang di atas),
melalui {@link android.app.Activity#onNewIntent onNewIntent()}).
<p>Tidak ada nilai untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang menghasilkan perilaku ini.</p>
<p>{@code FLAG_ACTIVITY_CLEAR_TOP} paling sering digunakan bersama dengan
{@code FLAG_ACTIVITY_NEW_TASK}.
Bila digunakan bersama-sama, flag ini adalah cara penempatan aktivitas yang ada
dalam tugas lain dan meletakkannya dalam posisi yang memungkinkannya merespons intent. </p>
<p class="note"><strong>Catatan:</strong> Jika mode pembuka aktivitas yang didesain adalah
{@code "standard"},
ini juga akan dihapus dari back-stack dan instance baru akan diluncurkan di tempatnya untuk menangani
intent yang masuk. Itu karena instance baru selalu dibuat untuk intent baru bila
mode peluncuran adalah {@code "standard"}. </p>
</dd>
</dl>
<h3 id="Affinities">Menangani afinitas</h3>
<p><em>Afinitas</em> menunjukkan tugas mana yang disukai aktivitas untuk dimiliki. Secara default, semua
aktivitas aplikasi yang sama memiliki afinitas untuk satu sama lain. Jadi, secara default, semua
aktivitas dalam aplikasi yang sama lebih menyukai berada dalam tugas yang sama. Akan tetapi, Anda bisa memodifikasi
afinitas default untuk suatu aktivitas. Aktivitas yang didefinisikan dalam
aplikasi yang berbeda bisa berbagi afinitas, atau aktivitas yang didefinisikan dalam aplikasi yang sama bisa
diberi afinitas tugas yang berbeda.</p>
<p>Anda bisa memodifikasi afinitas untuk setiap yang diberikan
dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.</p>
<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
mengambil nilai string, yang harus unik dari nama paket default
yang dideklarasikan dalam elemen <a href="{@docRoot}guide/topics/manifest/manifest-element.html">
{@code &lt;manifest&gt;}
</a>, karena sistem menggunakan nama untuk mengidentifikasi afinitas
tugas default untuk aplikasi.</p>
<p>Afinitas berperan dalam dua keadaan:</p>
<ul>
<li>Bila intent yang meluncurkan aktivitas berisi flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
.
<p>Aktivitas baru, secara default, diluncurkan ke dalam tugas aktivitas
yang disebut {@link android.app.Activity#startActivity startActivity()}. Ini didorong ke back-stack
yang sama seperti caller. Akan tetapi, jika intent yang diteruskan ke
{@link android.app.Activity#startActivity startActivity()}
berisi flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
, maka sistem akan mencari tugas yang berbeda untuk menampung aktivitas baru. Sering kali, itu adalah tugas baru.
Akan tetapi, tidak harus demikian. Jika sudah ada tugas lama dengan afinitas yang sama seperti
aktivitas baru, aktivitas ini akan diluncurkan ke dalam tugas tersebut. Jika tidak, tugas baru akan dimulai.</p>
<p>Jika flag ini menyebabkan aktivitas memulai tugas baru dan pengguna menekan tombol <em>Home</em>
untuk meninggalkannya,
harus ada cara bagi pengguna untuk mengarahkan kembali ke tugas. Beberapa entitas (seperti
notification manager) selalu memulai aktivitas dalam tugas eksternal, tidak pernah sebagai bagian dari miliknya sendiri, jadi
selalu menempatkan {@code FLAG_ACTIVITY_NEW_TASK} dalam intent yang diteruskan ke
{@link android.app.Activity#startActivity startActivity()}.
Jika Anda memiliki aktivitas yang bisa dipanggil melalui
entitas eksternal yang mungkin menggunakan flag ini, hati-hatilah karena pengguna memiliki cara independen untuk kembali
ke tugas yang telah dimulai, seperti dengan ikon launcher (aktivitas akar dari tugas
memiliki filter intent {@link android.content.Intent#CATEGORY_LAUNCHER}; lihat bagian <a href="#Starting">Memulai tugas</a> di bawah ini).</p>
</li>
<li>Bila aktivitas memiliki atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a> sendiri yang diatur ke {@code "true"}.
<p>Dalam hal ini, aktivitas bisa berpindah dari tugas yang dimulainya ke tugas yang afinitasnya
dimilikinya, bila tugas tersebut di bawa ke latar depan.</p>
<p>Misalnya, anggaplah sebuah aktivitas melaporkan kondisi cuaca di sejumlah kota terpilih
yang didefinisikan sebagai bagian dari aplikasi perjalanan. Aktivitas memiliki afinitas yang sama dengan aktivitas lain dalam aplikasi
yang sama (afinitas aplikasi default) dan aktivitas ini memungkinkan re-parenting dengan atribut ini.
Bila salah satu aktivitas Anda memulai aktivitas laporan cuaca, awalnya aktivitas ini dimiliki oleh tugas
yang sama dengan aktivitas Anda. Akan tetapi, bila tugas aplikasi perjalanan di bawa ke latar depan,
aktivitas laporan cuaca akan ditetapkan kembali ke tugas itu dan ditampilkan di dalamnya.</p>
</li>
</ul>
<p class="note"><strong>Tip:</strong> Jika file {@code .apk} berisi lebih dari satu "aplikasi"
dari sudut pandang pengguna, Anda mungkin perlu menggunakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
untuk menetapkan afinitas berbeda pada aktivitas yang terkait dengan setiap "aplikasi".</p>
<h3 id="Clearing">Menghapus back-stack</h3>
<p>Jika pengguna meninggalkan tugas dalam waktu yang lama, sistem akan menghapus tugas semua aktivitas kecuali
aktivitas akar. Bila pengguna kembali ke tugas itu lagi, hanya aktivitas akar yang akan dipulihkan.
Sistem berperilaku seperti ini, karena, setelah sekian waktu, pengguna mungkin telah mengabaikan
apa yang mereka kerjakan sebelum dan kembali ke tugas itu untuk memulai sesuatu yang baru. </p>
<p>Ada beberapa atribut aktivitas yang bisa Anda gunakan untuk memodifikasi perilaku ini: </p>
<dl>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
</dt>
<dd>Jika atribut ini ditetapkan ke {@code "true"} dalam aktivitas akar tugas,
perilaku default yang baru dijelaskan tidak akan terjadi.
Tugas akan mempertahankan semua aktivitas dalam back-stack bahkan setelah sekian lama.</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
<dd>Jika atribut ini diatur ke {@code "true"} dalam aktivitas akar tugas, back-
stack akan dihapus hingga aktivitas akar bila pengguna meninggalkan tugas
dan kembali lagi. Dengan kata lain, ini adalah lawan dari
<a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a>. Pengguna selalu kembali ke tugas dengan
status awalnya, walaupun hanya sebentar meninggalkan tugas.</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
</dt>
<dd>Atribut ini seperti <a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>,
namun beroperasi pada
satu aktivitas, bukan pada seluruh tugas. Hal ini juga bisa menyebabkan aktivitas
hilang, termasuk aktivitas akar. Bila ini diatur ke {@code "true"},
aktivitas akan tetap menjadi bagian dari tugas hanya untuk sesi saat ini. Jika pengguna
keluar dan kemudian kembali ke tugas tersebut, tugas tidak akan ada lagi.</dd>
</dl>
<h3 id="Starting">Memulai tugas</h3>
<p>Anda bisa mengatur aktivitas sebagai titik masuk untuk tugas dengan memberikan filter intent dengan
{@code "android.intent.action.MAIN"} sebagai tindakan yang ditetapkan dan
{@code "android.intent.category.LAUNCHER"}
sebagai kategori yang ditetapkan. Misalnya:</p>
<pre>
&lt;activity ... &gt;
&lt;intent-filter ... &gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
...
&lt;/activity&gt;
</pre>
<p>Filter intent semacam ini akan menyebabkan ikon dan label untuk
aktivitas ditampilkan dalam launcher aplikasi, yang akan memberi cara kepada pengguna untuk meluncurkan aktivitas dan
kembali ke tugas yang dibuatnya kapan saja setelah ia telah diluncurkan.
</p>
<p>Kemampuan kedua ini penting: Pengguna harus bisa meninggalkan tugas dan kemudian kembali ke tugas tersebut
nanti dengan menggunakan launcher aktivitas ini. Karena itu, kedua <a href="#LaunchModes">mode
pembuka</a> yang menandai aktivitas selalu memulai tugas, {@code "singleTask"} dan
{@code "singleInstance"}, hanya boleh digunakan bila aktivitas memiliki filter
{@link android.content.Intent#ACTION_MAIN}
dan {@link android.content.Intent#CATEGORY_LAUNCHER}. Bayangkan, misalnya, apa yang akan
terjadi jika filter tidak ada: Intent meluncurkan aktivitas{@code "singleTask"}, memulai
tugas yang baru, dan pengguna menghabiskan lebih banyak waktu mengerjakan tugas tersebut. Pengguna kemudian menekan tombol
<em>Home</em>. Tugas kini dikirim ke latar belakang dan tidak terlihat. Sekarang pengguna tidak memiliki cara untuk kembali
ke tugas tersebut, karena tidak dinyatakan dalam launcher aplikasi.</p>
<p>Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
pada
<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a>
elemen ke {@code "true"} (lihat <a href="#Clearing">Menghapus back-stack</a>).</p>
<p>Informasi lebih jauh tentang cara menyatakan dan mengelola tugas dan aktivitas dalam
layar ikhtisar tersedia dalam<a href="{@docRoot}guide/components/recents.html">
Layar Ikhtisar</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how to use intents to
activate other application components and publish the intents to which your components
respond, continue with the <b><a
href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
Filters</a></b> document.</p>
-->

View File

@@ -1,74 +0,0 @@
page.title=Pengantar Android
@jd:body
<div class="sidebox" style="width:220px"><!-- width to match col-4 below -->
<p>Untuk mempelajari cara kerja aplikasi, mulailah dengan
<a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>.</p>
<p>Untuk langsung memulai pemrograman, bacalah <a href="{@docRoot}training/basics/firstapp/index.html">Membangun Aplikasi Pertama Anda.</a></p>
</div>
<p>Android menyediakan kerangka kerja aplikasi yang kaya dan memungkinkan Anda membangun aplikasi dan permainan
inovatif untuk perangkat seluler di lingkungan bahasa pemrograman Java. Dokumen yang tercantum di navigasi
sebelah kiri menyediakan detail tentang cara membangun aplikasi menggunakan berbagai API Android.</p>
<p>Jika Anda masih baru dengan pengembangan Android, Anda perlu memahami
konsep dasar berikut mengenai kerangka kerja aplikasi Android:</p>
<div class="landing-banner">
<div class="col-6">
<h4>Aplikasi menyediakan beberapa titik masuk</h4>
<p>Aplikasi Android dibangun sebagai kombinasi beragam komponen yang bisa dipanggil
satu per satu. Misalnya, satu <em>aktivitas</em> individual menyediakan satu
layar untuk antarmuka pengguna, dan <em>layanan</em> yang secara terpisah melakukan
tugas di latar belakang.</p>
<p>Dari satu komponen Anda dapat memulai komponen lainnya menggunakan <em>intent</em>. Anda bahkan dapat memulai
satu komponen dalam aplikasi berbeda, seperti aktivitas dalam aplikasi peta untuk menampilkan alamat. Model ini
menyediakan beberapa titik masuk untuk aplikasi tunggal dan memungkinkan setiap aplikasi untuk berfungsi sebagai "default"
pengguna bagi tindakan yang dapat dipanggil aplikasi lain.</p>
<p><b>Ketahui selengkapnya:</b></p>
<ul class="nolist">
<li><a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
<li><a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
</ul>
</div>
<div class="col-6">
<h4>Aplikasi beradaptasi dengan perangkat berbeda</h4>
<p>Android menyediakan kerangka kerja aplikasi adaptif yang memungkinkan Anda menyediakan sumber daya unik
bagi konfigurasi perangkat yang berbeda-beda. Misalnya, Anda bisa membuat berbagai file layout
XML untuk ukuran layar yang berbeda-beda dan sistem akan menentukan
layout yang akan diterapkan berdasarkan ukuran layar perangkat yang ada saat ini.</p>
<p>Anda dapat melakukan query ketersediaan fitur perangkat saat dijalankan (runtime) jika ada fitur aplikasi yang memerlukan
perangkat keras spesifik seperti kamera. Jika diperlukan, Anda juga bisa mendeklarasikan fitur yang dibutuhkan aplikasi
agar pasar aplikasi seperti Google Play Store tidak mengizinkan instalasi pada perangkat yang tidak
mendukung fitur itu.</p>
<p><b>Ketahui selengkapnya:</b></p>
<ul class="nolist">
<li><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>
<li><a href="{@docRoot}guide/topics/resources/overview.html">Ikhtisar Sumber Daya</a>
<li><a href="{@docRoot}guide/topics/ui/overview.html">Ikhtisar Antarmuka Pengguna</a>
</ul>
</div>
</div><!-- end landing-banner -->

View File

@@ -1,197 +0,0 @@
page.title=Fitur Bahasa Java 8
page.keywords="android N", "Java 8", "Jack"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<ol>
<li>
<a href="#supported-features">API dan Fitur Bahasa Java 8 yang didukung</a>
</li>
<li>
<a href="#configuration">Mengaktifkan Fitur Java 8 dan Jack Toolchain</a>
</li>
</ol>
</div>
</div>
<p>Android N memperkenalkan dukungan untuk fitur bahasa Java 8
yang bisa Anda gunakan saat mengembangkan aplikasi yang menargetkan Android N.
Halaman ini menjelaskan fitur bahasa baru yang didukung dalam Android N
Preview, cara menyiapkan proyek Anda dengan benar untuk menggunakannya, dan setiap masalah
yang diketahui yang mungkin Anda temui.
</p>
<p>Untuk mulai menggunakan fitur-fitur ini, Anda perlu mengunduh dan menyiapkan Android
Studio 2.1 dan Android N Preview SDK, yang menyertakan
Jack toolchain yang diperlukan dan Plugin Android untuk Gradle yang telah diperbarui. Jika Anda belum
memasang Android N Preview SDK, lihat <a href="{@docRoot}preview/setup-sdk.html">Menyiapkan Pengembangan untuk Android N</a>.</p>
<p class="note">
<strong>Catatan:</strong> Menggunakan fitur bahasa Java 8 yang baru bukanlah
persyaratan untuk mengembangkan aplikasi yang menargetkan platform Android N. Jika Anda
tidak ingin menulis kode dengan fitur bahasa Java 8, Anda bisa membiarkan nilai kompatibilitas
sumber dan target proyek disetel ke Java 7, namun Anda tetap harus
mengompilasi dengan JDK 8 untuk membangun pada platform Android N.
</p>
<h2 id="supported-features">
API dan Fitur Bahasa Java 8 yang Didukung
</h2>
<p>
Saat ini tidak semua fitur bahasa Java 8 didukung Android. Akan tetapi,
fitur berikut sekarang tersedia saat mengembangkan aplikasi yang menargetkan
Android N Preview:
</p>
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">Metode
antarmuka default dan statis</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">
Ekspresi Lambda</a> (juga tersedia pada API level 23 dan yang lebih rendah)
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html">Anotasi
yang bisa diulang</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html">
Referensi Metode</a> (juga tersedia pada API level 23 dan yang lebih rendah)
</li>
</ul>
<p class="note">
<strong>Catatan:</strong> Untuk menguji ekspresi lambda dan referensi metode pada
Android versi sebelumnya, bukalah file {@code build.gradle}
Anda, serta setel {@code compileSdkVersion} dan {@code targetSdkVersion} ke 23 atau
yang lebih rendah. Anda tetap perlu <a href="#configuration">mengaktifkan Jack
toolchain</a> untuk menggunakan fitur Java 8 ini.
</p>
<p>
Selain itu, API fitur bahasa Java 8 berikut ini sekarang tersedia:
</p>
<ul>
<li>Reflection API dan API terkait bahasa:
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html">
{@code java.lang.FunctionalInterface}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/Repeatable.html">
{@code java.lang.annotation.Repeatable}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--">
{@code java.lang.reflect.Method.isDefault()}</a>
</li>
<li>dan Reflection API yang terkait dengan anotasi yang bisa diulang, seperti
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AnnotatedElement.html#getAnnotationsByType-java.lang.Class-">
{@code AnnotatedElement.getAnnotationsByType(Class)}</a>
</li>
</ul>
</li>
<li>Utility API:
<ul>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html">
{@code java.util.function}</a>
</li>
<li>
<a class="external-link" href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html">
{@code java.util.stream}</a>
</li>
</ul>
</li>
</ul>
<h2 id="configuration">
Mengaktifkan Fitur Java 8 dan Jack Toolchain
</h2>
<p>
Agar dapat menggunakan fitur bahasa Java 8 yang baru, Anda juga perlu menggunakan
<a class="external-link" href="https://source.android.com/source/jack.html">Jack toolchain</a> yang baru. Toolchain Android
yang baru ini mengompilasi sumber bahasa Java menjadi dex
bytecode yang bisa dibaca Android, memiliki format pustaka {@code .jack} sendiri, dan menyediakan sebagian besar fitur toolchain
sebagai bagian dari alat bantu tunggal: pengemasan ulang, penciutan, pengaburan, dan
multidex.
</p>
<p>Inilah perbandingan dua toolchain yang digunakan untuk membangun file Android DEX:</p>
<ul>
<li>Toolchain javac lawas:<br>
<b>javac</b> ({@code .java} --&gt; {@code .class}) --&gt; <b>dx</b> ({@code
.class} --&gt; {@code .dex})
</li>
<li>Jack Toolchain baru:<br>
<b>Jack</b> ({@code .java} --&gt; {@code .jack} --&gt; {@code .dex})
</li>
</ul>
<h3>
Mengonfigurasi Gradle
</h3>
<p>
Untuk mengaktifkan fitur bahasa Java 8 dan Jack bagi proyek Anda, masukkan
yang berikut dalam file {@code build.gradle} level modul Anda:
</p>
<pre>
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
</pre>
<h3 id="known-issues">
Masalah yang Diketahui
</h3>
<p>
<a href="{@docRoot}tools/building/building-studio.html#instant-run">Instant
Run</a> saat ini tidak berfungsi pada Jack dan akan dinonaktifkan saat menggunakan
toolchain baru.
</p>
<p>Karena Jack tidak menghasilkan file kelas antara saat mengompilasi sebuah
aplikasi, alat yang bergantung pada file-file ini sekarang tidak berfungsi pada Jack. Beberapa
contoh alat ini adalah:</p>
<ul>
<li>Pendeteksi lint yang beroperasi pada file kelas
</li>
<li>Alat dan pustaka yang mewajibkan file kelas aplikasi (misalnya
pengujian instrumentasi dengan JaCoCo)
</li>
</ul>
<p>Jika Anda menemukan masalah lain saat menggunakan Jack, <a href="http://tools.android.com/filing-bugs">laporkan bug</a>.</p>

View File

@@ -1,517 +0,0 @@
page.title=Manifes Aplikasi
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#filestruct">Struktur File Manifes</a></li>
<li><a href="#filec">Konvensi File</a>
<li><a href="#filef">Fitur File</a>
<ol>
<li><a href="#ifs">Filter Intent</a></li>
<li><a href="#iconlabel">Ikon dan Label</a></li>
<li><a href="#perms">Izin</a></li>
<li><a href="#libs">Pustaka</a></li>
</ol></li>
</ol>
</div>
</div>
<p>
Setiap aplikasi harus memiliki file AndroidManifest.xml (bernama persis seperti ini) di direktori akar.
<span itemprop="description">File manifes
menyediakan informasi penting tentang aplikasi ke sistem Android,
informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode
aplikasi.</span> Di antaranya, manifes melakukan hal berikut ini:
</p>
<ul>
<li>Menamai paket Java untuk aplikasi.
Nama paket berfungsi sebagai identifier unik untuk aplikasi.</li>
<li>Menjelaskan berbagai komponen aplikasi&mdash;aktivitas,
layanan, penerima siaran, dan penyedia konten
yang membentuk aplikasi. Menamai kelas yang mengimplementasikan setiap komponen dan
mempublikasikan kemampuannya (misalnya, pesan {@link android.content.Intent
Intent} mana yang bisa ditanganinya). Deklarasi ini memberi tahu sistem Android mengenai
komponennya dan dalam kondisi apa bisa diluncurkan.</li>
<li>Menentukan proses yang akan menjadi host komponen aplikasi.</li>
<li>Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk
mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.</li>
<li>Juga mendeklarasikan izin lain yang harus dimiliki untuk
untuk berinteraksi dengan komponen aplikasi.</li>
<li>Mencantumkan daftar kelas {@link android.app.Instrumentation} yang memberikan
profil dan informasi lain saat aplikasi berjalan. Deklarasi ini
hanya ada di manifes saat aplikasi dibuat dan diuji;
deklarasi dihapus sebelum aplikasi dipublikasikan.</li>
<li>Mendeklarasikan tingkat minimum API Android yang diperlukan
aplikasi.</li>
<li>Mencantumkan daftar pustaka yang harus ditautkan aplikasi.</li>
</ul>
<h2 id="filestruct">Struktur File Manifes</h2>
<p>
Diagram di bawah ini menampilkan struktur umum file manifes dan setiap
elemen yang bisa ditampungnya. Setiap elemen, bersama
atributnya, didokumentasikan secara lengkap dalam file terpisah. Untuk melihat
informasi terperinci tentang setiap elemen, klik nama elemen dalam diagram,
dalam daftar abjad elemen yang mengikuti diagram, atau penyebutan nama
elemen lainnya.
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration /&gt;</a> <!-- ##api level 3## -->
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">&lt;compatible-screens /&gt;</a> <!-- ##api level 9## -->
<a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture /&gt;</a> <!-- ##api level 11## -->
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;/activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;/activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data/&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;/service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;/receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/path-permission-element.html">&lt;path-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;/provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;/application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;/manifest&gt;</a>
</pre>
<p>
Semua elemen yang bisa muncul dalam file manifes tercantum di bawah ini
dalam urutan abjad. Ini adalah satu-satunya elemen legal; Anda tidak bisa
menambahkan elemen atau atribut sendiri.
</p>
<p style="margin-left: 2em">
<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code> <!-- ##api level 3## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code>
</p>
<h2 id="filec">Konvensi File</h2>
<p>
Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen
dan atribut di manifes:
</p>
<dl>
<dt><b>Elemen</b></dt>
<dd>Hanya elemen
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> dan
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali.
Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi &mdash; meskipun
setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang
berarti.
<p>
Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain.
Semua nilai diatur melalui atribut, bukan sebagai data karakter dalam elemen.
</p>
<p>
Elemen yang sama tingkatan umumnya tidak diurutkan. Misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>, dan
<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
bisa dicampur dalam urutan apa pun. (Elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
merupakan eksepsi untuk aturan ini: Elemen ini harus mengikuti
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
ini aliasnya.)
</p></dd>
<dt><b>Atribut</b></dt>
<dd>Secara formal, semua atribut opsional. Akan tetapi, ada sebagian
yang harus ditetapkan agar elemen bisa mencapai tujuannya. Gunakan
dokumentasi sebagai panduan. Bagi atribut yang benar-benar opsional, ini menyebutkan
nilai default atau menyatakan apa yang terjadi jika tidak ada spesifikasi.
<p>Selain untuk beberapa atribut elemen akar
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>,
semua nama atribut dimulai dengan awalan {@code android:} &mdash;
misalnya, {@code android:alwaysRetainTaskState}. Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut
dengan nama.
</p></dd>
<dt><b>Mendeklarasikan nama kelas</b></dt>
<dd>Banyak elemen berhubungan dengan objek Java, termasuk elemen
aplikasi itu sendiri (elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
) dan aktivitas komponen &mdash; utamanya
(<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>),
layanan
(<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>),
penerima siaran
(<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>),
dan penyedia konten
(<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>).
<p>
Jika mendefinisikan subkelas, seperti yang selalu Anda definisikan untuk kelas komponen
({@link android.app.Activity}, {@link android.app.Service},
{@link android.content.BroadcastReceiver}, dan {@link android.content.ContentProvider}),
subkelas dideklarasikan melalui atribut {@code name}. Nama harus menyertakan tujuan
paket lengkap.
Misalnya, subkelas {@link android.app.Service} mungkin dideklarasikan sebagai berikut:
</p>
<pre>&lt;manifest . . . &gt;
&lt;application . . . &gt;
&lt;service android:name="com.example.project.SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik,
string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
melalui atribut
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
). Penetapan berikut sama dengan di atas:
</p>
<pre>&lt;manifest package="com.example.project" . . . &gt;
&lt;application . . . &gt;
&lt;service android:name=".SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama.
Jika subkelas tidak ditetapkan, maka akak dibuat instance kelas dasar.
</p></dd>
<dt><b>Banyak nilai</b></dt>
<dd>Jika lebih dari satu nilai yang dapat ditetapkan, elemen ini hampir selalu
diulangi, bukan menampilkan daftar banyak nilai dalam satu elemen.
Misalnya, filter intent dapat mencantumkan beberapa tindakan:
<pre>&lt;intent-filter . . . &gt;
&lt;action android:name="android.intent.action.EDIT" /&gt;
&lt;action android:name="android.intent.action.INSERT" /&gt;
&lt;action android:name="android.intent.action.DELETE" /&gt;
. . .
&lt;/intent-filter&gt;</pre></dd>
<dt><b>Nilai sumber daya</b></dt>
<dd>Beberapa atribut memiliki nilai yang bisa ditampilkan kepada pengguna &mdash; misalnya
, label dan ikon aktivitas. Nilai atribut ini
harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema. Nilai sumber
daya dinyatakan dalam format berikut,</p>
<p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>:<i>name</i>}</p>
<p>
dalam hal ini nama <i>package</i> boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan
dengan aplikasi, <i>type</i> adalah tipe sumber daya &mdash; seperti "string" atau
"drawable" &mdash; dan <i>name</i> adalah nama yang mengidentifikasi sumber daya tertentu.
Misalnya:
</p>
<pre>&lt;activity android:icon="@drawable/smallPic" . . . &gt</pre>
<p>
Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}'
dan bukan '{@code @}':
</p>
<p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>:<i>name</i>}
</p></dd>
<dt><b>Nilai-nilai string</b></dt>
<dd>Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}')
harus digunakan untuk meninggalkan karakter &mdash; misalnya, '{@code \\n}' untuk
baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.</dd>
</dl>
<h2 id="filef">Fitur File</h2>
<p>
Bagian berikut menjelaskan cara menerapkan sebagian fitur Android
dalam file manifest.
</p>
<h3 id="ifs">Filter Intent</h3>
<p>
Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima
siaran) diaktifkan oleh <i>intent</i>. Intent adalah
sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan
tindakan yang diinginkan &mdash; termasuk data yang akan ditindaklanjuti, kategori
komponen yang harus melakukan tindakan, dan petunjuk terkait lainnya.
Android mencari komponen yang sesuai untuk merespons intent, meluncurkan
instance komponen baru jika diperlukan, dan meneruskannya ke
objek Intent.
</p>
<p>
Komponen mengiklankan kemampuannya &mdash; jenis intent yang bisa diresponsnya
&mdash; melalui <i>filter intent</i>. Karena sistem Android
harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen,
filter intent ditetapkan dalam manifes sebagai elemen
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
. Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan
kemampuan yang berbeda.
</p>
<p>
Intent yang secara eksplisit menamai komponen target akan mengaktifkan komponen itu;
filter tidak berperan. Namun intent yang tidak menetapkan target
dengan nama dapat mengaktifkan komponen hanya jika dapat melewati salah satu filter
komponen.
</p>
<p>
Untuk informasi tentang cara objek Intent diuji terhadap filter intent,
lihat dokumen terpisah,
<a href="{@docRoot}guide/components/intents-filters.html">Intent
dan Filter Intent</a>.
</p>
<h3 id="iconlabel">Ikon dan Label</h3>
<p>
Sejumlah elemen memiliki atribut {@code icon} dan {@code label} untuk
ikon kecil dan label teks yang bisa ditampilkan kepada pengguna. Sebagian ada juga yang memiliki atribut
{@code description}untuk teks penjelasan yang lebih panjang yang juga bisa
ditampilkan pada layar. Misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
memiliki ketiga atribut ini, jadi saat pengguna ditanya apakah akan
memberi izin bagi aplikasi yang memintanya, ikon yang mewakili
izin, nama izin, dan keterangan yang
mengikutinya bisa ditampilkan kepada pengguna.
</p>
<p>
Dalam setiap kasus, ikon dan label yang ditetapkan dalam elemen yang memuatnya menjadi
{@code icon} default dan pengaturan {@code label} untuk semua subelemen kontainer ini.
Karena itu, ikon dan label yang ditetapkan dalam elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
adalah ikon dan label default untuk setiap komponen aplikasi.
Demikian pula, ikon dan label yang ditetapkan untuk komponen &mdash; misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
&mdash; adalah pengaturan default untuk setiap elemen komponen
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
. Jika elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
menetapkan label, namun suatu aktivitas dan filter intent-nya tidak menetapkan label,
maka label aplikasi akan dianggap sama-sama sebagai label aktvitas dan
filter intent.
</p>
<p>
Ikon dan label yang ditetapkan untuk filter intent digunakan untuk mewakili komponen
kapan saja komponen ditampilkan kepada pengguna saat memenuhi fungsi yang
diiklankan oleh filter. Misalnya, filter dengan pengaturan
"{@code android.intent.action.MAIN}" dan
"{@code android.intent.category.LAUNCHER}" mengiklankan aktivitas
sebagai aktivitas yang memulai aplikasi&mdash;, yaitu
sebagai salah satu aktivitas yang harus ditampilkan dalam launcher aplikasi. Ikon dan label yang
diatur dalam filter karenanya adalah ikon dan label yang ditampilkan dalam launcher.
</p>
<h3 id="perms">Izin</h3>
<p>
Sebuah <i>izin</i> adalah pembatasan yang membatasi akses ke bagian
kode atau ke data pada perangkat. Pembatasan diberlakukan untuk melindungi data dan kode
penting yang bisa disalahgunakan untuk mengganggu atau merusak pengalaman pengguna.
</p>
<p>
Setiap izin diidentifikasi melalui label yang unik. Sering kali, label menunjukkan
tindakan yang dibatasi. Misalnya, berikut ini adalah beberapa izin yang didefinisikan
oleh Android:
</p>
<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
<br/>{@code android.permission.READ_OWNER_DATA}
<br/>{@code android.permission.SET_WALLPAPER}
<br/>{@code android.permission.DEVICE_POWER}</p>
<p>
Sebuah fitur bisa dilindungi paling banyak oleh satu izin.
</p>
<p>
Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin,
aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
dalam manifes. Kemudian, bila aplikasi telah diinstal pada
perangkat, installer akan menentukan apakah izin yang diminta akan diberikan atau tidak
dengan memeriksa otoritas yang menandatangani
sertifikat aplikasi dan, dalam beberapa kasus, bertanya pada pengguna.
Jika izin diberikan, aplikasi tersebut bisa menggunakan
fitur yang dilindungi. Jika tidak, upaya aplikasi untuk mengakses fitur tersebut akan gagal
tanpa ada pemberitahuan apa pun kepada pengguna.
</p>
<p>
Aplikasi juga bisa melindungi komponennya sendiri (aktivitas, layanan,
penerima siaran, dan penyedia konten) dengan izin. Aplikasi bisa menerapkan
izin mana pun yang didefinisikan oleh Android (tercantum dalam
{@link android.Manifest.permission android.Manifest.permission}) atau dideklarasikan
oleh aplikasi lain. Atau aplikasi bisa mendefinisikannya sendiri. Izin baru dideklarasikan
dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
. Misalnya, aktivitas dapat dilindungi sebagai berikut:
</p>
<pre>
&lt;manifest . . . &gt;
&lt;permission android:name="com.example.project.DEBIT_ACCT" . . . /&gt;
&lt;uses-permission android:name="com.example.project.DEBIT_ACCT" /&gt;
. . .
&lt;application . . .&gt;
&lt;activity android:name="com.example.project.FreneticActivity"
android:permission="com.example.project.DEBIT_ACCT"
. . . &gt;
. . .
&lt;/activity&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>
Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya
dideklarasikan dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
, penggunaannya juga diminta dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
. Penggunaannya harus diminta agar komponen
aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu
diberlakukan oleh aplikasi itu sendiri.
</p>
<p>
Dalam contoh yang sama, jika atribut {@code permission} ditetapkan
untuk izin yang dideklarasikan di tempat lain
lain (seperti {@code android.permission.CALL_EMERGENCY_NUMBERS}, maka atribut
tidak perlu mendeklarasikannya lagi dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
. Akan tetapi, penggunaannya masih perlu dengan
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
</p>
<p>
Elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam
kode. Dan
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
dan yang dideklarasikan di tempat lain). Ini hanya memengaruhi cara izin
dikelompokkan saat ditampilkan kepada pengguna. Elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
tidak menetapkan izin mana dimiliki grup;
elemen hanya memberi nama grup. Izin ditempatkan dalam grup
dengan memberikan nama grup ke elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
melalui atribut
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">permissionGroup</a></code>
.
</p>
<h3 id="libs">Pustaka</h3>
<p>
Setiap aplikasi ditautkan dengan pustaka default Android, yang
menyertakan paket dasar untuk membangun aplikasi (dengan kelas umum
seperti Activity, Service, Intent, View, Button, Application, ContentProvider,
dan sebagainya).
</p>
<p>
Akan tetapi, sebagian paket berada dalam pustakanya sendiri. Jika aplikasi Anda
menggunakan kode salah satu paket ini, aplikasi secara eksplisit meminta untuk ditautkan dengan
paket tersebut. Manifes harus berisi elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code> yang
terpisah untuk menamai setiap pustaka. (Nama pustaka bisa ditemukan
dalam dokumentasi paket.)
</p>

View File

@@ -1,108 +0,0 @@
page.title=Penyedia konten
@jd:body
<div id="qv-wrapper">
<div id="qv">
<!-- In this document -->
<h2>Topik</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
Membuat Penyedia Konten</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/calendar-provider.html">Penyedia Kalender</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/contacts-provider.html">Penyedia Kontak</a>
</li>
</ol>
<!-- Related Samples -->
<h2>Contoh-Contoh Terkait</h2>
<ol>
<li>
<a href="{@docRoot}resources/samples/ContactManager/index.html">
Aplikasi Contact Manager</a>
</li>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
"Kursor (Orang)"
</a>
</li>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
"Kursor (Telepon)"</a>
</li>
<li>
<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
Contoh Adaptor Sinkronisasi</a>
</li>
</ol>
</div>
</div>
<p>
Penyedia konten mengelola akses ke set data terstruktur. Penyedia ini membungkus
data, dan menyediakan mekanisme untuk mendefinisikan keamanan data. Penyedia konten adalah antarmuka
standar yang menghubungkan data dalam satu proses dengan kode yang berjalan dalam proses lain.
</p>
<p>
Bila Anda ingin mengakses data di penyedia konten, Anda menggunakan
{@link android.content.ContentResolver} objek dalam
{@link android.content.Context} aplikasi untuk berkomunikasi dengan penyedia sebagai klien.
Objek {@link android.content.ContentResolver} berkomunikasi dengan objek penyedia, yakni
instance kelas yang mengimplementasikan {@link android.content.ContentProvider}. Objek penyedia
menerima permintaan data dari klien, melakukan tindakan yang diminta, dan
mengembalikan hasilnya.
</p>
<p>
Anda tidak perlu mengembangkan penyedia sendiri jika tidak bermaksud untuk berbagi data dengan
aplikasi lain. Akan tetapi, Anda memerlukan penyedia buatan sendiri untuk menyediakan saran pencarian custom
dalam aplikasi Anda sendiri. Anda juga memerlukan penyedia sendiri jika ingin menyalin dan
menempelkan data atau file yang kompleks dari aplikasi Anda ke aplikasi lain.
</p>
<p>
Android sendiri berisi penyedia konten yang mengelola data seperti informasi audio, video, gambar, dan
kontak pribadi. Anda bisa melihat sebagian informasi ini tercantum dalam dokumentasi
acuan untuk paket
<code><a href="{@docRoot}reference/android/provider/package-summary.html">android.provider</a>
</code>. Dengan beberapa batasan, semua penyedia ini bisa diakses oleh aplikasi Android
apa saja.
</p><p>
Topik-topik berikut menjelaskan penyedia konten secara lebih detail:
</p>
<dl>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten</a></strong>
</dt>
<dd>
Cara mengakses data di penyedia konten bila data disusun dalam tabel.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
Membuat Penyedia Konten</a></strong>
</dt>
<dd>
Cara membuat penyedia konten sendiri.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/calendar-provider.html">
Penyedia Kalender</a></strong>
</dt>
<dd>
Cara mengakses Penyedia Kalender yang merupakan bagian dari platform Android.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/contacts-provider.html">
Penyedia Kontak</a></strong>
</dt>
<dd>
Cara mengakses Penyedia Kontak yang merupakan bagian dari platform Android.
</dd>
</dl>

View File

@@ -1,916 +0,0 @@
page.title=Storage Access Framework
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini
<a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
<span class="more">tampilkan maksimal</span>
<span class="less" style="display:none">tampilkan minimal</span></a></h2>
<ol id="toc44" class="hide-nested">
<li>
<a href="#overview">Ikhtisar</a>
</li>
<li>
<a href="#flow">Arus Kontrol</a>
</li>
<li>
<a href="#client">Menulis Aplikasi Klien</a>
<ol>
<li><a href="#search">Mencari dokumen</a></li>
<li><a href="#process">Memproses hasil</a></li>
<li><a href="#metadata">Memeriksa metadata dokumen</a></li>
<li><a href="#open">Membuka dokumen</a></li>
<li><a href="#create">Membuat dokumen baru</a></li>
<li><a href="#delete">Menghapus dokumen</a></li>
<li><a href="#edit">Mengedit dokumen</a></li>
<li><a href="#permissions">Mempertahankan izin</a></li>
</ol>
</li>
<li><a href="#custom">Menulis Penyedia Dokumen Custom</a>
<ol>
<li><a href="#manifest">Manifes</a></li>
<li><a href="#contract">Kontrak</a></li>
<li><a href="#subclass">Subkelas DocumentsProvider</a></li>
<li><a href="#security">Keamanan</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.provider.DocumentsProvider}</li>
<li>{@link android.provider.DocumentsContract}</li>
</ol>
<h2>Video</h2>
<ol>
<li><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4">
DevBytes: Android 4.4 Storage Access Framework: Penyedia</a></li>
<li><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ">
DevBytes: Android 4.4 Storage Access Framework: Klien</a></li>
</ol>
<h2>Contoh Kode</h2>
<ol>
<li><a href="{@docRoot}samples/StorageProvider/index.html">
Penyedia Penyimpanan</a></li>
<li><a href="{@docRoot}samples/StorageClient/index.html">
Klien Penyimpanan</a></li>
</ol>
<h2>Lihat Juga</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten
</a>
</li>
</ol>
</div>
</div>
<p>Android 4.4 (API level 19) memperkenalkan Storage Access Framework (SAF, Kerangka Kerja Akses Penyimpanan). SAF
memudahkan pengguna menyusuri dan membuka dokumen, gambar, dan file lainnya
di semua penyedia penyimpanan dokumen pilihannya. UI standar yang mudah digunakan
memungkinkan pengguna menyusuri file dan mengakses yang terbaru dengan cara konsisten di antara berbagai aplikasi dan penyedia.</p>
<p>Layanan penyimpanan cloud atau lokal bisa dilibatkan dalam ekosistem ini dengan mengimplementasikan sebuah
{@link android.provider.DocumentsProvider} yang membungkus layanannya. Aplikasi klien
yang memerlukan akses ke dokumen sebuah penyedia bisa berintegrasi dengan SAF cukup dengan beberapa
baris kode.</p>
<p>SAF terdiri dari berikut ini:</p>
<ul>
<li><strong>Penyedia dokumen</strong>&mdash;Penyedia konten yang memungkinkan
layanan penyimpanan (seperti Google Drive) untuk menampilkan file yang dikelolanya. Penyedia dokumen
diimplementasikan sebagai subkelas dari kelas {@link android.provider.DocumentsProvider}.
Skema penyedia dokumen berdasarkan hierarki file biasa,
walaupun cara penyedia dokumen Anda secara fisik menyimpan data adalah terserah Anda.
Platform Android terdiri dari beberapa penyedia dokumen bawaan, seperti
Downloads, Images, dan Videos.</li>
<li><strong>Aplikasi klien</strong>&mdash;Aplikasi custom yang memanggil intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan/atau
{@link android.content.Intent#ACTION_CREATE_DOCUMENT} dan menerima
file yang dihasilkan penyedia dokumen.</li>
<li><strong>Picker</strong>&mdash;UI sistem yang memungkinkan pengguna mengakses dokumen dari semua
penyedia dokumen yang memenuhi kriteria pencarian aplikasi klien.</li>
</ul>
<p>Beberapa fitur yang disediakan oleh SAF adalah sebagai berikut:</p>
<ul>
<li>Memungkinkan pengguna menyusuri konten dari semua penyedia dokumen, bukan hanya satu aplikasi.</li>
<li>Memungkinkan aplikasi Anda memiliki akses jangka panjang dan tetap ke
dokumen yang dimiliki oleh penyedia dokumen. Melalui akses ini pengguna bisa menambah, mengedit,
menyimpan, dan menghapus file pada penyedia.</li>
<li>Mendukung banyak akun pengguna dan akar jangka pendek seperti penyedia penyimpanan
USB, yang hanya muncul jika drive itu dipasang. </li>
</ul>
<h2 id ="overview">Ikhtisar</h2>
<p>SAF berpusat di seputar penyedia konten yang merupakan
subkelas dari kelas {@link android.provider.DocumentsProvider}. Dalam <em>penyedia dokumen</em>, data
distrukturkan sebagai hierarki file biasa:</p>
<p><img src="{@docRoot}images/providers/storage_datamodel.png" alt="data model" /></p>
<p class="img-caption"><strong>Gambar 1.</strong> Model data penyedia dokumen. Root menunjuk ke satu Document,
yang nanti memulai pemekaran seluruh pohon.</p>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Setiap penyedia dokumen melaporkan satu atau beberapa
"akar" yang merupakan titik awal penyusuran pohon dokumen.
Masing-masing akar memiliki sebuah {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID} yang unik,
dan menunjuk ke satu dokumen (satu direktori)
yang mewakili konten di bawah akar itu.
Akar sengaja dibuat dinamis untuk mendukung kasus penggunaan seperti multiakun,
perangkat penyimpanan USB jangka pendek, atau masuk/keluar pengguna.</li>
<li>Di bawah tiap akar terdapat satu dokumen. Dokumen itu menunjuk ke dokumen-dokumen 1-ke-<em>N</em>,
yang nanti masing-masing bisa menunjuk ke dokumen 1-ke-<em>N</em>. </li>
<li>Tiap backend penyimpanan memunculkan
masing-masing file dan direktori dengan mengacunya lewat sebuah
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang unik.
ID dokumen harus unik dan tidak berubah setelah dibuat, karena ID ini digunakan untuk
URI persisten yang diberikan pada saat reboot perangkat.</li>
<li>Dokumen bisa berupa file yang bisa dibuka (dengan tipe MIME tertentu), atau
direktori yang berisi dokumen tambahan (dengan tipe MIME
{@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR}).</li>
<li>Tiap dokumen bisa mempunyai kemampuan berbeda, sebagaimana yang dijelaskan oleh
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}.
Misalnya, {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE},
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE}, dan
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL}.
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang sama bisa
dimasukkan dalam beberapa direktori.</li>
</ul>
<h2 id="flow">Arus Kontrol</h2>
<p>Seperti dinyatakan di atas, model data penyedia dokumen dibuat berdasarkan hierarki file
biasa. Akan tetapi, Anda bisa menyimpan secara fisik data dengan cara apa pun yang disukai,
selama data bisa diakses melalui API {@link android.provider.DocumentsProvider}. Misalnya, Anda
bisa menggunakan penyimpanan cloud berbasis tag untuk data Anda.</p>
<p>Gambar 2 menampilkan contoh cara aplikasi foto bisa menggunakan SAF
untuk mengakses data tersimpan:</p>
<p><img src="{@docRoot}images/providers/storage_dataflow.png" alt="app" /></p>
<p class="img-caption"><strong>Gambar 2.</strong> Arus Storage Access Framework</p>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Di SAF, penyedia dan klien tidak berinteraksi
secara langsung. Klien meminta izin untuk berinteraksi
dengan file (yakni, membaca, mengedit, membuat, atau menghapus file).</li>
<li>Interaksi dimulai bila sebuah aplikasi (dalam contoh ini adalah aplikasi foto) mengeluarkan intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} atau {@link android.content.Intent#ACTION_CREATE_DOCUMENT}. Intent bisa berisi filter
untuk mempersempit kriteria&mdash;misalnya, "beri saya semua file yang bisa dibuka
yang memiliki tipe MIME 'gambar'".</li>
<li>Setelah intent dibuat, picker sistem akan pergi ke setiap penyedia yang terdaftar
dan menunjukkan kepada pengguna akar konten yang cocok.</li>
<li>Picker memberi pengguna antarmuka standar untuk mengakses dokumen,
walaupun penyedia dokumen dasar bisa sangat berbeda. Misalnya, gambar 2
menunjukkan penyedia Google Drive, penyedia USB, dan penyedia cloud.</li>
</ul>
<p>Gambar 3 menunjukkan picker yang di digunakan pengguna mencari gambar telah memilih
akun Google Drive:</p>
<p><img src="{@docRoot}images/providers/storage_picker.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
<p class="img-caption"><strong>Gambar 3.</strong> Picker</p>
<p>Bila pengguna memilih Google Drive, gambar-gambar akan ditampilkan, seperti yang ditampilkan dalam
gambar 4. Dari titik itu, pengguna bisa berinteraksi dengan gambar dengan cara apa pun
yang didukung oleh penyedia dan aplikasi klien.
<p><img src="{@docRoot}images/providers/storage_photos.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
<p class="img-caption"><strong>Gambar 4.</strong> Gambar</p>
<h2 id="client">Menulis Aplikasi Klien</h2>
<p>Pada Android 4.3 dan yang lebih rendah, jika Anda ingin aplikasi mengambil file dari
aplikasi lain, aplikasi Anda harus memanggil intent seperti {@link android.content.Intent#ACTION_PICK}
atau {@link android.content.Intent#ACTION_GET_CONTENT}. Pengguna nanti harus memilih
satu aplikasi yang akan digunakan untuk mengambil file dan aplikasi yang dipilih harus menyediakan antarmuka pengguna
bagi untuk menyusuri dan mengambil dari file yang tersedia. </p>
<p>Pada Android 4.4 dan yang lebih tinggi, Anda mempunyai opsi tambahan dalam menggunakan intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT},
yang menampilkan UI picker yang dikontrol oleh sistem yang memungkinkan pengguna
menyusuri semua file yang disediakan aplikasi lain. Dari satu UI ini, pengguna
bisa mengambil file dari aplikasi apa saja yang didukung.</p>
<p>{@link android.content.Intent#ACTION_OPEN_DOCUMENT}
tidak dimaksudkan untuk menjadi pengganti {@link android.content.Intent#ACTION_GET_CONTENT}.
Yang harus Anda gunakan bergantung pada kebutuhan aplikasi:</p>
<ul>
<li>Gunakan {@link android.content.Intent#ACTION_GET_CONTENT} jika Anda ingin aplikasi
cuma membaca/mengimpor data. Dengan pendekatan ini, aplikasi akan mengimpor salinan data,
misalnya file gambar.</li>
<li>Gunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT} jika Anda ingin aplikasi
memiliki akses jangka panjang dan jangka pendek ke dokumen yang dimiliki oleh penyedia
dokumen. Contohnya adalah aplikasi pengeditan foto yang memungkinkan pengguna mengedit
gambar yang tersimpan dalam penyedia dokumen. </li>
</ul>
<p>Bagian ini menjelaskan cara menulis aplikasi klien berdasarkan
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan
intent {@link android.content.Intent#ACTION_CREATE_DOCUMENT}.</p>
<h3 id="search">Mencari dokumen</h3>
<p>
Cuplikan berikut menggunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
untuk mencari penyedia dokumen yang
berisi file gambar:</p>
<pre>private static final int READ_REQUEST_CODE = 42;
...
/**
* Fires an intent to spin up the &quot;file chooser&quot; UI and select an image.
*/
public void performFileSearch() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
// browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as a
// file (as opposed to a list of contacts or timezones)
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be &quot;audio/ogg&quot;.
// To search for all documents available via installed storage providers,
// it would be &quot;*/*&quot;.
intent.setType(&quot;image/*&quot;);
startActivityForResult(intent, READ_REQUEST_CODE);
}</pre>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Saat aplikasi mengeluarkan intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
, aplikasi akan menjalankan picker yang menampilkan semua penyedia dokumen yang cocok.</li>
<li>Menambahkan kategori {@link android.content.Intent#CATEGORY_OPENABLE} ke
intent akan menyaring hasil agar hanya menampilkan dokumen yang bisa dibuka, seperti file gambar.</li>
<li>Pernyataan {@code intent.setType("image/*")} menyaring lebih jauh agar hanya
menampilkan dokumen yang memiliki tipe data MIME gambar.</li>
</ul>
<h3 id="results">Memproses Hasil</h3>
<p>Setelah pengguna memilih dokumen di picker,
{@link android.app.Activity#onActivityResult onActivityResult()} akan dipanggil.
URI yang menunjuk ke dokumen yang dipilih dimasukkan dalam parameter {@code resultData}
. Ekstrak URI dengan {@link android.content.Intent#getData getData()}.
Setelah mendapatkannya, Anda bisa menggunakannya untuk mengambil dokumen yang diinginkan pengguna. Misalnya
:</p>
<pre>&#64;Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code
// READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
// response to some other intent, and the code below shouldn't run at all.
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter.
// Pull that URI using resultData.getData().
Uri uri = null;
if (resultData != null) {
uri = resultData.getData();
Log.i(TAG, "Uri: " + uri.toString());
showImage(uri);
}
}
}
</pre>
<h3 id="metadata">Memeriksa metadata dokumen</h3>
<p>Setelah Anda memiliki URI untuk dokumen, Anda akan mendapatkan akses ke metadatanya. Cuplikan
ini memegang metadata sebuah dokumen yang disebutkan oleh URI, dan mencatatnya:</p>
<pre>public void dumpImageMetaData(Uri uri) {
// The query, since it only applies to a single document, will only return
// one row. There's no need to filter, sort, or select fields, since we want
// all fields for one document.
Cursor cursor = getActivity().getContentResolver()
.query(uri, null, null, null, null, null);
try {
// moveToFirst() returns false if the cursor has 0 rows. Very handy for
// &quot;if there's anything to look at, look at it&quot; conditionals.
if (cursor != null &amp;&amp; cursor.moveToFirst()) {
// Note it's called &quot;Display Name&quot;. This is
// provider-specific, and might not necessarily be the file name.
String displayName = cursor.getString(
cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Log.i(TAG, &quot;Display Name: &quot; + displayName);
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
// If the size is unknown, the value stored is null. But since an
// int can't be null in Java, the behavior is implementation-specific,
// which is just a fancy term for &quot;unpredictable&quot;. So as
// a rule, check if it's null before assigning to an int. This will
// happen often: The storage API allows for remote files, whose
// size might not be locally known.
String size = null;
if (!cursor.isNull(sizeIndex)) {
// Technically the column stores an int, but cursor.getString()
// will do the conversion automatically.
size = cursor.getString(sizeIndex);
} else {
size = &quot;Unknown&quot;;
}
Log.i(TAG, &quot;Size: &quot; + size);
}
} finally {
cursor.close();
}
}
</pre>
<h3 id="open-client">Membuka dokumen</h3>
<p>Setelah mendapatkan URI dokumen, Anda bisa membuka dokumen atau melakukan apa saja
yang diinginkan padanya.</p>
<h4>Bitmap</h4>
<p>Berikut ini adalah contoh cara membuka {@link android.graphics.Bitmap}:</p>
<pre>private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
</pre>
<p>Perhatikan bahwa Anda tidak boleh melakukan operasi ini pada thread UI. Lakukan hal ini di latar belakang
, dengan menggunakan {@link android.os.AsyncTask}. Setelah membuka bitmap, Anda
bisa menampilkannya dalam {@link android.widget.ImageView}.
</p>
<h4>Mendapatkan InputStream</h4>
<p>Berikut ini adalah contoh cara mendapatkan {@link java.io.InputStream} dari URI. Dalam cuplikan ini
, baris-baris file dibaca ke dalam sebuah string:</p>
<pre>private String readTextFromUri(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
fileInputStream.close();
parcelFileDescriptor.close();
return stringBuilder.toString();
}
</pre>
<h3 id="create">Membuat dokumen baru</h3>
<p>Aplikasi Anda bisa membuat dokumen baru dalam penyedia dokumen dengan menggunakan intent
{@link android.content.Intent#ACTION_CREATE_DOCUMENT}
. Untuk membuat file, Anda memberikan satu tipe MIME dan satu nama file pada intent, dan
menjalankannya dengan kode permintaan yang unik. Selebihnya akan diurus untuk Anda:</p>
<pre>
// Here are some examples of how you might call this method.
// The first parameter is the MIME type, and the second parameter is the name
// of the file you are creating:
//
// createFile("text/plain", "foobar.txt");
// createFile("image/png", "mypicture.png");
// Unique request code.
private static final int WRITE_REQUEST_CODE = 43;
...
private void createFile(String mimeType, String fileName) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as
// a file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Create a file with the requested MIME type.
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, WRITE_REQUEST_CODE);
}
</pre>
<p>Setelah membuat dokumen baru, Anda bisa mendapatkan URI-nya dalam
{@link android.app.Activity#onActivityResult onActivityResult()}, sehingga Anda
bisa terus menulis ke dokumen itu.</p>
<h3 id="delete">Menghapus dokumen</h3>
<p>Jika Anda memiliki URI dokumen dan
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS Document.COLUMN_FLAGS}
dokumen berisi
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE SUPPORTS_DELETE},
Anda bisa menghapus dokumen tersebut. Misalnya:</p>
<pre>
DocumentsContract.deleteDocument(getContentResolver(), uri);
</pre>
<h3 id="edit">Mengedit dokumen</h3>
<p>Anda bisa menggunakan SAF untuk mengedit dokumen teks langsung di tempatnya.
Cuplikan ini memicu
intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan menggunakan
kategori {@link android.content.Intent#CATEGORY_OPENABLE} untuk menampilkan
dokumen yang bisa dibuka saja. Ini akan menyaring lebih jauh untuk menampilkan file teks saja:</p>
<pre>
private static final int EDIT_REQUEST_CODE = 44;
/**
* Open a file for writing and append some text to it.
*/
private void editDocument() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's
// file browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as a
// file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only text files.
intent.setType(&quot;text/plain&quot;);
startActivityForResult(intent, EDIT_REQUEST_CODE);
}
</pre>
<p>Berikutnya, dari {@link android.app.Activity#onActivityResult onActivityResult()}
(lihat <a href="#results">Memproses hasil</a>) Anda bisa memanggil kode untuk mengedit.
Cuplikan berikut mendapatkan {@link java.io.FileOutputStream}
dari {@link android.content.ContentResolver}. Secara default, snipet menggunakan mode “tulis”.
Inilah praktik terbaik untuk meminta jumlah akses minimum yang Anda perlukan, jadi jangan meminta
baca/tulis jika yang Anda perlukan hanyalah tulis:</p>
<pre>private void alterDocument(Uri uri) {
try {
ParcelFileDescriptor pfd = getActivity().getContentResolver().
openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream =
new FileOutputStream(pfd.getFileDescriptor());
fileOutputStream.write(("Overwritten by MyCloud at " +
System.currentTimeMillis() + "\n").getBytes());
// Let the document provider know you're done by closing the stream.
fileOutputStream.close();
pfd.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}</pre>
<h3 id="permissions">Mempertahankan izin</h3>
<p>Bila aplikasi Anda membuka file untuk membaca atau menulis, sistem akan memberi
aplikasi Anda izin URI untuk file itu. Pemberian ini berlaku hingga perangkat pengguna di-restart.
Namun anggaplah aplikasi Anda adalah aplikasi pengeditan gambar, dan Anda ingin pengguna bisa
mengakses 5 gambar terakhir yang dieditnya, langsung dari aplikasi Anda. Jika perangkat pengguna telah
di-restart, maka Anda harus mengirim pengguna kembali ke picker sistem untuk menemukan
file, hal ini jelas tidak ideal.</p>
<p>Untuk mencegah terjadinya hal ini, Anda bisa mempertahankan izin yang diberikan
sistem ke aplikasi Anda. Secara efektif, aplikasi Anda akan "mengambil" pemberian izin URI yang bisa dipertahankan
yang ditawarkan oleh sistem. Hal ini memberi pengguna akses kontinu ke file
melalui aplikasi Anda, sekalipun perangkat telah di-restart:</p>
<pre>final int takeFlags = intent.getFlags()
&amp; (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);</pre>
<p>Ada satu langkah akhir. Anda mungkin telah menyimpan
URI terbaru yang diakses aplikasi, namun URI itu mungkin tidak lagi valid,&mdash;aplikasi lain
mungkin telah menghapus atau memodifikasi dokumen. Karena itu, Anda harus selalu memanggil
{@code getContentResolver().takePersistableUriPermission()} untuk memeriksa
data terbaru.</p>
<h2 id="custom">Menulis Penyedia Dokumen Custom</h2>
<p>
Jika Anda sedang mengembangkan aplikasi yang menyediakan layanan penyimpanan untuk file (misalnya
layanan penyimpanan cloud), Anda bisa menyediakan file melalui
SAF dengan menulis penyedia dokumen custom. Bagian ini menjelaskan
caranya.</p>
<h3 id="manifest">Manifes</h3>
<p>Untuk mengimplementasikan penyedia dokumen custom, tambahkan yang berikut ini ke manifes aplikasi
Anda:</p>
<ul>
<li>Target berupa API level 19 atau yang lebih tinggi.</li>
<li>Elemen <code>&lt;provider&gt;</code> yang mendeklarasikan penyedia penyimpanan custom
Anda. </li>
<li>Nama penyedia Anda, yaitu nama kelasnya, termasuk nama paket.
Misalnya: <code>com.example.android.storageprovider.MyCloudProvider</code>.</li>
<li>Nama otoritas Anda, yaitu nama paket Anda (dalam contoh ini,
<code>com.example.android.storageprovider</code>) plus tipe penyedia konten
(<code>documents</code>). Misalnya, {@code com.example.android.storageprovider.documents}.</li>
<li>Atribut <code>android:exported</code> yang diatur ke <code>&quot;true&quot;</code>.
Anda harus mengekspor penyedia sehingga aplikasi lain bisa membacanya.</li>
<li>Atribut <code>android:grantUriPermissions</code> yang diatur ke
<code>&quot;true&quot;</code>. Pengaturan ini memungkinkan sistem memberi aplikasi lain akses
ke konten dalam penyedia Anda. Untuk pembahasan cara mempertahankan pemberian bagi
dokumen tertentu, lihat <a href="#permissions">Mempertahankan izin</a>.</li>
<li>Izin {@code MANAGE_DOCUMENTS}. Secara default, penyedia tersedia
bagi siapa saja. Menambahkan izin ini akan membatasi penyedia Anda pada sistem.
Pembatasan ini penting untuk keamanan.</li>
<li>Atribut {@code android:enabled} yang diatur ke nilai boolean didefinisikan dalam file
sumber daya. Tujuan atribut ini adalah menonaktifkan penyedia pada perangkat yang menjalankan Android 4.3 atau yang lebih rendah.
Misalnya, {@code android:enabled="@bool/atLeastKitKat"}. Selain
memasukkan atribut ini dalam manifes, Anda perlu melakukan hal-hal berikut:
<ul>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;false&lt;/bool&gt;</pre></li>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;true&lt;/bool&gt;</pre></li>
</ul></li>
<li>Sebuah filter intent berisi tindakan
{@code android.content.action.DOCUMENTS_PROVIDER}, agar penyedia Anda
muncul dalam picker saat sistem mencari penyedia.</li>
</ul>
<p>Berikut ini adalah kutipan contoh manifes berisi penyedia yang:</p>
<pre>&lt;manifest... &gt;
...
&lt;uses-sdk
android:minSdkVersion=&quot;19&quot;
android:targetSdkVersion=&quot;19&quot; /&gt;
....
&lt;provider
android:name=&quot;com.example.android.storageprovider.MyCloudProvider&quot;
android:authorities=&quot;com.example.android.storageprovider.documents&quot;
android:grantUriPermissions=&quot;true&quot;
android:exported=&quot;true&quot;
android:permission=&quot;android.permission.MANAGE_DOCUMENTS&quot;
android:enabled=&quot;&#64;bool/atLeastKitKat&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.content.action.DOCUMENTS_PROVIDER&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/provider&gt;
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<h4 id="43">Mendukung perangkat yang menjalankan Android 4.3 dan yang lebih rendah</h4>
<p>Intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} hanya tersedia
pada perangkat yang menjalankan Android 4.4 dan yang lebih tinggi.
Jika ingin aplikasi Anda mendukung {@link android.content.Intent#ACTION_GET_CONTENT}
untuk mengakomodasi perangkat yang menjalankan Android 4.3 dan yang lebih rendah, Anda harus
menonaktifkan filter inten {@link android.content.Intent#ACTION_GET_CONTENT} dalam
manifes untuk perangkat yang menjalankan Android 4.4 atau yang lebih tinggi. Penyedia
dokumen dan {@link android.content.Intent#ACTION_GET_CONTENT} harus dianggap
saling eksklusif. Jika Anda mendukung keduanya sekaligus, aplikasi Anda akan
muncul dua kali dalam UI picker sistem, yang menawarkan dua cara mengakses
data tersimpan Anda. Hal ini akan membingungkan pengguna.</p>
<p>Berikut ini adalah cara yang disarankan untuk menonaktifkan
filter intent {@link android.content.Intent#ACTION_GET_CONTENT} untuk perangkat
yang menjalankan Android versi 4.4 atau yang lebih tinggi:</p>
<ol>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;true&lt;/bool&gt;</pre></li>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;false&lt;/bool&gt;</pre></li>
<li>Tambahkan
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">alias
aktivitas</a> untuk menonaktifkan filter intent {@link android.content.Intent#ACTION_GET_CONTENT}
bagi versi 4.4 (API level 19) dan yang lebih tinggi. Misalnya:
<pre>
&lt;!-- This activity alias is added so that GET_CONTENT intent-filter
can be disabled for builds on API level 19 and higher. --&gt;
&lt;activity-alias android:name=&quot;com.android.example.app.MyPicker&quot;
android:targetActivity=&quot;com.android.example.app.MyActivity&quot;
...
android:enabled=&quot;@bool/atMostJellyBeanMR2&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.intent.action.GET_CONTENT&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.OPENABLE&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
&lt;data android:mimeType=&quot;image/*&quot; /&gt;
&lt;data android:mimeType=&quot;video/*&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/activity-alias&gt;
</pre>
</li>
</ol>
<h3 id="contract">Kontrak</h3>
<p>Biasanya bila Anda menulis penyedia konten custom, salah satu tugas adalah
mengimplementasikan kelas kontrak, seperti dijelaskan dalam panduan pengembang
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#ContractClass">
Penyedia Konten</a>. Kelas kontrak adalah kelas {@code public final}
yang berisi definisi konstanta untuk URI, nama kolom, tipe MIME, dan
metadata lain yang berkenaan dengan penyedia. SAF
menyediakan kelas-kelas kontrak ini untuk Anda, jadi Anda tidak perlu menulisnya
sendiri:</p>
<ul>
<li>{@link android.provider.DocumentsContract.Document}</li>
<li>{@link android.provider.DocumentsContract.Root}</li>
</ul>
<p>Misalnya, berikut ini adalah kolom-kolom yang bisa Anda hasilkan di kursor bila
penyedia dokumen Anda membuat query dokumen atau akar:</p>
<pre>private static final String[] DEFAULT_ROOT_PROJECTION =
new String[]{Root.COLUMN_ROOT_ID, Root.COLUMN_MIME_TYPES,
Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES,};
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
String[]{Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS, Document.COLUMN_SIZE,};
</pre>
<h3 id="subclass">Subkelas DocumentsProvider</h3>
<p>Langkah berikutnya dalam menulis penyedia dokumen custom adalah menjadikan
kelas abstrak sebagai subkelas {@link android.provider.DocumentsProvider}. Setidaknya, Anda perlu
mengimplementasikan metode berikut:</p>
<ul>
<li>{@link android.provider.DocumentsProvider#queryRoots queryRoots()}</li>
<li>{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}</li>
<li>{@link android.provider.DocumentsProvider#queryDocument queryDocument()}</li>
<li>{@link android.provider.DocumentsProvider#openDocument openDocument()}</li>
</ul>
<p>Hanya inilah metode yang diwajibkan kepada Anda secara ketat untuk diimplementasikan, namun ada
banyak lagi yang mungkin Anda inginkan. Lihat {@link android.provider.DocumentsProvider}
untuk detailnya.</p>
<h4 id="queryRoots">Mengimplementasikan queryRoots</h4>
<p>Implementasi {@link android.provider.DocumentsProvider#queryRoots
queryRoots()} oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua
direktori akar penyedia dokumen, dengan menggunakan kolom-kolom yang didefinisikan dalam
{@link android.provider.DocumentsContract.Root}.</p>
<p>Dalam cuplikan berikut, parameter {@code projection} mewakili bidang-bidang
tertentu yang ingin didapatkan kembali oleh pemanggil. Cuplikan ini membuat kursor baru
dan menambahkan satu baris ke satu akar&mdash; kursor, satu direktori level atas, seperti
Downloads atau Images. Kebanyakan penyedia hanya mempunyai satu akar. Anda bisa mempunyai lebih dari satu,
misalnya, jika ada banyak akun pengguna. Dalam hal itu, cukup tambahkan sebuah
baris kedua ke kursor.</p>
<pre>
&#64;Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
// Create a cursor with either the requested fields, or the default
// projection if "projection" is null.
final MatrixCursor result =
new MatrixCursor(resolveRootProjection(projection));
// If user is not logged in, return an empty root cursor. This removes our
// provider from the list entirely.
if (!isUserLoggedIn()) {
return result;
}
// It's possible to have multiple roots (e.g. for multiple accounts in the
// same app) -- just add multiple cursor rows.
// Construct one row for a root called &quot;MyCloud&quot;.
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, ROOT);
row.add(Root.COLUMN_SUMMARY, getContext().getString(R.string.root_summary));
// FLAG_SUPPORTS_CREATE means at least one directory under the root supports
// creating documents. FLAG_SUPPORTS_RECENTS means your application's most
// recently used documents will show up in the &quot;Recents&quot; category.
// FLAG_SUPPORTS_SEARCH allows users to search all documents the application
// shares.
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE |
Root.FLAG_SUPPORTS_RECENTS |
Root.FLAG_SUPPORTS_SEARCH);
// COLUMN_TITLE is the root title (e.g. Gallery, Drive).
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.title));
// This document id cannot change once it's shared.
row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(mBaseDir));
// The child MIME types are used to filter the roots and only present to the
// user roots that contain the desired type somewhere in their file hierarchy.
row.add(Root.COLUMN_MIME_TYPES, getChildMimeTypes(mBaseDir));
row.add(Root.COLUMN_AVAILABLE_BYTES, mBaseDir.getFreeSpace());
row.add(Root.COLUMN_ICON, R.drawable.ic_launcher);
return result;
}</pre>
<h4 id="queryChildDocuments">Mengimplementasikan queryChildDocuments</h4>
<p>Implementasi
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua file dalam
direktori yang ditentukan, dengan menggunakan kolom-kolom yang didefinisikan dalam
{@link android.provider.DocumentsContract.Document}.</p>
<p>Metode ini akan dipanggil bila Anda memilih akar aplikasi dalam picker UI.
Metode mengambil dokumen anak dari direktori di bawah akar. Metode ini bisa dipanggil pada level apa saja dalam
hierarki file, bukan hanya akar. Cuplikan ini
membuat kursor baru dengan kolom-kolom yang diminta, lalu menambahkan informasi tentang
setiap anak langsung dalam direktori induk ke kursor.
Satu anak bisa berupa gambar, direktori lain&mdash;file apa saja:</p>
<pre>&#64;Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
String sortOrder) throws FileNotFoundException {
final MatrixCursor result = new
MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(parentDocumentId);
for (File file : parent.listFiles()) {
// Adds the file's display name, MIME type, size, and so on.
includeFile(result, null, file);
}
return result;
}
</pre>
<h4 id="queryDocument">Mengimplementasikan queryDocument</h4>
<p>Implementasi
{@link android.provider.DocumentsProvider#queryDocument queryDocument()}
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke file yang disebutkan,
dengan menggunakan kolom-kolom yang didefinisikan dalam {@link android.provider.DocumentsContract.Document}.
</p>
<p>Metode {@link android.provider.DocumentsProvider#queryDocument queryDocument()}
menghasilkan informasi yang sama yang diteruskan dalam
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()},
namun untuk file tertentu:</p>
<pre>&#64;Override
public Cursor queryDocument(String documentId, String[] projection) throws
FileNotFoundException {
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new
MatrixCursor(resolveDocumentProjection(projection));
includeFile(result, documentId, null);
return result;
}
</pre>
<h4 id="openDocument">Mengimplementasikan openDocument</h4>
<p>Anda harus mengimplementasikan {@link android.provider.DocumentsProvider#openDocument
openDocument()} untuk menghasilkan {@link android.os.ParcelFileDescriptor} yang mewakili
file yang disebutkan. Aplikasi lain bisa menggunakan {@link android.os.ParcelFileDescriptor}
yang dihasilkan untuk mengalirkan data. Sistem memanggil metode ini setelah pengguna memilih file
dan aplikasi klien meminta akses ke file itu dengan memanggil
{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}.
Misalnya:</p>
<pre>&#64;Override
public ParcelFileDescriptor openDocument(final String documentId,
final String mode,
CancellationSignal signal) throws
FileNotFoundException {
Log.v(TAG, &quot;openDocument, mode: &quot; + mode);
// It's OK to do network operations in this method to download the document,
// as long as you periodically check the CancellationSignal. If you have an
// extremely large file to transfer from the network, a better solution may
// be pipes or sockets (see ParcelFileDescriptor for helper methods).
final File file = getFileForDocId(documentId);
final boolean isWrite = (mode.indexOf('w') != -1);
if(isWrite) {
// Attach a close listener if the document is opened in write mode.
try {
Handler handler = new Handler(getContext().getMainLooper());
return ParcelFileDescriptor.open(file, accessMode, handler,
new ParcelFileDescriptor.OnCloseListener() {
&#64;Override
public void onClose(IOException e) {
// Update the file with the cloud server. The client is done
// writing.
Log.i(TAG, &quot;A file with id &quot; +
documentId + &quot; has been closed!
Time to &quot; +
&quot;update the server.&quot;);
}
});
} catch (IOException e) {
throw new FileNotFoundException(&quot;Failed to open document with id &quot;
+ documentId + &quot; and mode &quot; + mode);
}
} else {
return ParcelFileDescriptor.open(file, accessMode);
}
}
</pre>
<h3 id="security">Keamanan</h3>
<p>Anggaplah penyedia dokumen Anda sebuah layanan penyimpanan cloud yang dilindungi kata sandi
dan Anda ingin memastikan bahwa pengguna sudah login sebelum Anda mulai berbagi file mereka.
Apakah yang harus dilakukan aplikasi Anda jika pengguna tidak login? Solusinya adalah menghasilkan
akar nol dalam implementasi {@link android.provider.DocumentsProvider#queryRoots
queryRoots()} Anda. Yakni, sebuah kursor akar kosong:</p>
<pre>
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
...
// If user is not logged in, return an empty root cursor. This removes our
// provider from the list entirely.
if (!isUserLoggedIn()) {
return result;
}
</pre>
<p>Langkah lainnya adalah memanggil {@code getContentResolver().notifyChange()}.
Ingat {@link android.provider.DocumentsContract}? Kita menggunakannya untuk membuat
URI ini. Cuplikan berikut memberi tahu sistem untuk membuat query akar penyedia dokumen Anda
kapan saja status login pengguna berubah. Jika pengguna tidak
login, panggilan ke {@link android.provider.DocumentsProvider#queryRoots queryRoots()} akan menghasilkan
kursor kosong, seperti yang ditampilkan di atas. Cara ini akan memastikan bahwa dokumen penyedia hanya
tersedia jika pengguna login ke penyedia itu.</p>
<pre>private void onLoginButtonClick() {
loginOrLogout();
getContentResolver().notifyChange(DocumentsContract
.buildRootsUri(AUTHORITY), null);
}
</pre>

View File

@@ -1,337 +0,0 @@
page.title=Mengakses Sumber Daya
parent.title=Sumber Daya Aplikasi
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Tampilan Cepat</h2>
<ul>
<li>Sumber daya bisa diacu dari kode dengan menggunakan integer dari {@code R.java}, seperti
{@code R.drawable.myimage}</li>
<li>Sumber daya bisa diacu dari sumber daya dengan menggunakan sintaks XML khusus, seperti {@code
&#64;drawable/myimage}</li>
<li>Anda juga bisa mengakses sumber daya aplikasi Anda dengan berbagai metode di
{@link android.content.res.Resources}</li>
</ul>
<h2>Kelas-Kelas Utama</h2>
<ol>
<li>{@link android.content.res.Resources}</li>
</ol>
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#ResourcesFromCode">Mengakses Sumber Daya dari Kode</a></li>
<li><a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>
<ol>
<li><a href="#ReferencesToThemeAttributes">Mengacu atribut gaya</a></li>
</ol>
</li>
<li><a href="#PlatformResources">Mengakses Sumber Daya Platform</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
</ol>
</div>
</div>
<p>Setelah Anda menyediakan sumber daya dalam aplikasi Anda (yang dibicarakan di <a href="providing-resources.html">Menyediakan Sumber Daya</a>), Anda bisa menerapkannya dengan
mengacu ID sumber dayanya. Semua ID sumber daya didefinisikan di kelas {@code R} proyek Anda, yang
dihasilkan oleh alat {@code aapt} secara otomatis.</p>
<p>Bila aplikasi Anda dikompilasi, {@code aapt} akan membuat kelas {@code R}, yang berisi
ID sumber daya untuk semua sumber daya dalam direktori {@code
res/} Anda. Untuk masing-masing tipe sumber daya, ada subkelas {@code R} (misalnya,
{@code R.drawable} untuk semua sumber daya yang bisa ditarik), dan untuk masing-masing sumber daya dari tipe itu, ada satu integer statis
(misalnya, {@code R.drawable.icon}). Integer ini adalah ID sumber daya yang bisa Anda gunakan
untuk mengambil sumber daya Anda.</p>
<p>Walaupun kelas {@code R} adalah tempat menyebutkan ID sumber daya, Anda tidak perlu
melihat ke sana untuk menemukan ID sumber daya. ID sumber daya selalu terdiri dari:</p>
<ul>
<li><em>Tipe sumber daya</em>: Masing-masing sumber daya dikelompokkan menjadi "tipe", misalnya {@code
string}, {@code drawable}, dan {@code layout}. Untuk mengetahui selengkapnya tentang berbagai tipe, lihat <a href="available-resources.html">Tipe Sumber Daya</a>.
</li>
<li><em>Nama sumber daya</em>, bisa berupa: nama file,
tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika
sumber daya itu sebuah nilai sederhana (misalnya sebuah string).</li>
</ul>
<p>Ada dua cara untuk mengakses sumber daya:</p>
<ul>
<li><strong>Dalam kode:</strong> Menggunakan integer statis dari subkelas dari kelas {@code R}
, misalnya:
<pre class="classic no-pretty-print">R.string.hello</pre>
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Ada banyak
API Android yang bisa mengakses sumber daya Anda bila Anda menyediakan ID sumber daya dengan format ini. Lihat
<a href="#ResourcesFromCode">Mengakses Sumber Daya dalam Kode</a>.</p>
</li>
<li><strong>Dalam XML:</strong> Menggunakan sebuah sintaks XML khusus yang juga berkaitan dengan
ID sumber daya yang didefinisikan dalam kelas {@code R}, misalnya:
<pre class="classic no-pretty-print">&#64;string/hello</pre>
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Anda bisa menggunakan
sintaks ini dalam sumber daya XML di mana saja Anda ingin menyediakan sebuah nilai dalam sebuah sumber daya. Lihat <a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>.</p>
</li>
</ul>
<h2 id="ResourcesFromCode">Mengakses Sumber Daya dalam Kode </h2>
<p>Anda bisa menggunakan sumber daya dalam kode dengan menyalurkan ID sumber daya sebagai sebuah parameter metode. Misalnya,
Anda bisa mengatur sebuah {@link android.widget.ImageView} agar menggunakan sumber daya{@code res/drawable/myimage.png}
dengan menggunakan {@link android.widget.ImageView#setImageResource(int) setImageResource()}:</p>
<pre>
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(<strong>R.drawable.myimage</strong>);
</pre>
<p>Anda juga bisa mengambil tiap sumber daya dengan menggunakan berbagai metode di {@link
android.content.res.Resources}, di mana Anda bisa mendapatkan instance
{@link android.content.Context#getResources()}.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Akses ke File Asli</h2>
<p>Walaupun tidak lazim, Anda mungkin perlu mengakses file dan direktori asli Anda. Jika demikian, maka
menyimpan file Anda di {@code res/} tidak akan berhasil, karena satu-satunya cara untuk membaca sebuah sumber daya dari
{@code res/} adalah dengan ID sumber daya. Sebagai gantinya, Anda bisa menyimpan sumber daya dalam direktori
{@code assets/}.</p>
<p>File yang tersimpan di direktori {@code assets/} <em>tidak</em> diberi ID
sumber daya, sehingga Anda tidak bisa mengacunya melalui kelas {@code R} atau dari sumber daya XML. Sebagai gantinya, Anda bisa melakukan
query file di direktori {@code assets/} seperti sebuah sistem file biasa dan membaca data mentah dengan menggunakan
{@link android.content.res.AssetManager}.</p>
<p>Akan tetapi, jika yang Anda butuhkan hanya kemampuan membaca data mentah (misalnya sebuah file video atau audio),
maka simpanlah file itu di direktori {@code res/raw/} dan baca aliran byte dengan menggunakan {@link
android.content.res.Resources#openRawResource(int) openRawResource()}.</p>
</div>
</div>
<h3>Sintaks</h3>
<p>Inilah sintaks untuk mengacu sumber daya dalam kode:</p>
<pre class="classic no-pretty-print">
[<em>&lt;package_name&gt;</em>.]R.<em>&lt;resource_type&gt;</em>.<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li><em> {@code &lt;package_name&gt;}</em>adalah nama paket yang di dalamnya terdapat sumber daya (tidak
dibutuhkan bila mengacu sumber daya dari paket Anda sendiri).</li>
<li><em>{@code &lt;resource_type&gt;}</em> adalah subkelas {@code R} untuk tipe sumber daya.</li>
<li><em>{@code &lt;resource_name&gt;}</em> bisa berupa nama file sumber daya
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
sederhana).</li>
</ul>
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
<h3>Kasus penggunaan</h3>
<p>Ada banyak metode yang menerima parameter ID sumber daya dan Anda bisa mengambil sumber daya dengan menggunakan
metode di {@link android.content.res.Resources}. Anda bisa mengambil instance {@link
android.content.res.Resources} dengan {@link android.content.Context#getResources
Context.getResources()}.</p>
<p>Berikut adalah beberapa contoh cara mengakses sumber daya dalam kode:</p>
<pre>
// Load a background for the current screen from a drawable resource
{@link android.app.Activity#getWindow()}.{@link
android.view.Window#setBackgroundDrawableResource(int)
setBackgroundDrawableResource}(<strong>R.drawable.my_background_image</strong>) ;
// Set the Activity title by getting a string from the Resources object, because
// this method requires a CharSequence rather than a resource ID
{@link android.app.Activity#getWindow()}.{@link android.view.Window#setTitle(CharSequence)
setTitle}(getResources().{@link android.content.res.Resources#getText(int)
getText}(<strong>R.string.main_title</strong>));
// Load a custom layout for the current screen
{@link android.app.Activity#setContentView(int)
setContentView}(<strong>R.layout.main_screen</strong>);
// Set a slide in animation by getting an Animation from the Resources object
mFlipper.{@link android.widget.ViewAnimator#setInAnimation(Animation)
setInAnimation}(AnimationUtils.loadAnimation(this,
<strong>R.anim.hyperspace_in</strong>));
// Set the text on a TextView object using a resource ID
TextView msgTextView = (TextView) findViewById(<strong>R.id.msg</strong>);
msgTextView.{@link android.widget.TextView#setText(int)
setText}(<strong>R.string.hello_message</strong>);
</pre>
<p class="caution"><strong>Perhatian:</strong> Anda tidak boleh memodifikasi file {@code
R.java} secara manual&mdash;, ini dihasilkan oleh alat {@code aapt} bila proyek Anda telah
dikompilasi. Perubahan apa pun akan ditimpa bila nanti Anda mengompilasi.</p>
<h2 id="ResourcesFromXml">Mengakses Sumber Daya dari XML</h2>
<p>Anda bisa mendefinisikan nilai untuk beberapa atribut dan elemen XML dengan menggunakan
acuan ke sumber daya yang ada. Anda akan sering melakukannya saat membuat file layout, untuk
memasok string dan gambar bagi widget Anda.</p>
<p>Misalnya, jika Anda menambahkan sebuah {@link android.widget.Button} ke layout, Anda harus menggunakan
sebuah <a href="string-resource.html">sumber daya string</a> bagi teks tombolnya:</p>
<pre>
&lt;Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="<strong>@string/submit</strong>" /&gt;
</pre>
<h3>Sintaks</h3>
<p>Berikut adalah sintaks untuk mengacu sumber daya di sumber daya XML:</p>
<pre class="classic no-pretty-print">
&#64;[<em>&lt;package_name&gt;</em>:]<em>&lt;resource_type&gt;</em>/<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li>{@code &lt;package_name&gt;} adalah nama paket yang di dalamnya terdapat sumber daya (tidak
dibutuhkan bila mengacu sumber daya dari paket yang sama)</li>
<li>{@code &lt;resource_type&gt;} adalah subkelas
{@code R} untuk tipe sumber daya</li>
<li>{@code &lt;resource_name&gt;} bisa berupa nama file sumber daya
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
sederhana).</li>
</ul>
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
<h3>Kasus penggunaan</h3>
<p>Dalam beberapa kasus, Anda harus menggunakan sumber daya untuk suatu nilai dalam XML (misalnya, untuk menerapkan gambar yang bisa ditarik
pada widget), namun Anda juga bisa menggunakan sumber daya di XML mana saja yang menerima nilai sederhana. Misalnya, jika
Anda mempunyai file sumber daya berikut yang berisi <a href="more-resources.html#Color">sumber daya warna</a> dan <a href="string-resource.html">sumber daya string</a>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;color name="opaque_red">#f00&lt;/color>
&lt;string name="hello">Hello!&lt;/string>
&lt;/resources>
</pre>
<p>Anda bisa menggunakan sumber daya ini dalam file layout berikut untuk mengatur warna teks dan
string teks:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;color/opaque_red</strong>&quot;
android:text=&quot;<strong>&#64;string/hello</strong>&quot; /&gt;
</pre>
<p>Dalam hal ini, Anda tidak perlu menyebutkan nama paket dalam sumber daya acuan karena
sumber daya berasal dari paket Anda sendiri. Untuk
mengacu sumber daya sistem, Anda perlu memasukkan nama paketnya. Misalnya:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;android:color/secondary_text_dark</strong>&quot;
android:text=&quot;&#64;string/hello&quot; /&gt;
</pre>
<p class="note"><strong>Catatan:</strong> Anda harus menggunakan sumber daya string sepanjang
waktu, sehingga aplikasi Anda bisa dilokalkan untuk bahasa lain.
Untuk informasi tentang cara menciptakan
sumber daya alternatif (seperti string lokal), lihat <a href="providing-resources.html#AlternativeResources">Menyediakan Sumber Daya Alternatif
</a>. Untuk panduan lengkap melokalkan aplikasi Anda ke bahasa lain,
lihat <a href="localization.html">Pelokalan</a>.</p>
<p>Anda bahkan bisa menggunakan sumber daya dalam XML untuk membuat alias. Misalnya, Anda bisa membuat
sumber daya yang bisa ditarik yang merupakan alias bagi sumber daya yang bisa ditarik lainnya:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/other_drawable" />
</pre>
<p>Hal ini terdengar berlebihan, namun bisa sangat berguna saat menggunakan sumber daya alternatif. Baca selengkapnya tentang
<a href="providing-resources.html#AliasResources">Membuat sumber daya alias</a>.</p>
<h3 id="ReferencesToThemeAttributes">Mengacu atribut gaya</h3>
<p>Sumber daya atribut gaya memungkinkan Anda mengacu nilai
suatu atribut dalam tema yang diterapkan saat ini. Dengan mengacu sebuah atribut gaya memungkinkan Anda
menyesuaikan tampilan elemen UI dengan mengatur gayanya agar cocok dengan beragam variasi standar yang dipasok oleh
tema saat ini, sebagai ganti memasok nilai yang ditanamkan (hard-coded). Mengacu sebuah atribut gaya
pada dasarnya adalah "gunakan gaya yang didefinisikan oleh atribut ini, dalam tema saat ini".</p>
<p>Untuk mengacu sebuah atribut gaya, sintaks namanya hampir sama dengan format sumber daya normal
, namun sebagai ganti simbol @ ({@code @}), gunakan sebuah tanda tanya ({@code ?}), dan
porsi tipe sumber daya bersifat opsional. Sebagai contoh:</p>
<pre class="classic">
?[<em>&lt;package_name&gt;</em>:][<em>&lt;resource_type&gt;</em>/]<em>&lt;resource_name&gt;</em>
</pre>
<p>Misalnya, begini cara Anda mengacu suatu atribut untuk mengatur warna teks agar cocok dengan
warna teks "utama" tema sistem:</p>
<pre>
&lt;EditText id=&quot;text&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:textColor=&quot;<strong>?android:textColorSecondary</strong>&quot;
android:text=&quot;&#64;string/hello_world&quot; /&gt;
</pre>
<p>Di sini, atribut {@code android:textColor} menyebutkan nama atribut gaya
dalam tema saat ini. Android kini menggunakan nilai yang diterapkan pada atribut gaya {@code android:textColorSecondary}
sebagai nilai untuk {@code android:textColor} dalam widget ini. Karena alat sumber daya
mengetahui bahwa atribut sumber daya diharapkan dalam konteks ini,
maka Anda tidak perlu menyatakan tipenyanya secara eksplisit (yang akan berupa
<code>?android:attr/textColorSecondary</code>)&mdash;Anda bisa mengecualikan tipe {@code attr}.</p>
<h2 id="PlatformResources">Mengakses Sumber Daya Platform</h2>
<p>Android berisi sejumlah sumber daya standar, seperti gaya, tema, dan layout. Untuk
mengakses semua sumber daya ini, tetapkan acuan sumber daya Anda dengan nama paket
<code>android</code>. Misalnya, Android menyediakan sumber daya layout yang bisa Anda gunakan untuk
item daftar dalam{@link android.widget.ListAdapter}:</p>
<pre>
{@link android.app.ListActivity#setListAdapter(ListAdapter)
setListAdapter}(new {@link
android.widget.ArrayAdapter}&lt;String&gt;(this, <strong>android.R.layout.simple_list_item_1</strong>, myarray));
</pre>
<p>Dalam contoh ini, {@link android.R.layout#simple_list_item_1} adalah sumber daya layout yang didefinisikan oleh
platform untuk item di {@link android.widget.ListView}. Anda bisa menggunakannya sebagai ganti menciptakan
layout sendiri untuk item daftar. Untuk informasi selengkapnya, lihat panduan pengembang
<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>.</p>

View File

@@ -1,103 +0,0 @@
page.title=Ikhtisar Sumber Daya
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topik</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
<li><a href="runtime-changes.html">Menangani Perubahan Runtime</a></li>
<li><a href="localization.html">Pelokalan</a></li>
</ol>
<h2>Acuan</h2>
<ol>
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
</ol>
</div>
</div>
<p>Anda harus selalu mengeksternalkan sumber daya seperti gambar dan string dari kode
aplikasi, agar Anda bisa memeliharanya secara independen. Mengeksternalkan
sumber daya juga membuat Anda dapat menyediakan sumber daya alternatif yang mendukung konfigurasi
perangkat tertentu seperti bahasa atau ukuran layar yang berbeda, yang semakin penting
seiring semakin banyak tersedianya perangkat berbasis Android dengan konfigurasi berbeda. Untuk
memberikan kompatibilitas dengan konfigurasi berbeda, Anda harus menata sumber daya dalam
direktori {@code res/} proyek Anda, menggunakan berbagai subdirektori yang mengelompokkan sumber daya menurut tipe
dan konfigurasinya.</p>
<div class="figure" style="width:429px">
<img src="{@docRoot}images/resources/resource_devices_diagram1.png" height="167" alt="" />
<p class="img-caption">
<strong>Gambar 1.</strong> Dua perangkat berbeda, masing-masing menggunakan layout default
(aplikasi tidak menyediakan layout alternatif).</p>
</div>
<div class="figure" style="width:429px">
<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="167" alt="" />
<p class="img-caption">
<strong>Gambar 2.</strong> Dua perangkat berbeda, masing-masing menggunakan layout berbeda yang tersedia untuk
ukuran layar berbeda.</p>
</div>
<p>Bagi setiap tipe sumber daya, Anda bisa menetapkan sumber daya <em>default</em> dan sumber daya
<em>alternatif</em> untuk aplikasi Anda:</p>
<ul>
<li>Sumber daya default adalah sumber daya yang harus digunakan apa pun
konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai
dengan konfigurasi saat ini.</li>
<li>Sumber daya alternatif adalah sumber daya yang Anda desain untuk digunakan dengan
konfigurasi tertentu. Untuk menetapkan bahwa satu kelompok sumber daya ditujukan bagi konfigurasi tertentu,
tambahkan qualifier konfigurasi yang sesuai ke nama direktori.</li>
</ul>
<p>Misalnya, walaupun layout
UI default Anda disimpan dalam direktori {@code res/layout/}, Anda dapat menetapkan layout berbeda
untuk digunakan saat layar dalam orientasi lanskap, dengan menyimpannya dalam direktori {@code res/layout-land/}
. Android secara otomatis memberlakukan sumber daya yang sesuai dengan mencocokkan konfigurasi perangkat
saat ini dengan nama direktori sumber daya.</p>
<p>Gambar 1 mengilustrasikan cara sistem memberlakukan layout yang sama untuk
dua perangkat berbeda saat sumber daya alternatif tidak tersedia. Gambar 2 menunjukkan
aplikasi yang sama saat menambahkan sumber daya layout alternatif untuk layar yang lebih besar.</p>
<p>Dokumen-dokumen berikut berisi panduan lengkap mengenai cara menata sumber daya aplikasi,
menetapkan sumber daya alternatif, mengaksesnya dalam aplikasi, dan banyak lagi:</p>
<dl>
<dt><strong><a href="providing-resources.html">Menyediakan Sumber Daya</a></strong></dt>
<dd>Jenis sumber daya yang dapat Anda sediakan dalam aplikasi, tempat menyimpannya, dan cara membuat sumber daya
alternatif untuk konfigurasi perangkat tertentu.</dd>
<dt><strong><a href="accessing-resources.html">Mengakses Sumber Daya</a></strong></dt>
<dd>Cara menggunakan sumber daya yang telah Anda sediakan, baik dengan mengacunya dari kode
aplikasi Anda atau dari sumber daya XML lainnya.</dd>
<dt><strong><a href="runtime-changes.html">Menangani Perubahan Runtime</a></strong></dt>
<dd>Cara mengelola perubahan konfigurasi yang terjadi saat Aktivitas Anda berjalan.</dd>
<dt><strong><a href="localization.html">Pelokalan</a></strong></dt>
<dd>Panduan dari pengalaman untuk melokalkan aplikasi menggunakan sumber daya alternatif. Walaupun ini
hanya satu penggunaan tertentu dari sumber daya alternatif, hal ini sangat penting dalam meraih pengguna lebih
banyak.</dd>
<dt><strong><a href="available-resources.html">Tipe Sumber Daya</a></strong></dt>
<dd>Acuan dari berbagai tipe sumber daya yang dapat Anda sediakan, menjelaskan elemen-elemen XML,
atribut, dan sintaksnya. Misalnya, acuan ini menunjukkan kepada Anda cara membuat sumber daya untuk
menu aplikasi, drawable, animasi, dan lainnya.</dd>
</dl>
<!--
<h2>Raw Assets</h2>
<p>An alternative to saving files in {@code res/} is to save files in the {@code
assets/} directory. This should only be necessary if you need direct access to original files and
directories by name. Files saved in the {@code assets/} directory will not be given a resource
ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
query data in the {@code assets/} directory like an ordinary file system, search through the
directory and
read raw data using {@link android.content.res.AssetManager}. For example, this can be more useful
when dealing with textures for a game. However, if you only need to read raw data from a file
(such as a video or audio file), then you should save files into the {@code res/raw/} directory and
then read a stream of bytes using {@link android.content.res.Resources#openRawResource(int)}. This
is uncommon, but if you need direct access to original files in {@code assets/}, refer to the {@link
android.content.res.AssetManager} documentation.</p>
-->

View File

@@ -1,281 +0,0 @@
page.title=Menangani Perubahan Runtime
page.tags=aktivitas,daur hidup
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</a></li>
<li><a href="#HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</a>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
<li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Perubahan
Orientasi Layar yang Lebih Cepat</a></li>
</ol>
</div>
</div>
<p>Sebagian konfigurasi perangkat bisa berubah selama runtime
(seperti orientasi layar, ketersediaan keyboard, dan bahasa). Saat perubahan demikian terjadi,
Android akan me-restart
{@link android.app.Activity} yang berjalan ({@link android.app.Activity#onDestroy()} dipanggil, diikuti oleh {@link
android.app.Activity#onCreate(Bundle) onCreate()}). Perilaku restart didesain untuk membantu
aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan kembali aplikasi Anda secara otomatis dengan
sumber daya alternatif sumber yang sesuai dengan konfigurasi perangkat baru.</p>
<p>Untuk menangani restart dengan benar, aktivitas Anda harus mengembalikan
statusnya seperti semula melalui <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup
aktivitas</a> normal, dalam hal ini Android akan memanggil
{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} sebelum menghentikan
aktivitas Anda sehingga Anda dapat menyimpan data mengenai status aplikasi. Selanjutnya Anda bisa mengembalikan status
selama {@link android.app.Activity#onCreate(Bundle) onCreate()} atau {@link
android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p>
<p>Untuk menguji bahwa aplikasi me-restart sendiri dengan status tak berubah, Anda harus
memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai
tugas dalam aplikasi. Aplikasi Anda harus dapat me-restart setiap saat tanpa kehilangan
data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon
masuk lalu kembali ke aplikasi setelah proses
aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup aktivitas</a>.</p>
<p>Akan tetapi, Anda mungkin menemui situasi ketika me-restart aplikasi dan
mengembalikan data dalam jumlah besar malah menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi
demikian, Anda memiliki dua opsi lain:</p>
<ol type="a">
<li><a href="#RetainingAnObject">Mempertahankan objek selama perubahan konfigurasi</a>
<p>Izinkan aktivitas Anda me-restart saat konfigurasi berubah, namun bawa objek
berstatus (stateful) ke instance baru aktivitas Anda.</p>
</li>
<li><a href="#HandlingTheChange">Menangani sendiri perubahan konfigurasi</a>
<p>Cegah sistem me-restart aktivitas selama perubahan konfigurasi
tertentu, namun terima callback saat konfigurasi benar-benar berubah, agar Anda bisa memperbarui
aktivitas secara manual bila diperlukan.</p>
</li>
</ol>
<h2 id="RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</h2>
<p>Jika me-restart aktivitas mengharuskan pemulihan seperangkat data dalam jumlah besar, menghubungkan kembali koneksi
jaringan, atau melakukan operasi intensif lainnya, maka restart penuh karena perubahan konfigurasi mungkin
menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya mengembalikan status
aktivitas dengan {@link android.os.Bundle} yang disimpan sistem untuk Anda dengan callback {@link
android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}&mdash;itu tidaklah
didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian
dinon-serialkan, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi
demikian, Anda bisa meringankan beban memulai kembali aktivitas Anda dengan mempertahankan {@link
android.app.Fragment} saat aktivitas Anda di-restart karena perubahan konfigurasi. Fragmen ini
bisa berisi acuan ke objek stateful yang ingin Anda pertahankan.</p>
<p>Bila sistem Android menghentikan aktivitas Anda karena perubahan konfigurasi, fragmen
aktivitas yang telah ditandai untuk dipertahankan tidak akan dimusnahkan. Anda dapat menambahkan fragmen tersebut ke
aktivitas untuk mempertahankan objek stateful.</p>
<p>Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:</p>
<ol>
<li>Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful
Anda.</li>
<li>Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat.
</li>
<li>Tambahkan fragmen ke aktivitas.</li>
<li>Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas
di-restart.</li>
</ol>
<p>Misalnya, definisikan fragmen sebagai berikut:</p>
<pre>
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
public void setData(MyDataObject data) {
this.data = data;
}
public MyDataObject getData() {
return data;
}
}
</pre>
<p class="caution"><strong>Perhatian:</strong> Meskipun bisa menyimpan objek apa saja, Anda
sama sekali tidak boleh meneruskan objek yang terkait dengan {@link android.app.Activity}, seperti {@link
android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View}
atau objek lainnya mana pun yang terkait dengan {@link android.content.Context}. Jika Anda melakukannya, hal tersebut akan
membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber daya yang bocor
berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak
memori yang hilang.)</p>
<p>Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas.
Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan
konfigurasi runtime. Misalnya, definisikan aktivitas Anda sebagai berikut:</p>
<pre>
public class MyActivity extends Activity {
private RetainedFragment dataFragment;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
// create the fragment and data the first time
if (dataFragment == null) {
// add the fragment
dataFragment = new DataFragment();
fm.beginTransaction().add(dataFragment, “data”).commit();
// load the data from the web
dataFragment.setData(loadMyData());
}
// the data is available in dataFragment.getData()
...
}
&#64;Override
public void onDestroy() {
super.onDestroy();
// store the data in the fragment
dataFragment.setData(collectMyLoadedData());
}
}
</pre>
<p>Dalam contoh ini, {@link android.app.Activity#onCreate(Bundle) onCreate()} menambahkan fragmen
atau mengembalikan referensinya. {@link android.app.Activity#onCreate(Bundle) onCreate()} juga
menyimpan objek stateful dalam instance fragmen.
{@link android.app.Activity#onDestroy() onDestroy()} akan memperbarui objek stateful dalam
instance fragmen yang dipertahankan.</p>
<h2 id="HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</h2>
<p>Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi
tertentu <em>dan</em> Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk
menghindari restart aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan
konfigurasinya, sehingga mencegah sistem me-restart aktivitas.</p>
<p class="note"><strong>Catatan:</strong> Menangani sendiri perubahan konfigurasi bisa jauh lebih
mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis
untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari restart
karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.</p>
<p>Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> yang sesuai
dalam file manifes Anda agar menyertakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> dengan nilai yang mewakili konfigurasi yang ingin
ditangani. Nilai yang memungkinkan tercantum dalam dokumentasi untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> (nilai paling sering digunakan adalah {@code "orientation"} untuk
mencegah restart saat orientasi layar berubah dan {@code "keyboardHidden"} untuk mencegah
restart saat ketersediaan keyboard berubah). Anda dapat mendeklarasikan beberapa nilai konfigurasi
dalam atribut dengan memisahkannya menggunakan karakter pipa {@code |}.</p>
<p>Misalnya, kode manifes berikut menyatakan aktivitas yang menangani
perubahan orientasi layar maupun perubahan ketersediaan keyboard:</p>
<pre>
&lt;activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
</pre>
<p>Sekarang, bila salah satu konfigurasi ini berubah, {@code MyActivity} tidak akan me-restart.
Sebagai gantinya, {@code MyActivity} akan menerima panggilan ke {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Metode ini
meneruskan objek {@link android.content.res.Configuration} yang menetapkan
konfigurasi perangkat baru. Dengan membaca bidang-bidang dalam {@link android.content.res.Configuration},
Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui
sumber daya yang digunakan dalam antarmuka. Pada saat
metode ini dipanggil, objek {@link android.content.res.Resources} aktivitas Anda akan diperbarui untuk
mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah
me-reset elemen UI tanpa membuat sistem me-restart aktivitas Anda.</p>
<p class="caution"><strong>Perhatian:</strong> Mulai Android 3.2 (API level 13), <strong>
"ukuran layar" juga berubah</strong> bila perangkat beralih orientasi antara potret
dan lanskap. Jadi jika Anda tidak ingin runtime di-restart karena perubahan orientasi saat mengembangkan
API level 13 atau yang lebih tinggi (sebagaimana dideklarasikan oleh atribut <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> dan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>
), Anda harus menyertakan nilai {@code "screenSize"} selain nilai {@code
"orientation"}. Yaitu Anda harus mendeklarasikan {@code
android:configChanges="orientation|screenSize"}. Akan tetapi, jika aplikasi Anda menargetkan API level
12 atau yang lebih rendah, maka aktivitas Anda akan selalu menangani sendiri perubahan konfigurasi ini (perubahan
konfigurasi ini tidak me-restart aktivitas Anda, bahkan saat berjalan pada perangkat Android 3.2 atau yang lebih tinggi).</p>
<p>Misalnya, implementasi {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} berikut akan
memeriksa orientasi perangkat saat ini:</p>
<pre>
&#64;Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>Objek {@link android.content.res.Configuration} mewakili semua konfigurasi
saat ini, tidak hanya konfigurasi yang telah berubah. Seringkali Anda tidak perlu memperhatikan dengan persis bagaimana
konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk
konfigurasi sedang ditangani. Misalnya, karena objek {@link
android.content.res.Resources} sekarang diperbarui, Anda dapat me-reset
setiap {@link android.widget.ImageView} dengan {@link android.widget.ImageView#setImageResource(int)
setImageResource()}
dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti dijelaskan dalam <a href="providing-resources.html#AlternateResources">Menyediakan Sumber Daya</a>).</p>
<p>Perhatikan bahwa nilai-nilai dari bidang {@link
android.content.res.Configuration} adalah integer yang sesuai dengan konstanta spesifik
dari kelas {@link android.content.res.Configuration}. Untuk dokumentasi tentang konstanta
yang harus digunakan di setiap bidang, lihat bidang yang sesuai dalam referensi {@link
android.content.res.Configuration}.</p>
<p class="note"><strong>Ingatlah:</strong> Saat mendeklarasikan aktivitas untuk menangani perubahan
konfigurasi, Anda bertanggung jawab untuk me-reset setiap elemen yang alternatifnya Anda berikan. Jika Anda
mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah
antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
<p>Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan
konfigurasi ini, sebagai gantinya Anda bisa saja <em>tidak</em> mengimplementasikan {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Dalam
hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan
dan Anda hanya menghindari restart aktivitas. Akan tetapi, aplikasi Anda harus selalu
bisa dimatikan dan di-restart dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik
ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya
karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk me-restart aplikasi, namun
juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan
dimusnahkan sebelum pengguna kembali ke aplikasi.</p>
<p>Untuk informasi selengkapnya tentang perubahan konfigurasi yang bisa Anda tangani dalam aktivitas, lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> dan kelas {@link android.content.res.Configuration}
.</p>

View File

@@ -1,90 +0,0 @@
page.title=Kontrol Input
parent.title=Antarmuka Pengguna
parent.link=index.html
@jd:body
<div class="figure" style="margin:0">
<img src="{@docRoot}images/ui/ui-controls.png" alt="" style="margin:0" />
</div>
<p>Kontrol input adalah komponen interaktif dalam antarmuka pengguna aplikasi Anda. Android menyediakan
aneka ragam kontrol yang bisa Anda gunakan dalam UI, seperti tombol, bidang teks, bilah pencarian,
kotak cek, tombol zoom, tombol toggle, dan masih banyak lagi.</p>
<p>Menambahkan sebuah kontrol input ke UI adalah semudah menambahkan satu elemen XML ke <a href="{@docRoot}guide/topics/ui/declaring-layout.html">layout XML</a>. Misalnya, inilah sebuah
layout dengan satu bidang teks dan satu tombol:</p>
<pre style="clear:right">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
&lt;EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
&lt;Button android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"
android:onClick="sendMessage" />
&lt;/LinearLayout>
</pre>
<p>Tiap kontrol input mendukung satu set kejadian input sehingga Anda bisa menangani berbagai kejadian seperti saat
pengguna memasukkan teks atau menyentuh tombol.</p>
<h2 id="CommonControls">Kontrol Umum</h2>
<p>Berikut adalah daftar beberapa kontrol umum yang bisa Anda gunakan dalam aplikasi. Ikuti tautan ini untuk mengetahui
selengkapnya tentang penggunaannya masing-masing.</p>
<p class="note"><strong>Catatan:</strong> Android menyediakan beberapa kontrol lain yang tidak tercantum
di sini. Telusuri paket {@link android.widget} untuk mengetahui selengkapnya. Jika aplikasi Anda memerlukan
semacam kontrol input tertentu, Anda bisa membangun <a href="{@docRoot}guide/topics/ui/custom-components.html">komponen custom</a> sendiri.</p>
<table>
<tr>
<th scope="col">Tipe Kontrol</th>
<th scope="col">Keterangan</th>
<th scope="col">Kelas Terkait</th>
</tr>
<tr>
<td><a href="controls/button.html">Tombol</a></td>
<td>Tombol tekan yang bisa ditekan, atau diklik, oleh pengguna untuk melakukan suatu tindakan.</td>
<td>{@link android.widget.Button Button} </td>
</tr>
<tr>
<td><a href="controls/text.html">Bidang teks</a></td>
<td>Bidang teks yang bisa diedit. Anda bisa menggunakan widget <code>AutoCompleteTextView</code> untuk membuat widget entri teks yang menyediakan saran pelengkapan otomatis</td>
<td>{@link android.widget.EditText EditText}, {@link android.widget.AutoCompleteTextView}</td>
</tr>
<tr>
<td><a href="controls/checkbox.html">Kotak cek</a></td>
<td>Switch aktif/nonaktif yang bisa diubah oleh pengguna. Anda harus menggunakan kotak cek saat menampilkan sekumpulan opsi yang bisa dipilih pengguna dan bila keduanya mungkin terjadi bersamaan.</td>
<td>{@link android.widget.CheckBox CheckBox} </td>
</tr>
<tr>
<td><a href="controls/radiobutton.html">Tombol radio</a></td>
<td>Mirip dengan kotak cek, hanya saja cuma satu opsi yang bisa dipilih dalam kumpulan tersebut.</td>
<td>{@link android.widget.RadioGroup RadioGroup}
<br>{@link android.widget.RadioButton RadioButton} </td>
</tr>
<tr>
<td><a href="controls/togglebutton.html" style="white-space:nowrap">Tombol toggle</a></td>
<td>Tombol aktif/nonaktif dengan indikator cahaya.</td>
<td>{@link android.widget.ToggleButton ToggleButton} </td>
</tr>
<tr>
<td><a href="controls/spinner.html">Spinner</a></td>
<td>Daftar tarik-turun yang memungkinkan pengguna memilih salah satu dari serangkaian nilai.</td>
<td>{@link android.widget.Spinner Spinner} </td>
</tr>
<tr>
<td><a href="controls/pickers.html">Picker</a></td>
<td>Dialog bagi pengguna untuk memilih satu nilai dari satu kumpulan dengan menggunakan tombol naik/turun atau dengan gerakan mengusap. Gunakan widget <code>DatePicker</code>code&gt; untuk memasukkan nilai tanggal (bulan, hari, tahun) atau widget <code>TimePicker</code> untuk memasukkan nilai waktu (jam, menit, AM/PM), yang akan diformat secara otomatis untuk lokasi pengguna tersebut.</td>
<td>{@link android.widget.DatePicker}, {@link android.widget.TimePicker}</td>
</tr>
</table>

View File

@@ -1,492 +0,0 @@
page.title=Layout
page.tags=view,viewgroup
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#write">Tulis XML</a></li>
<li><a href="#load">Muat Sumber Daya XML</a></li>
<li><a href="#attributes">Atribut</a>
<ol>
<li><a href="#id">ID</a></li>
<li><a href="#layout-params">Parameter Layout</a></li>
</ol>
</li>
<li><a href="#Position">Posisi Layout</a></li>
<li><a href="#SizePaddingMargins">Ukuran, Pengisi, dan Margin</a></li>
<li><a href="#CommonLayouts">Layout Umum</a></li>
<li><a href="#AdapterViews">Membangun Layout dengan Adaptor</a>
<ol>
<li><a href="#FillingTheLayout">Mengisi tampilan adaptor dengan data</a></li>
<li><a href="#HandlingUserSelections">Menangani kejadian klik</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.view.ViewGroup.LayoutParams}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Membangun Antarmuka Pengguna
Sederhana</a></li> </div>
</div>
<p>Layout mendefinisikan struktur visual untuk antarmuka pengguna, seperti UI sebuah <a href="{@docRoot}guide/components/activities.html">aktivitas</a> atau <a href="{@docRoot}guide/topics/appwidgets/index.html">widget aplikasi</a>.
Anda dapat mendeklarasikan layout dengan dua cara:</p>
<ul>
<li><strong>Deklarasikan elemen UI dalam XML</strong>. Android menyediakan sebuah kosakata XML
sederhana yang sesuai dengan kelas dan subkelas View, seperti halnya untuk widget dan layout.</li>
<li><strong>Buat instance elemen layout saat runtime</strong>. Aplikasi Anda
bisa membuat objek View dan ViewGroup (dan memanipulasi propertinya) lewat program. </li>
</ul>
<p>Kerangka kerja Android memberi Anda fleksibilitas untuk menggunakan salah satu atau kedua metode ini guna mendeklarasikan dan mengelola UI aplikasi Anda. Misalnya, Anda bisa mendeklarasikan layout default aplikasi Anda dalam XML, termasuk elemen-elemen layar yang akan muncul di dalamnya dan di propertinya. Anda nanti bisa menambahkan kode dalam aplikasi yang akan memodifikasi status objek layar, termasuk yang dideklarasikan dalam XML, saat runtime. </p>
<div class="sidebox-wrapper">
<div class="sidebox">
<ul>
<li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
Plugin for Eclipse</a> menawarkan preview layout XML &mdash;
Anda dengan file XML yang dibuka, pilih tab <strong>Layout</strong>.</li>
<li>Anda juga harus mencoba alat
<a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a>,
untuk merunut layout &mdash; alat ini akan menampilkan nilai-nilai properti layout,
menggambar bentuk kerangka dengan indikator pengisi/margin, dan tampilan yang dirender penuh selagi
Anda merunut pada emulator atau perangkat.</li>
<li>Alat <a href="{@docRoot}tools/debugging/debugging-ui.html#layoutopt">layoutopt</a> memungkinkan
Anda menganalisis layout dan hierarki dengan untuk mengetahui ketidakefisienan atau masalah lainnya.</li>
</div>
</div>
<p>Keuntungan mendeklarasikan UI dalam XML adalah karena hal ini memungkinkan Anda memisahkan penampilan aplikasi dari kode yang mengontrol perilakunya dengan lebih baik. Keterangan UI Anda bersifat eksternal bagi kode aplikasi Anda, yang berarti bahwa Anda bisa memodifikasi atau menyesuaikannya tanpa harus memodifikasi dan mengompilasi ulang kode sumber. Misalnya, Anda bisa membuat layout XML untuk berbagai orientasi layar, berbagai ukuran layar perangkat, dan berbagai bahasa. Selain itu, mendeklarasikan layout dalam XML akan mempermudah Anda memvisualisasikan struktur UI, sehingga lebih mudah merunut masalahnya. Karena itu, dokumen ini berfokus pada upaya mengajari Anda cara mendeklarasikan layout dalam XML. Jika Anda
tertarik dalam membuat instance objek View saat runtime, lihat referensi kelas {@link android.view.ViewGroup} dan
{@link android.view.View}.</p>
<p>Secara umum, kosakata XML untuk mendeklarasikan elemen UI mengikuti dengan sangat mirip struktur serta penamaan kelas dan metode, dengan nama elemen dipadankan dengan nama kelas dan nama atribut dipadankan dengan metode. Sebenarnya, pemadanan ini kerap kali begitu jelas sehingga Anda bisa menebak atribut XML yang berpadanan dengan sebuah metode kelas, atau menebak kelas yang berpadanan dengan sebuah elemen XML. Akan tetapi, perhatikan bahwa tidak semua kosakata identik. Dalam beberapa kasus, ada sedikit perbedaan penamaan. Misalnya
, elemen EditText memiliki atribut <code>text</code> yang berpadanan dengan
<code>EditText.setText()</code>. </p>
<p class="note"><strong>Tip:</strong> Ketahui selengkapnya berbagai tipe layout dalam <a href="{@docRoot}guide/topics/ui/layout-objects.html">Objek
Layout Umum</a>. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>.</p>
<h2 id="write">Tulis XML</h2>
<p>Dengan menggunakan kosakata XML Android, Anda bisa mendesain secara cepat layout UI dan elemen layar yang dimuatnya, sama dengan cara membuat halaman web dalam HTML &mdash; dengan serangkaian elemen tersarang. </p>
<p>Tiap file layout harus berisi persis satu elemen akar, yang harus berupa sebuah objek View atau ViewGroup. Setelah mendefinisikan elemen akar, Anda bisa menambahkan objek atau widget layout tambahan sebagai elemen anak untuk membangun hierarki View yang mendefinisikan layout Anda secara bertahap. Misalnya, inilah layout XML yang menggunakan {@link android.widget.LinearLayout}
vertikal untuk menyimpan {@link android.widget.TextView} dan {@link android.widget.Button}:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Setelah Anda mendeklarasikan layout dalam XML, simpanlah file dengan ekstensi <code>.xml</code>,
dalam direktori <code>res/layout/</code> proyek Android, sehingga nanti bisa dikompilasi dengan benar. </p>
<p>Informasi selengkapnya tentang sintaks untuk file XML layout tersedia dalam dokumen <a href="{@docRoot}guide/topics/resources/layout-resource.html">Sumber Daya Layout</a>.</p>
<h2 id="load">Muat Sumber Daya XML</h2>
<p>Saat mengompilasi aplikasi, masing-masing file layout XML akan dikompilasi dalam sebuah sumber daya
{@link android.view.View}. Anda harus memuat sumber daya layout dari kode aplikasi, dalam implementasi
callback {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}.
Lakukan dengan memanggil <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
dengan meneruskan acuan ke sumber daya layout berupa:
<code>R.layout.<em>layout_file_name</em></code>.
Misalnya, jika XML layout Anda disimpan sebagai <code>main_layout.xml</code>, Anda akan memuatnya
untuk Activity seperti ini:</p>
<pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
</pre>
<p>Metode callback <code>onCreate()</code> dalam Activity dipanggil oleh kerangka kerja Android saat
Activity Anda dijalankan (lihat diskusi tentang daur hidup, dalam dokumen
<a href="{@docRoot}guide/components/activities.html#Lifecycle">Aktivitas</a>
).</p>
<h2 id="attributes">Atribut</h2>
<p>Setiap objek View dan ViewGroup mendukung variasi atribut XML-nya sendiri.
Sebagian atribut bersifat spesifik untuk objek View (misalnya, TextView mendukung atribut <code>textSize</code>
), namun atribut ini juga diwarisi oleh sembarang objek View yang dapat memperluas kelas ini.
Sebagian atribut bersifat umum untuk semua objek View, karena diwarisi dari kelas View akar (seperti
atribut <code>id</code>). Dan, atribut lain dianggap sebagai "parameter layout" yaitu
atribut yang menjelaskan orientasi layout tertentu dari objek View, seperti yang didefinisikan oleh objek ViewGroup induk
dari objek itu.</p>
<h3 id="id">ID</h3>
<p>Objek View apa saja dapat memiliki ID integer yang dikaitkan dengannya, untuk mengidentifikasi secara unik View dalam pohon.
Bila aplikasi dikompilasi, ID ini akan diacu sebagai integer, namun ID biasanya
ditetapkan dalam file XML layout sebagai string, dalam atribut <code>id</code>.
Ini atribut XML yang umum untuk semua objek View
(yang didefinisikan oleh kelas {@link android.view.View}) dan Anda akan sering sekali menggunakannya.
Sintaks untuk ID dalam tag XML adalah:</p>
<pre>android:id="&#64;+id/my_button"</pre>
<p>Simbol "at" (@) pada awal string menunjukkan parser XML harus mengurai dan memperluas
ID string selebihnya dan mengenalinya sebagai ID sumber daya. Simbol tanda tambah (+) berarti ini nama sumber daya baru yang harus
dibuat dan ditambahkan ke sumber daya kita (dalam file <code>R.java</code>). Ada sejumlah sumber daya ID lain yang
ditawarkan oleh kerangka kerja Android. Saat mengacu sebuah ID sumber daya Android, Anda tidak memerlukan simbol tanda tambah,
namun harus menambahkan namespace paket <code>android</code>, sehingga:</p>
<pre>android:id="&#64;android:id/empty"</pre>
<p>Dengan namespace paket <code>android</code> yang tersedia, kita sekarang mengacu ID dari kelas sumber daya <code>android.R</code>
, daripada kelas sumber daya lokal.</p>
<p>Untuk membuat tampilan dan mengacunya dari aplikasi, pola yang umum adalah:</p>
<ol>
<li>Mendefinisikan tampilan/widget dalam file layout dan memberinya ID unik:
<pre>
&lt;Button android:id="&#64;+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/my_button_text"/>
</pre>
</li>
<li>Kemudian buat instance objek tampilan dan tangkap instance itu dari layout
(biasanya dalam metode <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code>):
<pre>
Button myButton = (Button) findViewById(R.id.my_button);
</pre>
</li>
</ol>
<p>Mendefinisikan ID untuk objek tampilan adalah penting saat membuat {@link android.widget.RelativeLayout}.
Dalam layout relatif, tampilan saudara bisa mendefinisikan layout secara relatif terhadap tampilan saudara lainnya,
yang diacu melalui ID unik.</p>
<p>ID tidak perlu unik di seluruh pohon, namun harus
unik di bagian pohon yang Anda cari (yang mungkin sering kali seluruh pohon, jadi lebih baik
benar-benar unik bila memungkinkan).</p>
<h3 id="layout-params">Parameter Layout</h3>
<p>Atribut layout XML bernama <code>layout_<em>something</em></code> mendefinisikan
parameter layout View yang cocok untuk ViewGroup tempatnya berada.</p>
<p>Setiap kelas ViewGroup mengimplementasikan kelas tersarang yang memperluas {@link
android.view.ViewGroup.LayoutParams}. Subkelas ini
berisi tipe properti yang mendefinisikan ukuran dan posisi masing-masing tampilan anak, sebagaimana
mestinya untuk grup tampilan. Seperti yang bisa Anda lihat dalam gambar 1,
grup tampilan induk mendefinisikan parameter layout untuk masing-masing tampilan anak (termasuk grup tampilan anak).</p>
<img src="{@docRoot}images/layoutparams.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Visualisasi hierarki tampilan dengan parameter layout
yang dikaitkan dengan tiap tampilan.</p>
<p>Perhatikan bahwa setiap subkelas LayoutParams memiliki sintaksnya sendiri untuk menetapkan
nilai-nilai. Tiap elemen anak harus mendefinisikan LayoutParams yang semestinya bagi induknya,
meskipun elemen itu bisa juga mendefinisikan LayoutParams untuk anak-anaknya sendiri. </p>
<p>Semua grup tampilan berisi lebar dan tinggi (<code>layout_width</code> dan
<code>layout_height</code>), dan masing-masing tampilan harus mendefinisikannya. Banyak
LayoutParams yang juga menyertakan margin dan border opsional. <p>
<p>Anda bisa menetapkan lebar dan tinggi dengan ukuran persis, meskipun Anda mungkin
tidak ingin sering-sering melakukannya. Lebih sering, Anda akan menggunakan salah satu konstanta ini untuk
mengatur lebar atau tinggi: </p>
<ul>
<li><var>wrap_content</var> memberi tahu tampilan Anda agar menyesuaikan sendiri ukurannya dengan dimensi
yang dibutuhkan oleh isinya.</li>
<li><var>match_parent</var> (bernama <var>fill_parent</var> sebelum API Level 8)
memberi tahu tampilan Anda agar menjadi sebesar yang diperbolehkan oleh grup tampilan induknya.</li>
</ul>
<p>Secara umum, menetapkan lebar dan tinggi layout dengan satuan mutlak seperti
piksel tidaklah disarankan. Melainkan dengan menggunakan ukuran relatif seperti
satuan piksel yang tidak bergantung pada kerapatan (<var>dp</var>), <var>wrap_content</var>, atau
<var>match_parent</var>, adalah sebuah pendekatan yang lebih baik, karena membantu memastikan bahwa
aplikasi Anda akan ditampilkan dengan benar pada berbagai ukuran layar perangkat.
Tipe ukuran yang diterima didefinisikan dalam dokumen
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
Sumber Daya yang Tersedia</a>.</p>
<h2 id="Position">Posisi Layout</h2>
<p>
Geometri tampilan adalah persegi panjang. Sebuah tampilan memiliki lokasi,
yang dinyatakan berupa sepasang koordinat <em>kiri</em> dan <em>atas</em>, dan
dua dimensi, yang dinyatakan berupa lebar dan tinggi. Satuan untuk lokasi
dan dimensi adalah piksel.
</p>
<p>
Lokasi tampilan dapat diambil dengan memanggil metode
{@link android.view.View#getLeft()} dan {@link android.view.View#getTop()}. Metode terdahulu menghasilkan koordinat kiri, atau X,
persegi panjang yang mewakili tampilan. Metode selanjutnya menghasilkan koordinat
atas, atau Y, persegi panjang yang mewakili tampilan. Kedua metode ini
menghasilkan lokasi tampilan relatif terhadap induknya. Misalnya,
bila <code>getLeft()</code> menghasilkan 20, berarti tampilan berlokasi 20 piksel ke
kanan dari tepi kiri induk langsungnya.
</p>
<p>
Selain itu, beberapa metode praktis ditawarkan untuk menghindari komputasi yang tidak perlu,
yakni {@link android.view.View#getRight()} dan {@link android.view.View#getBottom()}.
Kedua metode ini menghasilkan koordinat tepi kanan dan bawah
persegi panjang yang mewakili tampilan. Misalnya, memanggil {@link android.view.View#getRight()}
serupa dengan komputasi berikut: <code>getLeft() + getWidth()</code>.
</p>
<h2 id="SizePaddingMargins">Ukuran, Pengisi, dan Margin</h2>
<p>
Ukuran tampilan dinyatakan dengan lebar dan tinggi. Tampilan sebenarnya
memiliki dua pasang nilai lebar dan tinggi.
</p>
<p>
Sepasang pertama disebut <em>lebar terukur</em> dan
<em>tinggi terukur</em>. Dimensi ini mendefinisikan seberapa besar tampilan yang diinginkan
dalam induknya. Dimensi
terukur bisa diperoleh dengan memanggil {@link android.view.View#getMeasuredWidth()}
dan {@link android.view.View#getMeasuredHeight()}.
</p>
<p>
Sepasang kedua cukup disebut dengan <em>lebar</em> dan <em>tinggi</em>, atau
kadang-kadang <em>lebar penggambaran</em> dan <em>tinggi penggambaran</em>. Dimensi-dimensi ini
mendefinisikan ukuran tampilan sebenarnya pada layar, saat digambar dan
setelah layout. Nilai-nilai ini mungkin, namun tidak harus, berbeda dengan
lebar dan tinggi terukur. Lebar dan tinggi bisa diperoleh dengan memanggil
{@link android.view.View#getWidth()} dan {@link android.view.View#getHeight()}.
</p>
<p>
Untuk mengukur dimensinya, tampilan akan memperhitungkan pengisinya (padding). Pengisi
dinyatakan dalam piksel untuk bagian kiri, atas, kanan, dan bawah tampilan.
Pengisi bisa digunakan untuk meng-offset isi tampilan dengan
piksel dalam jumlah tertentu. Misalnya, pengisi kiri sebesar 2 akan mendorong isi tampilan sebanyak
2 piksel ke kanan dari tepi kiri. Pengisi bisa diatur menggunakan
metode {@link android.view.View#setPadding(int, int, int, int)} dan diketahui dengan memanggil
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
{@link android.view.View#getPaddingRight()}, dan {@link android.view.View#getPaddingBottom()}.
</p>
<p>
Meskipun bisa mendefinisikan pengisi, tampilan tidak menyediakan dukungan untuk
margin. Akan tetapi, grup tampilan menyediakan dukungan tersebut. Lihat
{@link android.view.ViewGroup} dan
{@link android.view.ViewGroup.MarginLayoutParams} untuk informasi lebih jauh.
</p>
<p>Untuk informasi selengkapnya tentang dimensi, lihat
<a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Nilai-Nilai Dimensi</a>.
</p>
<style type="text/css">
div.layout {
float:left;
width:200px;
margin:0 0 20px 20px;
}
div.layout.first {
margin-left:0;
clear:left;
}
</style>
<h2 id="CommonLayouts">Layout Umum</h2>
<p>Tiap subkelas dari kelas {@link android.view.ViewGroup} menyediakan cara unik untuk menampilkan
tampilan yang Anda sarangkan di dalamnya. Di bawah ini adalah beberapa tipe layout lebih umum yang dibuat
ke dalam platform Android.</p>
<p class="note"><strong>Catatan:</strong> Walaupun Anda bisa menyarangkan satu atau beberapa layout dalam
layout lain untuk mendapatkan desain UI, Anda harus berusaha menjaga hierarki layout sedangkal
mungkin. Layout Anda akan digambar lebih cepat jika memiliki layout tersarang yang lebih sedikit (hierarki tampilan yang melebar
lebih baik daripada hierarki tampilan yang dalam).</p>
<!--
<h2 id="framelayout">FrameLayout</h2>
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
object. It's basically a blank space on your screen that you can
later fill with a single object &mdash; for example, a picture that you'll swap in and out.
All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
specify a different location for a child view. Subsequent child views will simply be drawn over
previous ones,
partially or totally obscuring them (unless the newer object is transparent).
</p>
-->
<div class="layout first">
<h4><a href="layout/linear.html">Layout Linier</a></h4>
<a href="layout/linear.html"><img src="{@docRoot}images/ui/linearlayout-small.png" alt="" /></a>
<p>Layout yang mengatur anak-anaknya menjadi satu baris horizontal atau vertikal. Layout ini
akan membuat scrollbar jika panjang jendela melebihi panjang layar.</p>
</div>
<div class="layout">
<h4><a href="layout/relative.html">Layout Relatif</a></h4>
<a href="layout/relative.html"><img src="{@docRoot}images/ui/relativelayout-small.png" alt="" /></a>
<p>Memungkinkan Anda menentukan lokasi objek anak relatif terhadap satu sama lain (anak A di
kiri anak B) atau terhadap induk (disejajarkan dengan atas induknya).</p>
</div>
<div class="layout">
<h4><a href="{@docRoot}guide/webapps/webview.html">Tampilan Web</a></h4>
<a href="{@docRoot}guide/webapps/webview.html"><img src="{@docRoot}images/ui/webview-small.png" alt="" /></a>
<p>Menampilkan halaman web.</p>
</div>
<h2 id="AdapterViews" style="clear:left">Membangun Layout dengan Adaptor</h2>
<p>Bila isi layout bersifat dinamis atau tidak dipastikan sebelumnya, Anda bisa menggunakan layout yang menjadi
subkelas {@link android.widget.AdapterView} untuk mengisi layout dengan tampilan saat runtime.
Subkelas dari kelas {@link android.widget.AdapterView} menggunakan {@link android.widget.Adapter} untuk
mengikat data ke layoutnya. {@link android.widget.Adapter} berfungsi sebagai penghubung antara sumber data
dan layout{@link android.widget.AdapterView}&mdash;{@link android.widget.Adapter}
menarik data (dari suatu sumber seperti larik (array) atau query database) dan mengubah setiap entri
menjadi tampilan yang bisa ditambahkan ke dalam layout {@link android.widget.AdapterView}.</p>
<p>Layout umum yang didukung oleh adaptor meliputi:</p>
<div class="layout first">
<h4><a href="layout/listview.html">Tampilan Daftar</a></h4>
<a href="layout/listview.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a>
<p>Menampilkan daftar kolom tunggal yang bergulir.</p>
</div>
<div class="layout">
<h4><a href="layout/gridview.html">Tampilan Petak</a></h4>
<a href="layout/gridview.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a>
<p>Menampilkan petak bergulir yang terdiri atas kolom dan baris.</p>
</div>
<h3 id="FillingTheLayout" style="clear:left">Mengisi tampilan adaptor dengan data</h3>
<p>Anda bisa mengisi {@link android.widget.AdapterView} seperti {@link android.widget.ListView} atau
{@link android.widget.GridView} dengan mengikat instance {@link android.widget.AdapterView} ke
{@link android.widget.Adapter}, yang akan mengambil data dari sumber eksternal dan membuat {@link
android.view.View} yang mewakili tiap entri data.</p>
<p>Android menyediakan beberapa subkelas {@link android.widget.Adapter} yang berguna untuk
menarik berbagai jenis data dan membangun tampilan untuk {@link android.widget.AdapterView}. Dua
adaptor yang paling umum adalah:</p>
<dl>
<dt>{@link android.widget.ArrayAdapter}</dt>
<dd>Gunakan adaptor ini bila sumber data Anda berupa larik. Secara default, {@link
android.widget.ArrayAdapter} akan membuat tampilan untuk tiap elemen larik dengan memanggil {@link
java.lang.Object#toString()} pada tiap elemen dan menempatkan isinya dalam {@link
android.widget.TextView}.
<p>Misalnya, jika Anda memiliki satu larik string yang ingin ditampilkan dalam {@link
android.widget.ListView}, buatlah {@link android.widget.ArrayAdapter} baru dengan konstruktor
untuk menentukan layout setiap string dan larik string:</p>
<pre>
ArrayAdapter&lt;String> adapter = new ArrayAdapter&lt;String>(this,
android.R.layout.simple_list_item_1, myStringArray);
</pre>
<p>Argumen-argumen untuk konstruktor ini adalah:</p>
<ul>
<li>{@link android.content.Context} aplikasi Anda</li>
<li>Layout yang berisi {@link android.widget.TextView} untuk tiap string dalam larik</li>
<li>Larik string</li>
</ul>
<p>Kemudian tinggal panggil
{@link android.widget.ListView#setAdapter setAdapter()} pada {@link android.widget.ListView} Anda:</p>
<pre>
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
</pre>
<p>Untuk menyesuaikan penampilan setiap item, Anda bisa mengesampingkan metode {@link
java.lang.Object#toString()} bagi objek dalam larik Anda. Atau, untuk membuat tampilan tiap
elemen selain {@link android.widget.TextView} (misalnya, jika Anda menginginkan
{@link android.widget.ImageView} bagi setiap item larik), perluas kelas {@link
android.widget.ArrayAdapter} dan kesampingkan {@link android.widget.ArrayAdapter#getView
getView()} agar memberikan tipe tampilan yang Anda inginkan bagi tiap item.</p>
</dd>
<dt>{@link android.widget.SimpleCursorAdapter}</dt>
<dd>Gunakan adaptor ini bila data Anda berasal dari {@link android.database.Cursor}. Saat
menggunakan {@link android.widget.SimpleCursorAdapter}, Anda harus menentukan layout yang akan digunakan untuk tiap
baris dalam {@link android.database.Cursor} dan di kolom mana di {@link android.database.Cursor}
harus memasukkan tampilan layout. Misalnya, jika Anda ingin untuk membuat daftar
nama orang dan nomor telepon, Anda bisa melakukan query yang menghasilkan {@link
android.database.Cursor} yang berisi satu baris untuk tiap orang dan kolom-kolom untuk nama dan
nomor. Selanjutnya Anda membuat larik string yang menentukan kolom dari {@link
android.database.Cursor} yang Anda inginkan dalam layout untuk setiap hasil dan larik integer yang menentukan
tampilan yang sesuai untuk menempatkan masing-masing kolom:</p>
<pre>
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
</pre>
<p>Bila Anda membuat instance {@link android.widget.SimpleCursorAdapter}, teruskan layout yang akan digunakan untuk
setiap hasil, {@link android.database.Cursor} yang berisi hasil tersebut, dan dua larik ini:</p>
<pre>
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
</pre>
<p>{@link android.widget.SimpleCursorAdapter} kemudian membuat tampilan untuk tiap baris dalam
{@link android.database.Cursor} dengan layout yang disediakan dengan memasukkan setiap item {@code
fromColumns} ke dalam tampilan {@code toViews} yang sesuai.</p></dd>
</dl>
<p>Jika, selama aplikasi berjalan, Anda mengubah data sumber yang dibaca oleh
adaptor, maka Anda harus memanggil {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. Hal ini akan
memberi tahu tampilan yang bersangkutan bahwa data telah berubah dan tampilan harus memperbarui dirinya sendiri.</p>
<h3 id="HandlingUserSelections">Menangani kejadian klik</h3>
<p>Anda bisa merespons kejadian klik pada setiap item dalam {@link android.widget.AdapterView} dengan
menerapkan antarmuka {@link android.widget.AdapterView.OnItemClickListener}. Misalnya:</p>
<pre>
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// Do something in response to the click
}
};
listView.setOnItemClickListener(mMessageClickedHandler);
</pre>

View File

@@ -1,798 +0,0 @@
page.title=Dialog
page.tags=alertdialog,dialogfragment
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#DialogFragment">Membuat Fragmen Dialog</a></li>
<li><a href="#AlertDialog">Membuat Dialog Peringatan</a>
<ol>
<li><a href="#AddingButtons">Menambahkan tombol</a></li>
<li><a href="#AddingAList">Menambahkan daftar</a></li>
<li><a href="#CustomLayout">Membuat Layout Custom</a></li>
</ol>
</li>
<li><a href="#PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</a></li>
<li><a href="#ShowingADialog">Menampilkan Dialog</a></li>
<li><a href="#FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</a>
<ol>
<li><a href="#ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</a></li>
</ol>
</li>
<li><a href="#DismissingADialog">Menutup Dialog</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.DialogFragment}</li>
<li>{@link android.app.AlertDialog}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}design/building-blocks/dialogs.html">Panduan desain dialog</a></li>
<li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a> (dialog Tanggal/Waktu)</li>
</ol>
</div>
</div>
<p>Dialog adalah jendela kecil yang meminta pengguna untuk
membuat keputusan atau memasukkan informasi tambahan. Dialog tidak mengisi layar dan
biasanya digunakan untuk kejadian modal yang mengharuskan pengguna untuk melakukan tindakan sebelum bisa melanjutkan.</p>
<div class="note design">
<p><strong>Desain Dialog</strong></p>
<p>Untuk informasi tentang cara mendesain dialog, termasuk saran
untuk bahasa, bacalah panduan Desain <a href="{@docRoot}design/building-blocks/dialogs.html">dialog</a>.</p>
</div>
<img src="{@docRoot}images/ui/dialogs.png" />
<p>Kelas {@link android.app.Dialog} adalah kelas basis untuk dialog, namun Anda
harus menghindari pembuatan instance {@link android.app.Dialog} secara langsung.
Sebagai gantinya, gunakan salah satu subkelas berikut:</p>
<dl>
<dt>{@link android.app.AlertDialog}</dt>
<dd>Dialog yang bisa menampilkan judul, hingga tiga tombol, daftar
item yang dapat dipilih, atau layout custom.</dd>
<dt>{@link android.app.DatePickerDialog} atau {@link android.app.TimePickerDialog}</dt>
<dd>Dialog berisi UI yang sudah didefinisikan dan memungkinkan pengguna memilih tanggal atau waktu.</dd>
</dl>
<div class="sidebox">
<h2>Hindari ProgressDialog</h2>
<p>Android menyertakan kelas dialog lain yang disebut
{@link android.app.ProgressDialog} yang menampilkan dialog berisi progress-bar. Akan tetapi, jika Anda
perlu menunjukkan kemajuan pemuatan ataupun kemajuan yang tidak pasti, maka Anda harus mengikuti
panduan desain untuk <a href="{@docRoot}design/building-blocks/progress.html">Kemajuan &amp;
Aktivitas</a> dan menggunakan {@link android.widget.ProgressBar} dalam layout Anda.</p>
</div>
<p>Kelas-kelas ini mendefinisikan gaya dan struktur dialog Anda, namun Anda harus
menggunakan {@link android.support.v4.app.DialogFragment} sebagai kontainer dialog Anda.
Kelas {@link android.support.v4.app.DialogFragment} menyediakan semua kontrol yang Anda
perlukan untuk membuat dialog dan mengelola penampilannya, sebagai ganti memanggil metode
pada objek {@link android.app.Dialog}.</p>
<p>Menggunakan {@link android.support.v4.app.DialogFragment} untuk mengelola dialog
akan memastikan bahwa kelas itu menangani kejadian daur hidup
dengan benar seperti ketika pengguna menekan tombol <em>Back</em> atau memutar layar. Kelas {@link
android.support.v4.app.DialogFragment} juga memungkinkan Anda menggunakan ulang dialog UI sebagai
komponen yang bisa ditanamkan dalam UI yang lebih besar, persis seperti {@link
android.support.v4.app.Fragment} tradisional (seperti saat Anda ingin dialog UI muncul berbeda
pada layar besar dan kecil).</p>
<p>Bagian-bagian berikutnya dalam panduan ini akan menjelaskan cara menggunakan {@link
android.support.v4.app.DialogFragment} yang dikombinasikan dengan objek {@link android.app.AlertDialog}
. Jika Anda ingin membuat picker tanggal atau waktu, Anda harus membaca panduan
<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a>.</p>
<p class="note"><strong>Catatan:</strong>
Karena kelas {@link android.app.DialogFragment} mulanya ditambahkan pada
Android 3.0 (API level 11), dokumen ini menjelaskan cara menggunakan kelas {@link
android.support.v4.app.DialogFragment} yang disediakan bersama <a href="{@docRoot}tools/support-library/index.html">Pustaka Dukungan</a>. Dengan menambahkan pustaka ini
ke aplikasi, Anda bisa menggunakan {@link android.support.v4.app.DialogFragment} dan berbagai
API lain pada perangkat yang menjalankan Android 1.6 atau yang lebih tinggi. Jika versi minimum yang didukung aplikasi Anda
adalah API level 11 atau yang lebih tinggi, maka Anda bisa menggunakan versi kerangka kerja {@link
android.app.DialogFragment}, namun ketahuilah bahwa tautan dalam dokumen ini adalah untuk API
pustaka dukungan. Saat menggunakan pustaka dukungan,
pastikan Anda mengimpor kelas <code>android.support.v4.app.DialogFragment</code>
dan <em>bukan</em> <code>android.app.DialogFragment</code>.</p>
<h2 id="DialogFragment">Membuat Fragmen Dialog</h2>
<p>Anda bisa menghasilkan beragam rancangan dialog&mdash;termasuk
layout custom dan desain yang dijelaskan dalam panduan desain <a href="{@docRoot}design/building-blocks/dialogs.html">Dialog</a>
&mdash;dengan memperluas
{@link android.support.v4.app.DialogFragment} dan membuat {@link android.app.AlertDialog}
dalam metode callback {@link android.support.v4.app.DialogFragment#onCreateDialog
onCreateDialog()}.</p>
<p>Misalnya, berikut ini sebuah {@link android.app.AlertDialog} dasar yang dikelola dalam
{@link android.support.v4.app.DialogFragment}:</p>
<pre>
public class FireMissilesDialogFragment extends DialogFragment {
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
</pre>
<div class="figure" style="width:290px;margin:0 0 0 20px">
<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong>
Dialog dengan satu pesan dan dua tombol tindakan.</p>
</div>
<p>Sekarang, bila Anda membuat instance kelas ini dan memanggil {@link
android.support.v4.app.DialogFragment#show show()} pada objek itu, dialog akan muncul seperti
yang ditampilkan dalam gambar 1.</p>
<p>Bagian berikutnya menjelaskan lebih jauh tentang penggunaan API {@link android.app.AlertDialog.Builder}
untuk membuat dialog.</p>
<p>Bergantung pada seberapa rumit dialog tersebut, Anda bisa menerapkan berbagai metode callback lain
dalam {@link android.support.v4.app.DialogFragment}, termasuk semua
<a href="{@docRoot}guide/components/fragments.html#Lifecycle">metode daur hidup fragmen</a> dasar.
<h2 id="AlertDialog">Membuat Dialog Peringatan</h2>
<p>Kelas {@link android.app.AlertDialog} memungkinkan Anda membuat berbagai desain dialog dan
seringkali satu-satunya kelas dialog yang akan Anda perlukan.
Seperti yang ditampilkan dalam gambar 2, ada tiga area pada dialog peringatan:</p>
<div class="figure" style="width:311px;margin-top:0">
<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" />
<p class="img-caption"><strong>Gambar 2.</strong> Layout dialog.</p>
</div>
<ol>
<li><b>Judul</b>
<p>Area ini opsional dan hanya boleh digunakan bila area konten
ditempati oleh pesan terperinci, daftar, atau layout custom. Jika Anda perlu menyatakan
pesan atau pertanyaan sederhana (seperti dialog dalam gambar 1), Anda tidak memerlukan judul.</li>
<li><b>Area konten</b>
<p>Area ini bisa menampilkan pesan, daftar, atau layout custom lainnya.</p></li>
<li><b>Tombol tindakan</b>
<p>Tidak boleh ada lebih dari tiga tombol tindakan dalam sebuah dialog.</p></li>
</ol>
<p>Kelas {@link android.app.AlertDialog.Builder}
menyediakan API yang memungkinkan Anda membuat {@link android.app.AlertDialog}
dengan jenis konten ini, termasuk layout custom.</p>
<p>Untuk membuat {@link android.app.AlertDialog}:</p>
<pre>
<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
builder.setMessage(R.string.dialog_message)
.setTitle(R.string.dialog_title);
<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
AlertDialog dialog = builder.create();
</pre>
<p>Topik-topik selanjutnya menampilkan cara mendefinisikan berbagai atribut dialog dengan menggunakan
kelas {@link android.app.AlertDialog.Builder}.</p>
<h3 id="AddingButtons">Menambahkan tombol</h3>
<p>Untuk menambahkan tombol tindakan seperti dalam gambar 2,
panggil metode {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} dan
{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()}:</p>
<pre style="clear:right">
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Set other dialog properties
...
// Create the AlertDialog
AlertDialog dialog = builder.create();
</pre>
<p>Metode <code>set...Button()</code> mengharuskan adanya judul bagi tombol (disediakan
oleh suatu <a href="{@docRoot}guide/topics/resources/string-resource.html">sumber daya string</a>) dan
{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil
bila pengguna menekan tombol.</p>
<p>Ada tiga macam tombol tindakan yang Anda bisa tambahkan:</p>
<dl>
<dt>Positif</dt>
<dd>Anda harus menggunakan tipe ini untuk menerima dan melanjutkan tindakan (tindakan "OK").</dd>
<dt>Negatif</dt>
<dd>Anda harus menggunakan tipe ini untuk membatalkan tindakan.</dd>
<dt>Netral</dt>
<dd>Anda harus menggunakan tipe ini bila pengguna mungkin tidak ingin melanjutkan tindakan,
namun tidak ingin membatalkan. Tipe ini muncul antara tombol positif dan
tombol negatif. Misalnya, tindakan bisa berupa "Ingatkan saya nanti".</dd>
</dl>
<p>Anda hanya bisa menambahkan salah satu tipe tombol ke {@link
android.app.AlertDialog}. Artinya, Anda tidak bisa memiliki lebih dari satu tombol "positif".</p>
<div class="figure" style="width:290px;margin:0 0 0 40px">
<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
<p class="img-caption"><strong>Gambar 3.</strong>
Dialog dengan satu judul dan daftar.</p>
</div>
<h3 id="AddingAList">Menambahkan daftar</h3>
<p>Ada tiga macam daftar yang tersedia pada API {@link android.app.AlertDialog}:</p>
<ul>
<li>Daftar pilihan tunggal biasa</li>
<li>Daftar pilihan tunggal persisten (tombol radio)</li>
<li>Daftar pilihan ganda persisten (kotak cek)</li>
</ul>
<p>Untuk membuat daftar pilihan tunggal seperti dalam gambar 3,
gunakan metode {@link android.app.AlertDialog.Builder#setItems setItems()}:</p>
<pre style="clear:right">
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color)
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
}
});
return builder.create();
}
</pre>
<p>Karena daftar muncul dalam area konten dialog,
dialog tidak bisa menampilkan pesan dan daftar sekaligus dan Anda harus menetapkan judul untuk
dialog dengan {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
Untuk menentukan item daftar, panggil {@link
android.app.AlertDialog.Builder#setItems setItems()}, dengan meneruskan larik.
Atau, Anda bisa menetapkan daftar menggunakan {@link
android.app.AlertDialog.Builder#setAdapter setAdapter()}. Hal ini memungkinkan Anda mendukung daftar
dengan data dinamis (seperti dari database) dengan menggunakan {@link android.widget.ListAdapter}.</p>
<p>Jika Anda memilih untuk mendukung daftar dengan {@link android.widget.ListAdapter},
selalu gunakan sebuah {@link android.support.v4.content.Loader} agar konten dimuat
secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan
<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Membuat Layout
dengan Adaptor</a> dan <a href="{@docRoot}guide/components/loaders.html">Loader</a>
.</p>
<p class="note"><strong>Catatan:</strong> Secara default, menyentuh sebuah item daftar akan menutup dialog,
kecuali Anda menggunakan salah satu daftar pilihan persisten berikut ini.</p>
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
<p class="img-caption"><strong>Gambar 4.</strong>
Daftar item pilihan ganda.</p>
</div>
<h4 id="Checkboxes">Menambahkan daftar pilihan ganda atau pilihan tunggal persisten</h4>
<p>Untuk menambahkan daftar item pilihan ganda (kotak cek) atau
item pilihan tunggal (tombol radio), gunakan masing-masing metode
{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()}, atau
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()}.</p>
<p>Misalnya, berikut ini cara membuat daftar pilihan ganda seperti
yang ditampilkan dalam gambar 4 yang menyimpan item
yang dipilih dalam {@link java.util.ArrayList}:</p>
<pre style="clear:right">
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mSelectedItems = new ArrayList(); // Where we track the selected items
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
// User clicked OK, so save the mSelectedItems results somewhere
// or return them to the component that opened the dialog
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
...
}
});
return builder.create();
}
</pre>
<p>Walaupun daftar tradisional maupun daftar dengan tombol radio
menyediakan tindakan "pilihan tunggal", Anda harus menggunakan {@link
android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()} jika ingin mempertahankan pilihan pengguna.
Yakni, jika nanti membuka dialog lagi untuk menunjukkan pilihan pengguna,
maka Anda perlu membuat daftar dengan tombol radio.</p>
<h3 id="CustomLayout">Membuat Layout Custom</h3>
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
<p class="img-caption"><strong>Gambar 5.</strong> Layout dialog custom.</p>
</div>
<p>Jika Anda menginginkan layout custom dalam dialog, buatlah layout dan tambahkan ke
{@link android.app.AlertDialog} dengan memanggil {@link
android.app.AlertDialog.Builder#setView setView()} pada objek {@link
android.app.AlertDialog.Builder} Anda.</p>
<p>Secara default, layout custom akan mengisi jendela dialog, namun Anda masih bisa
menggunakan metode {@link android.app.AlertDialog.Builder} untuk menambahkan tombol dan judul.</p>
<p>Misalnya, berikut ini adalah file layout untuk dialog dalam Gambar 5:</p>
<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
&lt;ImageView
android:src="@drawable/header_logo"
android:layout_width="match_parent"
android:layout_height="64dp"
android:scaleType="center"
android:background="#FFFFBB33"
android:contentDescription="@string/app_name" />
&lt;EditText
android:id="@+id/username"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="@string/username" />
&lt;EditText
android:id="@+id/password"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="16dp"
android:fontFamily="sans-serif"
android:hint="@string/password"/>
&lt;/LinearLayout>
</pre>
<p class="note"><strong>Tip:</strong> Secara default, bila Anda telah mengatur sebuah elemen {@link android.widget.EditText}
agar menggunakan tipe input {@code "textPassword"}, keluarga font akan diatur ke spasi tunggal, sehingga
Anda harus mengubah keluarga font ke {@code "sans-serif"} sehingga kedua bidang teks menggunakan
gaya font yang cocok.</p>
<p>Untuk memekarkan layout dalam {@link android.support.v4.app.DialogFragment} Anda,
ambillah {@link android.view.LayoutInflater} dengan
{@link android.app.Activity#getLayoutInflater()} dan panggil
{@link android.view.LayoutInflater#inflate inflate()}, dengan parameter pertama
adalah ID sumber daya layout dan parameter kedua adalah tampilan induk untuk layout.
Selanjutnya Anda bisa memanggil {@link android.app.AlertDialog#setView setView()}
untuk menempatkan layout dalam dialog.</p>
<pre>
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
</pre>
<div class="note">
<p><strong>Tip:</strong> Jika Anda menginginkan dialog custom,
Anda bisa menampilkan {@link android.app.Activity} sebagai dialog
daripada menggunakan API {@link android.app.Dialog}. Cukup buat satu aktivitas dan mengatur temanya ke
{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
di elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>:</p>
<pre>
&lt;activity android:theme="&#64;android:style/Theme.Holo.Dialog" >
</pre>
<p>Demikian saja. Aktivitas sekarang ditampilkan dalam jendela dialog, sebagai ganti layar penuh.</p>
</div>
<h2 id="PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</h2>
<p>Bila pengguna menyentuh salah satu tombol tindakan dialog atau memilih satu item dari daftarnya,
{@link android.support.v4.app.DialogFragment} Anda bisa melakukan sendiri tindakan yang diperlukan
, namun sering kali Anda perlu mengirim kejadian itu ke aktivitas atau fragmen yang
membuka dialog. Caranya, definisikan antarmuka dengan sebuah metode untuk masing-masing tipe kejadian klik.
Lalu implementasikan antarmuka itu dalam komponen host yang akan
menerima kejadian tindakan dari dialog.</p>
<p>Misalnya, berikut ini adalah {@link android.support.v4.app.DialogFragment} yang mendefinisikan
antarmuka yang akan digunakan untuk mengirim kembali suatu kejadian ke aktivitas host:</p>
<pre>
public class NoticeDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
&#64;Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
...
}
</pre>
<p>Aktivitas yang menjadi host dialog tersebut akan membuat instance dialog
dengan konstruktor fragmen dialog dan menerima kejadian dialog
melalui implementasi antarmuka {@code NoticeDialogListener}:</p>
<pre>
public class MainActivity extends FragmentActivity
implements NoticeDialogFragment.NoticeDialogListener{
...
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
DialogFragment dialog = new NoticeDialogFragment();
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
}
// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the NoticeDialogFragment.NoticeDialogListener interface
&#64;Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User touched the dialog's positive button
...
}
&#64;Override
public void onDialogNegativeClick(DialogFragment dialog) {
// User touched the dialog's negative button
...
}
}
</pre>
<p>Karena aktivitas host mengimplementasikan {@code NoticeDialogListener}&mdash;yang
diberlakukan oleh metode callback {@link android.support.v4.app.Fragment#onAttach onAttach()}
di atas,&mdash;fragmen dialog bisa menggunakan
metode callback antarmuka untuk mengirimkan kejadian klik ke aktivitas:</p>
<pre>
public class NoticeDialogFragment extends DialogFragment {
...
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Build the dialog and set up the button click handlers
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the positive button event back to the host activity
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
mListener.onDialogNegativeClick(NoticeDialogFragment.this);
}
});
return builder.create();
}
}
</pre>
<h2 id="ShowingADialog">Menampilkan Dialog</h2>
<p>Bila Anda ingin menampilkan dialog, buatlah instance {@link
android.support.v4.app.DialogFragment} dan panggil {@link android.support.v4.app.DialogFragment#show
show()}, dengan meneruskan {@link android.support.v4.app.FragmentManager} dan nama tag
untuk fragmen dialognya.</p>
<p>Anda bisa mendapatkan {@link android.support.v4.app.FragmentManager} dengan memanggil
{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} dari
{@link android.support.v4.app.FragmentActivity} atau {@link
android.support.v4.app.Fragment#getFragmentManager()} dari {@link
android.support.v4.app.Fragment}. Misalnya:</p>
<pre>
public void confirmFireMissiles() {
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
}
</pre>
<p>Argumen kedua, {@code "missiles"}, adalah nama tag unik yang digunakan sistem untuk menyimpan
dan memulihkan status fragmen bila diperlukan. Tag ini juga memungkinkan Anda mendapatkan handle ke
fragmen dengan memanggil {@link android.support.v4.app.FragmentManager#findFragmentByTag
findFragmentByTag()}.</p>
<h2 id="FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</h2>
<p>Anda mungkin memiliki desain UI yang di dalamnya Anda ingin UI muncul sebagai dialog dalam beberapa
situasi, namun sebagai layar penuh atau fragmen tertanam dalam situasi lain (mungkin bergantung pada apakah
perangkat memiliki layar besar atau layar kecil). Kelas {@link android.support.v4.app.DialogFragment}
menawarkan fleksibilitas ini karena masih bisa berperilaku sebagai {@link
android.support.v4.app.Fragment} yang bisa ditanamkan.</p>
<p>Akan tetapi, dalam hal ini Anda tidak bisa menggunakan {@link android.app.AlertDialog.Builder AlertDialog.Builder}
atau objek {@link android.app.Dialog} lain untuk membangun dialog. Jika
Anda ingin {@link android.support.v4.app.DialogFragment}
bisa ditanamkan, Anda harus mendefinisikan dialog UI dalam layout, lalu memuat layout itu dalam metode callback
{@link android.support.v4.app.DialogFragment#onCreateView
onCreateView()}.</p>
<p>Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai
dialog maupun fragmen yang bisa ditanamkan (menggunakan layout bernama <code>purchase_items.xml</code>):</p>
<pre>
public class CustomDialogFragment extends DialogFragment {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
&#64;Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.purchase_items, container, false);
}
/** The system calls this only when creating the layout in a dialog. */
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
}
</pre>
<p>Dan berikut ini adalah beberapa kode yang memutuskan apakah akan menampilkan fragmen sebagai dialog
atau UI layar penuh, berdasarkan ukuran layar:</p>
<pre>
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment();
if (mIsLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog");
} else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
}
</pre>
<p>Untuk informasi selengkapnya tentang melakukan transaksi fragmen, lihat panduan
<a href="{@docRoot}guide/components/fragments.html">Fragmen</a>.</p>
<p>Dalam contoh ini, nilai boolean <code>mIsLargeLayout</code> menentukan apakah perangkat saat ini
harus menggunakan desain layout besar aplikasi (dan dengan demikian menampilkan fragmen ini sebagai dialog, bukan
layar penuh). Cara terbaik untuk mengatur jenis boolean ini adalah mendeklarasikan
<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">nilai sumber daya boolean</a>
dengan nilai <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">sumber daya alternatif</a> untuk berbagai ukuran layar. Misalnya, berikut ini adalah dua
versi sumber daya boolean untuk berbagai ukuran layar:</p>
<p class="code-caption">res/values/bools.xml</p>
<pre>
&lt;!-- Default boolean values -->
&lt;resources>
&lt;bool name="large_layout">false&lt;/bool>
&lt;/resources>
</pre>
<p class="code-caption">res/values-large/bools.xml</p>
<pre>
&lt;!-- Large screen boolean values -->
&lt;resources>
&lt;bool name="large_layout">true&lt;/bool>
&lt;/resources>
</pre>
<p>Selanjutnya Anda bisa menetapkan nilai {@code mIsLargeLayout} selama
metode {@link android.app.Activity#onCreate onCreate()} aktivitas:</p>
<pre>
boolean mIsLargeLayout;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
}
</pre>
<h3 id="ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</h3>
<p>Sebagai ganti menampilkan dialog berupa UI layar penuh saat di layar kecil, Anda bisa memperoleh
hasil yang sama dengan menampilkan {@link android.app.Activity} sebagai dialog saat di
layar besar. Pendekatan yang Anda pilih bergantung pada desain aplikasi, namun
menampilkan aktivitas sebagai dialog sering kali berguna bila aplikasi Anda sudah didesain untuk
layar kecil dan Anda ingin meningkatkan pengalaman pada tablet dengan menampilkan aktivitas berjangka pendek
sebagai dialog.</p>
<p>Untuk menampilkan aktivitas sebagai dialog hanya saat di layar besar,
terapkan tema {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
pada elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>:</p>
<pre>
&lt;activity android:theme="&#64;android:style/Theme.Holo.DialogWhenLarge" >
</pre>
<p>Untuk informasi selengkapnya tentang mengatur gaya aktivitas Anda dengan tema, lihat panduan <a href="{@docRoot}guide/topics/ui/themes.html">Gaya dan Tema</a>.</p>
<h2 id="DismissingADialog">Menutup Dialog</h2>
<p>Bila pengguna menyentuh salah satu tombol tindakan yang dibuat dengan
{@link android.app.AlertDialog.Builder}, sistem akan menutup dialog untuk Anda.</p>
<p>Sistem juga menutup dialog bila pengguna menyentuh sebuah item dalam daftar dialog, kecuali
bila daftar itu menggunakan tombol radio atau kotak cek. Jika tidak, Anda bisa menutup dialog secara manual
dengan memanggil {@link android.support.v4.app.DialogFragment#dismiss()} pada {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p>Jika Anda perlu melakukan
tindakan tertentu saat dialog menghilang, Anda bisa menerapkan metode {@link
android.support.v4.app.DialogFragment#onDismiss onDismiss()} dalam {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p>Anda juga bisa <em>membatalkan</em> dialog. Ini merupakan kejadian khusus yang menunjukkan bahwa pengguna
secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol
<em>Back</em>, menyentuh layar di luar area dialog,
atau jika Anda secara eksplisit memanggil {@link android.app.Dialog#cancel()} pada {@link
android.app.Dialog} (seperti saat merespons tombol "Cancel" dalam dialog).</p>
<p>Seperti yang ditampilkan dalam contoh di atas, Anda bisa merespons kejadian batal dengan menerapkan
{@link android.support.v4.app.DialogFragment#onCancel onCancel()} dalam kelas {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p class="note"><strong>Catatan:</strong> Sistem akan memanggil
{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} pada tiap kejadian yang
memanggil callback {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Akan tetapi,
jika Anda memanggil {@link android.app.Dialog#dismiss Dialog.dismiss()} atau {@link
android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
sistem akan memanggil {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>namun
bukan</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Jadi biasanya Anda harus
memanggil {@link android.support.v4.app.DialogFragment#dismiss dismiss()} bila pengguna menekan tombol
<em>positif</em> dalam dialog untuk menghilangkan tampilan dialog.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,589 +0,0 @@
page.title=Dukungan Multi-Jendela
page.metaDescription=Dukungan baru di Android N untuk menampilkan lebih dari satu aplikasi sekaligus.
page.keywords="multi-window", "android N", "split screen", "free-form"
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#overview">Ringkasan</a></li>
<li><a href="#lifecycle">Daur Hidup Multi-Jendela</a></li>
<li><a href="#configuring">Mengonfigurasi Aplikasi Anda untuk Mode
Multi-Jendela</a></li>
<li><a href="#running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</a></li>
<li><a href="#testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</a></li>
</ol>
<h2>Lihat Juga</h2>
<ol>
<li><a class="external-link" href="https://github.com/googlesamples/android-MultiWindowPlayground">Aplikasi contoh Playground
Multi-Jendela</a></li>
<li><a class="external-link" href="https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64">Lima Tip untuk Mempersiapkan Multi-Jendela di Android N</a></li>
</ol>
</div>
</div>
<p>
Android N menambahkan dukungan untuk menampilkan lebih dari satu aplikasi
sekaligus. Pada perangkat genggam, dua aplikasi bisa berjalan berdampingan atau
atas-bawah dalam mode <em>layar terbagi</em>. Pada perangkat TV, aplikasi bisa
menggunakan mode <em>gambar-dalam-gambar</em> untuk melanjutkan pemutaran video selagi pengguna
berinteraksi dengan aplikasi lain.
</p>
<p>
Jika Anda membangun aplikasi Anda dengan N Preview SDK, Anda bisa mengonfigurasi cara aplikasi
menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi
minimum yang diizinkan aktivitas Anda. Anda juga bisa menonaktifkan tampilan multi-jendela untuk
aplikasi, sehingga memastikan sistem hanya menampilkan aplikasi Anda dalam mode
layar penuh.
</p>
<h2 id="overview">Ringkasan</h2>
<p>
Android N memungkinkan beberapa aplikasi berbagi layar sekaligus. Misalnya,
pengguna bisa membagi layar, melihat halaman web di sisi kiri
sambil menulis email di sisi kanan. Pengalaman pengguna bergantung pada
perangkat:
</p>
<ul>
<li>Perangkat genggam yang menjalankan Android N menawarkan mode
layar terbagi. Di mode ini, sistem mengisi layar dengan dua aplikasi, menampilkannya secara
berdampingan atau atas-bawah. Pengguna bisa menyeret garis pembagi
yang memisahkan keduanya untuk membuat satu aplikasi lebih besar dan yang lainnya lebih kecil.
</li>
<li>Pada Nexus Player yang menjalankan Android N, aplikasi bisa menempatkan diri
dalam <a href="picture-in-picture.html">mode gambar-dalam-gambar</a>, yang memungkinkannya
untuk terus menampilkan materi selagi pengguna menjelajahi atau berinteraksi dengan
aplikasi lain.
</li>
<li>Produsen perangkat berukuran lebih besar bisa memilih untuk mengaktifkan mode
bentuk bebas, di mana pengguna bisa bebas mengubah ukuran setiap aktivitas. Jika
produsen mengaktifkan fitur ini, perangkat akan menawarkan mode bentuk bebas sebagai tambahan
untuk mode layar terbagi.
</li>
</ul>
<img src="{@docRoot}images/android-7.0/mw-splitscreen.png" alt="" width="650" srcset="{@docRoot}images/android-7.0/mw-splitscreen.png 1x,
{@docRoot}images/android-7.0/mw-splitscreen_2x.png 2x," id="img-split-screen" />
<p class="img-caption">
<strong>Gambar 1.</strong> Dua aplikasi berjalan berdampingan dalam mode layar terbagi.
</p>
<p>
Pengguna bisa beralih ke mode multi-jendela dengan cara berikut:
</p>
<ul>
<li>Jika pengguna membuka <a href="{@docRoot}guide/components/recents.html">layar
Ringkasan</a> dan menekan lama pada
judul aktivitas, mereka bisa menyeret aktivitas itu ke bagian yang disorot pada layar
untuk menempatkan aktivitas dalam mode multi-jendela.
</li>
<li>Jika pengguna menekan lama pada tombol Ringkasan, perangkat akan menempatkan
aktivitas saat ini dalam mode multi-jendela, dan membuka layar Ringkasan guna
memungkinkan pengguna memilih aktivitas lain untuk berbagi layar.
</li>
</ul>
<p>
Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">seret dan
lepas</a> data dari aktivitas satu ke aktivitas lain sewaktu aktivitas berbagi
layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam aktivitas
tunggal.)
</p>
<h2 id="lifecycle">Daur Hidup Multi-Jendela</h2>
<p>
Mode multi-jendela tidak mengubah <a href="{@docRoot}training/basics/activity-lifecycle/index.html">daur hidup
aktivitas</a>.
</p>
<p>
Dalam mode multi-jendela, hanya aktivitas yang paling sering digunakan pengguna
yang akan aktif pada waktu tertentu. Aktivitas ini dianggap <em>teratas</em>.
Semua aktivitas lainnya dalam keadaan berhenti sementara, sekalipun terlihat.
Akan tetapi, sistem memberikan aktivitas, yang berhenti-sementara-namun-terlihat ini, prioritas lebih tinggi
daripada aktivitas yang tidak terlihat. Jika pengguna berinteraksi dengan salah satu
aktivitas yang berhenti sementara, aktivitas tersebut akan dilanjutkan kembali, dan aktivitas
teratas sebelumnya akan dihentikan sementara.
</p>
<p class="note">
<strong>Catatan:</strong> Dalam mode multi-jendela, aplikasi bisa berada dalam keadaan berhenti sementara
dan masih terlihat oleh pengguna. Sebuah aplikasi mungkin perlu melanjutkan aktivitasnya
bahkan saat berhenti sementara. Misalnya, aplikasi pemutar video yang ada dalam
mode berhenti sementara namun terlihat harus tetap menampilkan videonya. Karena alasan
ini, kami menyarankan aktivitas yang memutar video <em>tidak</em> menghentikan sementara video
dalam handler {@link android.app.Activity#onPause onPause()} mereka.
Sebagai gantinya, aktivitas itu harus menghentikan sementara video di {@link android.app.Activity#onStop
onStop()}, dan melanjutkan pemutaran di {@link android.app.Activity#onStart
onStart()}.
</p>
<p>
Bila pengguna menempatkan aplikasi dalam mode multi-jendela, sistem akan memberi tahu
aktivitas tersebut mengenai perubahan konfigurasi, sebagaimana ditetapkan dalam <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
Waktu Proses</a>. Hal ini juga terjadi ketika pengguna mengubah skala aplikasi, atau menempatkan kembali aplikasi
ke mode layar penuh.
Pada dasarnya, perubahan ini memiliki implikasi daur hidup aktivitas yang sama
seperti saat sistem memberi tahu aplikasi bahwa perangkat telah beralih
dari mode potret ke mode lanskap, kecuali dimensi perangkat
telah berubah sebagai ganti bertukar posisi. Seperti yang dibahas di <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani Perubahan
Waktu Proses</a>, aktivitas Anda bisa menangani perubahan konfigurasi itu sendiri, atau
mengizinkan sistem memusnahkan aktivitas dan membuatnya kembali dengan dimensi
baru.
</p>
<p>
Jika pengguna mengubah ukuran jendela dan membuat dimensinya lebih besar, sistem
akan mengubah ukuran aktivitas untuk menyesuaikan dengan tindakan pengguna dan mengeluarkan <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan waktu proses</a>
bila diperlukan. Jika aplikasi tertinggal dibandingkan gambar di area yang baru diekspos,
sistem untuk sementara mengisi area tersebut dengan warna yang ditetapkan oleh atribut {@link
android.R.attr#windowBackground windowBackground} atau dengan atribut gaya
<code>windowBackgroundFallback</code> secara default.
</p>
<h2 id="configuring">Mengonfigurasi Aplikasi Anda untuk Mode Multi-Jendela</h2>
<p>
Jika aplikasi Anda menargetkan Android N, Anda bisa mengonfigurasi bagaimana dan
apakah aktivitas aplikasi Anda mendukung tampilan multi-jendela. Anda bisa menyetel
atribut dalam manifes untuk mengontrol ukuran dan layoutnya.
Setelan atribut aktivitas root berlaku pada semua aktivitas
dalam tumpukan tugasnya. Misalnya, jika aktivitas root memiliki
<code>android:resizeableActivity</code> yang disetel ke true, maka semua aktivitas
dalam tumpukan tugas bisa diubah ukurannya.
</p>
<p class="note">
<strong>Catatan:</strong> Jika Anda membangun aplikasi multi-orientasi dengan versi
SDK lebih rendah dari Android N, dan pengguna menggunakan aplikasi
dalam mode multi-jendela, sistem akan mengubah ukuran aplikasi secara paksa. Sistem akan menampilkan kotak
dialog yang memperingatkan pengguna bahwa aplikasi mungkin berperilaku tidak terduga. Sistem
<em>tidak</em> mengubah ukuran aplikasi yang berorientasi tetap; jika
pengguna berusaha membuka aplikasi berorientasi tetap saat mode multi-jendela,
aplikasi akan menggunakan seluruh layar.
</p>
<h4 id="resizeableActivity">android:resizeableActivity</h4>
<p>
Setel atribut ini dalam manifes <code>&lt;activity&gt;</code> Anda atau simpul
<code>&lt;application&gt;</code> untuk mengaktifkan atau menonaktifkan tampilan
multi-jendela:
</p>
<pre>
android:resizeableActivity=["true" | "false"]
</pre>
<p>
Jika atribut ini disetel ke true, aktivitas bisa dijalankan di
mode layar terbagi dan mode bentuk bebas. Jika atribut ini disetel ke false, aktivitas
tidak akan mendukung mode multi-jendela. Jika nilai ini false, dan pengguna
berusaha memulai aktivitas dalam mode multi-jendela, aktivitas akan menggunakan
layar penuh.
</p>
<p>
Jika aplikasi Anda menargetkan Android N, namun Anda tidak menetapkan nilai
untuk atribut ini, nilai atribut default adalah true.
</p>
<h4 id="supportsPictureInPicture">android:supportsPictureInPicture</h4>
<p>
Setel atribut ini dalam simpul <code>&lt;activity&gt;</code> manifes Anda untuk
menunjukkan apakah aktivitas mendukung tampilan gambar-dalam-gambar. Atribut ini
diabaikan jika <code>android:resizeableActivity</code> bernilai false.
</p>
<pre>
android:supportsPictureInPicture=["true" | "false"]
</pre>
<h3 id="layout">Atribut layout</h3>
<p>
Dengan Android N, elemen manifes <code>&lt;layout&gt;</code>
mendukung beberapa atribut yang memengaruhi cara aktivitas berperilaku dalam
mode multi-jendela:
</p>
<dl>
<dt>
<code>android:defaultWidth</code>
</dt>
<dd>
Lebar default aktivitas saat dijalankan dalam mode bentuk bebas.
</dd>
<dt>
<code>android:defaultHeight</code>
</dt>
<dd>
Tinggi default aktivitas saat dijalankan dalam mode bentuk bebas.
</dd>
<dt>
<code>android:gravity</code>
</dt>
<dd>
Penempatan awal dari aktivitas saat dibuka dalam mode bentuk bebas. Lihat referensi
{@link android.view.Gravity} untuk mengetahui nilai yang cocok.
</dd>
<dt>
<code>android:minimalHeight</code>, <code>android:minimalWidth</code>
</dt>
<dd>
Tinggi dan lebar minimum untuk aktivitas dalam mode layar terbagi
dan mode bentuk bebas. Jika pengguna memindahkan pembagi dalam mode layar terbagi
untuk membuat aktivitas lebih kecil dari minimum yang ditetapkan, sistem akan memangkas
aktivitas sesuai dengan ukuran yang diminta pengguna.
</dd>
</dl>
<p>
Misalnya, kode berikut menampilkan cara menetapkan ukuran dan lokasi default
aktivitas, dan ukuran minimumnya, bila aktivitas ditampilkan dalam
mode bentuk bebas:
</p>
<pre>
&lt;activity android:name=".MyActivity"&gt;
&lt;layout android:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minimalHeight="450dp"
android:minimalWidth="300dp" /&gt;
&lt;/activity&gt;
</pre>
<h2 id="running">Menjalankan Aplikasi Anda dalam Mode Multi-Jendela</h2>
<p>
Android N menawarkan fungsionalitas baru untuk mendukung aplikasi yang bisa berjalan
dalam mode multi-jendela.
</p>
<h3 id="disabled-features">Fitur yang dinonaktifkan dalam mode multi-jendela</h3>
<p>
Fitur tertentu akan dinonaktifkan atau diabaikan bila perangkat berada dalam mode
multi-jendela, karena dianggap tidak logis bagi suatu aktivitas yang mungkin berbagi
layar perangkat dengan aktivitas atau aplikasi lainnya. Fitur tersebut meliputi:
<ul>
<li>Beberapa opsi penyesuaian di <a href="{@docRoot}training/system-ui/index.html">System UI</a>
dinonaktifkan; misalnya, aplikasi tidak bisa menyembunyikan bilah status
jika tidak berjalan dalam mode layar penuh.
</li>
<li>Sistem akan mengabaikan perubahan pada atribut <code><a href=
"{@docRoot}guide/topics/manifest/activity-element.html#screen"
>android:screenOrientation</a></code>.
</li>
</ul>
<h3 id="change-notification">Pemberitahuan perubahan multi-jendela dan melakukan kueri</h3>
<p>
Metode baru berikut telah ditambahkan ke kelas {@link android.app.Activity}
untuk mendukung tampilan multi-jendela. Untuk mengetahui detail tentang setiap
metode, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
Preview SDK</a>.
</p>
<dl>
<dt>
<code>Activity.isInMultiWindowMode()</code>
</dt>
<dd>
Panggil untuk mengetahui apakah aktivitas berada dalam mode multi-jendela.
</dd>
<dt>
<code>Activity.isInPictureInPictureMode()</code>
</dt>
<dd>
Panggil untuk mengetahui apakah aktivitas berada dalam mode gambar-dalam-gambar.
<p class="note">
<strong>Catatan:</strong> Mode gambar-dalam-gambar adalah kasus khusus pada
mode multi-jendela. Jika <code>myActivity.isInPictureInPictureMode()</code>
mengembalikan nilai true, maka <code>myActivity.isInMultiWindowMode()</code> juga
mengembalikan nilai true.
</p>
</dd>
<dt>
<code>Activity.onMultiWindowModeChanged()</code>
</dt>
<dd>
Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
mode multi-jendela. Sistem akan meneruskan ke metode sebuah nilai true jika
aktivitas tersebut memasuki mode multi-jendela, dan nilai false jika aktivitas
tersebut meninggalkan mode multi-jendela.
</dd>
<dt>
<code>Activity.onPictureInPictureModeChanged()</code>
</dt>
<dd>
Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari
mode gambar-dalam-gambar. Sistem akan meneruskan ke metode sebuah nilai true jika
aktivitas tersebut memasuki mode gambar-dalam-gambar, dan nilai false jika aktivitas
tersebut meninggalkan mode gambar-dalam-gambar.
</dd>
</dl>
<p>
Ada juga versi {@link android.app.Fragment} untuk setiap
metode ini, misalnya <code>Fragment.isInMultiWindowMode()</code>.
</p>
<h3 id="entering-pip">Memasuki mode gambar-dalam-gambar</h3>
<p>
Untuk menempatkan aktivitas dalam mode gambar-dalam-gambar, panggil metode baru
<code>Activity.enterPictureInPictureMode()</code>. Metode ini tidak berpengaruh jika
perangkat tidak mendukung mode gambar-dalam-gambar. Untuk informasi selengkapnya,
lihat dokumentasi <a href="picture-in-picture.html">Gambar-dalam-Gambar</a>.
</p>
<h3 id="launch">Meluncurkan Aktivitas Baru dalam Mode Multi-Jendela</h3>
<p>
Bila meluncurkan aktivitas baru, Anda bisa memberi petunjuk pada sistem bahwa aktivitas
baru harus ditampilkan bersebelahan dengan aktivitas yang sedang aktif, jika memungkinkan. Caranya,
gunakan flag
<code>Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT</code>. Meneruskan
flag ini akan meminta perilaku berikut:
</p>
<ul>
<li>Jika perangkat berada dalam mode layar terbagi, sistem akan berupaya membuat
aktivitas baru di sebelah aktivitas yang meluncurkannya, sehingga kedua aktivitas tersebut
berbagi layar. Tidak ada jaminan sistem mampu melakukannya, namun sistem akan
membuat aktivitas bersebelahan jika memungkinkan.
</li>
<li>Jika perangkat tidak berada dalam mode layar terbagi, flag ini tidak akan berpengaruh.
</li>
</ul>
<p>
Jika perangkat dalam mode bentuk bebas dan Anda menjalankan aktivitas baru, Anda bisa
menetapkan dimensi aktivitas baru dan lokasi layar dengan memanggil
<code>ActivityOptions.setLaunchBounds()</code>. Metode ini tidak berpengaruh jika
perangkat tidak berada dalam mode multi-jendela.
</p>
<p class="note">
<strong>Catatan:</strong> Jika Anda meluncurkan aktivitas dalam tumpukan tugas, aktivitas
tersebut akan menggantikan aktivitas pada layar, dengan mewarisi semua
properti multi-jendelanya. Jika Anda ingin meluncurkan aktivitas baru sebagai jendela
terpisah dalam mode multi-jendela, Anda harus meluncurkannya dalam tumpukan tugas baru.
</p>
<h3 id="dnd">Mendukung seret dan lepas</h3>
<p>
Pengguna bisa <a href="{@docRoot}guide/topics/ui/drag-drop.html">menyeret dan
melepas</a> data dari satu aktivitas ke aktivitas yang lain selagi kedua aktivitas
berbagi layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam
aktivitas tunggal.) Karena alasan ini, Anda mungkin perlu menambahkan fungsionalitas
seret dan lepas ke aplikasi jika aplikasi saat ini belum mendukungnya.
</p>
<p>
N Preview SDK menambahkan paket <a href="{@docRoot}reference/android/view/package-summary.html"><code>android.view</code></a>
untuk mendukung seret dan lepas lintas-aplikasi. Untuk mengetahui detail tentang kelas dan metode
berikut, lihat <a href="{@docRoot}preview/setup-sdk.html#docs-dl">Referensi N
Preview SDK</a>.
</p>
<dl>
<dt>
<code>android.view.DropPermissions</code>
</dt>
<dd>
Objek token bertanggung jawab menetapkan izin yang diberikan kepada aplikasi
yang menerima pelepasan tersebut.
</dd>
<dt>
<code>View.startDragAndDrop()</code>
</dt>
<dd>
Alias baru untuk {@link android.view.View#startDrag View.startDrag()}. Untuk
mengaktifkan seret dan lepas lintas-aktivitas, teruskan flag baru
<code>View.DRAG_FLAG_GLOBAL</code>. Jika Anda perlu memberikan izin URI ke
aktivitas penerima, teruskan flag baru,
<code>View.DRAG_FLAG_GLOBAL_URI_READ</code> atau
<code>View.DRAG_FLAG_GLOBAL_URI_WRITE</code>, sebagaimana mestinya.
</dd>
<dt>
<code>View.cancelDragAndDrop()</code>
</dt>
<dd>
Membatalkan operasi seret yang sedang berlangsung. Hanya bisa dipanggil oleh
aplikasi yang menghasilkan operasi seret.
</dd>
<dt>
<code>View.updateDragShadow()</code>
</dt>
<dd>
Menggantikan bayangan penyeretan untuk operasi seret yang sedang berlangsung. Hanya
bisa dipanggil oleh aplikasi yang menghasilkan operasi seret.
</dd>
<dt>
<code>Activity.requestDropPermissions()</code>
</dt>
<dd>
Meminta izin untuk URI materi yang diteruskan dengan {@link
android.content.ClipData} yang terdapat dalam {@link android.view.DragEvent}.
</dd>
</dl>
<h2 id="testing">Menguji Dukungan Multi-Jendela Aplikasi Anda</h2>
<p>
Apakah Anda memperbarui aplikasi untuk Android N atau tidak, Anda harus
verifikasi bagaimana perilakunya di mode multi-jendela saat pengguna mencoba untuk menjalankannya
dalam mode multi-jendela pada perangkat yang menjalankan Android N.
</p>
<h3 id="configuring">Mengonfigurasi Perangkat Pengujian</h3>
<p>
Jika Anda pasang Android N pada perangkat, mode
layar terbagi secara otomatis didukung.
</p>
<h3 id="test-non-n">Jika aplikasi Anda tidak dibangun dengan N Preview SDK</h3>
<p>
Jika Anda tidak membangun aplikasi dengan N Preview SDK dan pengguna berupaya menggunakan
aplikasi dalam mode multi-jendela, sistem secara paksa akan mengubah ukuran aplikasi kecuali jika aplikasi
mendeklarasikan orientasi tetap.
</p>
<p>
Jika aplikasi Anda tidak mendeklarasikan orientasi tetap, Anda harus meluncurkan aplikasi
pada perangkat yang menjalankan Android N dan berupaya menempatkan aplikasi tersebut dalam
mode layar terbagi. Verifikasi pengalaman pengguna
bisa diterima bila aplikasi secara paksa diubah ukurannya.
</p>
<p>
Jika aplikasi mendeklarasikan orientasi tetap, Anda harus berupaya menempatkan aplikasi dalam
mode multi-jendela. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
mode layar penuh.
</p>
<h3 id="test-mw">Jika Anda mendukung mode multi-jendela</h3>
<p>
Jika Anda membuat aplikasi Anda dengan N Preview SDK dan belum menonaktifkan
dukungan multi-jendela, verifikasi perilaku berikut dalam mode layar terbagi
dan mode bentuk bebas.
</p>
<ul>
<li>Luncurkan aplikasi dalam mode layar penuh, kemudian beralih ke mode multi-jendela dengan
menekan lama pada tombol Ringkasan. Verifikasi apakah aplikasi beralih dengan benar.
</li>
<li>Jalankan aplikasi secara langsung dalam mode multi-jendela, dan verifikasi aplikasi
diluncurkan dengan benar. Anda bisa meluncurkan aplikasi dalam mode multi-jendela dengan menekan
tombol Ringkasan, kemudian menekan lama baris judul pada aplikasi Anda dan menyeretnya
ke salah satu area yang disorot di layar.
</li>
<li>Ubah ukuran aplikasi Anda dalam mode layar terbagi dengan menyeret garis pembagi.
Verifikasi apakah aplikasi mengubah ukuran tanpa mogok, dan apakah elemen UI yang diperlukan
terlihat.
</li>
<li>Jika Anda telah menetapkan dimensi minimum aplikasi, cobalah untuk mengubah ukuran
aplikasi di bawah dimensi tersebut. Verifikasi apakah Anda tidak bisa mengubah ukuran aplikasi menjadi
lebih kecil dari minimum yang ditetapkan.
</li>
<li>Melalui semua pengujian, verifikasi apakah kinerja aplikasi Anda bisa diterima. Misalnya,
verifikasi apakah tidak ada jeda yang terlalu lama untuk memperbarui UI setelah
aplikasi diubah ukurannya.
</li>
</ul>
<h4 id="test-checklist">Daftar periksa pengujian</h4>
<p>
Untuk verifikasi kinerja aplikasi Anda dalam mode multi-jendela, cobalah operasi
berikut. Anda harus mencoba semua operasi ini dalam mode layar terbagi dan
dan mode multi-jendela, kecuali jika dinyatakan berbeda.
</p>
<ul>
<li>Masuki dan tinggalkan mode multi-jendela.
</li>
<li>Beralih dari aplikasi Anda ke aplikasi lain, dan verifikasi apakah aplikasi berperilaku
sebagaimana mestinya saat terlihat namun tidak aktif. Misalnya, jika aplikasi Anda
sedang memutar video, verifikasi apakah video terus diputar selagi pengguna
berinteraksi dengan aplikasi lain.
</li>
<li>Dalam mode layar terbagi, cobalah menggeser garis pembagi untuk membuat aplikasi
Anda menjadi lebih besar dan lebih kecil. Coba operasi ini dalam konfigurasi berdampingan dan
atas-bawah. Verifikasi apakah aplikasi tidak mogok,
fungsionalitas penting bisa terlihat, dan operasi mengubah ukuran tidak memakan waktu terlalu
lama.
</li>
<li>Lakukan beberapa operasi ubah ukuran berturut-turut dalam waktu cepat. Verifikasi apakah
aplikasi Anda tidak mogok atau mengalami kebocoran memori. Untuk informasi tentang memeriksa penggunaan memori
aplikasi Anda, lihat <a href="{@docRoot}tools/debugging/debugging-memory.html">
Menyelidiki Penggunaan RAM Anda</a>.
</li>
<li>Gunakan aplikasi secara normal di sejumlah konfigurasi jendela yang berbeda, dan
verifikasi apakah aplikasi berperilaku sebagaimana mestinya. Verifikasi apakah teks terbaca, dan apakah
elemen UI tidak terlalu kecil untuk interaksi.
</li>
</ul>
<h3 id="test-disabled-mw">Jika Anda telah menonaktifkan dukungan multi-jendela</h3>
<p>
Jika Anda menonaktifkan dukungan multi-jendela dengan menyetel
<code>android:resizableActivity="false"</code>, Anda harus menjalankan aplikasi pada
perangkat yang menjalankan Android N dan berusaha menempatkan aplikasi dalam
mode bentuk bebas dan mode layar terbagi. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam
mode layar penuh.
</p>

View File

@@ -1,979 +0,0 @@
page.title=Pemberitahuan
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Design">Pertimbangan Desain</a></li>
<li><a href="#CreateNotification">Membuat Pemberitahuan</a>
<ol>
<li><a href="#Required">Isi pemberitahuan yang diperlukan</a></li>
<li><a href="#Optional">Isi dan pengaturan pemberitahuan opsional</a></li>
<li><a href="#Actions">Tindakan pemberitahuan</a></li>
<li><a href="#Priority">Prioritas pemberitahuan</a></li>
<li><a href="#SimpleNotification">Membuat pemberitahuan sederhana</a></li>
<li><a href="#ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</a></li>
<li><a href="#Compatibility">Menangani kompatibilitas</a></li>
</ol>
</li>
<li><a href="#Managing">Mengelola Pemberitahuan</a>
<ol>
<li><a href="#Updating">Memperbarui pemberitahuan</a></li>
<li><a href="#Removing">Menghapus pemberitahuan</a></li>
</ol>
</li>
<li><a href="#NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</a>
<ol>
<li><a href="#DirectEntry">Menyiapkan PendingIntent aktivitas biasa</a></li>
<li><a href="#ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</a></li>
</ol>
</li>
<li><a href="#Progress">Menampilkan Kemajuan dalam Pemberitahuan</a>
<ol>
<li><a href="#FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</a></li>
<li><a href="#ActivityIndicator">Menampilkan indikator aktivitas berlanjut</a></li>
</ol>
</li>
<li><a href="#metadata">Metadata Pemberitahuan</a></li>
<li><a href="#Heads-up">Pemberitahuan Pendahuluan</a></li>
<li><a href="#lockscreenNotification">Pemberitahuan Layar Kunci</a></li>
<ol>
<li><a href="#visibility">Mengatur Visibilitas</a></li>
<li><a href="#controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</a></li>
</ol>
<li><a href="#CustomNotification">Layout Pemberitahuan Custom</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.NotificationManager}</li>
<li>{@link android.support.v4.app.NotificationCompat}</li>
</ol>
<h2>Video</h2>
<ol>
<li>
<a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&amp;feature=player_detailpage#t=1672s">
Pemberitahuan di 4.1</a>
</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li>
<a href="{@docRoot}design/patterns/notifications.html">Desain Android: Pemberitahuan</a>
</li>
</ol>
</div>
</div>
<p>
Pemberitahuan adalah pesan yang bisa Anda tampilkan kepada pengguna di luar
UI normal aplikasi. Bila Anda memberi tahu sistem untuk mengeluarkan pemberitahuan, pemberitahuan akan muncul lebih dahulu sebagai ikon dalam
<strong>area pemberitahuan</strong>. Untuk melihat detail pemberitahuan, pengguna membuka
<strong>laci pemberitahuan</strong>. Baik area pemberitahuan maupun laci pemberitahuan
adalah area-area yang dikontrol sistem yang bisa dilihat pengguna kapan saja.
</p>
<img id="figure1" src="{@docRoot}images/ui/notifications/notification_area.png" height="" alt="" />
<p class="img-caption">
<strong>Gambar 1.</strong> Pemberitahuan di area pemberitahuan.
</p>
<img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png" width="280px" alt="" />
<p class="img-caption">
<strong>Gambar 2.</strong> Pemberitahuan di laci pemberitahuan.
</p>
<p class="note"><strong>Catatan:</strong> Kecuali disebutkan, panduan ini mengacu pada
kelas {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}
dalam <a href="{@docRoot}tools/support-library/index.html">Support Library</a> versi 4.
Kelas {@link android.app.Notification.Builder Notification.Builder} telah ditambahkan pada Android
3.0 (API level 11).</p>
<h2 id="Design">Pertimbangan Desain</h2>
<p>Pemberitahuan, sebagai bagian penting dari antarmuka pengguna Android, memiliki panduan desainnya sendiri.
Perubahan desain materi yang diperkenalkan dalam Android 5.0 (API level 21) adalah sangat
penting, dan Anda harus meninjau pelatihan <a href="{@docRoot}training/material/index.html">Desain Bahan</a>
untuk informasi selengkapnya. Untuk mengetahui cara mendesain pemberitahuan dan interaksinya, bacalah panduan desain
<a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.</p>
<h2 id="CreateNotification">Membuat Pemberitahuan</h2>
<p>Anda menetapkan informasi dan tindakan UI bagi pemberitahuan dalam
objek {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
Untuk membuat pemberitahuan itu sendiri, panggil
{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},
yang akan mengembalikan objek {@link android.app.Notification} berisi spesifikasi Anda. Untuk mengeluarkan
pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem dengan memanggil
{@link android.app.NotificationManager#notify NotificationManager.notify()}.</p>
<h3 id="Required">Isi pemberitahuan yang diperlukan</h3>
<p>
Objek {@link android.app.Notification} <em>harus</em> berisi yang berikut ini:
</p>
<ul>
<li>
Ikon kecil, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
</li>
<li>
Judul, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
</li>
<li>
Teks detail, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
</li>
</ul>
<h3 id="Optional">Isi dan pengaturan pemberitahuan opsional</h3>
<p>
Semua isi dan pengaturan pemberitahuan lainnya bersifat opsional. Untuk mengetahui selengkapnya tentang semua itu,
lihat dokumentasi acuan untuk {@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Actions">Tindakan pemberitahuan</h3>
<p>
Walaupun bersifat opsional, Anda harus menambahkan setidaknya satu tindakan pada pemberitahuan.
Tindakan memungkinkan pengguna beralih langsung dari pemberitahuan ke
{@link android.app.Activity} dalam aplikasi Anda, tempat pengguna bisa melihat satu atau beberapa kejadian
atau melakukan pekerjaan lebih jauh.
</p>
<p>
Pemberitahuan bisa menyediakan beberapa tindakan sekaligus. Anda harus selalu mendefinisikan tindakan yang
akan diaktifkan bila pengguna mengklik pemberitahuan; biasanya tindakan ini akan membuka
{@link android.app.Activity} dalam aplikasi Anda. Anda juga bisa menambahkan tombol pada pemberitahuan
yang melakukan tindakan tambahan seperti mendiamkan alarm atau segera merespons
pesan teks; fitur ini tersedia mulai Android 4.1. Jika menggunakan tombol tindakan tambahan, Anda
juga harus membuat fungsionalitasnya tersedia dalam {@link android.app.Activity} di aplikasi Anda; lihat
bagian <a href="#Compatibility">Menangani kompatibilitas</a> untuk detail selengkapnya.
</p>
<p>
Dalam {@link android.app.Notification}, tindakan itu sendiri didefinisikan oleh
{@link android.app.PendingIntent} berisi
{@link android.content.Intent} yang memulai
{@link android.app.Activity} dalam aplikasi Anda. Untuk mengaitkan
{@link android.app.PendingIntent} dengan gestur, panggil metode
{@link android.support.v4.app.NotificationCompat.Builder} yang sesuai. Misalnya, jika ingin memulai
{@link android.app.Activity} bila pengguna mengklik teks pemberitahuan pada
laci pemberitahuan, tambahkan {@link android.app.PendingIntent} dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
</p>
<p>
Memulai {@link android.app.Activity} bila pengguna mengklik pemberitahuan adalah
skenario tindakan yang paling umum. Anda juga bisa memulai {@link android.app.Activity} bila pengguna
menghilangkan pemberitahuan. Dalam Android 4.1 dan yang lebih baru, Anda bisa memulai
{@link android.app.Activity} dari tombol tindakan. Untuk mengetahui selengkapnya, bacalah panduan acuan untuk
{@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Priority">Prioritas pemberitahuan</h3>
<p>
Jika diinginkan, Anda bisa mengatur prioritas pemberitahuan. Prioritas berfungsi
sebagai petunjuk bagi UI perangkat tentang cara menampilkan pemberitahuan.
Untuk mengatur prioritas pemberitahuan, panggil {@link
android.support.v4.app.NotificationCompat.Builder#setPriority(int)
NotificationCompat.Builder.setPriority()} dan teruskan salah satu konstanta prioritas {@link
android.support.v4.app.NotificationCompat}. Ada
lima level prioritas, mulai dari {@link
android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) hingga {@link
android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); jika tidak diatur,
prioritas default akan ditetapkan {@link
android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
</p>
<p> Untuk informasi tentang mengatur level prioritas, lihat "Mengatur
dan mengelola prioritas pemberitahuan dengan benar" dalam panduan
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="SimpleNotification">Membuat pemberitahuan sederhana</h3>
<p>
Cuplikan berikut mengilustrasikan pemberitahuan sederhana yang menetapkan aktivitas untuk dibuka bila
pengguna mengklik pemberitahuan. Perhatikan bahwa kode ini membuat
objek {@link android.support.v4.app.TaskStackBuilder} dan menggunakannya untuk membuat
{@link android.app.PendingIntent} untuk tindakan. Pola ini dijelaskan secara lebih detail
di bagian <a href="#NotificationResponse">
Mempertahankan Navigasi saat Memulai Aktivitas</a>:
</p>
<pre>
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
</pre>
<p>Demikian saja. Pengguna Anda kini telah diberi tahu.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</h3>
<p>
Agar pemberitahuan muncul dalam tampilan yang diperluas, buat dahulu
objek {@link android.support.v4.app.NotificationCompat.Builder} dengan opsi tampilan normal
yang Anda inginkan. Berikutnya, panggil {@link android.support.v4.app.NotificationCompat.Builder#setStyle
Builder.setStyle()} dengan objek layout yang diperluas sebagai argumennya.
</p>
<p>
Ingatlah bahwa pemberitahuan yang diperluas tidak tersedia pada platform-platform sebelum Android 4.1. Untuk
mengetahui cara menangani pemberitahuan untuk Android 4.1 dan untuk platform-platform sebelumnya, bacalah
bagian <a href="#Compatibility">Menangani kompatibilitas</a>.
</p>
<p>
Misalnya, cuplikan kode berikut memperagakan cara mengubah pemberitahuan yang dibuat
dalam cuplikan sebelumnya untuk menggunakan layout yang diperluas:
</p>
<pre>
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Event tracker")
.setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
new NotificationCompat.InboxStyle();
String[] events = new String[6];
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i &lt; events.length; i++) {
inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.
</pre>
<h3 id="Compatibility">Menangani kompatibilitas</h3>
<p>
Tidak semua fitur pemberitahuan tersedia untuk versi tertentu, walaupun
metode untuk mengaturnya ada dalam kelas pustaka dukungan
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
Misalnya, tombol tindakan, yang bergantung pada pemberitahuan yang diperluas, hanya muncul pada Android
4.1 dan lebih tinggi, karena pemberitahuan yang diperluas itu sendiri hanya tersedia pada
Android 4.1 dan yang lebih tinggi.
</p>
<p>
Untuk memastikan kompatibilitas terbaik, buatlah pemberitahuan dengan
{@link android.support.v4.app.NotificationCompat NotificationCompat} dan subkelasnya,
khususnya {@link android.support.v4.app.NotificationCompat.Builder
NotificationCompat.Builder}. Selain itu, ikutilah proses ini bila Anda mengimplementasikan pemberitahuan:
</p>
<ol>
<li>
Sediakan semua fungsionalitas pemberitahuan kepada semua pengguna, terlepas dari versi
yang mereka gunakan. Caranya, pastikan semua fungsionalitas tersedia dari
{@link android.app.Activity} dalam aplikasi Anda. Anda mungkin perlu menambahkan sebuah
{@link android.app.Activity} baru untuk melakukannya.
<p>
Misalnya, jika Anda ingin menggunakan
{@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} untuk
menyediakan kontrol yang menghentikan dan memulai pemutaran media, implementasikan dahulu
kontrol ini pada {@link android.app.Activity} dalam aplikasi Anda.
</p>
</li>
<li>
Pastikan semua pengguna bisa memperoleh fungsionalitas dalam {@link android.app.Activity},
dengan memulainya bila pengguna mengklik pemberitahuan. Caranya,
buatlah {@link android.app.PendingIntent}
untuk {@link android.app.Activity}. Panggil
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()} untuk menambahkan {@link android.app.PendingIntent} pada pemberitahuan.
</li>
<li>
Kini tambahkan fitur pemberitahuan diperluas yang ingin Anda gunakan pada pemberitahuan. Ingatlah
bahwa setiap fungsionalitas yang Anda tambahkan juga harus tersedia dalam {@link android.app.Activity}
yang akan dimulai bila pengguna mengklik pemberitahuan.
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Managing">Mengelola Pemberitahuan</h2>
<p>
Bila perlu mengeluarkan pemberitahuan beberapa kali untuk tipe kejadian yang sama,
hindari membuat pemberitahuan yang sama sekali baru. Sebagai gantinya, Anda harus mempertimbangkan untuk memperbarui
pemberitahuan sebelumnya, baik dengan mengubah sebagian nilainya atau dengan menambahkan nilai, atau keduanya.
</p>
<p>
Misalnya, Gmail akan memberi tahu pengguna bila ada email baru dengan menambah hitungan
pesan tidak terbaca dan dengan menambahkan rangkuman tiap email ke pemberitahuan. Ini disebut dengan
"stacking" (menumpuk) pemberitahuan; hal ini dijelaskan lebih detail dalam panduan
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
</p>
<p class="note">
<strong>Catatan:</strong> Fitur Gmail ini mensyaratkan layout "kotak masuk" diperluas, yang merupakan
bagian dari fitur pemberitahuan diperluas yang tersedia mulai Android 4.1.
</p>
<p>
Bagian berikut menjelaskan cara memperbarui pemberitahuan dan cara menghapusnya.
</p>
<h3 id="Updating">Memperbarui pemberitahuan</h3>
<p>
Untuk menyiapkan pemberitahuan agar bisa diperbarui, keluarkan pemberitahuan bersama ID pemberitahuan dengan
memanggil {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.
Untuk memperbarui pemberitahuan ini setelah Anda
mengeluarkan, memperbarui, atau membuat objek {@link android.support.v4.app.NotificationCompat.Builder},
buat objek {@link android.app.Notification} darinya, dan keluarkan
{@link android.app.Notification} bersama ID yang sama dengan yang Anda gunakan sebelumnya. Jika
pemberitahuan sebelumnya tetap terlihat, sistem akan memperbaruinya dari konten
objek {@link android.app.Notification}. Jika pemberitahuan sebelumnya telah dihilangkan, sebuah
pemberitahuan baru akan dibuat.
</p>
<p>
Cuplikan berikut memperagakan pemberitahuan yang diperbarui untuk mencerminkan
jumlah kejadian yang telah terjadi. Cuplikan ini menumpuk pemberitahuan, yang menampilkan rangkuman:
</p>
<pre>
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
...
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Removing">Menghapus pemberitahuan</h3>
<p>
Pemberitahuan tetap terlihat hingga salah satu kejadian berikut terjadi:
</p>
<ul>
<li>
Pengguna menghilangkan pemberitahuan satu per satu atau dengan menggunakan "Clear All" (jika
pemberitahuan bisa dihapus).
</li>
<li>
Pengguna mengklik pemberitahuan, dan Anda memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} bila
Anda telah membuat pemberitahuan.
</li>
<li>
Anda memanggil {@link android.app.NotificationManager#cancel(int) cancel()} untuk
ID pemberitahuan tertentu. Metode ini juga menghapus pemberitahuan yang berjalan.
</li>
<li>
Anda memanggil {@link android.app.NotificationManager#cancelAll() cancelAll()}, yang menghapus
semua pemberitahuan yang dikeluarkan sebelumnya.
</li>
</ul>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</h2>
<p>
Bila memulai {@link android.app.Activity} dari pemberitahuan, Anda harus mempertahankan
pengalaman navigasi yang diharapkan pengguna. Mengklik <i>Back</i> harus membawa pengguna kembali melalui
aliran pekerjaan normal aplikasi ke layar Home, dan mengklik <i>Recents</i> harus menampilkan
{@link android.app.Activity} sebagai tugas terpisah. Untuk mempertahankan pengalaman navigasi, Anda
harus memulai {@link android.app.Activity} dalam tugas baru. Cara menyiapkan
{@link android.app.PendingIntent} untuk memberi Anda tugas baru bergantung pada sifat
{@link android.app.Activity} yang Anda mulai. Ada dua situasi umum:
</p>
<dl>
<dt>
Aktivitas rutin
</dt>
<dd>
Anda memulai {@link android.app.Activity} yang merupakan bagian dari aliran pekerjaan normal
aplikasi. Dalam situasi ini, siapkan {@link android.app.PendingIntent} untuk
memulai tugas baru, dan sediakan {@link android.app.PendingIntent} bersama back-stack
yang meniru perilaku <i>Back</i> biasa.
<p>
Pemberitahuan dari aplikasi Gmail memperagakan hal ini. Bila Anda mengklik pemberitahuan untuk
satu pesan email, Anda akan melihat pesan itu sendiri. Menyentuh <b>Back</b> akan membawa Anda
kembali melalui Gmail ke layar Home, persis seperti jika memasuki Gmail dari
layar Home bukannya memasukinya dari pemberitahuan.
</p>
<p>
Hal ini terjadi terlepas dari aplikasi tempat Anda berada saat menyentuh
pemberitahuan. Misalnya, jika Anda dalam Gmail sedang menulis pesan, dan Anda mengklik
pemberitahuan untuk satu email, Anda akan segera dibawa ke email itu. Menyentuh <i>Back</i>
akan membawa Anda ke kotak masuk kemudian layar Home, bukannya membawa Anda ke
pesan yang sedang ditulis.
</p>
</dd>
<dt>
Aktivitas khusus
</dt>
<dd>
Pengguna hanya melihat {@link android.app.Activity} ini jika dimulai dari pemberitahuan.
Dalam beberapa hal, {@link android.app.Activity} akan memperluas pemberitahuan dengan menyediakan
informasi yang akan sulit untuk ditampilkan dalam pemberitahuan itu sendiri. Untuk situasi ini,
siapkan {@link android.app.PendingIntent} untuk dimulai dalam tugas baru. Tidak perlu
membuat back-stack, karena {@link android.app.Activity} yang dimulai bukan bagian dari
aliran aktivitas aplikasi. Mengklik <i>Back</i> tetap akan membawa pengguna ke
layar Home.
</dd>
</dl>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="DirectEntry">Menyiapkan PendingIntent aktivitas biasa</h3>
<p>
Untuk menyiapkan {@link android.app.PendingIntent} yang memulai entri langsung
{@link android.app.Activity}, ikuti langkah-langkah ini:
</p>
<ol>
<li>
Definisikan hierarki {@link android.app.Activity} aplikasi Anda dalam manifes.
<ol style="list-style-type: lower-alpha;">
<li>
Tambahkan dukungan untuk Android 4.0.3 dan yang terdahulu. Caranya, tetapkan induk
{@link android.app.Activity} yang Anda mulai dengan menambahkan elemen
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
sebagai anak
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
<p>
Untuk elemen ini, atur
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
Atur
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
dengan <code>&lt;parent_activity_name&gt;</code> sebagai nilai
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
untuk elemen induk
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
. Lihat XML berikut sebagai contoh.
</p>
</li>
<li>
Juga tambahkan dukungan untuk Android 4.1 dan yang lebih baru. Caranya, tambahkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
pada elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
dari {@link android.app.Activity} yang Anda mulai.
</li>
</ol>
<p>
XML akhir akan terlihat seperti ini:
</p>
<pre>
&lt;activity
android:name=".MainActivity"
android:label="&#64;string/app_name" &gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity"&gt;
&lt;meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/&gt;
&lt;/activity&gt;
</pre>
</li>
<li>
Buat back-stack berdasarkan {@link android.content.Intent} yang memulai
{@link android.app.Activity}:
<ol style="list-style-type: lower-alpha;">
<li>
Buat {@link android.content.Intent} untuk memulai {@link android.app.Activity}.
</li>
<li>
Buat stack-builder (pembangun tumpukan) dengan memanggil {@link android.app.TaskStackBuilder#create
TaskStackBuilder.create()}.
</li>
<li>
Tambahkan back-stack ke stack-builder dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
Untuk setiap {@link android.app.Activity} dalam hierarki yang telah Anda definisikan dalam
manifes, back-stack berisi objek {@link android.content.Intent} yang
memulai {@link android.app.Activity}. Metode ini juga menambahkan flag yang memulai
back-stack dalam tugas baru.
<p class="note">
<strong>Catatan:</strong> Walaupun argumen untuk
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
adalah acuan ke {@link android.app.Activity} yang dimulai, panggilan metode
tidak akan menambahkan {@link android.content.Intent} yang memulai
{@link android.app.Activity}. Sebagai gantinya, hal itu ditangani dalam langkah berikutnya.
</p>
</li>
<li>
Tambahkan {@link android.content.Intent} yang memulai {@link android.app.Activity}
dari pemberitahuan, dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
Teruskan {@link android.content.Intent} yang Anda buat dalam langkah pertama sebagai
argumen ke
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
</li>
<li>
Jika perlu, tambahkan argumen ke objek {@link android.content.Intent} pada
back-stack dengan memanggil {@link android.support.v4.app.TaskStackBuilder#editIntentAt
TaskStackBuilder.editIntentAt()}. Kadang-kadang perlu memastikan apakah
{@link android.app.Activity} target menampilkan data bermakna saat pengguna menelusurinya
dengan menggunakan <i>Back</i>.
</li>
<li>
Dapatkan {@link android.app.PendingIntent} untuk back-stack ini dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
</li>
</ol>
<p>
Cuplikan kode berikut memperagakan prosesnya:
</p>
<pre>
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</h3>
<p>
Bagian berikut menjelaskan cara menyiapkan aktivitas khusus
{@link android.app.PendingIntent}.
</p>
<p>
{@link android.app.Activity} khusus tidak memerlukan back-stack, sehingga Anda tidak perlu
mendefinisikan hierarki {@link android.app.Activity}-nya dalam manifes, dan Anda tidak perlu
memanggil
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} untuk membuat
back-stack. Sebagai gantinya, gunakan manifes untuk menyiapkan opsi tugas {@link android.app.Activity},
dan buat {@link android.app.PendingIntent} dengan memanggil
{@link android.app.PendingIntent#getActivity getActivity()}:
</p>
<ol>
<li>
Dalam manifes, tambahkan atribut berikut pada elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
untuk {@link android.app.Activity}
<dl>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
</dt>
<dd>
Nama kelas mutlak (fully qualified) aktivitas.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
</dt>
<dd>
Dikombinasikan dengan flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
yang Anda atur dalam kode, ini memastikan bahwa {@link android.app.Activity} ini tidak
masuk ke dalam tugas default aplikasi. Setiap tugas yang ada yang memiliki
afinitas default aplikasi tidak terpengaruh.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
</dt>
<dd>
Mengecualikan tugas baru dari <i>Recents</i>, sehingga pengguna tidak bisa tanpa sengaja
mengarahkan kembali.
</dd>
</dl>
<p>
Cuplikan ini menampilkan elemen:
</p>
<pre>
&lt;activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true"&gt;
&lt;/activity&gt;
...
</pre>
</li>
<li>
Buat dan keluarkan pemberitahuan:
<ol style="list-style-type: lower-alpha;">
<li>
Buat {@link android.content.Intent} yang memulai
{@link android.app.Activity}.
</li>
<li>
Atur {@link android.app.Activity} untuk dimulai dalam tugas kosong yang baru dengan memanggil
{@link android.content.Intent#setFlags setFlags()} dengan flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
dan
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
</li>
<li>
Atur setiap opsi lain yang Anda perlukan untuk {@link android.content.Intent}.
</li>
<li>
Buat {@link android.app.PendingIntent} dari {@link android.content.Intent}
dengan memanggil {@link android.app.PendingIntent#getActivity getActivity()}.
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
<p>
Cuplikan kode berikut memperagakan prosesnya:
</p>
<pre>
// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
</pre>
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Progress">Menampilkan Kemajuan dalam Pemberitahuan</h2>
<p>
Pemberitahuan bisa menyertakan indikator kemajuan beranimasi yang menampilkan status
operasi yang berjalan kepada pengguna. Jika Anda bisa memperkirakan lamanya operasi berlangsung dan berapa banyak
yang sudah selesai pada suatu waktu, gunakan bentuk indikator yang "pasti"
(baris kemajuan). Jika Anda tidak bisa memperkirakan lamanya operasi, gunakan
bentuk indikator "tidak pasti" (indikator aktivitas).
</p>
<p>
Indikator kemajuan ditampilkan bersama implementasi platform
kelas {@link android.widget.ProgressBar}.
</p>
<p>
Untuk menggunakan indikator kemajuan pada platform mulai dari Android 4.0, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. Untuk
versi sebelumnya, Anda harus membuat layout pemberitahuan custom sendiri yang
menyertakan tampilan {@link android.widget.ProgressBar}.
</p>
<p>
Bagian berikut ini menjelaskan cara menampilkan kemajuan dalam pemberitahuan dengan menggunakan
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</h3>
<p>
Untuk menampilkan baris kemajuan pasti, tambahkan baris itu ke pemberitahuan dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(max, progress, false)}, kemudian keluarkan pemberitahuan. Selagi operasi berlangsung,
tambah <code>progress</code>, dan perbarui pemberitahuan. Di akhir operasi,
<code>progress</code> harus sama dengan <code>max</code>. Satu cara umum memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
adalah mengatur <code>max</code> ke 100, kemudian tambah <code>progress</code> sebagai
nilai "persen selesai"untuk operasi itu.
</p>
<p>
Anda bisa membiarkan baris kemajuan ditampilkan saat operasi selesai, atau menghilangkannya. Dalam
hal apa pun, ingatlah memperbarui teks pemberitahuan untuk menampilkan bahwa operasi telah selesai.
Untuk menghapus baris kemajuan, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(0, 0, false)}. Misalnya:
</p>
<pre>
...
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
&#64;Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr &lt;= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(5*1000);
} catch (InterruptedException e) {
Log.d(TAG, "sleep failure");
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(ID, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ActivityIndicator">Menampilkan indikator aktivitas berlanjut</h3>
<p>
Untuk menampilkan indikator aktivitas tidak pasti, tambahkan aktivitas ke pemberitahuan dengan
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
(dua argumen pertama akan diabaikan), dan keluarkan pemberitahuan. Hasilnya adalah indikator
yang memiliki gaya yang sama dengan baris kemajuan, hanya saja animasinya terus berjalan.
</p>
<p>
Keluarkan pemberitahuan di awal operasi. Animasi akan berjalan hingga Anda
memodifikasi pemberitahuan. Bila operasi selesai, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
kemudian perbarui pemberitahuan untuk menghapus indikator aktivitas.
Selalu lakukan ini; jika makan animasi akan terus berjalan sekalipun operasi telah selesai. Juga
ingatlah mengubah teks pemberitahuan untuk menunjukkan bahwa operasi telah selesai.
</p>
<p>
Untuk melihat cara kerja indikator aktivitas, lihat cuplikan terdahulu. Cari lokasi baris-baris berikut:
</p>
<pre>
// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<p>
Ganti baris yang telah Anda temukan dengan baris berikut:
</p>
<pre>
// Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<h2 id="metadata">Metadata Pemberitahuan</h2>
<p>Pemberitahuan dapat disortir sesuai metadata yang Anda tetapkan dengan
metode {@link android.support.v4.app.NotificationCompat.Builder} berikut:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}
memberi tahu sistem cara menangani pemberitahuan aplikasi Anda bila perangkat berada dalam mode Priority
(misalnya, jika pemberitahuan menyatakan suatu panggilan masuk, pesan instan, atau alarm).</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} menyebabkan
pemberitahuan dengan bidang prioritas diatur ke {@code PRIORITY_MAX} atau {@code PRIORITY_HIGH}
muncul dalam jendela kecil mengambang jika pemberitahuan juga memiliki suara atau getaran.</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}
memungkinkan Anda menambahkan daftar orang ke pemberitahuan. Aplikasi Anda bisa menggunakannya untuk memberi isyarat pada
sistem bahwa sistem harus mengelompokkan bersama pemberitahuan dari orang-orang yang ditetapkan, atau memberi peringkat lebih penting pada pemberitahuan
untuk orang-orang ini.</li>
</ul>
<div class="figure" style="width:230px">
<img src="{@docRoot}images/ui/notifications/heads-up.png" alt="" width="" height="" id="figure3" />
<p class="img-caption">
<strong>Gambar 3.</strong> Aktivitas layar penuh yang menampilkan pemberitahuan pendahuluan
</p>
</div>
<h2 id="Heads-up">Pemberitahuan Pendahuluan</h2>
<p>Dengan Android 5.0 (API level 21), pemberitahuan bisa muncul dalam jendela kecil mengambang
(yang disebut juga dengan <em>pemberitahuan pendahuluan</em>) saat perangkat aktif
(yakni, perangkat dibuka kuncinya dan layarnya menyala). Pemberitahuan ini
muncul seperti bentuk ringkas pemberitahuan Anda, hanya saja
pemberitahuan pendahuluan juga menampilkan tombol tindakan. Pengguna bisa menindaklanjuti atau mengabaikan,
pemberitahuan pendahuluan tanpa meninggalkan aplikasi saat ini.</p>
<p>Contoh-contoh kondisi yang dapat memicu pemberitahuan pendahuluan antara lain:</p>
<ul>
<li>Aktivitas pengguna berada dalam mode layar penuh (aplikasi menggunakan
{@link android.app.Notification#fullScreenIntent}), atau</li>
<li>Pemberitahuan memiliki prioritas tinggi dan menggunakan nada dering atau
getaran</li>
</ul>
<h2 id="lockscreenNotification">Pemberitahuan Layar Kunci</h2>
<p>Dengan rilis Android 5.0 (API level 21), pemberitahuan kini dapat muncul pada
layar kunci. Aplikasi Anda bisa menggunakan fungsionalitas ini untuk menyediakan kontrol pemutaran media dan
tindakan umum lainnya. Pengguna bisa memilih lewat Settings apakah akan menampilkan pemberitahuan pada layar kunci, dan
Anda bisa mendesain apakah pemberitahuan aplikasi akan terlihat pada layar kunci.</p>
<h3 id="visibility">Mengatur Visibilitas</h3>
<p>Aplikasi Anda bisa mengatur level detail terlihat pada pemberitahuan yang ditampilkan di
layar kunci aman. Anda memanggil {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}
dan menetapkan salah satu nilai berikut:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} menampilkan isi lengkap
pemberitahuan.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} tidak menampilkan bagian apa pun dari
pemberitahuan ini pada layar kunci.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} menampilkan informasi dasar,
misalnya ikon dan judul isi pemberitahuan, namun menyembunyikan isi lengkap pemberitahuan.</li>
</ul>
<p>Bila {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} telah diatur, Anda juga bisa
menyediakan versi alternatif isi pemberitahuan yang menyembunyikan detail tertentu. Misalnya,
aplikasi SMS dapat menampilkan pemberitahuan yang menampilkan <em>Anda memiliki 3 pesan teks baru</em>, namun menyembunyikan
isi dan pengirim pesan. Untuk menyediakan pemberitahuan alternatif ini, buat dahulu pemberitahuan
pengganti menggunakan {@link android.support.v4.app.NotificationCompat.Builder}. Bila Anda membuat
objek pemberitahuan privat, lampirkan pemberitahuan pengganti melalui metode
{@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}
.</p>
<h3 id="controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</h3>
<p>Dalam Android 5.0 (API level 21) layar kunci tidak lagi menampilkan kontrol media
berdasarkan {@link android.media.RemoteControlClient}, yang sekarang telah dihilangkan. Sebagai gantinya, gunakan
template {@link android.app.Notification.MediaStyle} dengan metode
{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
, yang mengubah tindakan menjadi ikon yang bisa diklik.</p>
<p class="note"><strong>Catatan:</strong> Template dan metode {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
tidak disertakan dalam pustaka dukungan, sehingga fitur-fitur ini berjalan pada Android 5.0 dan yang lebih tinggi
saja.</p>
<p>Untuk menampilkan kontrol pemutaran media di layar kunci dalam Android 5.0, atur visibilitas
ke {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, seperti dijelaskan di atas. Kemudian tambahkan
tindakan dan atur template {@link android.app.Notification.MediaStyle}, seperti dijelaskan dalam contoh kode
berikut:</p>
<pre>
Notification notification = new Notification.Builder(context)
// Show controls on lock screen even when user hides sensitive content.
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_stat_player)
// Add media control buttons that invoke intents in your media service
.addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
// Apply the media style template
.setStyle(new Notification.MediaStyle()
.setShowActionsInCompactView(1 /* #1: pause button */)
.setMediaSession(mMediaSession.getSessionToken())
.setContentTitle("Wonderful music")
.setContentText("My Awesome Band")
.setLargeIcon(albumArtBitmap)
.build();
</pre>
<p class="note"><strong>Catatan:</strong> Dihilangkannya {@link android.media.RemoteControlClient}
memiliki implikasi lebih jauh untuk mengontrol media. Lihat
<a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Kontrol Pemutaran Media</a>
untuk informasi selengkapnya tentang API baru untuk mengelola sesi media dan mengontrol pemutaran.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="CustomNotification">Layout Pemberitahuan Custom</h2>
<p>
Kerangka kerja pemberitahuan memungkinkan Anda mendefinisikan layout pemberitahuan custom, yang
mendefinisikan penampilan pemberitahuan dalam objek {@link android.widget.RemoteViews}.
Pemberitahuan dengan layout custom serupa pemberitahuan normal, namun dibuat berdasarkan
{@link android.widget.RemoteViews} yang didefinisikan dalam file layout XML.
</p>
<p>
Tinggi yang tersedia untuk layout pemberitahuan custom bergantung pada tampilan pemberitahuan. Layout
tampilan normal dibatasi hingga 64 dp, dan layout tampilan yang diperluas dibatasi hingga 256 dp.
</p>
<p>
Untuk mendefinisikan layout pemberitahuan custom, mulailah dengan membuat instance
objek {@link android.widget.RemoteViews} yang memekarkan file layout XML. Kemudian,
sebagai ganti memanggil metode seperti
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
panggil {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Untuk mengatur
detail isi pemberitahuan custom, gunakan metode dalam
{@link android.widget.RemoteViews} untuk mengatur nilai anak tampilan:
</p>
<ol>
<li>
Buat layout XML untuk pemberitahuan di file terpisah. Anda bisa menggunakan nama file
apa saja yang diinginkan, namun Anda harus menggunakan ekstensi <code>.xml</code>
</li>
<li>
Dalam aplikasi Anda, gunakan metode {@link android.widget.RemoteViews} untuk mendefinisikan
ikon dan teks pemberitahuan. Masukkan objek {@link android.widget.RemoteViews} ini ke dalam
{@link android.support.v4.app.NotificationCompat.Builder} Anda dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Hindari
mengatur {@link android.graphics.drawable.Drawable} latar belakang pada
objek {@link android.widget.RemoteViews} Anda, karena warna teks bisa menjadi tidak terbaca.
</li>
</ol>
<p>
Kelas {@link android.widget.RemoteViews} juga menyertakan metode yang bisa Anda gunakan untuk
menambahkan {@link android.widget.Chronometer} atau {@link android.widget.ProgressBar}
dengan mudah ke layout pemberitahuan Anda. Untuk informasi selengkapnya tentang cara membuat layout custom
pemberitahuan Anda, lihat dokumentasi acuan {@link android.widget.RemoteViews}.
</p>
<p class="caution">
<strong>Perhatian:</strong> Bila Anda menggunakan layout pemberitahuan custom, berhati-hatilah
untuk memastikan bahwa layout custom itu bekerja pada berbagai orientasi dan resolusi perangkat. Walaupun
berlaku bagi semua layout View, nasihat ini khususnya penting untuk pemberitahuan karena
ruang di laci pemberitahuan sangat terbatas. Jangan buat layout custom terlalu
kompleks, dan pastikan mengujinya di berbagai konfigurasi.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h4>Menggunakan sumber daya gaya untuk teks pemberitahuan custom</h4>
<p>
Selalu gunakan sumber daya gaya untuk teks pemberitahuan custom. Warna latar belakang
pemberitahuan bisa bervariasi di berbagai perangkat dan versi, dan menggunakan sumber daya gaya
membantu Anda menangani hal ini. Mulai Android 2.3, sistem mendefinisikan sebuah gaya untuk
teks layout pemberitahuan standar. Jika Anda menggunakan gaya yang sama dalam aplikasi yang menargetkan Android
2.3 atau yang lebih tinggi, Anda akan memastikan bahwa teks terlihat pada latar belakang tampilan.
</p>

View File

@@ -1,71 +0,0 @@
page.title=Ikhtisar UI
@jd:body
<p>Semua elemen antarmuka pengguna dalam aplikasi Android dibangun menggunakan objek {@link android.view.View} dan
{@link android.view.ViewGroup}. {@link android.view.View} adalah objek yang menarik
sesuatu di layar dan dapat berinteraksi dengan pengguna. {@link android.view.ViewGroup} merupakan sebuah
objek yang menyimpan objek {@link android.view.View} lainnya (dan {@link android.view.ViewGroup}) untuk
mendefinisikan layout antarmuka.</p>
<p>Android menyediakan sekumpulan subkelas {@link android.view.View} dan {@link
android.view.ViewGroup} yang menawarkan kontrol input umum (seperti tombol dan bidang
teks) serta berbagai model layout (seperti layout linear atau relatif).</p>
<h2 id="Layout">Layout Antarmuka Pengguna</h2>
<p>Antarmuka pengguna untuk setiap komponen aplikasi Anda didefinisikan menggunakan hierarki objek {link
android.view.View} dan {@link android.view.ViewGroup}, seperti yang ditampilkan dalam gambar 1. Setiap kelompok tampilan
merupakan kontainer tak terlihat yang mengelola tampilan anak, sementara tampilan anak ini dapat menjadi kontrol
input atau widget lain yang
menarik sebagian dari UI. Pohon hierarki ini bisa sederhana atau bisa juga kompleks bergantung kebutuhan
(namun yang sederhana paling baik untuk kinerja).</p>
<img src="{@docRoot}images/viewgroup.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi dari hierarki tampilan, yang mendefinisikan layout
UI.</p>
<p>Untuk mendeklarasikan layout, Anda dapat menyediakan objek {@link android.view.View} dalam kode dan mulai
membangun pohon, namun cara termudah dan terefektif untuk mendefinisikan layout adalah dengan file XML.
XML menawarkan struktur layout yang dapat dibaca manusia, serupa dengan HTML.</p>
<p>Nama elemen XML untuk tampilan sesuai dengan kelas Android yang diwakilinya. Dengan demikian elemen
<code>&lt;TextView&gt;</code> membuat widget {@link android.widget.TextView} dalam UI Anda,
dan elemen <code>&lt;LinearLayout&gt;</code> membuat kelompok tampilan {@link android.widget.LinearLayout}
. </p>
<p>Misalnya, layout vertikal sederhana dengan tampilan teks dan tombol akan tampak seperti ini:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Saat Anda memuat sumber daya layout di aplikasi, Android akan menginisialisasi setiap simpul layout menjadi
objek runtime yang bisa Anda gunakan untuk mendefinisikan perilaku tambahan, query status objek, atau memodifikasi
layout.</p>
<p>Untuk mendapatkan panduan lengkap mengenai pembuatan layout UI, lihat <a href="declaring-layout.html">Layout
XML</a>.
<h2 id="UIComponents">Komponen Antarmuka Pengguna</h2>
<p>Anda tidak harus membuat semua UI menggunakan objek {@link android.view.View} dan {link
android.view.ViewGroup}. Android menyediakan beberapa komponen aplikasi yang menawarkan
layout UI standar yang tinggal Anda definisikan kontennya. Komponen UI ini masing-masing
memiliki set API unik yang dijelaskan dalam masing-masing dokumennya, seperti <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>, <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialog</a>, dan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Status</a>.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -1,291 +0,0 @@
page.title=Kejadian Input
parent.title=Antarmuka Pengguna
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#EventListeners">Event Listener</a></li>
<li><a href="#EventHandlers">Event Handler</a></li>
<li><a href="#TouchMode">Mode Sentuh</a></li>
<li><a href="#HandlingFocus">Menangani Fokus</a></li>
</ol>
</div>
</div>
<p>Di Android, ada lebih dari satu cara untuk mencegat kejadian dari interaksi pengguna dengan aplikasi Anda.
Saat mempertimbangkan kejadian dalam antarmuka pengguna Anda, pendekatannya adalah menangkap kejadian
dari objek View tertentu yang digunakan pengguna untuk berinteraksi. Kelas View menyediakan sarana untuk melakukannya.</p>
<p>Dalam berbagai kelas View yang akan digunakan untuk menyusun layout, Anda mungkin melihat beberapa metode callback
publik yang tampak berguna untuk kejadian UI. Metode ini dipanggil oleh kerangka kerja Android ketika masing-masing
tindakan terjadi pada objek itu. Misalnya, bila View (seperti Button/Tombol) disentuh,
metode <code>onTouchEvent()</code> akan dipanggil pada objek itu. Akan tetapi, untuk mencegatnya, Anda harus memperluas
kelas dan mengesampingkan metode itu. Akan tetapi, memperluas setiap objek View
untuk menangani kejadian seperti itu tidaklah praktis. Karena itulah kelas View juga berisi
sekumpulan antarmuka tersarang dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini,
yang disebut <a href="#EventListeners">event listener</a>, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.</p>
<p>Walaupun Anda akan lebih sering menggunakan event listener ini untuk interaksi pengguna,
mungkin ada saatnya Anda ingin memperluas kelas View, untuk membuat komponen custom.
Mungkin Anda ingin memperluas kelas {@link android.widget.Button}
untuk membuat sesuatu yang lebih menarik. Dalam hal ini, Anda akan dapat mendefinisikan perilaku kejadian default untuk kelas Anda dengan menggunakan
kelas <a href="#EventHandlers">event handler</a>.</p>
<h2 id="EventListeners">Event Listener</h2>
<p>Event listener merupakan antarmuka di kelas {@link android.view.View} yang berisi metode
callback tunggal. Metode ini akan dipanggil oleh kerangka kerja Android bila View yang
telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dalam UI.</p>
<p>Yang juga disertakan dalam antarmuka event listener adalah metode callback berikut ini:</p>
<dl>
<dt><code>onClick()</code></dt>
<dd>Dari {@link android.view.View.OnClickListener}.
Ini dipanggil baik saat pengguna menyentuh item
(bila dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
menekan tombol "enter" yang sesuai atau menekan trackball.</dd>
<dt><code>onLongClick()</code></dt>
<dd>Dari {@link android.view.View.OnLongClickListener}.
Ini dipanggil baik saat pengguna menyentuh dan menahan item (bila dalam mode sentuh),
maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
menekan serta menahan tombol "enter" yang sesuai atau menekan dan menahan trackball (selama satu detik).</dd>
<dt><code>onFocusChange()</code></dt>
<dd>Dari {@link android.view.View.OnFocusChangeListener}.
Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.</dd>
<dt><code>onKey()</code></dt>
<dd>Dari {@link android.view.View.OnKeyListener}.
Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol fisik pada perangkat.</dd>
<dt><code>onTouch()</code></dt>
<dd>Dari {@link android.view.View.OnTouchListener}.
Ini dipanggil saat pengguna melakukan tindakan yang digolongkan sebagai kejadian sentuh, termasuk penekanan, pelepasan,
atau gerak perpindahan pada layar (dalam batasan item itu).</dd>
<dt><code>onCreateContextMenu()</code></dt>
<dd>Dari {@link android.view.View.OnCreateContextMenuListener}.
Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi
tentang menu konteks di panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menu</a>.
</dd>
</dl>
<p>Metode ini satu-satunya yang menempati antarmukanya masing-masing. Untuk mendefinisikan salah satu metode ini
dan menangani kejadian Anda, implementasikan antarmuka tersarang dalam Aktivitas Anda atau definisikan sebagai kelas anonim.
Kemudian, teruskan satu
instance implementasi Anda pada masing-masing metode <code>View.set...Listener()</code>. (Misalnya, panggil
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
dan teruskan implementasi {@link android.view.View.OnClickListener OnClickListener} Anda.)</p>
<p>Contoh di bawah menunjukkan cara mendaftarkan on-click listener untuk Button. </p>
<pre>
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
</pre>
<p>Anda juga akan merasa lebih praktis mengimplementasikan OnClickListener sebagai bagian dari Aktivitas.
Ini akan menghindari beban kelas ekstra dan alokasi objek. Misalnya:</p>
<pre>
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
</pre>
<p>Perhatikan bahwa callback <code>onClick()</code> dalam contoh di atas tidak memiliki
nilai hasil, namun beberapa metode event listener lainnya harus mengembalikan boolean. Sebabnya
bergantung pada kejadian. Untuk sebagian yang mengembalikan boolean, ini sebabnya:</p>
<ul>
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
on-click listener lainnya.</li>
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
on-key listener lainnya.</li>
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah listener Anda telah menggunakan kejadian ini. Yang penting adalah
kejadian ini bisa memiliki beberapa tindakan yang saling mengikuti. Jadi, jika Anda mengembalikan <em>salah</em>saat
kejadian tindakan turun diterima, itu menunjukkan bahwa Anda belum menggunakan kejadian itu dan juga
tidak tertarik dengan tindakan berikutnya dari kejadian ini. Karena itu, Anda tidak akan diminta untuk melakukan tindakan
lainnya dalam kejadian, seperti gerakan jari, atau kejadian tindakan naik yang akan terjadi.</li>
</ul>
<p>Ingatlah bahwa kejadian tombol fisik selalu disampaikan ke View yang sedang difokus. Kejadian ini dikirim mulai dari atas
hierarki View, kemudian turun hingga tujuan yang sesuai. Jika View Anda (atau anak View Anda)
saat ini sedang fokus, maka Anda dapat melihat kejadian berpindah melalui metode.<code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
dispatchKeyEvent()}</code> Sebagai pengganti untuk menangkap kejadian penting melalui View, Anda juga dapat menerima
semua kejadian dalam Aktivitas Anda dengan <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
dan <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
<p>Selain itu, saat memikirkan tentang input teks aplikasi Anda, ingatlah bahwa banyak perangkat yang hanya memiliki
metode input perangkat lunak. Metode seperti itu tidak harus berbasis tombol; sebagian mungkin menggunakan input suara, tulisan tangan, dan seterusnya. Meskipun
metode input menyajikan antarmuka seperti keyboard, itu umumnya <strong>tidak</strong> memicu keluarga kejadian
<code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>. Anda sama sekali tidak boleh
membangun UI yang mengharuskan penekanan tombol tertentu dikontrol kecuali jika Anda ingin membatasi aplikasi Anda pada perangkat yang memiliki
keyboard fisik. Khususnya, jangan mengandalkan metode ini untuk memvalidasi input saat pengguna menekan tombol
enter; melainkan, gunakan tindakan seperti {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE} untuk menandai
metode input mengenai reaksi yang diharapkan aplikasi Anda, sehingga bisa mengubah UI-nya secara signifikan. Hindari anggapan
tentang bagaimana metode input perangkat lunak seharusnya bekerja dan percayalah bahwa metode akan menyediakan teks yang sudah diformat bagi aplikasi Anda.</p>
<p class="note"><strong>Catatan:</strong> Android akan memanggil event handler terlebih dahulu kemudian handler
default yang sesuai dari definisi kelas. Karena itu, mengembalikan <em>benar</em> dari event listener ini akan menghentikan
penyebaran kejadian ke event listener lain dan juga akan memblokir callback ke
event handler default di View. Pastikan bahwa Anda ingin mengakhiri kejadian saat mengembalikan <em>true</em>.</p>
<h2 id="EventHandlers">Event Handler</h2>
<p>Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa
metode callback sebagai event handler default.
Dalam dokumen tentang <a href="{@docRoot}guide/topics/ui/custom-components.html">Komponen
Custom</a>, Anda akan melihat penggunaan beberapa callback umum untuk penanganan kejadian,
termasuk:</p>
<ul>
<li><code>{@link android.view.View#onKeyDown}</code> - Dipanggil bila terjadi kejadian tombol baru.</li>
<li><code>{@link android.view.View#onKeyUp}</code> - Dipanggil bila terjadi kejadian tombol naik.</li>
<li><code>{@link android.view.View#onTrackballEvent}</code> - Dipanggil bila terjadi kejadian gerakan trackball.</li>
<li><code>{@link android.view.View#onTouchEvent}</code> - Dipanggil bila terjadi kejadian gerakan layar sentuh.</li>
<li><code>{@link android.view.View#onFocusChanged}</code> - Dipanggil bila View memperoleh atau kehilangan fokus.</li>
</ul>
<p>Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View,
namun bisa berdampak langsung pada kemampuan Anda menangani kejadian. Jadi, saat mengelola kejadian yang lebih kompleks dalam
layout, pertimbangkanlah metode-metode lain ini:</p>
<ul>
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
Activity.dispatchTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
android.app.Activity} Anda mencegat semua kejadian sentuh sebelum dikirim ke jendela.</li>
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
android.view.ViewGroup} memantau kejadian saat dikirim ke View anak.</li>
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Panggil ini
pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan <code>{@link
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
</ul>
<h2 id="TouchMode">Mode Sentuh</h2>
<p>
Saat pengguna menyusuri antarmuka pengguna dengan tombol pengarah atau trackball, Anda
perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa mengetahui apa
yang akan menerima input. Akan tetapi jika perangkat memiliki kemampuan sentuh, dan pengguna
mulai berinteraksi dengan antarmuka dengan menyentuhnya, maka Anda tidak perlu lagi
menyorot item, atau memfokuskan pada View tertentu. Karena itu, ada mode
untuk interaksi yang bernama "mode sentuh".
</p>
<p>
Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat
akan masuk ke mode sentuh. Dari sini dan selanjutnya, hanya View dengan
{@link android.view.View#isFocusableInTouchMode} benar yang akan dapat difokus, seperti widget pengedit teks.
View lain yang dapat disentuh, seperti tombol, tidak akan difokus bila disentuh; View ini akan
langsung memicu on-click listener bila ditekan.
</p>
<p>
Kapan saja pengguna menekan tombol pengarah atau menggulir dengan trackball, perangkat akan
keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bisa melanjutkan interaksi
dengan antarmuka pengguna tanpa menyentuh layar.
</p>
<p>
Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas).
Untuk query status saat ini, Anda bisa memanggil
{@link android.view.View#isInTouchMode} untuk mengetahui apakah perangkat saat ini sedang dalam mode sentuh.
</p>
<h2 id="HandlingFocus">Menangani Fokus</h2>
<p>Kerangka kerja ini akan menangani gerakan fokus rutin sebagai respons input pengguna.
Ini termasuk mengubah fokus saat View dihapus atau disembunyikan, atau saat tersedia View
baru. View menunjukkan kesediaannya untuk mengambil fokus
melalui metode <code>{@link android.view.View#isFocusable()}</code>. Untuk mengubah apakah View bisa mengambil
fokus, panggil <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. Saat dalam mode sentuh,
Anda dapat me-query apakah View memungkinkan fokus dengan <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
Anda bisa mengubahnya dengan <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
</p>
<p>Gerakan fokus berdasarkan pada algoritma yang mencari tetangga terdekat dalam
arah yang diberikan. Dalam kasus yang jarang terjadi, algoritma default mungkin
tidak cocok dengan perilaku yang diinginkan pengembang. Dalam situasi ini, Anda bisa memberikan
pengesampingan eksplisit dengan mengikuti atribut XML berikut dalam file layout:
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, dan
<var>nextFocusUp</var>. Tambahkan salah satu atribut ini ke View <em>dari</em> mana fokus
meninggalkan. Definisikan nilai atribut untuk menjadi ID View
<em>ke</em> mana fokus harus diberikan. Misalnya:</p>
<pre>
&lt;LinearLayout
android:orientation="vertical"
... >
&lt;Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
&lt;Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
&lt;/LinearLayout>
</pre>
<p>Biasanya, dalam layout vertikal ini, navigasi ke atas dari Button pertama tidak akan membawa ke
mana pun, tidak pula akan menyusuri ke bawah dari Button kedua. Karena sekarang Button atas telah
mendefinisikan Button bawah sebagai <var>nextFocusUp</var> (dan sebaliknya), fokus navigasi akan
silih berganti dari atas ke bawah dan bawah ke atas.</p>
<p>Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus),
tambahkan atribut XML <code>android:focusable</code> ke View, dalam deklarasi layout Anda.
Atur nilai <var>true</var>. Anda juga bisa mendeklarasikan View
sebagai dapat difokus saat dalam Mode Sentuh dengan <code>android:focusableInTouchMode</code>.</p>
<p>Untuk meminta View tertentu difokus, panggil <code>{@link android.view.View#requestFocus()}</code>.</p>
<p>Untuk mendengarkan kejadian fokus (diberi tahu bila View menerima atau kehilangan fokus), gunakan
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>
, seperti yang dibahas di bagian <a href="#EventListeners">Event Listener</a>, di atas.</p>
<!--
<h2 is="EventCycle">Event Cycle</h2>
<p>The basic cycle of a View is as follows:</p>
<ol>
<li>An event comes in and is dispatched to the appropriate View. The View
handles the event and notifies any listeners.</li>
<li>If, in the course of processing the event, the View's bounds may need
to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
<li>Similarly, if in the course of processing the event the View's appearance
may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
<li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
the framework will take care of measuring, laying out, and drawing the tree
as appropriate.</li>
</ol>
<p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
the UI thread when calling any method on any View.
If you are doing work on other threads and want to update the state of a View
from that thread, you should use a {@link android.os.Handler}.
</p>
-->

View File

@@ -1,181 +0,0 @@
page.title=Direct Boot
page.keywords=pratinjau,sdk,direct boot
page.tags=androidn
page.image=images/cards/card-nyc_2x.jpg
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#run">Meminta Akses untuk Berjalan Selama Direct Boot</a></li>
<li><a href="#access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</a></li>
<li><a href="#notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</a></li>
<li><a href="#migrating">Migrasi Data yang Ada</a></li>
<li><a href="#testing">Menguji Aplikasi Peka Enkripsi Anda</a></li>
</ol>
</div>
</div>
<p>Android N berjalan dalam mode <i>Direct Boot</i> yang aman
bila perangkat telah dihidupkan namun pengguna tidak membuka
kunci perangkat. Untuk mendukung hal ini, sistem menyediakan dua lokasi penyimpanan untuk data:</p>
<ul>
<li><i>Penyimpanan yang dienkripsi dengan kredensial</i>, yang merupakan lokasi penyimpanan default
dan hanya tersedia setelah pengguna membuka kunci perangkat.</li>
<li><i>Penyimpanan yang dienkripsi dengan perangkat</i>, yang merupakan lokasi penyimpanan yang tersedia
selama mode Direct Boot dan setelah pengguna membuka kunci perangkat.</li>
</ul>
<p>Secara default, aplikasi tidak berjalan selama mode Direct Boot.
Jika aplikasi Anda perlu melakukan tindakan selama mode Direct Boot, Anda bisa mendaftarkan
komponen aplikasi yang harus dijalankan selama mode ini. Beberapa kasus penggunaan umum
untuk aplikasi yang perlu dijalankan selama mode Direct Boot antara lain:</p>
<ul>
<li>Aplikasi yang telah menjadwalkan pemberitahuan, seperti aplikasi
beker.</li>
<li>Aplikasi yang menyediakan pemberitahuan pengguna yang penting, seperti aplikasi SMS.</li>
<li>Aplikasi yang menyediakan layanan aksesibilitas, seperti TalkBack.</li>
</ul>
<p>Jika aplikasi Anda perlu mengakses data saat dijalankan dalam mode Direct Boot, gunakan
penyimpanan yang dienkripsi dengan perangkat. Penyimpanan yang dienkripsi dengan perangkat berisi data
yang dienkripsi dengan kunci yang hanya tersedia setelah perangkat melakukan
booting yang berhasil diverifikasi.</p>
<p>Untuk data yang harus dienkripsi dengan kunci yang dikaitkan dengan kredensial
pengguna, seperti PIN atau kata sandi, gunakan penyimpanan yang dienkripsi dengan kredensial.
Penyimpanan yang dienkripsi dengan kredensial hanya tersedia setelah pengguna berhasil
membuka kunci perangkat, hingga saat pengguna menghidupkan ulang perangkat lagi. Jika
pengguna mengaktifkan layar kunci setelah membuka kunci perangkat, hal ini tidak akan mengunci
penyimpanan yang dienkripsi dengan kredensial.</p>
<h2 id="run">Meminta Akses untuk Berjalan Selama Direct Boot</h2>
<p>Aplikasi harus mendaftarkan komponennya pada sistem agar
bisa berjalan selama mode Direct Boot atau mengakses
penyimpanan yang dienkripsi dengan perangkat. Aplikasi mendaftar pada sistem dengan menandai komponen sebagai
<i>peka enkripsi</i>. Untuk menandai komponen Anda sebagai peka enkripsi, setel atribut
<code>android:directBootAware</code> ke true dalam manifes Anda.<p>
<p>Komponen yang peka enkripsi bisa mendaftar untuk menerima pesan siaran
<code>LOCKED_BOOT_COMPLETED</code> dari
sistem bila perangkat telah dihidupkan ulang. Pada tahap ini
penyimpanan yang dienkripsi dengan perangkat akan tersedia, dan komponen Anda bisa mengeksekusi tugas-tugas yang perlu
dijalankan selama mode Direct Boot, seperti memicu alarm yang terjadwal.</p>
<p>Cuplikan kode berikut adalah contoh cara mendaftarkan
{@link android.content.BroadcastReceiver} sebagai peka enkripsi, dan menambahkan sebuah
filter intent untuk <code>LOCKED_BOOT_COMPLETED</code>, dalam manifes aplikasi:</p>
<pre>
&lt;receiver
android:directBootAware="true" &gt;
...
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /&gt;
&lt;/intent-filter&gt;
&lt;/receiver&gt;
</pre>
<p>Setelah pengguna membuka kunci perangkat, semua komponen bisa mengakses
penyimpanan yang dienkripsi dengan perangkat serta penyimpanan yang dienkripsi dengan kredensial.</p>
<h2 id="access">Mengakses Penyimpanan yang Dienkripsi dengan Perangkat</h2>
<p>Untuk mengakses penyimpanan yang dienkripsi dengan perangkat, buat instance
{@link android.content.Context} kedua dengan memanggil
<code>Context.createDeviceProtectedStorageContext()</code>. Semua panggilan
API penyimpanan yang dibuat menggunakan konteks ini mengakses penyimpanan yang dienkripsi dengan perangkat. Contoh
berikut mengakses penyimpanan yang dienkripsi dengan perangkat dan membuka file data aplikasi
yang ada:</p>
<pre>
Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...
</pre>
<p>Gunakan penyimpanan yang dienkripsi dengan perangkat hanya untuk
informasi yang harus bisa diakses selama mode Direct Boot.
Jangan gunakan penyimpanan yang dienkripsi dengan perangkat sebagai penyimpanan terenkripsi serba guna.
Untuk informasi pengguna yang bersifat pribadi, atau data terenkripsi yang tidak diperlukan selama
mode Direct Boot, gunakan penyimpanan yang dienkripsi dengan kredensial.</p>
<h2 id="notification">Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci</h2>
<p>Setelah pengguna membuka kunci perangkat setelah restart, aplikasi Anda bisa beralih untuk
mengakses penyimpanan yang dienkripsi dengan kredensial dan menggunakan layanan sistem biasa yang
bergantung pada kredensial pengguna.</p>
<p>Agar diberi tahu bila pengguna membuka kunci perangkat setelah boot ulang,
daftarkan {@link android.content.BroadcastReceiver} dari komponen yang berjalan
untuk mendengarkan pesan <code>ACTION_USER_UNLOCKED</code>. Atau, Anda bisa
menerima pesan {@link android.content.Intent#ACTION_BOOT_COMPLETED
ACTION_BOOT_COMPLETED} yang ada, yang sekarang menunjukkan bahwa perangkat telah dihidupkan dan
pengguna telah membuka kunci perangkat.</p>
<p>Anda bisa langsung kueri apakah pengguna telah membuka kunci perangkat dengan memanggil
<code>UserManager.isUserUnlocked()</code>.</p>
<h2 id="migrating">Migrasi Data yang Ada</h2>
<p>Jika pengguna memperbarui perangkat mereka untuk menggunakan mode Direct Boot,
data Anda yang ada mungkin perlu dipindahkan ke penyimpanan yang dienkripsi dengan perangkat. Gunakan
<code>Context.moveSharedPreferencesFrom()</code> dan
<code>Context.moveDatabaseFrom()</code> untuk memindahkan data preferensi dan
basis data antara penyimpanan yang dienkripsi dengan kredensial dan penyimpanan yang dienkripsi dengan perangkat.</p>
<p>Pertimbangkan dengan baik saat memutuskan data apa yang akan dipindahkan dari
penyimpanan yang dienkripsi dengan kredensial ke penyimpanan yang dienkripsi dengan perangkat. Anda sebaiknya tidak memindahkan
informasi pengguna yang bersifat rahasia, seperti kata sandi atau token otorisasi, ke
penyimpanan yang dienkripsi dengan perangkat. Dalam beberapa skenario, Anda mungkin perlu mengelola
set data terpisah pada dua tempat penyimpanan yang dienkripsi.</p>
<h2 id="testing">Menguji Aplikasi Peka Enkripsi Anda</h2>
<p>Uji aplikasi peka enkripsi Anda menggunakan mode Direct Boot baru. Ada
dua cara untuk mengaktifkan Direct Boot.</p>
<p class="caution"><strong>Perhatian:</strong> Mengaktifkan Direct Boot
akan menghapus semua data pengguna pada perangkat.</p>
<p>Pada perangkat yang didukung dengan Android N terpasang, aktifkan
Direct Boot dengan melakukan salah satu hal berikut:</p>
<ul>
<li>Pada perangkat, aktifkan <b>Developer options</b> jika Anda belum melakukannya dengan
masuk ke <b>Settings &gt; About phone</b>, dan menyentuh <b>Build number</b>
tujuh kali. Setelah layar Developer options terbuka, masuk ke
<b>Settings &gt; Developer options</b> dan pilih
<b>Convert to file encryption</b>.</li>
<li>Gunakan perintah shell adb berikut untuk mengaktifkan mode Direct Boot:
<pre class="no-pretty-print">
$ adb reboot-bootloader
$ fastboot --wipe-and-use-fbe
</pre>
</li>
</ul>
<p>Mode emulasi Direct Boot juga tersedia, jika Anda perlu mengganti
mode pada perangkat pengujian. Mode emulasi sebaiknya hanya digunakan selama
pengembangan dan bisa menyebabkan kehilangan data. Untuk mengaktifkan mode emulasi Direct Boot,
setel pola kunci pada perangkat, pilih "No thanks" jika ditanya mengenai
layar start-up aman saat menetapkan pola kunci, kemudian gunakan
perintah shell adb berikut:</p>
<pre class="no-pretty-print">
$ adb shell sm set-emulate-fbe true
</pre>
<p>Untuk menonaktifkan mode emulasi Direct Boot, gunakan perintah berikut:</p>
<pre class="no-pretty-print">
$ adb shell sm set-emulate-fbe false
</pre>
<p>Menggunakan perintah ini akan menyebabkan perangkat melakukan boot ulang.</p>

Some files were not shown because too many files have changed in this diff Show More