Android ofrece varias opciones para almacenar datos de aplicaciones que utilizan un sistema de archivos similar al sistema basado en disco en plataformas informáticas
- Almacenamiento específico de la aplicación: almacene archivos de datos en directorios de volúmenes internos o externos. Estos archivos de datos están destinados solo para el uso de la aplicación. Utiliza directorios de almacenamiento interno para guardar información confidencial, como un nombre de usuario y una contraseña, a los que otras aplicaciones no deben acceder.
- Almacenamiento compartido: almacena archivos de datos como imágenes, audio, video, documentos, etc. que la aplicación puede necesitar compartir con otras aplicaciones.
- Preferencias compartidas: almacene tipos de datos primitivos como enteros, flotantes, booleanos, strings, largos en pares clave-valor.
- Bases de datos: almacene datos estructurados, como información del usuario (nombre, edad, teléfono, correo electrónico, dirección, etc.) en bases de datos privadas.
Se recomienda a los desarrolladores que utilicen las opciones disponibles para almacenar datos según el espacio requerido , el acceso confiable a los datos y la privacidad de los datos . Los archivos de datos guardados en dispositivos de almacenamiento externo son de acceso público en el almacenamiento externo compartido mediante la transferencia de almacenamiento masivo USB. Los archivos de datos almacenados en almacenamiento externo mediante un objeto FileOutputStream y se pueden leer mediante un objeto FileInputStream .
Disponibilidad de almacenamiento externo
Para evitar bloquear la aplicación primero, debemos verificar que la tarjeta SD de almacenamiento esté disponible para operaciones de lectura y escritura. El método getExternalStorageState() se usa para determinar el estado de los medios de almacenamiento montados, como si falta la tarjeta SD, es de solo lectura o se puede leer y escribir. A continuación se muestra el fragmento de código que utilizaremos para comprobar la disponibilidad de almacenamiento externo.
Java
boolean isAvailable= false; boolean isWritable= false; boolean isReadable= false; String state = Environment.getExternalStorageState(); if(Environment.MEDIA_MOUNTED.equals(state)) { // Operation possible - Read and Write isAvailable= true; isWritable= true; isReadable= true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // Operation possible - Read Only isAvailable= true; isWritable= false; isReadable= true; } else { // SD card not available isAvailable = false; isWritable= false; isReadable= false; }
Métodos para almacenar datos en almacenamiento externo
- getExternalStoragePublicDirectory(): este es el método recomendado actualmente para mantener los archivos públicos y estos archivos no se eliminan incluso cuando la aplicación se desinstala del sistema. Por ejemplo: las imágenes en las que la cámara hace clic todavía están disponibles incluso después de desinstalar la cámara.
- getExternalFilesDir (tipo de string): este método se usa para almacenar datos privados que son específicos de la aplicación únicamente. Y los datos se eliminan a medida que desinstalamos la aplicación.
- getExternalStorageDirectory(): no se recomienda este método. Ahora es absoluto y se usa para acceder al almacenamiento externo en versiones anteriores, nivel de API inferior a 7.
Ejemplo
En este ejemplo, almacenaríamos datos de texto en el almacenamiento externo y buscaríamos para ver esos datos. whatTenga en cuenta que vamos a implementar este proyecto utilizando el lenguaje Java .
Implementación paso a paso
Paso 1: Crear un nuevo proyecto
Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Java como lenguaje de programación.
Paso 2: Permiso de acceso al almacenamiento externo
Para leer y escribir datos en el almacenamiento externo, la aplicación requería el permiso del sistema WRITE_EXTERNAL_STORAGE y READ_EXTERNAL_STORAGE . Estos permisos se agregan al archivo AndroidManifest.xml . Agregue estos permisos justo después del nombre del paquete.
XML
<manifest ... > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application ... > <activity android:name=".MainActivity" ... > ... </activity> </application> </manifest>
Paso 3: antes de crear el diseño y los archivos java correspondientes, agreguemos algunos atributos de string que estamos usando en nuestros archivos de diseño
Vaya a aplicación > res > valores > string.xml e inserte el siguiente fragmento de código
XML
<resources> ... <string name="text_view_data">Enter the Text Data</string> <string name="edit_text_data">Enter your information</string> <string name="view_button">View Information</string> <string name="save_button_public">Save Publicly</string> <string name="save_button_private">Save Privately</string> <string name="text_view_saved_data">Saved Text Data</string> <string name="saved_information">Click to view saved information</string> <string name="back_button">Go Back</string> <string name="show_button_public">Public Data</string> <string name="show_button_private">Private Data</string> ... </resources>
Ahora vaya a aplicación > res > valores > colores.xml y cambie los atributos de color de la siguiente manera para que la barra de aplicaciones sea más atractiva.
XML
<resources> <color name="colorPrimary">#0F9D58</color> <color name="colorPrimaryDark">#16E37F</color> <color name="colorAccent">#03DAC5</color> <color name="buttonColor">#0F9D58</color> <color name="textColor">#FFFFFF</color> </resources>
Vuelva a ir a app > res > drawable y cree un nuevo archivo de recursos Drawable y asígnele el nombre button_layout . En esto, estamos modificando el estilo de nuestro botón para una mejor UX/UI.
XML
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:bottomLeftRadius="25dp" android:bottomRightRadius="25dp" android:radius="50dp" android:topLeftRadius="25dp" android:topRightRadius="25dp" /> <padding android:bottom="0dp" android:left="0dp" android:right="0dp" android:top="0dp" /> <size android:width="64dp" android:height="16dp" /> <solid android:color="@color/buttonColor" /> </shape>
Paso 4: trabajar con el archivo activity_main.xml
Vaya a res > diseño > actividad_principal.xml y escriba el siguiente código. En este archivo de diseño, estamos creando una vista EditText de varias líneas para obtener los datos de los usuarios y los botones para guardar esos datos en medios de almacenamiento internos y externos.
XML
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/saveButton_public" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_below="@+id/editText_data" android:layout_marginEnd="48dp" android:layout_marginTop="8dp" android:background="@drawable/button_layout" android:onClick="savePublicly" android:padding="8dp" android:text="@string/save_button_public" android:textAllCaps="false" android:textColor="@color/textColor" /> <Button android:id="@+id/saveButton_private" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_below="@+id/editText_data" android:layout_marginStart="48dp" android:layout_marginTop="8dp" android:layout_toEndOf="@+id/saveButton_public" android:background="@drawable/button_layout" android:onClick="savePrivately" android:padding="8dp" android:text="@string/save_button_private" android:textAllCaps="false" android:textColor="@color/textColor" /> <Button android:id="@+id/viewButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/saveButton_public" android:layout_centerHorizontal="true" android:layout_marginTop="16dp" android:background="@drawable/button_layout" android:onClick="viewInformation" android:padding="8dp" android:text="@string/view_button" android:textAllCaps="false" android:textColor="@color/textColor" /> <EditText android:id="@+id/editText_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/textView_data" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" android:autofillHints="" android:hint="@string/edit_text_data" android:inputType="textMultiLine" /> <TextView android:id="@+id/textView_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="8dp" android:text="@string/text_view_data" android:textAllCaps="true" android:textStyle="bold" /> </RelativeLayout>
Paso 5: trabajar con el archivo MainActivity.java
En MainActivity definimos las funciones que manejaron el comportamiento onClick de los botones. Y obtenga los datos de EditText y guárdelos en un almacenamiento externo de forma pública y privada. También mostramos un mensaje Toast de la ruta donde se almacenan los datos.
Java
import android.Manifest; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.EditText; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class MainActivity extends AppCompatActivity { // After API 23 the permission request for accessing external storage is changed // Before API 23 permission request is asked by the user during installation of app // After API 23 permission request is asked at runtime private int EXTERNAL_STORAGE_PERMISSION_CODE = 23; EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // findViewById return a view, we need to cast it to EditText View editText = (EditText) findViewById(R.id.editText_data); } public void savePublicly(View view) { // Requesting Permission to access External Storage ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_PERMISSION_CODE); String editTextData = editText.getText().toString(); // getExternalStoragePublicDirectory() represents root of external storage, we are using DOWNLOADS // We can use following directories: MUSIC, PODCASTS, ALARMS, RINGTONES, NOTIFICATIONS, PICTURES, MOVIES File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); // Storing the data in file with name as geeksData.txt File file = new File(folder, "geeksData.txt"); writeTextData(file, editTextData); editText.setText(""); } public void savePrivately(View view) { String editTextData = editText.getText().toString(); // Creating folder with name GeekForGeeks File folder = getExternalFilesDir("GeeksForGeeks"); // Creating file with name gfg.txt File file = new File(folder, "gfg.txt"); writeTextData(file, editTextData); editText.setText(""); } public void viewInformation(View view) { // Creating an intent to start a new activity Intent intent = new Intent(MainActivity.this, ViewInformationActivity.class); startActivity(intent); } // writeTextData() method save the data into the file in byte format // It also toast a message "Done/filepath_where_the_file_is_saved" private void writeTextData(File file, String data) { FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); fileOutputStream.write(data.getBytes()); Toast.makeText(this, "Done" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Paso 6: crea una nueva actividad vacía
Crearemos una nueva actividad y la llamaremos ViewInformationActivity . Usamos esta actividad para mostrar los datos guardados del almacenamiento externo. Entonces, primero, creamos un diseño para esta actividad similar al diseño MainActivity. fragmento de código de diseño activity_view_information.xml :
XML
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ViewInformationActivity"> <Button android:id="@+id/showButton_public" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_below="@+id/textView_get_saved_data" android:layout_marginEnd="48dp" android:layout_marginTop="8dp" android:background="@drawable/button_layout" android:onClick="showPublicData" android:padding="8dp" android:text="@string/show_button_public" android:textAllCaps="false" android:textColor="@color/textColor" /> <Button android:id="@+id/showButton_private" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_below="@+id/textView_get_saved_data" android:layout_marginStart="48dp" android:layout_marginTop="8dp" android:layout_toEndOf="@+id/showButton_public" android:background="@drawable/button_layout" android:onClick="showPrivateData" android:padding="8dp" android:text="@string/show_button_private" android:textAllCaps="false" android:textColor="@color/textColor" /> <Button android:id="@+id/goBackButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/showButton_public" android:layout_centerHorizontal="true" android:layout_marginTop="16dp" android:background="@drawable/button_layout" android:onClick="back" android:padding="8dp" android:text="@string/back_button" android:textAllCaps="false" android:textColor="@color/textColor" /> <TextView android:id="@+id/textView_get_saved_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/textView_saved_data" android:layout_marginTop="8dp" android:gravity="center" android:hint="@string/saved_information" /> <TextView android:id="@+id/textView_saved_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center" android:text="@string/text_view_saved_data" android:textAllCaps="true" android:textStyle="bold" /> </RelativeLayout>
Ahora, crearemos un código java correspondiente para ViewInformationActivity . En esto, definimos los métodos showPublicData() y showPrivateData() sobre botones que obtendrán los datos de los archivos guardados en el almacenamiento externo y agregarán los datos al búfer, y luego completarán los datos en TextView para mostrarlos. Fragmento de código de ViewInformationAcity.java :
Java
import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.view.View; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class ViewInformationActivity extends AppCompatActivity { TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_information); // findViewById returns a view, we need to cast it into TextView textView = (TextView) findViewById(R.id.textView_get_saved_data); } public void showPublicData(View view) { // Accessing the saved data from the downloads folder File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); // geeksData represent the file data that is saved publicly File file = new File(folder, "geeksData.txt"); String data = getdata(file); if (data != null) { textView.setText(data); } else { textView.setText("No Data Found"); } } public void showPrivateData(View view) { // GeeksForGeeks represent the folder name to access privately saved data File folder = getExternalFilesDir("GeeksForGeeks"); // gft.txt is the file that is saved privately File file = new File(folder, "gfg.txt"); String data = getdata(file); if (data != null) { textView.setText(data); } else { textView.setText("No Data Found"); } } public void back(View view) { Intent intent = new Intent(ViewInformationActivity.this, MainActivity.class); startActivity(intent); } // getdata() is the method which reads the data // the data that is saved in byte format in the file private String getdata(File myfile) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(myfile); int i = -1; StringBuffer buffer = new StringBuffer(); while ((i = fileInputStream.read()) != -1) { buffer.append((char) i); } return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }