Desarrollo de aplicaciones para dispositivos móviles Android

Almacenamiento local

Johnattan Jaramillo G.

jjaramillo238@misena.edu.co

Contenido del curso

1- Introducción

2- Layouts y widgets

3- Actividades y fragmentos

4- Almacenamiento local

5- Almacenamiento remoto

6- Material design

7- Publicación y marketing de apps

ALMACENAMIENTO LOCAL

  • Contenedores
  • DataStorage
  • SQLite
  • Ejercicio

Contenedores

Listview

Es un grupo de vistas (ViewGroup) que muestra una lista de elementos desplazable

Definición

Listview

Adaptadores

Los elementos de la lista son insertados de un origen de datos usando un adaptador de clase (Class Adapter) 

Origen de Datos

Adaptador

ListView

Listview

Adaptadores

ORIGEN DE DATOS (DATA SOURCE)

  • Es responsable de indicar de donde se obtienen los datos
  • Puede ser desde un arreglo hasta una base de datos

ADAPTADOR (ADAPTER)

  • Es responsable de construir una vista para cada elemento de la lista obtenido desde el origen de datos 
  • Actúa como puente entre el ListView y el DataSource

VISTA DE ADAPTADOR (LISTVIEW)

  • Es responsable de presentar la lista de elementos al usuario

Listview

1- Definir el origen de datos (array)

ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, dias);

2- Definir el adaptador y proporcionarle

  • Origen de datos
  • Layout de una vista  simple (layout por defecto disponible en Android para mostrar un listview)
String[] dias = {"Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"};

3- Establecer el adaptador del ListView

ListView lv = (ListView) findViewById(R.id.idListView);
lv.setAdapter(adapter);

Implementación

Listview

4- Asociar un onItemClickListener para definir que acción se debería ejecutar al momento de dar click sobre un elemento de la lista

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView  adapterView, View view, int i, longo l){
        //Acciónes a ejecutar al seleccionar el elemento
    }
}

Implementación

Listview personalizado

  • Los ListView Personalizados (Custom ListView) son usados para mostrar más de una vista en cada fila
  • Por defecto, los adaptadores (ArrayAdapter) asumen cada fila en la lista de elementos como un elemento de texto simple (TextView). 
  • El layout por defecto para mostrar listas en Android (android.R.layout.simple_list_item_1) usa una vista simple (TextView) para cada fila
  • Si queremos mostrar más de una vista en cada fila necesitamos crear nuestro propio layout

Definición

Listview personalizado

1- Preparar los orígenes de datos

2- Crear un layout personalizado (custom_row.xml) el cual definirá como los elementos de la lista aparecerán en cada fila.

String[] artistas = {"Nach","ZPU","Canserbero","Lil Supa","Rocca"};
String[] descripciones = {"MC Español","MC Español","MC Venezolano","MC Venezolano","MC Colombiano"};
int [] imagenes ={R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable.img4,R.drawable.img5};

Implementación

Listview personalizado

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView android:id="@+id/idImagen"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />
    <TextView android:id="@+id/idArtista"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Artista"
        android:textSize="20sp"
        android:layout_toRightOf="@id/idImagen"/>
    <TextView android:id="@+id/idDescripcion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Descripción"
        android:layout_below="@id/idArtista"
        android:layout_toRightOf="@id/idImagen"/>

</RelativeLayout>

Implementación

Listview personalizado

3- Definir un adaptador personalizado (Custom Adapter) que extienda el adaptador por defecto (Array Adapter) ya que el adaptador por defecto muestra solo un TextView en cada fila

Implementación

4- Crear una clase de Java (Custom Adapter) que extienda de la clase del adaptador por defecto (Array Adapter)

5- Sobrescribir el constructor por defecto del adaptador por defecto  (Array Adapter)

6- Inflar el layout personalizado en el método getView() el cuál obtendrá la vista de una posición específica

7- Obtener referencias a objetos de la vista (XML) y asignarle a cada uno un elemento de la lista (Data Source)

Listview personalizado

class MyAdapter extends ArrayAdapter{

    int[] arrayImagenes;
    String[] arrayArtistas;
    String[] arrayDescripciones;

    public MyAdapter(Context context, String[] artistas, String[] descripciones, int[] imagenes){
        //Sobrescribir el constructor por defecto del ArrayAdapter
        super(context, R.layout.custom_row,R.idArtista,artistas);
        this.arrayImagenes = imagenes;
        this.arrayArtistas = artistas;
        this.arrayDescripciones = descripciones;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        //Inflar el layout
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row = inflater.inflate(R.layout.custom_row,parent,false);
        //Obtener la referencia a los objetos de la vista
        ImageView myImage = (ImageView) row.findViewById(R.id.idImagen);
        TextView myArtist = (TextView) row.findViewById(R.id.idArtista);
        TextView myDescription = (TextView) row.findViewById(R.id.idDescripcion);
        //Proporcionar un elemento del arreglo especificando su posición
        myImage.setImageResource(arrayImagenes[position]);
        myArtist.setText(arrayArtistas[position]);
        myDescription.setText(arrayDescripciones[position]);
        return row;
    }
}

Implementación

Listview personalizado

Implementación

MyAdapter adapter = new MyAdapter (this, artistas, descripciones, imagenes);

8- Definir el adaptador personalizado y proporcionarle sus parámetros

9- Establecer el adaptador del ListView

ListView lv = (ListView) findViewById(R.id.idListView);
lv.setAdapter(adapter);

Listview Expandible

  • Los ListView Expandibles (Expandable ListView) son usados para agrupar los elementos de la lista en categorías
  • Por defecto, los ListView solo muestran un grupo de elementos de una lista

Definición

Listview expandible

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <ExpandableListView android:id="@+id/idListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    
</LinearLayout>

Implementación

1- Crear archivo XML con el ExpandableListView

Listview expandible

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <TextView android:id="@+id/idTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Title"
        android:padding="2dp"/>
    
</RelativeLayout>

Implementación

2- Crear archivo XML para mostrar el encabezado de categorías (Categories header)

Listview expandible

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <TextView android:id="@+id/idChildItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Child"
        android:padding="2dp"/>
    
</RelativeLayout>

Implementación

3- Crear archivo XML para mostrar los elementos de cada categoría (Categories items)

Listview expandible

Implementación

4- Crear una clase de Java (Adapter Class) que extienda de la clase base del adaptador de lista expandible (BaseExpandableListAdapter) e implemente todos sus métodos

package sena.android.com.expandablelistview;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;

public class MyAdapter extends BaseExpandableListAdapter{
    @Override
    public int getGroupCount(){
        return 0;
    }   
    @Override
    public int getChildrenCount(int i){
        return 0;
    } 
    @Override
    public Object getGroup(int i){
        return null;
    }
    @Override
    public Object getChild(int i, int i1){
        return null;
    }
    @Override
    public Object getGroupId(int i){
        return 0;
    }  
    @Override
    public Object getChildId(int i, int i1){
        return 0;
    }   
    @Override
    public boolean hasStableIds(){
        return false;
    }
    @Override
    public View getGroupView(int i, boolean b, View view, ViewGroup viewgroup){
        return null;
    } 
    @Override
    public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewgroup){
        return null;
    }
    @Override
    public boolean isChildSelectable(int i, int i1){
        return false;
    }                        
}

Listview expandible

Implementación

5- Sobrescribir el constructor por defecto (Default Constructor) de la clase adaptador (Adapter Class) con tres parámetros

  1. Context
  2. Listado de ChildViews (o HashMap)
  3. Listado de HeaderViews
private Context ctx;
private HashMap<String,List<String>> ChildTitles;
private List<String> HeaderTitles;

MyAdapter(Context ctx, HashMap<String,List<String>> ChildTitles, List<String> HeaderTitles){
    this.ctx=ctx;
    this.ChildTitles = ChildTitles;
    this.HeaderTitles = HeaderTitles;
}

Listview expandible

Implementación

6- Pasar la cuenta del encabezado de categorías (Categories header) en el método getGroupCount()

public int getGroupCount(){
    return HeaderTitles.size();
}

7- Pasar la cuenta de los elementos de las categorías (Categories items) de cada encabezado de grupo (Group header)  en el método getChildrenCount()

public int getChildrenCount(int i){
    return ChildrTitles.get(HeaderTitles.get(i)).size();
}

Listview expandible

Implementación

8- Pasar la posición de cada vista de encabezado (Header view)

public Object getGroup(int i){
    return HeaderTitles.get(i);
}

9- Pasar la posición de cada elemento hijo (Children) para cada vista de encabezado (Header view) respectiva

public int getChild(int i, int i1){
    return ChildTitles.get(HeaderTitles.get(i)).get(i1);
}

Listview expandible

Implementación

10- Inflar el layout para la vista de encabezado (HeaderView) y las vistas de elementos (ChildViews).

Convertir las vistas XML en objetos de Java

public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup){
    String title = (String) this.getGroup(i);
    if(view == null){
        LayoutInflater inflater = (LayoutInflater) this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.custom_header, null);
    }
    TextView txt = (TextView) view.findViewById(R.id.idTitle);
    txt.setTypeface(null, Typeface.BOLD);
    txt.setText(title);
    return view;
}

public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup){
    String child = (String) this.getChild(i, i1);
    if(view == null){
        LayoutInflater inflater = (LayoutInflater) this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.custom_child, null);
    }
    TextView txt = (TextView) view.findViewById(R.id.idChildItem);
    txt.setText(child);
    return view;
}

Listview expandible

Implementación

11- Crear el proveedor de datos (DataProvider) para proporcionar la información a las vistas

public class DataProvider {
    public static HashMap> getInfo(){
        HashMap> HeaderDetails = new HashMap>();
        List ChildDetails1 = new ArrayList();
        ChildDetails1.add("This id Children11");
        ChildDetails1.add("This id Children12");
        ChildDetails1.add("This id Children13");        
        ChildDetails1.add("This id Children14");
        List ChildDetails2 = new ArrayList();
        ChildDetails2.add("This id Children21");
        ChildDetails2.add("This id Children22");
        ChildDetails2.add("This id Children23");        
        ChildDetails2.add("This id Children24");
        List ChildDetails3 = new ArrayList();
        ChildDetails3.add("This id Children31");
        ChildDetails3.add("This id Children32");
        ChildDetails3.add("This id Children33");        
        ChildDetails3.add("This id Children34");
        List ChildDetails4 = new ArrayList();
        ChildDetails4.add("This id Children41");
        ChildDetails4.add("This id Children42");
        ChildDetails4.add("This id Children43");        
        ChildDetails4.add("This id Children44");
        HeaderDetails.put("Header 1",ChildDetails1);
        HeaderDetails.put("Header 2",ChildDetails2);
        HeaderDetails.put("Header 3",ChildDetails3);
        HeaderDetails.put("Header 4",ChildDetails4);

        return HeaderDetails;
    }
}

Listview expandible

Implementación

MyAdapter adapter = new MyAdapter (this, myHeader, MyChild);

13- Definir el adaptador personalizado y proporcionarle sus parámetros

14- Establecer el adaptador del ListView

ExpandableListView expList = (ExpandableListView ) findViewById(R.id.idListView);
expList.setAdapter(adapter);
HashMap> myHeader = DataProvider.getInfo();
List myChild = new ArrayList(myHeader.keySet());

12- Preparar origen de datos (Data Source)

GridView

  • Son ViewGroups que disponen los elementos en una rejilla bidimensional desplazable
  • Los elementos son insertados automáticamente al layout usando un adaptador (Adapter)
  • Son similares a los ListView

Definición

Gridview

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <GridView android:id="@+id/idGridView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="2"/>
    
</LinearLayout>

Implementación

1- Agregar el GridView en el archivo XML 

Gridview

String[] data = {"data1","data2","data3","data4","data5","data6","data7","data8"};

Implementación

2- Crear el origen de datos (Data Source) para el GridView en la actividad (Activity)

3- Instanciar el GridView XML en un objeto de Java

GridView gridView = (GridView) findViewById(R.id.idGridView);

4- Definir un adaptador (Adapter) para el GridView y asignárselo

ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout_simple_list_item1,data);
gridView.setAdapter(adapter);

WebView

  • Es una vista que presenta una página web al interior de un contenedor, esto permite que nuestra aplicación se convierta en una aplicación web
  • Véase
    • Aplicaciones híbridas
    • Ionic 2

Definición

Webview

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <WebView android:id="@+id/idWebView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>
    
</LinearLayout>

Implementación

1- Agregar el elemento <WebView> en el archivo XML 

Webview

WebView browser = (WebView) findViewById(R.id.idWebView);

Implementación

2- Instanciar el WebView XML en un objeto de Java

3- Asignar la URL del WebView 

browser.loadUrl("https://www.google.com.co");

Webview

Permisos

  • Si se desea acceder a un archivo alojado en un servidor se necesitará de una conexión a internet
  • En estos casos, es necesario incluir el permiso de conexión en el archivo AndroidManifest.xml de la siguiente manera

 

<manifest>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

Webview

JavaScript

  • JavaScript se encuentra deshabilitado en el WebView por defecto
  • Se puede habilitar a través de los WebSettings del WebView
  • Los WebSettings se pueden recuperar con el método getSettings() y entonces habilitar JavaScript usando el método setJavaScriptEnabled() de la siguiente manera

 

WebView browser = (WebView) findViewById(R.id.idWebView);
WebSettings webSettings = browser.getSettings();
webSettings.setJavaScriptEnabled(true);

SearchView

Es una vista que proporciona una interfaz de usuario que permite ingresar una búsqueda y enviar la solicitud a un proveedor de búsquedas

Definición

SearchView

<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/idLayout">

    <SearchView android:id="@+id/idSearchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:iconifiedByDefault="false">
        <requestFocus />
    </SearchView>
    
</LinearLayout>

Implementación

1- Agregar el elemento <SearchView> en el archivo XML 

SearchView

SearchView searchView = (SearchView) findViewById(R.id.idSearchView);

Implementación

2- Instanciar el SearchView XML en un objeto de Java

3- Ejecutar la consulta y agregar el método setOnQueryTextListener() al searchView

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
    @Override
    public boolean onQueryTextSubmit(String s){
        return false;
    }
    @Override
    public boolean onQueryTextChange(String s){
        return false;
    }
});

Data Storage

Android proporciona diferentes opciones para manejar la persistencia de los datos de la aplicación

Depende de las necesidades, escogeremos  que opción de almacenamiento es más  conveniente para los nuestros datos

Data Storage

Preferencias compartidas

Almacena información privada en pares clave-valor

Almacenamiento Interno

Almacena información privada en la memoria del dispositivo

Almacenamiento Externo

Almacena información pública en el almacenamiento externo compartido

Base de datos SQLite

Almacena información estructurada en una base de datos privada. Permite guardar la información en tablas relacionadas

Remoto

Almacena información en tu propio servidor

Preferencias compartidas

  • Para recuperar un valor (value) de las preferencias compartidas debemos solicitarla a través de su clave (key)
  • Los datos persistirán a lo largo de las sesiones (incluso si la aplicación se cierra)

Shared preferences

Almacena información privada en pares clave-valor

Usuario

Contraseña

admin

123

Clave (key)

Valor (value)

Preferencias compartidas

data/data/<nombre_paquete>/shared-prefs

Ubicación

La información se almacena en un archivo XML en el directorio

Tipos de datos

  • Boolean
  • Int
  • Float
  • Long
  • String

Shared preferences

Preferencias compartidas

Acceso

Existen dos métodos para obtener un objeto con las preferencias de usuario 

  • getSharedPreferences(String name, int mode)
    • ​​Se usa cuando se necesitan múltiples archivos de preferencias (identificados por un nombre). El nombre se especifica en el primer parámetro
  • getPreferences(int mode)
    • ​​Se usa cuando solo se necesita un archivo de preferencias. Como solo existe un archivo de preferencias, no es necesario especificar su nombre

Preferencias compartidas

Modos

Modos de operación

MODE_PRIVATE

0 - Por defecto. Solo la aplicación puede acceder al archivo

Modo

Uso

MODE_READABLE

MODE_WRITEABLE

MODE_MULTI_PROCESS

Todas las aplicaciones pueden leer el archivo

Todas las aplicaciones pueden escribir el archivo

Múltiples procesos pueden modificar el mismo archivo de preferencias compartidas

Preferencias compartidas

Usos

  • Verificar si un usuario está usando tu aplicación
  • Verificar cuando fue actualizada tu aplicación 
  • Recordar credenciales de usuario
  • Recordar configuraciones de usuario
  • Caché de ubicaciones
getPreferences(int mode);

Guardar información

1- Obtener una referencia al objeto de preferencias compartidas

Preferencias compartidas

getSharedPreferences(String name, int mode);
  • Para un archivo simple
  • Para varios archivos 

2- Llamar al editor

SharedPreference.Editor editor = sharedpreferences.edit();
editor.putString("nombre","johnattan");
editor.putString("contraseña","ultrasecreta");

Guardar información

3- Usar el editor para agregar información en pares clave-valor

Preferencias compartidas

4- Ejecutar los cambios del editor

editor.commit();
getPreferences(int mode);

Obtener información

1- Obtener una referencia al objeto de preferencias compartidas

Preferencias compartidas

getSharedPreferences(String name, int mode);
  • Para un archivo simple
  • Para varios archivos 

Obtener información

2- Usar la clave (key) proporcionada previamente para obtener el valor (value)

Preferencias compartidas

3- Proporcionar un valor por defecto en caso que el valor no se encuentre

String nombre = sharedPreferences.getString("nombre","N/A");
String contraseña = sharedPreferences.getString("contraseña","N/A");

Almacenamiento interno

Internal Storage

  • Guarda archivos directamente en el almacenamiento interno del dispositivo
  • Por defecto, los archivos son privados para la aplicación, es decir, otras aplicaciones no pueden acceder a éstos
  • Los archivos son borrados cuando el usuario desinstala la aplicación

Almacenamiento Interno

data/data/<nombre_paquete>/files

Ubicación

La información se almacena en un archivo XML en el directorio

Tipos de datos

  • Archivos de texto
  • Archivos de imagen
  • Archivos de video
  • Archivos de audio

Shared preferences

Escribir información

1- Llamar al método openFileOutput(String filename, int mode) especificando:

  1. Nombre del archivo
  2. Modo de operación

Este retorna un FileOutputStream

Almacenamiento interno

Crear y escribir un archivo privado en el almacenamiento interno 

Escribir información

Almacenamiento interno

Context.MODE_PRIVATE

0 - Por defecto. Solo la aplicación puede acceder al archivo

Modo

Uso

Agregar información al contenido existente

Context.MODE_APPEND

Escribir información

2- Escribir en el archivo usando el método write()

Almacenamiento interno

3- Cerrar el flujo de escritura usando el método close()

String FILENAME = "archivo_prueba";
String string = "Hola mundo!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

Leer información

1- Llamar al método openFileInput(String filename) especificando:

  1. Nombre del archivo

Este retorna un FileInputStream

Almacenamiento interno

2- Leer los bytes del archivo usando el método read(). La lectura se ejecuta byte por byte para agregar cada caracter

3- Cerrar el flujo de lectura usando el método close()

Leer información

Almacenamiento interno

FileInputStream fis = openFileInput(FILENAME);
int read = -1;
StringBuffer buffer = new StringBuffer();
read = fis.read();
while( read != -1){
    buffer.append((char) read);
}
fis.close();

Almacenamiento externo

External Storage

  • Guarda u obtiene información desde un dispositivo de memoria externo (Memoria SD)
  • Por defecto, los archivos guardados en el almacenamiento externo son públicos y pueden ser modificados por el usuario cuando este habilite la transferencia de archivos al computador

Escribir información

1- Agregar permisos

Almacenamiento externo

WRITE_EXTERNAL_STORAGE
  • Para lectura
  • Para escritura
  • Para lectura y escritura
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

Agregar en el archivo AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Escribir información

2- Verificar disponibilidad de acceso al almacenamiento

Almacenamiento externo

Llamar al método getExternalStorageState() para verificar si el acceso al almacenamiento está disponible

//Disponible para escritura
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

//Disponible para lectura
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}

Escribir información

3- Obtener los archivos del directorio usando los métodos

Almacenamiento externo

a- getExternalStorageFilesDir(String type)

Archivos específicos a tu app, son eliminados al desinstalarla

File folder = getExternalStorageFilesDir("MyFolder");
File myfile = new File(folder, "mydata.txt");

Escribir información

3- Obtener los archivos del directorio usando los métodos

Almacenamiento externo

b- getExternalStoragePublicDirectory(String type)

Archivos no específicos a tu app, son deberían ser eliminados al desinstalarla

File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myfile = new File(folder, "mydata.txt");

Escribir información

