domingo, 30 de diciembre de 2007

Desarrollando aplicaciones - Bloques de construcción de Android

Documento original: Android Building Blocks

Bloques de construcción de Android

[Título original: Android Building Blocks]

Puedes ver una aplicación Android como una colección de componentes de varios tipos. Estos componentes en su mayoría tienen un bajo nivel de acloplamiento entre ellos, a tal grado que te permiten describirlos de manera muy precisa como una federación de componentes más que un aplicación como un todo.

Por lo general, todos estos componentes corren en el mismo proceso del sistema. Es posible (y muy común) crear múltiples "thread"s dentro de tal proceso, y además es posible crear procesos hijos completamente separados del proceso padre, si es que tú lo llegaras a necesitar. Estos últimos casos son poco comunes ya que Android trata en lo posible de hacer los procesos lo más transparente en tu código.

Estas son las partes más importantes de las APIs de Android:

  • AndroidManifest.xml : El archivo "AndroidManifest.xml" es el archivo de control que le dice al sistema qué es lo que debe hacer con los componentes de más alto nivel que tú haz creado (específicamente "Actividad", "Servicio", "Receptor de Intentos" y "Proveedor de Contenidos" descritos a continuación). Debido a esto, este archivo es considerado el "pegamento" que indica qué "Intent" serán recibidos por tus "Activity.

  • Actividad : Una "Activity" es, fundamentalmente, un objeto que tiene un ciclo de vida. Una "Activity" es un trozo de código que hace algún trabajo. Si fuera necesario, este trabajo puede incluir el despliegue de una UI al usuario. Sin embargo, lo anterior no es necesario y algunas "Activity" nunca despliegan una UI. Típicamente, tú designarás una de las "Activity" de tu aplicación como el punto de inicio de tu aplicación.

  • Vista : Una "View" es un objeto que sabe cómo dibujarse asimismo en la pantalla. Las interfaces de usuario de Android están conforman un árbol de "View". Si tú quieres realizar algún tipo de técnica gráfica especial entonces deberás crear una "View" (este es el caso en el cual tú quisieras crear un juego o construir un nuevo tipo de interface de usuario)

  • Intento : Un "Intent" es un simple mensaje que representa "la intención" de hacer algo. Por ejemplo, si tu aplicación quiere abrir una página web, debe expresar su "Intento" para ver la URI a través de la creación de una instancia de "Intent" y luego entregársela al sistema. Posteriormente, el sistema ubicará una pieza de código que sepa cómo manipular aquel "Intento" y la ejecuta (en este caso un browser). Los "Intent" también pueden ser usados para difundir eventos interesantes a través de todo el sistema (tales como notificaciones).

  • Servicio : Un "Service" es un cuerpo de código que se ejecuta en segundo plano. Se ejecuta dentro de su propio proceso o en el contexto del proceso de otra aplicación, dependiendo de sus necesidades. Otros componentes se "atan" a un "Servicio" e invocan sus métodos a través de "llamados remotos de procedimientos (RPC)". Un ejemplo de un "Service" es un reproductos de música. En este caso, el usuario podría usar una UI para seleccionar la música y posteriormente cerrar la UI, pero la música deberá continuar sonando. Esto se logra usando un "Servicio" que continuará la reproducción de la música.

  • Notificación : Una notificación es un pequeño ícono que aparece en la barra de estado. Los usuarios pueden interactuar con este ícono para recibir información. Las notificaciones más conocidas son los mensajes SMS, correo de voz; pero las aplicaciones pueden crear sus propias notificaciones. Las notificaciones son el mecanismo preferido para alertar al usuario que algo requiere de su atención.

  • Proveedor de Contenidos : Un "ContentProvider" es un almacen de datos que provee acceso a datos en el dispositivo. Un ejemplo clásico es el "ContentProvider" que es usado para tomar datos desde la lista de contactos. Tu aplicación puede utilizar datos que otras aplicaciones han expuesto vía un "ContentProvider". Tú también puede definir tus propios "ContentProvider" para así exponer tus propios datos.

  • viernes, 21 de diciembre de 2007

    Desarrollando aplicaciones - Escuchando notificaciones de la UI

    Documento original: Listening for UI Notifications

    Escuchando notificaciones de la UI

    [Título original: Listening for UI Notifications]

    Algunas notificaciones de la UI son automáticamente expuestas y llamadas por Android. Por ejemplo, una "Activity" sobreescribe los métodos "onKeyDown" y "onKeyUp" y "TextView" expone "onFocusChanged(boolean, int)". Sin embargo, algunos métodos "callbacks", tales como clic de botones no son expuestos de manera nativa y deben ser registrados manualmente como se muestra a continuación.

    public class SendResult extends Activity
    {
    /**
    * Initialization of the Screen after it is first created. Must at least
    * call setContentView() to
    * describe what is to be displayed in the screen.
    */
    protected void onCreate(Bundle savedValues)
    {
    ...

    // Listen for button clicks.
    Button button = (Button)findViewById(R.id.corky);
    button.setOnClickListener(mCorkyListener);
    }

    // Create an anonymous class to act as a button click listener.
    private OnClickListener mCorkyListener = new OnClickListener()
    {
    public void onClick(View v)
    {
    // To send a result, simply call setResult() before your
    // activity is finished.
    setResult(RESULT_OK, "Corky!");
    finish();
    }
    };

    Desarrollando aplicaciones - Enganchando un elemento de la pantalla

    Documento original: Hooking into a Screen Element

    Enganchando un elemento de la pantalla

    [Título original: Hooking into a Screen Element]

    Tú puedes obtener una referencia a un elemento de la pantalla llamando al método "Activity.findViewById()". Posteriormente, puedes usar esta referencia para modificar o recuperar valores expuestos por ese elemento.

    TextView msgTextView = (TextView)findViewById(R.id.msg);
    msgTextView.setText(R.string.push_me);

    Desarrollando aplicaciones - Definiendo tu pantalla con XML

    Documento original: Designing Your Screen in XML

    Definiendo tu pantalla con XML

    [Título original: Designing Your Screen in XML]

    Debido a que el diseño de una pantalla a través de código puede resultar muy engorroso, Android soporta una sintaxis XML para diseñar pantallas. Android define un gran número de elementos especialmente hechos para la plataforma, cada uno de ellos representando una subclase específica de Android View. Tú puedes diseñar tu pantalla de la misma forma en la que tú crear archivos HTML, es decir, como una serie de etiquetas anidades y guardadas en un archivo XML dentro del directorio "res/layout/" de tu aplicación. Para aprender qué elementos son expuestos y el formato del archivo XML lee el documento "Available Resource Types" y en especial la sección "Layout Resources". Cada etiqueta describe un único elemento "android.view.View", pero este elemento puede ser un simple elemento visual o un elemento de esquema que contiene una colección de objetos hijos (una pantalla o una porción de ella). Cuando Android compila tu aplicación, compila cada archivo en un "android.view.View" recurso que tú puedes cargar en tu código llamando al método "setContentView(R.layout.layout_file_name)" dentro de la implementación que hagas del método "onCreate()" de tu "Activity".

    Cada archivo XML esta formado por etiquetas que corresponden a clases GUI de Android. Estas etiquetas tienen atributos que en su mayoría corresponden a métodos en esa clase (por ejemplo, la etiqueta "EditText" tiene un atributo de texto que corresponde al método "setText()" de la clase "EditText").

    NOTA: No existe una correspondencia exacta entre nombres de clase/métodos y nombres de etiquetas/atributos. Son parecidos por no 1:1

    NOTA: Android tiende a dibujar los elementos en el orden en el cual aparecen en el documento XML. Por lo tanto, if hay elementos que se sobreponen, el último en el archivo será probablemente el que aparezca sobre cualquier otro que esté previamente declarado en su mismo espacio.

    Cada archivo XML es compilado dentro de un árbol que tiene como raíz un objeto "View" o "ViewGroup", por lo tanto debe tener una sola etiqueta raíz.

    Los atributos llamados "layout_algo" modifican el miembro "algo" del objeto "LayoutParams". El documento "Layout Resources" también describe cómo aprender la sintaxis para algunas propiedades específicas de "LayoutParams".

    Los siguientes valores son soportados para dimensiones (descritos en "TypedValue").

  • dip (pixeles independientes del dispositivo)

  • sp (pixeles escalados - mejor opción para tamaño de texto)

  • pt (puntos)

  • in (pulgadas)

  • mm (milimetros)

  • px (pixeles)

  • Ejemplo: android:layout_width="25px"

    Para más información sobre estas dimensiones, ver "Dimension Values".

    El siguiente archivo XML crea la pantalla que es mostrada debajo de él. El texto en el borde superior fue dibujado llamando al método "setTitle()" de la clase "Activity". Los atributos que se refieren elementos relativos ("layout_toLeft") hacen uso del ID del elemento usando la sintaxis de recursos relativos ("@id/id_number").

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Demonstrates using a relative layout to create a form -->
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/blue"
    android:padding="10px">

    <TextView id="@+id/label"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Type here:"/>

    <EditText id="@+id/entry"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:drawable/editbox_background"
    android:layout_below="@id/label"/>

    <Button id="@+id/ok"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/entry"
    android:layout_alignParentRight="true"
    android:layout_marginLeft="10px"
    android:text="OK" />

    <Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeft="@id/ok"
    android:layout_alignTop="@id/ok"
    android:text="Cancel" />
    </RelativeLayout>
    Figura:http://code.google.com/android/images/designing_ui_layout_example.png

    Cargando los recursos XML

    [Título original: Loading the XML Resource]

    Cargar y compilar los recursos del esquema de tu pantalla es muy sencillo y es hecho en un simple llamado dentro método "onCreate()", tal como se muestra a continuación:

    protected void onCreate(Bundle savedValues)
    {
    // Be sure to call the super class.
    super.onCreate(savedValues);

    // Load the compiled layout resource into the window's
    // default ViewGroup.
    // The source file is res/layout/hello_activity.xml
    setContentView(R.layout.hello_activity);

    // Retrieve any important stored values.
    restoreValues(savedValues);
    }

    Desarrollando aplicaciones - Trabajando con AdapterView

    Documento original: Working with AdapterViews (Binding to Data)

    Trabajando con AdapterViews (asociando datos a vistas)

    [Título original: Working with AdapterViews (Binding to Data) ]

    Como se mencionón, algunos grupos de vistas tienen UI. Estos objetos tipicamente son subclases de "AdapterView". Algunos ejemplos son "Gallery" (una "widget" con un selección de imágenes) y "ListView" (una lista de vistas. Estos objetos hacen dos tareas en común:

  • Llenar el esquema con datos.

  • Manipular las selecciones del usuario.

  • Llenando el esquema con datos

    [Título original: Filling the layout with data]

    Esto es típicamente hecho a través de la asociación de la clase con un "Adapter" que toma los datos de alguna parte: una lista que el código suministra o el resultado de una consulta a una base de datos del dispositivo.

    // Get a Spinner and bind it to an ArrayAdapter that 
    // references a String array.
    private String[] fruit = {"apples", "oranges", "lemons"}
    Spinner s1 = (Spinner)findViewById(R.id.fruitlist);
    s1.setAdapter(new ArrayAdapter<String>(this, R.layout.spinner_1, mStrings));

    // Load a Spinner and bind it to a data query.
    private String[] cols={android.provider.Contacts.PeopleColumns.NAME};
    private Cursor cur = managedQuery(android.provider.Contacts.People.CONTENT_URI, cols, null, null);
    s2.setAdapter(new CursorAdapter(cur, this));

    Manipular las selecciones del usuario

    [Título original: Handling user selections]

    Esto es hecho al asignar al miembro "AdapterView.OnItemClickListener" de la clase un objeto escuchador de eventos y capturar los cambios que el usuario hace en su selección.

    // 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)
    {
    // Display a messagebox.
    showAlert("You've got an event", "Clicked me!", "ok", false);
    }
    };

    // Now hook into our object and set its onItemClickListener member
    // to our class handler object.
    mHistoryView = (ListView)findViewById(R.id.history);
    mHistoryView.setOnItemClickListener(mMessageClickedHandler);

    martes, 18 de diciembre de 2007

    Desarrollando aplicaciones - Objetos comunes de esquema

    Documento original: Common Layout Objects

    Objetos comunes de esquema

    [Título original: Common Layout Objects]

    Los siguientes son los grupos de vistas más comunes que tú vas a usar en tus aplicaciones. Esta sección te entregará la información básica sobre cada uno de ellos. Para estudiar en más profundidad cada uno de ellos, puedes seleccionar el link que cada elemento provee.

    FrameLayout

    [Título original: FrameLayout]

    Un FrameLayout es el objeto de esquema más sencillo. Está expresamente diseñado como un espacio en blanco reservado en la pantalla que posteriormente podrás llenar con un único objeto, por ejemplo una fotografía cuya imagen será intercambiada. Todos los elementos hijos son posicionados en la parte superior izquierda de la pantalla. No es posible establecer una posición determinada para un elemento hijo de FrameLayout. Elementos hijos que posteriormente se agreguen serán simplemente dibujados sobre elementos que previamente hayan sido dibujados, lo que bloqueará su visión total o parcialmente (a menos que los nuevos elementos sean transparentes).

    LinearLayout

    [Título original: LinearLayout]

    Un LinearLayout alinea todos sus elementos hijos en una única dirección: vertical u horizontal, de acuerdo a qué propiedad tú definiste para LinearLayout. Todos los hijos son ubicados uno al lado del otro, por lo tanto una lista vertical sólo tendrá un hijo por fila sin importar cuan ancha sea la fila. De manera similar, un lista horizontal sólo tendrá un fila de alto (la altura del hijo más alto más el espacio de relleno definido, ie, "padding"). El LinearLayout respeta los márgenes entre hijos y también su gravedad (alineamiento del hijo hacia la derecha, centro o izquierda).

    El LinearLayout también soporta la asignación de peso a hijos de manera individual. Este peso, permite a los hijos expandirse para llenar cualquier espacio restante de la pantalla. Esto previene que una lista de pequeños objetos sea confinada hacia uno de los extremos de una pantalla grande y por el contrario se expanda para llenar todo el espacio disponible. El peso que los hios tienen especificado es utilizado para distribuir cualquier espacio restante en la misma proporción de su peso declarado. El valor por omisión del peso de un hijo es cero. Por lo ejemplo, si hay tres casillas de texto, y dos de ellas declaran un un peso de 1, dos de ellas se expandirán de con la misma proporción para llenar el espacio restante, y la tercera no crecerá ninguna cantidad adicional.

    Las imágenes de los formularios mostrados a continuación representan un LinearLayout con un conjunto de elementos: un botón, algunas etiquetas de texto y algunas casillas de texto. Ambos tienen definido valores para relleno de contorno, para así mantener un contorno que proporciona un agradable distribución. Las casillas de texto tienen sus anchos fijados al valor "FILL_PARENT", otros elementos lo tienen fijado a "WRAP_CONTENT". Por omisión, el valor de la gravedad es fijado a izquierda ("left"). El formulario de la izquierda no tiene valores de peso fijados, por lo tanto todos sus hijos tienen el valor cero (valor por omisión). El formulario de la derecha tiene fijado el valor del peso de la casilla de texto de comentarios a "1". Si el peso de la casilla de texto para el nombre hubiese sido fijado a "1", las casillas de texto para el nombre y los comentarios hubiesen tenido la misma altura.

    CONSEJO: Para crear un esquema de tamaño proporcionado en la pantalla, crea un objeto contenedor que sea "fill_parent", luego asigna la altura y ancho de los hijos a cero y finalmente asigna los valores de peso relativos a cada hijo dependiendo de la proporción que cada uno de ellos debe ocupar en la pantalla

    Figura:http://code.google.com/android/images/linearlayout.png

    Dentro de un LinearLayout, los items son alineados por la posición de sus líneas base del texto (la primera línea del primer elemento,i.e., la más alta o más a la izquierda es la línea considerada como referencia). Esto es así para evitar que las personas al llenar un formulario tengan que buscar un elemento en elementos vecinos. Esta característica puede ser desactivada agregando android:baselineAligned="false" en tu esquema XML.

    TableLayout

    [Título original: TableLayout]

    Un "TableLayout" posiciona sus hijos dentro de filas y columnas. Un "TableLayout" está compuesto por un número de objetos "TableRow", cada uno de ellos definiendo una fila (más adelante explicaremos que también es posible tener otros elementos hijos). Los contenedores "TableLayout" no despliegan contornos para sus filas, columnas y celdas. Cada fila tiene cero o mas celdas, y cada celda puede contener un objeto ""View"". Una tabla puede tener tantas columnas como lo tenga la fila con más celdas. Una tabla puede tener celdas vacías. Las celdas no pueden extenderse a otras columnas, como lo hace HTML. La siguiente imagen muestra un esquema de tabla en la cual los border invisibles son mostrados con líneas punteadas.

    Figura:http://code.google.com/android/images/table_layout.png

    Las columnas pueden estar ocultas, ser marcadas para estirarse y ocupar todo el espacio disponible, o marcadas para comprimirse hasta que la tabla se ajuste al tamaño de la pantalla. Encontrarás más información en el siguiente link: TableLayout

    AbsoluteLayout

    [Título original: AbsoluteLayout]

    El "AbsoluteLayout" permite que los elementos hijos especifiquen con precisión las coordenadas "x" e "y" en la cual deben ser desplegados. La posición (0,0) corresponde a la esquina superior izquierda, y sus valores se incrementan en la medida que tu avanzan hacia abajo y a la derecha. Márgenes no son soportados y el solapamiento de elementos está permitido (pero no es recomendado). La recomendación general es no usar "AbsoluteLayout" a menos que tengas una muy buena razón para usarlo, porque este esquema es muy rígido y no funciona bien en todos los dispositivos.

    RelativeLayout

    [Título original: ]

    El esquema "RelativeLayout" permite que sus elementos hijos espeficiquen su posición relativa entre ellos(indicando un ID) o con su padre. De esta forma, puedes alinear dos elementos por su contorno derecho, o poner uno debajo de otros, o centrarlo en la pantalla. Los elementos son dibujados en un order dado, de tal forma que si el primer elemento está centrado en la pantalla los otros elementos se alinearán considerando su posición relativa al centro de la pantalla. Si estás usando XML para describir el esquema de pantalla (como se describirá más adelante), un elemento referenciado debe ser declarado antes de hacer referencia a él.

    Aquí hay un ejemplo de un esquema relativo destacando los elementos invisibles y visibles. El objeto raíz del esquema de la pantalla es un "RelativeLayout".

    Figura:http://code.google.com/android/images/designing_ui_relative_layout.png

    Este diagrama muestra los nombres de las clases de los elementos en la pantalla, seguido por una lista de las propiedades de cada uno de ellos. Algunas de estas propiedades son soportadas directamente por los elementos y otras son soportadas por su miembro "LayoutParams" (una subclase de "RelativeLayout" en todos los elementos de esta pantalla, debido a que todos los elementos son hijos del objeto padre "RelativeLayout"). Los parámetros de "RelativeLayout" son: "width", "height", "below", "alignTop", "toLeft", "padding" y "marginLeft". Se debe observar que algunos de estos parámetros soportan valores relativos a otros hijos, de ahí viene el nombre "RelativeLayout". Esto incluye las propiedades "toLeft", "alignTop" y "below", las cuales referencian al objeto de la izquierda, de arriva y de abajo; respectivamente.

    Resumen de los grupos de vistas más importantes

    [Título original: Summary of Important View Groups]

    Todos estos objetos contienen elementos UI. Algunos proveen elementos UI visibles y otros sólo controlan el esquema de sus elementos hijos.

  • AbsoluteLayout : Permite que espeficiques la ubicación de los objetos hijos relativa al padre usando medidas exactas (por ejemplo, pixeles).

  • FrameLayout : Este esquema actúa como un marco que despliega sólo un objeto.

  • Gallery : Es un esquema para desplegar imágenes (tomadas de una lista) y tiene la capacidad para desplazar su contenido de manera horizontal.

  • GridView : Es un esquema cuadriculado de "n" filas por "m" columnas. Además, tiene capacidades para desplazar el contenido.

  • LinearLayout : Es un esquema que organiza sus elementos hijos dentro de una sólo fila, la cual puede ser horizontal o vertical.Crea una barra de desplazamiento si el tamaño de la cuadrícula excede el tamaño de la pantalla.

  • ListView : Es un esquema que despliega una lista dentro de una sola columna y tiene capacidad de desplazamiento del contenido.

  • PopupList : Es un esquema que despliega el contenido de una lista con bordes, de manera independiente y emergente

  • RelativeLayout : Este esquema permite que espeficiquemos la ubicación de sus elementos hijos relativa entre ellos (ejemplo: un elemento "A" al lado del elemento "B") o con el padre (por ejemplo: alineación con el borde superior del padre).

  • ScrollView : Es un esquema que despliega elementos en un columna vertical con capacidad de desplazamiento de contenido.

  • Spinner : Este esquema despliega un sólo elemento a la vez (tomado de una lista asociada) dentro de una casilla de texto de una fila. Este esquema es diferente de un esquema con una fila con capacidad para desplegar el contenido horizontalmente o verticalmente.

  • SurfaceView : Este esquema provee acceso directo a una superficie dedicada al dibujado. Puede contener elementos de vistas superpuestos sobre la superficie, pero está diseñado para aplicaciones que necesitan dibujar pixeles en vez de usar "widgets".

  • TabHost : Este esquema provee una lengüeta de selección que monitorea clics y permite que la aplicación cambie de pantalla en el momento en que la lengüeta es cliqueada.

  • TableLayout : Es un esquema tabular con un número arbitario de filas y columnas, cada una de las celdas contiene un "widget" de tu elección. Las filas ajustan su tamaño para ajustar la columna más grande. El contorno de las celdas no son visibles.

  • ViewFlipper : Es un esquema de despliega un elemento a la vez dentro de una casilla de texto de una fila. Puede ser configurado para intercambiar elementos a cierto intervalo de tiempo, como si fuera una presentación de diapositivas.

  • ViewSwitcher : Similar a ViewFlipper

  • lunes, 17 de diciembre de 2007

    Desarrollando aplicaciones - Jerarquía de los elementos de la pantalla

    Documento original: Hierarchy of Screen Elements

    Jerarquía de los elementos de la pantalla

    [Título original: Hierarchy of Screen Elements]

    La unidad funcional básica de una aplicación Android es la "Activity", el cual es un objeto de la clase "android.app.Activity". Una "Activity" puede hacer muchas cosas, pero por si misma ella no tiene presencia en la pantalla. Para otorgarle a tu "Activity" presencia en la pantalla y diseñar su interface de usuario, tienes que trabajar con "View" y "ViewGroup", las cuales son las unidades básicas de expresión de la interface de usuario en la plataforma Android.

    Vistas

    [Título original: Views]

    Una vista es un objeto cuya clase base es "android.view.View". Es una estructura de datos cuyas propiedades almacenan el esquema y contenido para una determinada área rectangular de la pantalla. Un objeto "View" manipula el dimensionamiento y esquema, realiza el pintado, controla los cambios de foco, desplazamiento de áreas y teclado/gestos para el área de la pantalla que representa.

    La clase "View" sirve de base para los "widgets", que son un conjunto de subclases implementadas completamente que dibujan elementos interactivos en la pantalla. Los "widgets" manipulan sus propios dimensionamientos y pintado, de tal forma que tú puedes usarlos para construir tus propias UI mucho más rápido. La lista de "widgets" disponibles incluye: "Text", "EditText", "InputMethod", "MovementMethod", "Button", "RadioButton", "Checkbox" y "ScrollView".

    Grupos de vistas

    [Título original: Viewgroups]

    Un "ViewGroup" es un objeto de la clase "android.view.Viewgroup". Como su nombre lo indica, un grupo de vistas es un tipo especial de objeto "View", cuya función es contener y administrar un conjunto subordinado de "View" y otros "ViewGroup". Los "ViewGroup" nos permiten agregar una estructura a nuestras "UI" y así construir elementos de pantalla mucho más complejos que puedan ser manipulados como un único elemento.

    La clase "ViewGroup" sirve de clase base para crear esquemas, los cuales son un conjunto de subclases implementadas completamente que provee de los tipos más comunes de elementos de pantalla. Los esquemas nos entregan una forma de construir una estructura para un conjunto de "View".

    Un árbol jeráquico de UI

    [Título original: A Tree-Structured UI]

    En la plataforma Android, tú puedes definir una "Activity" con UI usando un árbol de "View" y nodos de "ViewGroup", tal como lo muestra el diagrama que está a continuación. El árbol puede ser simple o complejo según tus necesidades, y puede ser construido usando un conjunto predefinido de "widgets" y elementos de Android o tipos de "View" con características especiales que tí hayas creado.

    Figura:http://code.google.com/android/images/viewgroup.png

    Para enlazar el árbol a la pantalla y así efectuar su visualización, nuestra actividad "Activity" llama a sus método "setContentView()" y pasa la referencia una referencia al objeto del nodo raíz. Una vez que el sistema Android tiene una referencia al objeto del nodo raíz, éste puede trabajar directamente con el nodo para invalidarlo, medirlo y dibujar el árbol. Cuando tú "Activity" se activa y recibe el foco, el sistema notifica a tu "Activity" y le solicita al nodo raíz que mida y dibuje el árbol. Entonces, el nodo raíz le solicita a sus nodos hijos que se dibujen así mismo, a su vez cada nodo de grupo de vistas del árbol es responsable de dibujar sus nodos hijos directos.

    Como se mencionó previamente, cada "ViewGroup" tiene la responsabilidad de medir su espacio disponible, posicionar sus hijos dentro del esquema y llamar al método "Draw()" por cada uno de sus hijos para que se dibujen asimismos. Los hijos podrían solicitar una ubicación y tamaño específico al padre, pero es el objeto padre quien tiene la última decisión con respecto a que tan grande cada hijo puede ser.

    LayoutParams: ¿Cómo especificar la posición y tamaño de un hijo?

    [Título original: LayoutParams: How a Child Specifies Its Position and Size]

    Cada "ViewGroup" usa una clase anidada que hereda de "ViewGroup.LayoutParams". Esta subclase contiene tipos de propiedades que definen el tamaño y posición de un hijo en propiedades que son apropiadas para esa clase de "ViewGroup".

    Figura:http://code.google.com/android/images/layoutparams.png

    NOTA: Cada subclase de "LayoutParams" tiene su propia sintaxis para asignar sus valores. Cada elemento hijo debe definir un "LayoutParams" que sea apropiado para su padre, aunque éste último podría definir un "LayoutParams" diferente para sus hijos.

    Todos los incluyen ancho y alto. Muchos incluso tienen márgenes y contorno. Tú puedes indicar un ancho y alto determinados, pero probablemente no lo harás de manera frecuente. Lo más probable es que dejarás que tu vista se auto dimensione al tamaño de sus contenidos o tan grande como el objeto que lo contiene lo permita.

    Desarrollando aplicaciones - Implementando la interface de usuario

    Documento original: Implementing a User Interface

    Implementando la interface de usuario

    [Título original: Implementing a User Interface]

    Esta sección describe las bases de cómo implementar la interface de usuario de una pantalla Android. Se describirán los elementos básicos para construir una pantalla, cómo definirla basada en un esquema XML y cómo cargarla en tu código. Además de varias otras tareas que tú vas a necesitar realizar en el diseño y desarrollo de la interface de usuario.

    Estos serán los tópicos abordados en esta sección:

  • Jerarquía de los elementos de la pantalla

  • Objetos comunes de esquema

  • Trabajando con AdapterViews (asociando datos a vistas)

  • Diseñando tu pantalla con XML

  • Enganchando un elemento de la pantalla

  • Escuchando notificaciones de la UI

  • Aplicando un tema a tu aplicación.

  • Elementos de UI y glosario de conceptos.

  • Desarrollando aplicaciones - Introducción

    Documento original: Developing Android Applications

    Desarrollando aplicaciones Android

    [Título original: Developing Android Applications]

    Tú puedes desarrollar una aplicación Android con el mismas herramientas de alta calidad que tú usas para desarrollar cualquier otra aplicación Java. Las "Android core libraries" proveen las funcionalidades necesarias para construir impresionantes y poderosas aplicaciones para dispositivos móviles, y las herramientas de desarrollo de Android para hacerla correr, depurar y testear muy rápidamente.

    Esta sección explica todos los detalles asociados con el desarrollo de aplicaciones Android y explica los delineamientos de la filosofía detrás del sistema y luego describe en detalle cada uno de los subsistemas claves. Después de leer esta sección tú tendrás el conocimiento y confidencia para comenzar a escribir cualquier aplicación Android que tengas en tu mente.

    Antes de leer esta sección tú deberías haber leído toda la sección "Manos a la obra", la cual te entrega la información necesaria para rápidamente impregnarte del "Android SDK" y mostrarte cómo construir tu primera aplicación y algunos tutoriales en los que aprenderás más sobre las aplicaciones Android. Esta sección está basada en la información entregada en "Manos a la obra".

    Aquí está el detalles de los contenidos que encontrarás en esta sección:

  • Implementando una "UI": esta sección explicará cómo construir e interactuar con las interfaces de usuario de las aplicaciones Android. Después de leer esta página tú vas a tener un sólido entendimiento de cómo los esquemas de pantalla son construidos, cómo ellos funcionan en tiempo de ejecución y cómo puedes cambiar su aspecto visual para mejorar su apariencia.

  • Bloques de construcción: esta sección contiene una descripción detallada de los componentes de Android. Cubre todos los pormenores de los componentes que fueron descritos en "Anatomía de una aplicación Android" y mucho más. Esta sección profundiza en los detalles de cada uno de los componentes claves de Andriod (Intent, Activity, View y eventos).

  • Almacenamiento y recuperación de datos: esta sección explica cómo leer y escribir datos desde/hacia varios mecanismos de almacenamiento provistos por Android y hacia servicios de red. Existen varias formas de leer y escribir datos desde una aplicación y cada uno de ellos está orientado a satisfaces diferentes necesidades. En esta sección encontrarás la descripción de todos ellos y la orientación necesaria para saber cual de ellos seleccionar en determinada situación.

  • Modelo de seguridad: esta sección explica cómo obtener acceso a los recursos y características del sistema de seguridad y cómo declarar los permisos necesarios para controlar el acceso a nuestras propias características de seguridad, es decir, el control de permisos que permiten que dada una aplicación sea pueda tener acceso a piezas de funcionalidad provistas por otra aplicación (por ejemplo, qué aplicación puede marcar un teléfono). Esta sección describe la forma en la cual los permisos funcionan y cómo solicitar los permisos que tú has definido.

  • Recursos e i18n: esta sección entrega información detallada del sistema de administración de los recursos y aplicaciones, incluyendo cómo es utilizado para propósitos de internalización y regionalización. Los "recursos" son el material que una aplicación necesita en tiempo de ejecución (tales como imágenes, cadenas de caracteres, archivos XML, etcétera). Esta sección describirá cómo Android resuelve cual recurso cargar desde una selección de ellos, y cómo crear y usar estos recursos.

  • ¿CÓMO HACER? - Reaccionar a un mensajes SMS

    Documento original: Recognize/React on incoming SMS

    En esta nota les explicaré el código documentado de una aplicación Android que reacciona a la recepción de la llegada de un mensaje SMS.

    SMSReceiver.java

    01 package com.northvortex.sms;
    02
    03 import android.app.NotificationManager;
    04 import android.content.Context;
    05 import android.content.Intent;
    06 import android.content.IntentReceiver;
    07 import android.os.Bundle;
    08 import android.provider.Telephony;
    09 import android.telephony.gsm.SmsMessage;
    10 import android.util.Log;
    11
    12 /**
    13 * android.content.IntentReceiver
    14 * Base class for code that will receive intents sent by broadcastIntent()...
    15 * http://code.google.com/android/reference/android/content/IntentReceiver.html
    16 *
    17 */
    18 public class SMSReceiver
    19 extends IntentReceiver
    20 {
    21 // Etiqueta usada para la bitacora.
    22 private static final String TAG_LOG = "SMSReceiver";
    23
    24 // Un numero aleatorio utilizado por la notificacion.
    25 private static final int ID_NOTIFICACION = 0x1221;
    26
    27 // Esta es la action que sera gatillada cuando un mensaje SMS es recibido.
    28 // Usamos la "Default Package-Visibility".
    29 private static final String ACCION = "android.provider.Telephony.SMS_RECEIVED";
    30
    31 /**
    32 * Este metodo es gatillado cuando se recibe el Intent que esperabamos.
    33 */
    34 @Override
    35 public void onReceiveIntent(Context parContext, Intent parIntent)
    36 {
    37 // As we want to display a Notification, we the NotificationManager.
    38 NotificationManager elNotificador = (NotificationManager)parContext.getSystemService(Context.NOTIFICATION_SERVICE);
    39
    40 // Verifico que la accion recibida es ''
    41 if (parIntent.getAction().equals(ACCION) == true)
    42 {
    43 // if(message starts with SMStretcher recognize BYTE)
    44 StringBuilder elContenido = new StringBuilder();
    45
    46 // La informacion del mensaje SMS vienen dentro del paquete de datos extras del Intent.
    47 Bundle losDatosExtras = parIntent.getExtras();
    48 if (losDatosExtras != null)
    49 {
    50 // Recuperamos los mensajes que vienen dentro del Intent.
    51 SmsMessage[] losMensajesSMS = Telephony.Sms.Intents.getMessagesFromIntent(parIntent);
    52
    53 // Creo el mensaje que mostrare en la pantalla.
    54 for (SmsMessage unMensaje : losMensajesSMS)
    55 {
    56 elContenido.append("Mensajes SMS\n");
    57 elContenido.append("enviado por:");
    58 // Numero de quien envio el mensaje.
    59 elContenido.append(unMensaje.getDisplayOriginatingAddress() + "\n");
    60 elContenido.append("Mensaje:\n");
    61 // Contenido del mensaje.
    62 elContenido.append(unMensaje.getDisplayMessageBody());
    63 }
    64 }
    65
    66 // Registramos en la bitacora el evento.
    67 Log.i(TAG_LOG, "onReceiveIntent: " + elContenido);
    68
    69 // Mostramos el mensaje utilizando el administrador de notificaciones
    70 elNotificador.notifyWithText(ID_NOTIFICACION, elContenido.toString(),
    71 NotificationManager.LENGTH_LONG, null);
    72
    73 // Consumimos este Intent, de esa forma ninguna otra aplicacion lo notara.
    74 this.abortBroadcast();
    75
    76 // Ahora intentamos gatillar una actividad adicional.
    77 Intent elIntento = new Intent(parContext, SMSActivity.class);
    78 elIntento.setLaunchFlags(Intent.NEW_TASK_LAUNCH);
    79 parContext.startActivity(elIntento);
    80 }
    81 return;
    82 }
    83 }


    SMSActivity.java

    01 package com.northvortex.sms;
    02
    03 import android.app.Activity;
    04 import android.os.Bundle;
    05
    06 /**
    07 *
    08 * Este es la clase que gatillare despues de mostrar el contenido del mensaje.
    09 *
    10 */
    11 public class SMSActivity
    12 extends Activity
    13 {
    14 /**
    15 * Esta clase es llamada la vez que la actividad es creada.
    16 */
    17 @Override
    18 public void onCreate(Bundle parICicle)
    19 {
    20 super.onCreate(parICicle);
    21
    22 setContentView(R.layout.main);
    23
    24 return;
    25 }
    26 }


    AndroidManifest.xml

    01 <?xml version="1.0" encoding="utf-8"?>
    02 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    03 package="com.northvortex.sms">
    04 <uses-permission id="android.permission.RECEIVE_SMS" />
    05 <application android:icon="@drawable/icon">
    06 <!-- The Main Activity that gets started by the IntentReceiver listed below -->
    07 <activity class=".SMSActivity" android:label="@string/app_name">
    08 <intent-filter>
    09 <action android:value="android.intent.action.MAIN" />
    10 <category android:value="android.intent.category.LAUNCHER" />
    11 </intent-filter>
    12 </activity>
    13 <!-- This class will react on the SMS show a notification and start the Main-App afterwards -->
    14 <receiver class=".SMSReceiver">
    15 <intent-filter>
    16 <action android:value="android.provider.Telephony.SMS_RECEIVED" />
    17 </intent-filter>
    18 </receiver>
    19 </application>
    20 </manifest>


    main.xml

    01 <?xml version="1.0" encoding="utf-8"?>
    02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    03 android:orientation="vertical"
    04 android:layout_width="fill_parent"
    05 android:layout_height="fill_parent"
    06 >
    07 <TextView
    08 android:layout_width="fill_parent"
    09 android:layout_height="wrap_content"
    10 android:text="SMS Activity"
    11 />
    12 </LinearLayout>


    strings.xml

    1 <?xml version="1.0" encoding="utf-8"?>
    2 <resources>
    3 <string name="app_name">SMS Receptor</string>
    4 </resources>

    ¿CÓMO HACER? - Simular envío de SMS al emulador

    Documento original: Simulating incoming Phone Calls / SMS in ECLIPSE


    En esta nota les explicaré como simular el envío de un mensaje SMS al emulador dentro de Eclipse.


    NOTA: Para este ejemplo necesitas haber instalado la versión "android_sdk_windows_m3-rc37a" del "Android SDK" o una versión posterior.


    A continuación está las instrucciones paso a paso:

    PASO #1 - Habilita la perspectiva "DDMS".

    Para esto presiona el botón "Open Perspective", tal como lo muestra la siguiente figura:

    Eso hará que se abra el siguiente menú:




    Esto hará que se habrá la ventan "Open Perspective". Selecciona "DDMS" y luego presiona el botón "OK". Como lo muestra la siguiente figura:




    Esto hará que se habilite la perspectiva "DDMS". Como lo muestra la siguiente figura:


    NOTA: En WINDOWS, después de habilitar esta perspectiva tendrás que reiniciar Eclipse ya que se perderán momentaneamente los tabuladores de la ventan "Run".



    PASO #2 - Envío del SMS

    Para esto ejecuta alguno de tus proyectos, de esa forma la perspectiva "DDMS" se activará.

    Una vez que tu aplicación esté corriendo, selecciona la perspectiva "DDMS". Dentro de esta perspectiva verás la siguiente el marco "Emulator Control". Usa estos controles para enviar tu mensaje SMS, tal como lo muestra la siguiente figura:


    sábado, 15 de diciembre de 2007

    Usando aapt

    Documento original : Using aapt

    Usando "aapt" (Using aapt)

    Las siglas "aapt" corresponde a "Android Asset Packaging Tool" y la puedes encontrar en el directorio "tools/" del "SDK". Esta herramienta te permite examinar, crear y actualizar archivos compatibles con "ZIP" (zip, jar, apk). También puede convertir (compilar) archivos de recursos a material binario.

    Aunque probablemente tú no utilices directamente "aapt", algunos "scripts" y "plugins" para IDEs pueden utilizar esta herramienta para empaquetar los archivos de una aplicación Android en un archivo ".apk".

    Para más detalles de cómo usar este comando, abre una consola de comandos y navega al directorio "tools/" y ejecuta el comando:

    Linux:

    ./aapt

    Windows:

    aapt.exe

    viernes, 14 de diciembre de 2007

    Manos a la obra - Herramientas para el desarrollo

    Documento original: Development Tools

    Herramientas de desarrollo

    [Título original: Development Tools]

    El "Android SDK" incluye una variedad de herramientas especialmente diseñadas para ayudarte en el desarrollo de aplicaciones móbiles sobre la plataforma Android. La herramienta más importante es el "Android Emulator" y las "Android Development Tools" plugin para Eclipse", pero el SDK también incluye un surtido de otras herramientas para depuración, empaquetado e instalación de aplicaciones en el dispositivo o emulador.

    Emulador Android

    [Título original: Android Emulator ]

    El "Android Emulator" es un dispositivo virtual que corren en tu computador. El emulador tiene como finalidad ayudarte a diseñar, depurar y testear tus aplicaciones en un ambiente similar al que existe en un dispositivo real.

    Android Development Tools Plugin para Eclipse IDE

    [Título original: Android Development Tools Plugin for the Eclipse IDE]

    El "ADT plugin" agrega poderosas extensiones al ambiente integrado de Eclipse haciendo que la creación y depuración de tus aplicaciones Android sea fácil y rápida. Si tú desarrollas estás usando Eclipse, el "ADT plugin" te da un increíble estímulo para el desarrollo de las aplicaciones Android. A continuación algunas de sus características:

  • Provee acceso a otras herramientas de desarrollo de Android desde el entorno de Eclipse IDE. Por ejemplo, "ADT" te permite el acceso a muchas de las capacidades de la herramienta "DDMS", tales como tomar fotografías de la pantalla, administrar el redireccionamiento de puertos, fijar puntos de quiebre y examinar la información "thread" y procesos directamente dentro de Eclipse.

  • Provee un asistente para la creación de proyectos Android, el cual te ayuda a crear rapidamente todos los directorios y archivos necesarios para crear una nueva aplicación Android.

  • Automatiza y simplifica el proceso de construcción de una aplicación.

  • Provee un editor de código Android que te ayuda a escribir XML válido para el archivo "AndroidManifest.xml".

  • Para mayor información sobre "ADT plugin", incluyendo las instrucciones de instalación, lee "Instalando el SDK". Para estudiar un simple ejemplo, lee "Hola Androide!".

    Dalvik Debug Monitor Service - ddms

    [Título original: Dalvik Debug Monitor Service - ddms]

    La "Dalvik Debug Monitor Service" es un herramienta integrada con la "Dalvik Virtual Machine", y nos permite administrar los procesos que corren en una instancia de emulador/dispositivo y nos asiste en la depuración de ellos. Podemos usar esta herramienta para terminar la ejecución de un proceso, seleccionar un determinado proceso para depurar, generar reportes a partir de información de bitácoras, examinar el "heap" y la información de "thread, tomar fotografías de la pantalla del emulador/dispositivo y mucho más.

    Android Debug Bridge - adb

    [Título original: Android Debug Bridge - adb]

    La herramienta "adb" nos permite instalar nuestras aplicaciones (archivos ".apk") en una instancia de emulador/dispositivo y accesar una instancia de emulador/dispositivo usando comandos de línea. También podemos utilizarlo para enlazar un depurador estándar al código de una aplicación que esté corriendo en una instancia de emulador/dispositivo.

    Herramienta Android Asset Packaging - aapt

    [Título original: Android Asset Packaging Tool - aapt]

    La herramienta "aapt" te permite crear archivos ".apk", los cuales contienen las imágenes binarias de tu código y recursos de tus aplicaciones.

    Android Interface Description Language - aidl

    [Título original: Android Interface Description Language - aidl]

    Te permite generar código para una interface de interproceso, tal como la que un servicio podría utilizar.

    sqlite3

    [Título original: sqlite3]

    Esta herramienta ha sido incluida para comodidad de los desarrolladores. Nos provee acceso a los archivos de datos "SQLite" creados y usados por las aplicaciones Android.

    Traceview

    [Título original: Traceview]

    Esta herramienta produce una vista gráfica del análisis de información contenida en bitácoras que puede ser generada desde una aplicación Android.

    mksdcard

    [Título original: mksdcard]

    Esta herramientas nos ayuda a crear una imagen de disco que podemos usar con el emulador, para simular la presencia de una tarjeta de almacenamiento externa (tal como una tarjeta "SD").

    dx

    [Título original: dx]

    La herramienta "dx" convierte los archivos de "bytecode" estándar (".class") en archivos "Android bytecode" (".dex").

    activityCreator

    [Título original: activityCreator]

    Es un "script" que genera archivos "Ant build" que puedes utilizar para compilar tus aplicaciones Android. Si tú estas desarrollando con Eclipse y "ADT plugin", no necesitas utilizar "activityCreator".

    Manos a la obra - Tutorial - Depurando tu aplicación

    Documento original: Tutorial: Extra Credit

    En este ejercicio, vas a usar el depurador para mirar de cerca el trabajo que hicimiento en el tutorial anterior Manos a la obra - Tutorial - Ejercicio #3

    Aprenderás a:

    • Fijar un punto de quiebre para examinar la ejecución de la aplicación.
    • Cómo correr una aplicación en modo de depuración.
    Paso 1

    Usando el proyecto "Notepadv3", colocaremos un punto de quiebre al comienzo del código fuente de los métodos "onCreate()", "onPause()", "onFreeze()" y "onResume()" de la clase "NoteEdit".

    NOTE: Para crear un punto de quiere (breakpoint) en Eclipse basta que abrás el menú emergente (clic con botón derecho) del borde gris del lado izquierdo de la ventana de edición, directamente sobre la línea en la cual quieres poner el punto de quiebre. Cuando aparesca el menú emergente, selecciones la opción "Toggle Breakpoint" y luego un punto azul debería aparecer sobre el borde gris.

    Paso 2

    Ahora inicializaremos la aplicación en mode de depuración:
    • Abre el menú emergente del proyecto "Notepadv3", expande la opción "Debug As" y selecciona "Android Application".
    • El emulador de Android debería desplegar por un instante el mensaje "waiting for debugger to connect" y entonces iniciar la ejecución de la aplicación.
    • Si llegará a quedarse pegado en la pantalla de "waiting...", termina la ejecución del emulador y también Ecliose. Luego, desde una terminal de comandos ejecuta el comando "adb kill-server" y entonces reinicia Eclipse y volver a intentar los pasos anteriores.
    Paso 3

    Al momento de crear una nueva nota deberías ver que la aplicación se detiene en uno de los puntos de quiebre que hemos definido.

    Paso 4

    Presiona el botón "Resume" para que la ejecución de la aplicación continúe (el botón "Resume" es aquel rectángulo amarillo con un triángulo verde a su derecha. Está ubicado en el lado izquierdo de la barra de herramientas de Eclipse).

    Paso 5

    Experimenta un poco presionando los botones "Confirm" y "Back". Prueba presional el botón "Home" y observa los eventos del ciclo de vida que son generados como resultado de esta operación.

    El "Android Eclipse plugin" no sólo ofrece un excelente soporte para depuración de tus aplicaciones, sino que además un poderoso soporte para perfilar (profiling). Si tu aplicación está corriendo muy lento, esta característica del plugin puede ayudarte a encontrar los cuello de botella y corregirlos.

    jueves, 13 de diciembre de 2007

    Android Debug Bridge

    Android Debug Bridge

    [Título original: Android Debug Bridge]

    Documento original: Android Debug Bridge

    El "Android Debug Bridge" ("adb") es un herramienta muy versátil que te permite controlar el estado de un dispositivo o un emulador.

    Algunas de las funciones cosas que puedes hacer con "adb" son:

  • Actualización de código del dispositivo o emulador, tales como aplicaciones o actualizaciones del sistema Android.

  • Ejecutar comandos de "shell" en el dispositivo.

  • Administrar el direccionamiento de puertos de un emulator o dispositivo.

  • Copiar archivos hacia o desde un emulador o dispositivo.

  • Las siguientes secciones describen algunos de los comandos más comunes de usar con "adb".

    Introducción

    [Título original: Overview]

    La herramienta "adb" es un programa cliente/servidor que incluye los siguientes componentes:

  • Un cliente que corre en tu máquina de desarrollo. Tú puedes invocar este cliente desde una consola de comandos ejecutando el comando "adb". Otras herramientas de Android, tales como el "ADT plugin" y "DDMS", crean sus propios clientes "adb".

  • Un servidor que se ejecuta como un proceso en segundo plano en tu máquina de desarrollo. Este servidor administra la comunicación entre el cliente y el "adb daemon" que corre dentro del emulador o dispositivo.

  • Un "daemon" que se ejecuta como un proceso de segundo plano en cada instancia de un emulador o dispositivo.

  • Cuando tú inicias un cliente "adb", lo primero que hace este cliente es verificar si hay un proceso servidor "adb" que esté corriendo. Si no lo hay, entonces el cliente inicia un proceso servidor "adb". Cuando el proceso servidor "adb" comienza a ejecutarse, asocia su servicio al puerto TCP número 5037 y se queda escuchando la llegada de comandos enviados desde los clientes "adb". Todos los clientes "adb" utilizan el puerto 5037 para comunicarse con el servidor "adb".

    Posteriormente, el servidor "adb" establece conexiones hacia todas las instancias de emuladores/dispositivos que estén corriendo. El servidor "adb" localiza a las instancias de emuladores/dispositivos examinando todos los puertos con número impar dentro del rango de 5555 a 5585, el cual es el rango utilizado por los emuladores/dispositivos. Cuando el servidor "adb" encuentra un "adb daemon", estable de inmediato una conexión con él. Algo importante de saber es que cada emulador/dispositivo adquiere un par de puertos consecutivos:

  • un puerto de número par para recibir solicitudes de conexión de consola.

  • un número de puerto impar para las conexiones con el servidor "adb".

  • Por ejemplo:

    Emulador #1:
    consola: 5554
    adb daemon: 5555

    Emulador #2:
    consola: 5556
    adb daemon: 5557

    Como se muestra en el ejemplo anterior, la instancia del emulador que está conectada con el servidor "adb" a través del puerto 5555, es la misma instancia cuya consola está escuchando en el puerto 5554.

    Una vez que el servidor "adb" ha establecido las conexiones con las instancias de los emuladores/dispositivos, podemos comenzar a usar comandos "adb" para controlar y tener acceso a esas instancias. Debido a que el servidor "adb" administra las conexiones hacia todas las instancias de emuladores/dispositivos y maneja los comandos enviados por múltiples clientes "adb", podemos controlar cualquier instancia de un emulador/dispositivo desde cualquier cliente "adb" o "script".

    Las secciones que leerás a continuación describen los comandos que tú puedes utilizar para utilizar las capacidades de "adb" y administrar el estado de un emulador/dispositivo. Ten en consideración que si tu estás desarrollando aplicaciones Android en Eclipse y has instalado el "ADT plugin", no es necesario que invoques "adb" desde una consola de comandos. El "ADT plugin" provee una integración transparente con "adb" dentro del entorno de desarrollo de Eclipse. Sin embargo, siempre puedes utilizar "adb" directamente.

    Utilizando comandos "adb"

    [Título original: Issuing adb Commands]

    Puedes invocar cualquier comando "adb" desde una consola de comandos en tu máquina de desarrollo o desde un "script". La sintáxis de los comandos es:

    adb [-d {<ID><serialNumber>}] <command>

    Cuando tú When you despachar un comando, el programa invoca un cliente "adb", el cual no está asociado a ninguna instancia de emulador en particular, por lo tanto si hay múltiples emuladores/dispositivos corriendo tienes que utilizar el parámetro "-d" para indicar la instancia hacia la cual el comando debe ser dirigido. Para mayor información sobre cómo usar este parámetro lee "Dirigiendo comando hacia un emulador/dispositivo específico".

    Averiguando qué emuladores/dispositivos están conectados

    [Título original: Querying for Emulator/Device Instances]

    Antes de comenzar a ejecutar comando "adb", es de mucha utilidad saber qué instancias de emuladores/dispositivos están conectadas al servidor "adb". Para obtener un listado de las instancias de emuladores/dispositivos que están corriendo y el estado de cada uno de ellos, podemos usar el siguiente comando:

    En respuesta, "adb" imprime la siguiente información de estado para cada una de las instancias:

  • Idetificador : es un identificador asignado por "adb" a cada instancia que es inicializada ("adb" asigna el identificador "1" a la primera instancia inicializada, y así sucesivamente).

  • Número de serie : es una cadena de caracteres creada por "adb" para identificar de manera única a cada instancia de emulaor/dispositivo asociado a un puerto específico.

  • Estado : es el estado de la conexión de la instancia. Hay tres estados que son soportados: (A) device : indica que la instancia está conectada al servidor "adb". (B) offline : indica que la instancia no está conectada o no responde. (C) bootloader : indica que el "bootloader" está corriendo.

  • Bloqueo: Indica si la instancia está bloqueada. Un valor de "0" significa que está no está bloqueada.

  • La salida de cada instancia es desplegada con el siguiente formato:

    [ID] [serialNumber] [state] [lock]

    Este es un ejemplo de cómo podría ser la salida de este comando:

    $ adb devices
    List of devices attached
    1 emulator-tcp-5555 device 0
    2 emulator-tcp-5557 device 0
    3 emulator-tcp-5559 device 0

    Si no hubiera ningún emulador/dispositivo corriendo, "adb" imprimiría "no device".

    Dirigiendo comando hacia un emulador/dispositivo específico

    [Título original: Directing Commands to a Specific Emulator/Device Instance]

    Si múltiples instancias de emuladores/dispositivos están corriendo, necesitas indicar a cual de ellas vas a dirigir tus comandos. Para hacer esto, usa el parámetro "-d" en cada uno de los comandos. La sintáxis para este parámetros es:

    Como se mostró, indicas la instancia objetivo utilizando el número de serie que "adb" asignó a cada una de ellas. Puedes utilizar el comando "devices" para obtener el número serial de las instancias de emuladores/dispositivos que estén corriendo.

    A continuación hay dos ejemplos:

    adb -d 2 install helloWorld.apk

    adb -d emulator-tcp-5557 install helloWorld.apk

    Ten en consideración que si envias un comando sin indicar el emulador/dispositivo objetivo, entonces "adb" por omisión enviará al comando a la primera instancia asociada al puerto "5555" (si es que hubiera una instancia conectada a ese puerto).

    Instalación de una aplicación

    [Título original: Installing an Application]

    Tú puedes utilizar "adb" para copiar una aplicación desde tu computador de desarrollo e instalar la en una instancia de emulador/dispositivo. Para hacer esto, usa el comando "install". Al usar este comando tú tienes que indicar la ubicación del archivo ".apk" que deseas instalar:

    adb install path_to_apk 

    Para mayor información sobre cómo crear un archivo ".apk" que pueda ser instalado en una instancia de emulador/dispositivo lee "Usando aapt".

    NOTA: Si tú estás usando Eclipse e instalaste "ADT plugin", no necesitas usar "adb" o "aapt" para instalar tus aplicaciones en el emulador/dispositivo. El "ADT plugin" se encarga del empaquetado e instalación de las aplicación.

    Redireccionamiento de puerto

    [Título original: Port Forwarding]

    Podemos usar el comando "forward" para fijar arbitrariamente el redireccionamiento de un puerto, y así direccionar los requerimientos de un puerto hacia uno diferente en una instancia de un emulador/dispositivo. A continuación hay un ejemplo de cómo fijar el redireccionamiento del puerto 6100 en el host al puerto 7100 en el emulador/dispositivo:

    adb forward tcp:6100 tcp:7100

    También podemos usar "adb" para redireccionar un puerto hacia un dominio de socket abstracto de UNIX. El siguiente ejemplo ilustra este caso:

    adb forward tcp:5556 local:logd 

    Copiando archivos desde o hacia una instancia de emulador/dispositivo

    [Título original: Copying Files to or from an Emulator/Device Instance]

    Podemos usar los comandos "pull" y "push" para copiar archivos hacia y desde una instancia de emulador/dispositivo. A diferencia del comando "install", el cual sólo copia un archivo ".apk" a una ubicación específica, los comandos "pull" y "push" nos permiten copiar archivos y directorios arbitrarios a cualquier ubicación dentro de la instancia del emulador/dispositivo.

    Para copiar un archivo o directorio (recursivamente) desde el emulador/dispositivo usa:

    adb pull <remote> <local>

    Para copiar un archivo o directorio (recursivamente) hacia el emulador/dispositivo usa:

    adb push <local> <remote>

    En los comandos, "local" y "remote" se refieren a ubicaciones de archivos/directorios en tu máquina de desarrollo ("local") y en la instancia del emulador/dispositivo ("remote").

    A continuación se muestra un ejemplo:

    adb push foo.txt /tmp/foo.txt

    Listado de comandos "adb"

    [Título original: Listing of adb Commands]

    A continuación se listan los comandos soportados por "adb" y se explica su significado y uso:

    Categoría: Opcional

    [Título original: Category: Option]

    Comando: -d {<ID><serialNumber>}
    Descripción: Permite que indiquemos una instancia de emulador/dispositivo a la cual deseamos enviar un comando.
    La instancia del emulador/dispositivo es referenciada utilizando su identificador o número de serie.
    Comentario: Si no se indica este parámetro, "adb" dirigirá el comando a la instancia por omisión
    (es decir, la instancia que está asociada al puerto "5555".

    Categoría: General

    [Título original: Category: General]

    Comando: devices
    Descripción: Imprime un listado de todos los emuladores/dispositivos que están conectados.
    Comentario: Para más detalles lee "Averiguando qué emuladores/dispositivos están conectados".
    Comando: help 
    Descripción: Imprime un listado con los comandos soportados por "adb"
    Comentario:
    Comando: version
    Descripción: Imprime la versión de "adb"
    Comentario:

    Categoría: Depuración

    [Título original: Category: Debug]

    Comando: logcat [<option>] [<filter-specs>]
    Descripción: Imprime el log de datos en la pantalla.
    Comentario:
    Comando: bugreport
    Descripción: Imprime información de "dumpsys", "dumpstate" y "logcat" en la pantalla, con el propósito de crear un reporte de defectos.
    Comentario:

    Categoría: Datos

    [Título original: Category: Data]

    Comando: install <path-to-apk>
    Descripción: Instala una aplicación Android en el emulador/dispositivo (debe indicarse la ubicación completa del archivo ".apk".
    Comentario:
    Comando: pull <remote> <local>
    Descripción: Copia un determinado archivo desde una instancia de emulador/dispositivo hacia tu máquina de desarrollo.
    Comentario:
    Comando: push <local> <remote>
    Descripción: Copia un determinado archivo desde tu máquina de desarrollo hacia una instancia del emulador/dispositivo.
    Comentario:

    Categoría: Puertos y redes

    [Título original: Category: Ports and Networking]

    Comando: forward <local> <remote>
    Descripción: Direcciona conexiones de socket desde un específico puerto local a un específico puerto remoto en una instancia de emulador/dispositivo.
    Comentario: La especificación de un puerto puede utilizar los siguientes esquemas:

    tcp:<portnum>
    local:<UNIX domain socket name>
    dev:<character device name>
    Comando: ppp <tty> [parm]...
    Descripción: Ejecuta "PPP" sobre "USB".
    <tty> es el "tty" para el "PPP stream". Por ejemplo, "dev:/dev/omap_csmi_ttyl.
    [parm]... es cero o más opciones "PPP/PPPD", tales como "defaultroute", "local", "notty", etc.
    NOTA: No debería iniciar automáticamente una conexión "PDP".
    Comentario:

    Categoría: Comandos de línea

    [Título original: Category: Scripting]

    Comando: get-serialno
    Descripción: Imprime el identificador de la instancia.
    Comentario:
    Comando: get-state
    Descripción: Imprime el estado "adb" de una instancia de emulador/dispositivo.
    Comentario:
    Comando: wait-for-bootloader
    Descripción: Bloquea la ejecución hasta que el "bootloader" esté en línea, esto es hasta que el estado de la instancia es "bootloader".
    Comentario:
    Comando: wait-for-device
    Descripción: Bloquea la ejecución hasta que el dispositivo esté en línea, esto es hasta que el estado de la instancia es "device".
    Comentario: Este comando puede ser anexado a otros comandos "adb".
    En este caso, "adb" va a esperar hasta que la instancia del emulador/dispositivo esté conectada antes de enviar el otro comando.
    Por ejemplo: adb wait-for-device <command>.

    Categoría: Servidor

    [Título original: Category: Server]

    Comando: start-server
    Descripción: Verifica si el proceso del servidor "adb" está corriendo y lo activa si no lo estuviera.
    Comentario:
    Comando: kill-server
    Descripción: Termina el proceso del servidor "adb".
    Comentario:

    Categoría: Intérprete de comandos

    [Título original: Category: Shell]

    Comando: shell
    Descripción: Inicia una "shell" remota en la instancia del emulador/dispositivo objetivo.
    Comentario: Lee "Enviando comandos de shell".
    Comando: shell [<shellCommand>]
    Descripción: Envia un comando de "shell" a la instancia del emulador/dispositivo objetivo y luego termina la "shell" remota.
    Comentario: Lee "Enviando comandos de shell".

    Enviando comandos al intérprete de comandos

    [Título original: Issuing Shell Commands]

    Podemos usar el comando "shell" para enviar comandos de "shell" remotos a una instancia de emulador/dispositivo. Podemos enviar un simple comando sin tener que abrir una sesión remota de "shell" o también podemos abrir una sesión de shell en donde naveguemos y enviemos comandos UNIX.

    Para enviar un simple comando sin ingresar a una sesión remota de "shell", usa el siguiente comando:

    adb [-d {<ID><serialNumber>}] shell <shellCommand>

    Para abrir una sesión remota de "shell" en una instancia de emulador/dispositivo, usa el siguiente comando:

    adb [-d {<ID><serialNumber>}] shell

    Cuando hayas terminado de ejecutar tus comando, usa "CTRL+D" o "exit" para cerrar la sesión de "shell".

    Las siguientes secciones proveen más información sobre comandos de "shell" que tú podrías utilizar.

    Examinando base de datos sqlite3 desde una shell remota

    [Título original: Examining sqlite3 Databases from a Remote Shell]

    Desde una sesión de shell remota, podemos usar "sqlite3", el cual es un programa de comandos de línea para administrar las base de datos "SQLite" creadas por las aplicaciones. La herramienta "sql3" incluye comandos de mucha utilidad, tales como ".dump" que permite imprimir el contenido de una tabla, y ".schema" que permite genera la sentencia "SQL CREATE" necesaria para reproducir una tabla existente. La herramienta también te provee la capacidad de ejecutar comando dinámicamente.

    Para usar "sqlite3", ingresa a una sesión de "shell" remota en la instancia del emulador, tal como se describió anteriormente, y luego invoca la herramienta usando el comando "sqlite3". De manera opcional, al invocar "sqlite3" puedes especificar la ubicación completa de la base de datos que deseas explorar. Las bases de datos en el emulador o dispositivo son almacenadas en el directorio "/data/data/nombrepaquete/databases/".

    A continuación se muestra dos ejemplos:

    $ adb -d emulator-tcp-5557 shell
    # sqlite3 /data/data/com.example.google.rss.rssexample/databases/rssitems.db
    SQLite version 3.3.12
    Enter ".help" for instructions
    .... enter commands, then quit...
    sqlite> .exit

    C:\Android SDK\android_sdk_windows_m3-rc20a\tools>adb shell
    sqlite3 /data/data/com.google.android.providers.contacts/databases/contacts.db
    sqlite> .tables
    .tables
    _deleted_people contact_methods peopleLookup
    calls people phones
    sqlite> .exit
    .exit

    Una vez que has invocado "sqlite3", puedes ingresar comandos "sqlite3" en la "shell". Pata terminar la sesión y retornar a la sesión de "shell" remota de "adb" usa el comando "exit" o "CTRL+D".

    Otros comandos del intérprete de comandos

    [Título original: Other Shell Commands]

    Comando de shell: dumpsys
    Descripción: Vacía el contenido de los datos del sistema.
    Comentario: La herramienta "Dalvik Debug Monitor Service (DDMS)" ofrece un entorno integrado de depuración que encontrarás más sencillo de utilizar.
    Comando de shell: dumpstate
    Descripción: Vacía la información de estado a un archivo.
    Comentario:
    Comando de shell: logcat [<option>]... [<filter-spec>]...
    Descripción: Habilita el "radio logging" e imprime la salida a la pantalla.
    Comentario:
    Comando de shell: dmesg
    Descripción: Imprime los mensajes de depuración a la pantalla.
    Comentario:
    Comando de shell: start
    Descripción: Activa (reinicializa) una instancia de emulador/dispositivo.
    Comentario:
    Comando de shell: stop
    Descripción: Detiene la ejecución de una instancia de emulador/dispositivo.
    Comentario:

    Habilitando logcat

    [Título original: Enabling logcat Logging]

    El sistema de bitácora de Android provee un mecanismo para recolectar y ver la información de depuración del sistema. Bitácoras de varias aplicaciones y porciones del systema son recolectadas en una serie de áreas de memoria temporal, las cuales pueden ser vistas y filtradas a través del comando "logcat".

    Usando comandos "logcat"

    [Título original: Using logcat Commands]

    Tú puedes usar el comando para ver y seguir el contenido de la bitácora del sistema. La sintaxis general de uso es:

    [adb] logcat [<option>] ... [<filter-spec>] ...

    Las secciones a continuación explican las especificaciones de filtrado y las opciones del comando. Para mayor información lee "Listado de opciones del comando logcat".

    Tú puedes usar el comando "logcat" desde tu computador de desarrollo o desde una sesión de "shell" remota en una instancia de emulador/dispositivo. Para ver la salida de la bitácora en tu computador de desarrollo, usa el siguiente comando:

    $ adb logcat

    y desde la sesión de "shell" remota, usa el siguiente comando:

    # logcat

    Filtrando la salida de la bitácora

    [Título original: Filtering Log Output]

    Cada mensaje de bitácora de Android tiene una etiqueta y una prioridad asociada.

  • La etiqueta de un mensaje de bitácora es una pequeña cadena de caracteres indicando el componente de sistema donde el mensaje fue originado (por ejemplo, "View" para una vista del sistema).

  • La prioridad es uno de los siguientes caracteres, ordenados desde la más baja a la más alta prioridad:

  • V - Verbose (baja prioridad) 
    D - Debug
    I - Info
    W - Warning
    E - Error
    F - Fatal
    S - Silent (alta prioridad, en la cual nada es impreso)

    Tú puedes obtener una lista de etiquetas usadas en el sistema junto con las prioridades, ejecutando el comando "logcat" y examinando las primeras dos columnas de cada mensaje dado como: <priority>/<tag>.

    A continuación hay un ejemplo de la salida de "logcat" que muestra un mensaje asociado con la prioridad de nivel "I" y con la etiqueta "ActivityManager":

    Para reducir la salida de la bitácora a un nivel manejable, tú puedes restringir la cantidad de información usando expresiones que filtren estos datos. Las expresiones de filtro te permiten indicarle al sistemas las prioridad y etiquetas en las cuales tú estás interesado y así el sistema suprime todos los otros mensajes.

    Una expresión de filtrado sigue el siguiente formato: "tag:priority ...", donde "tag" indica la etiqueta en la cual estamos interesados y "priority" indica el nivel mínimo de prioridad que deseamos examinar. Todos los mensajes para esa etiqueta que sean de la priodidad indica superior serán registrado en la bitácora. Podemos indicar cualquier número de especificaciones "tag:priority" es una expresión de filtrado. Las series de especificaciones son delimitadas por espacios en blanco.

    A continuación verás un ejemplo de una expresión de filtrado que suprime todos los mensajes de bitácora excepto aquellos con la etiqueta "ActivityManager" cuya prioridad es "Info" o superior, y todos los mensajes con etiqueta "MyApp" con prioridad "Debug" o superior:

    adb logcat ActivityManager:I MyApp:D *:S

    El elemento final de la expresión "*:S", fija el nivel de prioridad de todas las etiquetas a "silent", de esa forma nos aseguramos de ver sólo aquellos mensajes con "View" y "MyApp". El uso de "*:S" es una excelente forma de asegurar que la salida de la bitácora está restringida a los filtros que nosotros hemos explícitamente indicado y así nuestros filtros actúan como una "lista blanca" de mensajes de bitácora.

    La siguiente expresión desplega todos los mensajes de bitácora cuyo nivel de prioridad es "warning" o superior, para todas las etiquetas:

    Si tú estás corriendo "logcat" desde tu computador de desarrollo (en vez de correrlo en una sesión de "shell" remota), también puedes fijar una expresión de filtrado por omisión. Para hacer esto exporta la variable de entorno "ANDROID_LOG_TAGS":

    export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"

    NOTA: La variable de entorno "ANDROID_LOG_TAGS" no es exportada a la instancia del emulador/dispositivo, si tú estás corriendo "logcat" desde una sesión de "shell" remota o usando "adb shell logcat".

    Controlando la salida de la bitácora

    [Título original: Controlling Log Output Format]

    Los mensaje de bitácora, además de las etiquetas y nivel de prioridad, contienen información de metadatos. Podemos modificar el formato de salida de los mensajes para que se desplegue determinada información de metadatos. Para hacer esto, usa la opción "-v" e indica uno de los siguientes formatos listados a continuación:

    brief   - Desplega prioridad/etiqueta y PID del proceso que originó el mensaje (formato por omisión). 
    process - Desplega sólo el PID.
    tag - Desplega sólo prioridad/etiqueta.
    thread - Desplega sólo proceso:thread y prioridad/etiqueta.
    raw - Desplega toda la información del mensaje, sin metadatos.
    time - Desplega la fecha, hora de invocación, prioridad/etiqueta y PID del proceso que originó el mensaje.
    long - Desplega toda la información de metadatos y los mensajes separados por líneas en blanco.

    A continuación está la sintaxis general para ejecutar "logcat" e indicar el formato de salida que deseas:

    [adb] logcat [-v <format>]

    Aquí hay un ejemplo que muestra cómo generar mensajes usando el formato "thread":

    adb logcat -v thread

    NOTA: Sólo puedes indicar un sólo formato de salida con la opción"-v".

    Examinando bitácoras alternativas

    [Título original: Viewing Alternative Log Buffers]

    El sistema de bitácora de Android mantiene múltiples bitácoras circulares para registrar los mensajes de eventos, y no todos los mensajes son enviados a la bitácora circular por omisión. Para examinar mensajes adicionales, puedes correr "logcat" con la opción "-b", lo cual te permitirá ver bitácoras circulares alternativas. Puedes examinar cualquiera de las siguientes bitácoras alternativas:

    radio  - Muestra la bitácora de mensajes relacionados con radio/telefonía.
    events - Muestra la bitácora de mensajes conteniendo mensajes asociados a eventos.
    main - Muestra la bitácora principal de mensajes (por omisión)

    Sintaxis de uso de la opción "-b":

    [adb] logcat [-b <buffer>]

    Aquí hay un ejemplo de cómo examinar la bitácora que contiene mensajes asociados a "radio" y telefonía:

    adb logcat -b radio

    Examinando Viewing stdout y stderr

    [Título original: Viewing stdout and stderr]

    Por omisión, el sistema Android tiene asociado "stdout" y "stderr" ("System.out" y "System.err") con "/dev/null". En procesos que corren "Dalvik VM", el sistema puede escribir una copia de los mensajes de salida a un archivo de bitácora. En este caso, el sistema escribe los mensajes de bitácora usando las etiquetas "stdout" y "stderr", ambas con prioridad "I".

    Para rutear la salida de esta forma, debes detener la instancia del emulador/dispositivo y entonces usar el comando de shell "setprop" para habilitar el redireccionamiento de la salida. Aquí se muestra cómo hacerlo:


    $ adb shell stop
    $ adb shell setprop log.redirect-stdio true
    $ adb shell start

    El sistema mantiene esta configuración hasta que tu termines la ejecución de la instancia del emulador/dispositivo. Para usar esta configuración por omisión en la instancia del emulador/dispositivolt debes modificar el archivo "/data/local.prop" en el dispositivo.

    Listado de las opciones del comando logcat

    [Título original: Listing of logcat Command Options]

    Opción: -b <buffer>
    Descripción: Carga una bitácora alternativa para ser examinada, tal como "event" o "radio".
    Opción: -c
    Descripción: Borra completamente la bitácora y finaliza.
    Opción: -d
    Descripción: Vacía la bitácora a la pantalla y finaliza.

    Opción: -f <filename>
    Descripción: Escribe los mensajes de bitácora al archivo "filename". Por omisión es "stdout".
    Opción: -g
    Descripción: Imprime el tamaño de la bitácora y finaliza.
    Opción: -n <count>
    Descripción: Fija el número máximo de vueltas de una bitácora a "count". El valor por omisión es "4". Requiere la opción "-r".
    Opción: -r <kbytes>
    Descripción: Rota el archivo de bitácora cada "kbytes" de datos. El valor por omisión es "16". Requiere la opción "-f".
    Opción: -s
    Descripción: Fija el filtro a "silent".
    Opción: -v <format>
    Descripción: Fija el formato de salida de los mensajes de bitácora. Por omisión, el formato es "brief".

    Deteniendo el servidor "adb"

    [Título original: Stopping the adb Server]

    En algunos casos, podrías necesitar detener el proceso del servidor "adb" y luego reiniciarlo. Por ejemplo, si "adb" no está respondiendo a un comando. En este ejemplo, detener y reiniciar el proceso podría resolver el problema.

    Para detener el proceso del servidor "adb", usa el comando "kill-server". Posteriormente, puedes reiniciar el servidor enviando cualquier comando "adb".

    Información adicional

    [Título original: No es parte de la documentación oficial]

    Ejemplo salida : adb shell dmesg

    [Título original: No es parte de la documentación oficial]

    C:\android_sdk_windows_m3-rc22a\tools>adb shell dmesg 

    <5>Linux version 2.6.23-gcc3bc3b4 (arve@arvelnx.corp.google.com) (gcc version 4.2.1) #3 Tue Oct 30 16:28:18 PDT 2007
    <4>CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00003137
    <4>Machine: Goldfish
    <4>Memory policy: ECC disabled, Data cache writeback
    <7>On node 0 totalpages: 24576
    <7> DMA zone: 192 pages used for memmap
    <7> DMA zone: 0 pages reserved
    <7> DMA zone: 24384 pages, LIFO batch:3
    <7> Normal zone: 0 pages used for memmap
    <7> Movable zone: 0 pages used for memmap
    <4>CPU0: D VIVT write-through cache
    <4>CPU0: I cache: 4096 bytes, associativity 4, 32 byte lines, 32 sets
    <4>CPU0: D cache: 65536 bytes, associativity 4, 32 byte lines, 512 sets
    <4>Built 1 zonelists in Zone order. Total pages: 24384
    <5>Kernel command line: qemu=1 console=null android.checkjni=1 android.ril=ttyS0
    ...