Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ÍNDICE
OBJETIVO ESPECIFICO
INTRODUCCIÓN
Android, como sistema operativo, ha sido una interfaz de usuario flexible que se
diseñado para correr en distintos adapte a distintas configuraciones de
dispositivos, desde teléfonos a tabletas y pantallas. Lo anterior conlleva la
televisores. Como desarrollador, este rango incorporación de algunos elementos de
de dispositivos significa una audiencia compatibilidad. Dichos elementos, junto con
potencial gigante para una aplicación. Sin algunas nociones de lectura y escritura de
embargo, para que tu aplicación sea exitosa archivos, se revisarán durante esta semana.
en todos estos dispositivos, debe ser
tolerante a ciertas variaciones en las
características, y al mismo tiempo proveer de
Steve Ballmer.
Algunas de las variantes más importantes que se deben considerar al momento de desarrollar una
aplicación son: soporte para varios lenguajes, tamaños de pantalla y versiones distintas de la
plataforma Android (Developer.android.com, s. f.a). A continuación, se tratarán en profundidad
aquellos elementos de Android Studio que permiten adaptar una aplicación a distintas pantallas:
fragments, ActionBar y NavigationDrawer.
1.1. FRAGMENTS
Un fragment representa un comportamiento o una parte de la interfaz de usuario en una activity.
Se pueden combinar múltiples fragmentos en una sola actividad para crear una UI (interfaz de
usuario) multipanel y volver a usar un fragmento en múltiples actividades. Se puede pensar en un
fragmento como una sección modular de una actividad que tiene su ciclo de vida propio, recibe
sus propios eventos de entrada y que se puede agregar o quitar mientras la actividad se esté
ejecutando (algo así como una "subactividad" que se puede volver a usar en diferentes
actividades) (Developer.android.com, s. f.b).
Un fragmento siempre debe estar integrado a una actividad, donde el ciclo de vida del fragmento
se ve directamente afectado por el ciclo de vida de la actividad anfitriona. Por ejemplo, cuando la
actividad está pausada, también lo están todos sus fragmentos, y cuando la actividad se destruye,
lo mismo ocurre con todos los fragmentos. Sin embargo, mientras una actividad se está
ejecutando, se puede manipular cada fragmento de forma independiente; por ejemplo, para
agregarlos o quitarlos. Cuando se realiza una transacción de fragmentos como esta, también se
pueden agregar a una pila de actividades administrada por la actividad; cada entrada de la pila de
actividades en la actividad es un registro de la transacción de fragmentos realizada. La pila de
actividades le permitirá al usuario invertir una transacción de fragmentos (navegar hacia atrás) al
presionar el botón Atrás.
Al agregar un fragmento como parte del diseño de una actividad, este se ubica en el ViewGroup,
dentro de la jerarquía de vistas de la actividad y el fragmento define su propio diseño de vista. Se
puede insertar un fragmento en el diseño de una actividad declarando el fragmento en el archivo
de diseño de la actividad como elemento <fragment> o bien agregándolo a un ViewGroup
existente desde el código fuente de la aplicación. Sin embargo, no es necesario que un fragmento
forme parte del diseño de la actividad; también se puede usar un fragmento con su propia interfaz
de usuario.
Android introduce los fragmentos en Android 3.0 (nivel de API 11), principalmente para admitir
diseños de interfaz de usuario más dinámicos y flexibles en pantallas grandes, como las de las
tabletas. Como la pantalla de una tableta es mucho más grande que la de un teléfono, hay más
espacio para combinar e intercambiar componentes de la interfaz de usuario. Los fragmentos
admiten esos diseños sin la necesidad de que se administren cambios complejos en la jerarquía de
vistas. Al dividir el diseño de una actividad en fragmentos, se puede modificar el aspecto de la
actividad durante el tiempo de ejecución y conservar esos cambios en una pila de actividades
administrada por la actividad.
https://goo.gl/yosbcp
Por ejemplo, una aplicación de noticias puede usar un fragmento para mostrar una lista de
artículos a la izquierda y otro fragmento para mostrar un artículo a la derecha; ambos fragmentos
aparecen en una actividad, uno al lado del otro, y cada fragmento tiene su propio conjunto de
métodos callback del ciclo de vida y administran sus propios eventos de entrada del usuario.
Entonces, en lugar de usar una actividad para seleccionar un artículo y otra actividad para leer el
artículo, el usuario puede seleccionar un artículo y leerlo dentro de la misma actividad, tal y como
se ilustra en el diseño de tableta en la figura 1.
Figura 1. Ejemplo de la manera en que dos módulos de la interfaz de usuario definidos por fragmentos se
pueden combinar en una actividad para un diseño de tablet y se presentan por separados para un diseño
de teléfono.
Fuente: https://developer.android.com/guide/components/fragments.html
Así por ejemplo, para continuar con el ejemplo de la aplicación de noticias, la aplicación puede
integrar dos fragmentos en la Actividad A cuando se ejecuta en un dispositivo del tamaño de una
tableta. Sin embargo, en una pantalla de teléfono, no hay suficiente espacio para ambos
fragmentos, por lo que la Actividad A incluye solo el fragmento para la lista de artículos, y cuando
el usuario selecciona un artículo, se inicia la Actividad B, que incluye el segundo fragmento para
poder leer el artículo. Por lo tanto, la aplicación admite tabletas y teléfonos al reutilizar
fragmentos en diferentes combinaciones, como se ilustraba en la figura 1.
https://www.youtube.com/watch?v=m3A_82efr70
https://goo.gl/Xvl8NW
https://goo.gl/2KN3bZ
1.2. ACTIONBAR
El actionbar es un elemento que se encuentra en la parte superior de cada pantalla y que
generalmente es persistente a través de la aplicación, es decir, que persiste entre los cambios de
pantalla. En esta barra se ponen funciones importantes como buscar o nuevo, y al mismo tiempo
oculta otras menos importantes. Es uno de los elementos de diseño más importantes pues todas
las aplicaciones lo contienen. A continuación, se pueden ver ejemplos de ActionBars en las figuras
2 y 3.
Fuente: https://goo.gl/ZTPNx
Fuente: https://goo.gl/E8abAL
El ActionBar está dividido en 4 áreas funcionales que aplican en la mayoría de las aplicaciones
(figura 4). Como son:
Fuente: https://goo.gl/ZTPNx
Fuente: https://goo.gl/ZTPNx
2. View control: si la aplicación va a desplegar información en varias vistas, esta partirá del
ActionBar, que permite cambiar entre vistas. Un ejemplo de control que cambia entre
vistas es el menú desplegable. Ahora bien, si la aplicación no soporta distintas vistas, este
espacio se puede usar para desplegar contenido no interactivo como el título de la
aplicación u otro asociado al marketing de la misma.
3. Action buttons: muestran las acciones más importantes de la aplicación. Para ordenarlas,
hay que pensar cuáles van a ser usadas más frecuentemente que otras. Algo importante a
tener en cuenta es que esta barra debe mostrar solo acciones que están disponibles para
el usuario; así, si una acción no se encuentra disponible en un contexto, es mejor
esconderla y no mostrarla como deshabilitada. Ejemplos de botones de acción que usa la
aplicación Gmail se muestran en la figura 6.
Fuente: https://goo.gl/ZTPNx
https://www.youtube.com/watch?v=vzMhVYVLW_Q
1.3. NAVIGATIONDRAWER
Fuente: http://nixmash.com/x/blog/2015/navdrawer0109c.png
Fuente: https://s3-us-west-1.amazonaws.com/vizteck.bucket/uploads/navigation-drawer1.jpg
Antes de decidir usar un panel lateral de navegación en una aplicación, se deben comprender los
casos de uso y los principios de diseño definidos en la guía de diseño de panel lateral de
navegación1.
https://www.youtube.com/watch?v=-s39b_Ki1C8
1
Acceso a la guía en: https://material.io/guidelines/patterns/navigation-drawer.html#
2. ALMACENAMIENTO
Android ofrece diferentes opciones para guardar datos
persistentes de la aplicación. La solución que se elija dependerá
de ciertas necesidades específicas, por ejemplo, de si los datos
deben ser privados para la aplicación o estar disponibles para
otras aplicaciones (y el usuario), y de la cantidad de espacio
que requieren estos datos.
Fuente: https://goo.gl/S3fTJ6
La API para el manejo de estas preferencias es muy sencilla. Toda la gestión se centraliza en la
clase SharedPrefences, que representará a una colección de preferencias. Una aplicación Android
puede gestionar varias colecciones de preferencias, que se diferenciarán mediante un
identificador único. Para obtener una referencia a una colección determinada se utiliza el método
getSharedPrefences() al que se le pasa el identificador de la colección y un modo de acceso. El
modo de acceso indicará qué aplicaciones tendrán acceso a la colección de preferencias y qué
operaciones tendrán permitido realizar sobre ellas. Así, existen tres posibilidades (Herrera, s. f.):
Las dos últimas opciones son relativamente “peligrosas”, por lo que en condiciones normales no
deberían usarse. De hecho, se han declarado como obsoletas en la API 17 (Android 4.2). Teniendo
todo esto en cuenta, para obtener una referencia a una colección de preferencias llamada por
ejemplo “MisPreferencias” y como modo de acceso exclusivo para una aplicación, se haría lo
indicado en el código 1.
Fuente: https://goo.gl/qgOlGL
Fuente: https://goo.gl/qgOlGL
Para actualizar o insertar nuevas preferencias, el proceso será igual de sencillo, con la única
diferencia de que la actualización o inserción no se hará directamente sobre el objeto
SharedPreferences, sino sobre su objeto de edición SharedPreferences.Editor. A este último
objeto se accede mediante el método edit() de la clase SharedPreferences. Una vez obtenida la
referencia al editor, se utilizan los métodos put correspondientes al tipo de datos de cada
preferencia para actualizar/insertar su valor, por ejemplo putString(clave, valor), para actualizar
una preferencia de tipo String. De forma análoga a los métodos get vistos, se tendrán disponibles
métodos put para todos los tipos de datos básicos: putInt(), putFloat(), putBoolean(), etc.
Finalmente, una vez actualizados/insertados todos los datos necesarios, se debe llamar al método
commit() para confirmar los cambios. Un ejemplo sencillo se puede revisar en el código 3.
Fuente: https://goo.gl/qgOlGL
Pero, ¿dónde se almacenarán estas preferencias compartidas? Como se mencionó al comienzo del
punto 2.2, las preferencias no se almacenan en ficheros binarios como las bases de datos SQLite,
sino en ficheros XML. Estos ficheros XML se almacenan en una ruta que sigue el siguiente patrón:
/data/data/paquete.java/shared_prefs/nombre_coleccion.xml
https://www.youtube.com/watch?v=Pay4nZu9Kuc
Para crear y escribir un archivo privado en el almacenamiento interno, se deben seguir los
siguientes pasos:
Fuente: https://goo.gl/xLOiUa
Para leer un archivo desde el almacenamiento interno, se deben seguir los siguientes pasos:
1. Llamar a openFileInput() y usar el nombre del archivo que se desea leer. Esto muestra un
FileInputStream.
getDir(): crea un directorio (o abre uno existente) dentro del espacio de almacenamiento
interno.
La segunda forma de almacenar archivos en la memoria interna del dispositivo es incluirlos como
recurso en la propia aplicación. Aunque este método es útil en muchos casos, solo se debe utilizar
cuando no se necesiten realizar modificaciones sobre los archivos, ya que solo se pueden leer
estos archivos pero no escribir. Para incluir un fichero como recurso de la aplicación se debe
colocar en la carpeta “/resources/raw” del proyecto de Android Studio. Esta carpeta no suele estar
creada por defecto, por lo que se debe crear manualmente en Android Studio.
Una vez creada la carpeta /raw, se pueden colocar en ella cualquier archivo que se quiera incluir
con la aplicación en tiempo de compilación en forma de recurso. Para efectos del ejemplo que se
viene analizando, se incluirá un archivo llamado “prueba_raw.txt“. Ya en tiempo de ejecución se
puede acceder a este archivo, solo en modo de lectura, de una forma similar a la que ya se ha visto
para el resto de archivos en memoria interna. Para acceder al archivo, primero se debe acceder a
los recursos de la aplicación con el método getResources() y sobre estos se utiliza el método
openRawResource(id_del_recurso) para abrir el archivo en modo lectura. Este método devuelve
un objeto InputStream que se puede manipular con los métodos de la API java.io. Como ejemplo,
se convertirá el stream en un objeto BufferedReader para leer el texto contenido en el archivo de
ejemplo (por supuesto, los archivos de recurso también pueden ser binarios, como por ejemplo
archivos de imagen, video, etc.). El código quedaría como el que se muestra en el código 5.
Fuente: https://goo.gl/R0qimN
Fuente: https://goo.gl/VT7UEZ
MEDIA_MOUNTED, que indica que la memoria externa está disponible y se puede tanto
leer como escribir en ella.
Otra serie de valores que indicarán que existe algún problema y que por tanto no se puede
ni leer ni escribir en la memoria externa (MEDIA_UNMOUNTED, MEDIA_REMOVED, …). Se
Teniendo todo esto en cuenta, se podría realizar un chequeo previo del estado de la memoria
externa del dispositivo tal y como se muestra en el código 6.
Fuente: https://goo.gl/eUPuwc
Una vez chequeado el estado de la memoria externa, y dependiendo del resultado obtenido, ya se
puede leer o escribir en ella cualquier tipo de archivo. Así, el estado que permite leer y escribir es
MEDIA_MOUNTED; mientras que el estado que permite solo leer desde el dispositivo es
MEDIA_MOUNTED_READ_ONLY. Todos los otros estados no permitirán acceso al dispositivo.
Para escribir un fichero a la memoria externa se debe obtener en primer lugar la ruta al directorio
raíz de esta memoria. Para ello, se puede utilizar el método getExternalStorageDirectory() de la
clase Environment, el cual devuelve un objeto File con la ruta de dicho directorio. A partir de este
objeto, se construye otro con el nombre elegido para el archivo (como por ejemplo
“prueba_sd.txt“), creando un nuevo objeto File que combine ambos elementos. Tras esto, ya solo
queda encapsular en algún objeto de escritura de archivos de la API de Java y escribir algún dato
de prueba. En el caso de ejemplo, se convertirá una vez más a un objeto OutputStreamWriter para
escribir al archivo un mensaje de texto. El código quedaría como el que se muestra en el código 7.
2
Disponible en: https://developer.android.com/reference/android/os/Environment.html
Fuente: https://goo.gl/eUPuwc
El código 7 anterior funciona sin problemas, pero escribirá el fichero directamente en la carpeta
raíz de la memoria externa. Esto, aunque en ocasiones puede resultar necesario, no es una buena
práctica. Lo correcto sería disponer de una carpeta propia para la aplicación, lo que además tendrá
la ventaja de que al desinstalar la aplicación también se liberará este espacio. Esto se consigue
utilizando el método getExternalFilesDir(null), en vez de getExternalStorageDirectory(). El método
getExternalFilesDir() devuelve directamente la ruta de una carpeta específica para la aplicación
dentro de la memoria externa siguiendo el siguiente patrón:
<raíz_mem_ext>/Android/data/nuestro.paquete.java/files
<raíz_mem_ext>/Android/data/nuestro.paquete.java/files/Music
Esto último, además, ayuda a Android a saber qué tipo de contenidos hay en cada carpeta, de
forma que puedan clasificarse correctamente, por ejemplo, en la galería multimedia.
Sea como sea, para tener acceso a la memoria externa se tendrá que especificar en el archivo
AndroidManifest.xml que la aplicación necesita permiso de escritura en dicha memoria. Para
añadir un nuevo permiso se usa la cláusula <uses-permission> utilizando el valor concreto
Fuente: https://goo.gl/eUPuwc
Fuente: https://goo.gl/eUPuwc
Por su parte, leer un fichero desde la memoria externa es igual de sencillo. Se obtiene el directorio
raíz de la memoria externa con getExternalStorageDirectory(), o la carpeta específica
de la aplicación con getExternalFilesDir(), se crea un objeto File que combine esa ruta
con el nombre del archivo a leer y se encapsula dentro de algún objeto que facilite la lectura,
donde para leer texto se puede utilizar un BufferedReader. Un ejemplo de código se puede
revisar a continuación.
Fuente: https://goo.gl/eUPuwc
https://www.youtube.com/watch?v=lbBosCrFE7Y
COMENTARIO FINAL
Esta semana ha sido intensa en el abordaje de nuevos conceptos, considerando además que
Android Studio como herramienta de desarrollo también es una novedad, por lo que la curva de
aprendizaje puede que no sea tan rápida como se quisiera. Sin embargo, este proceso es
incremental y al mismo tiempo requiere de tiempo de maduración de los conceptos, por lo que
hay que tomárselo con calma.
REFERENCIAS
https://developer.android.com/training/basics/supporting-devices/index.html
https://developer.android.com/guide/components/fragments.html
https://developer.android.com/guide/topics/data/data-storage.html?hl=es
http://todosobreprogramacion.blogspot.cl/