4- Usar el FileInputStream y el FileOutputStream para realizar la operación requerida

Almacenamiento externo

String string = "Hola mundo!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();

Leer información

1- Obtener los archivos del directorio usando los métodos

Almacenamiento externo

a- getExternalStorageFilesDir(String type)

Archivos específicos a tu app, son eliminados al desinstalarla

File folder = getExternalStorageFilesDir("MyFolder");
File myfile = new File(folder, "mydata.txt");

Leer información

1- Obtener los archivos del directorio usando los métodos

Almacenamiento externo

b- getExternalStoragePublicDirectory(String type)

Archivos no específicos a tu app, son deberían ser eliminados al desinstalarla

File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myfile = new File(folder, "mydata.txt");

Leer información

Almacenamiento externo

FileInputStream fis = openFileInput(FILENAME);
int read = -1;
StringBuffer buffer = new StringBuffer();
read = fis.read();
while ( read != -1) {
    buffer.append((char) read);
}
fis.close();

2- Leer los bytes del archivo usando el método read(). La lectura se ejecuta byte por byte para agregar cada caracter

3- Cerrar el flujo de lectura usando el método close()

Almacenamiento en caché

Cache Storage

  • Guarda datos de la aplicación en la memoria RAM
  • Por defecto, los datos guardados en el almacenamiento en  caché no son permanentes y son borrados automáticamente por el sistema si siente que se encuentra escaso de memoria RAM

Almacenamiento en caché

data/data/<nombre_paquete>/cache

Ubicación

La información se almacena en un archivo XML en el directorio

Cache Storage

Almacenamiento en caché

Guardar datos

1- Usar el método getCacheDir() para abrir un archivo (File) que represente el directorio interno donde tu aplicación debería guardar los archivos (en caché)

2- Usar la clase archivo (File) para crear un archivo dentro de la carpeta cache

3- Llamar al método openFileOutput(String filename) con el nombre del archivo

Almacenamiento en caché

Obtener datos

1- Usar el método getCacheDir() para abrir un archivo (File) que represente el directorio interno donde tu aplicación debería leer los archivos (en caché)

2- Obtener el archivo usando la clase archivo (File) especificando su nombre

3- Usar la clase FileInputStream para leer la información de los archivos

SQLite

Database

  • Base de datos de código abierto
  • Ligera
  • Soporta todas las características pertenecientes a las bases de datos relacionales (Sintaxis SQL, transacciones y sentencias precompiladas)
  • Se encuentra embebida en el sistema operativo Android (no requiere instalación)

data/data/<nombre_paquete>/databases

Ubicación

La información se almacena en un archivo XML en el directorio

SQLite

Crear base de datos y tabla

1- Crear una nueva clase de Java llamada DataBaseHelper

2- Extender la clase con SQLiteOpenHelper

public class DataBaseHelper extends SQLiteOpenHelper{

}
public class DataBaseHelper extends SQLiteOpenHelper{
    @Override
    public void onCreate(SQLiteDatabase db){

    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){

    }
}

3- Implementar los métodos

SQLite

Crear base de datos y tabla

4- Crear el contructor por defecto

5- Definir el nombre de la base de datos y la tabla

public static final String DATABASE_NAME = "Empresa.db";
public static final String TABLE_NAME = "tblEmpleado";
public class DataBaseHelper extends SQLiteOpenHelper{
    public DataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
        super(context, name, factory, version);
    }
    @Override
    public void onCreate(SQLiteDatabase db){

    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){

    }
}

SQLite

Crear base de datos y tabla

6- Definir los nombres de las columnas (campos de la tabla)

public static final String COL_1 = "ID";
public static final String COL_2 = "NOMBRE";
public static final String COL_3 = "APELLIDO";
public class DataBaseHelper extends SQLiteOpenHelper{

    public static final String DATABASE_NAME = "Empresa.db";
    public static final String TABLE_NAME = "tblEmpleado";

    public static final String COL_1 = "ID";
    public static final String COL_2 = "NOMBRE";
    public static final String COL_3 = "APELLIDO";

    public DataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db){

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){

    }
}

El código luce así hasta ahora

SQLite

Crear base de datos y tabla

7- Modificar el constructor para tomar solo el  nombre de la base de datos y la versión para la superclase (Context.Provide)

public DataBaseHelper(Context context){
    super(context, DATABASE_NAME, null, 1);
}

8- En el método onCreate escribir la sentencia para crear la tabla

void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE " + DATABASE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, NOMBRE TEXT, APELLIDO TEXT)");
}

SQLite

Crear base de datos y tabla

9- En el método onUpgrade escribir la sentencia para borrar la tabla en caso de que esta exista

void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
}

10- Crear la base de datos usando el método getWritableDatabase() al interior del constructor

public DataBaseHelper(Context context){
    super(context, DATABASE_NAME, null, 1);
    SQLiteDatabase db = this.getWritableDatabase();
}

SQLite

Crear base de datos y tabla

public class DataBaseHelper extends SQLiteOpenHelper{

    public static final String DATABASE_NAME = "Empresa.db";
    public static final String TABLE_NAME = "tblEmpleado";

    public static final String COL_1 = "ID";
    public static final String COL_2 = "NOMBRE";
    public static final String COL_3 = "APELLIDO";

    public DataBaseHelper(Context context){
        super(context, DATABASE_NAME, null, 1);
        SQLiteDatabase db = this.getWritableDatabase();
    }

    @Override
    void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE " + DATABASE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, NOMBRE TEXT, APELLIDO TEXT)");
    }

    @Override
    void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
    }
}

El código luce así hasta ahora

SQLite

Crear base de datos y tabla

11- Crear un objeto de la clase DataBaseHelper en MainActivity y pasarle el contexto su constructor

DataBaseHelper myDb = new DataBaseHelper(this);

Al crear este objeto, la llamada a su método constructor permite crear la base de datos y sus tablas

SQLite

Insertar

1- Seguir los pasos anteriores para crear la base de datos y sus tablas

public boolean insertData(){

}

2- Crear un método en la clase DatabaseHelper para guardar datos en la tabla

3- Especificar en el método que datos se guardarán en la tabla

public boolean insertData(String nombre, String Apellido){

}

SQLite

Insertar

4- Crear una instancia de la clase ContentValues y usar el método put para guardar los datos en el objeto

ContentValues contentValues = new ContentValues():
contentValues.put(COL_2,nombre);
contentValues.put(COL_3,apellido);

5- Guardar la información en la tabla usando el método insert de la instancia de la clase SQLiteDatabase

long insert (String table, String nullColumnHack, ContentValues values)
Parámetro Uso
table La tabla en la que se insertará la fila actual
nullColumnHack Opcional. Valores por defecto en caso que el parámetro values esté vacío
values Mapeo que contiene los datos a insertar (nombres de columna y sus valores)

SQLite

Insertar

public class DataBaseHelper extends SQLiteOpenHelper{

    public static final String DATABASE_NAME = "Empresa.db";
    public static final String TABLE_NAME = "tblEmpleado";

    public static final String COL_1 = "ID";
    public static final String COL_2 = "NOMBRE";
    public static final String COL_3 = "APELLIDO";

    public DataBaseHelper(Context context){
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE " + DATABASE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, NOMBRE TEXT, APELLIDO TEXT)");
    }

    @Override
    void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
    }

    public boolean insertData(String nombre, String Apellido){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues():
        contentValues.put(COL_2,nombre);
        contentValues.put(COL_3,apellido);
        long result = db.insert(TABLE_NAME, null, contentValues);
        db.close();
        
        //Verificar si la información fue guardada en la base de datos
        if(result == -1){
            Toast.makeText(this, "No guardado", Toast.LENGTH_SHORT).show();
            return false;
        }else{
            Toast.makeText(this, "Guardado correctamente", Toast.LENGTH_SHORT).show();
            return true;
        }
    }
}

Tenemos entonces

SQLite

Insertar

6- Ahora en MainActivity

DataBaseHelper myDb;
myDb.insertData(nombre,apellido);
  • Obtener los valores de las cajas de texto (textFields) con los datos que serán guardados en la tabla
  • Crear un objeto de la clase DataBase Helper e invocar su método insertData

EJERCICIO

Listar

Modificar

Eliminar

Aplicaciones móviles - Almacenamiento local

By Johnattan Jaramillo

Aplicaciones móviles - Almacenamiento local

Curso Desarrollo de aplicaciones para dispositivos móviles

  • 1,080