5 maneiras de armazenar dados em aplicações Android

O Android fornece diversas opções para você salvar dados de sua aplicação. A solução escolhida depende de sua necessidade, como se os dados devem ser privados para sua aplicação ou devem ser acesssiveis para outras aplicações (e para o usuário) e quanto espaço seus dados precisam.

Suas opções de armazenamento de dados são as seguintes:

Shared Preferences
Armazena dados primitivos provados em pares chave-valor.
Internal Storage
Armazena dados privados na memória do dispositivo.
External Storage
Armazena dados públicos no cartão de memória.
SQLite Databases
Armazena dados estruturados num banco de dados privado.
Network Connection
Armazena dados na web no seu servidor de rede.

O Android fornece uma maneira para que você possa expor seus dados privados para outras aplicações – com um content provider. Um content provider é um componente opcional que permite o acesso de leitura e escrita aos dados de sua aplicação, sujeito às restrições impostas por você.

Usando Shared Preferences

A classe SharedPreferences fornece um framework geral que permite que você salve e recupere pares de chave-valor de tipos de dados primitivos. Você pode usar SharedPreferences para salvar qualquer tipo primitivo: boolean,floats, ints, longs, e strings. Esses dados serão persistentes entre sessões (mesmo que sua aplicação seja encerrada).

Para obter um objeto SharedPreferences para sua aplicação, use um dos dois metódos:

  • getSharedPreferences() – Use esse metódo se você precisar de múltiplos arquivos identificados por nome, que você deve especificar no primeiro parametro.
  • getPreferences() – Use esse metódo de você possuir um único arquivo para sua Activity. Por existir um único arquivo, você não precisa fornecer um nome.

Para escrever valores:

  1. Chame edit() para obter um SharedPreferences.Editor.
  2. Adicione valores com os metódos  putBoolean(), putString(), etc.
  3. Salve os novos valores com commit()

Para ler os valores, use os metódos correspondentes de SharedPreferences como getBoolean() e getString().

Abaixo segue um exemplo que salva uma preferência para definir o modo de tecla silenciosa em uma calculadora:

public class Calc extends Activity {
    public static final String PREFS_NAME = "MyPrefsFile";

    @Override
    protected void onCreate(Bundle state){
       super.onCreate(state);
       . . .

       // Restore preferences
       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
       boolean silent = settings.getBoolean("silentMode", false);
       setSilent(silent);
    }

    @Override
    protected void onStop(){
       super.onStop();

      // We need an Editor object to make preference changes.
      // All objects are from android.context.Context
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
      SharedPreferences.Editor editor = settings.edit();
      editor.putBoolean("silentMode", mSilentMode);

      // Commit the edits!
      editor.commit();
    }
}

Usando o Armazenamento interno

Você pode salvar arquivos diretamente na memória interna do dispositivo. Por padrão, arquivos salvos na memória interna são privados a sua aplicação e outras aplicações não podem acessá-las (nem o usuário). Quando o usuário desinstala a aplicação, esses arquivos são removidos.

Para criar e escrever um arquivo na memória interna siga os passos:

  1. Chame openFileOutput() com o nome do arquivo e o modo de operação. Isso retorna um FileOutputStream.
  2. Escreva no arquivo com write().
  3. Encerre o fluxo de dados com close().

Por examplo:

String FILENAME = "hello_file";
String string = "hello world!";

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

MODE_PRIVATE criará um arquivo novo (ou subscreverá um arquivo de mesmo nome) e tornará ele privado para sua aplicação. Os outros modos disponíveis são MODE_APPEND, MODE_WORLD_READABLE, e MODE_WORLD_WRITEABLE.

Para ler um arquivo localizado na memória interna:

  1. Chame openFileInput() e passe o nome do arquivo. Isso irá retorna um FileInputStream.
  2. Leia bytes desse arquivo com read().
  3. Quando terminar, encerre o fluxo de dados com close().

Dica: Se você quiser salvar um arquivo estático em sua aplicação durante a compilação, salve o arquivo em seu diretório res/raw/. Você poderá abri-lo com o metódo openRawResource(), passando o ID R.raw.<filename>. Esse metódo retorna umInputStream que você pode usar para acessar o conteúdo do arquivo (mas não poderá escrever no arquivo original).

Salvando arquivo de cache

Se você quiser armazenar alguma informação em cache, ao invés de armazena-las de modo persistente, deve usar getCacheDir() para abrir um File que representa o diretório interno onde sua aplicação irá salvar arquivos de cache temporários.

Quando o dispositivo estiver com pouco espaço de memória, o Android pode deletar esses arquivos de cache para recuperar o espaço. Porém, você não deveria deixar o sistema limpar esses arquivos para você. Você deveria sempre manter os seus arquivos de cache e deixa-los dentro de um limite de espaço razoavel, algo em torno de 1mB. Quando o usuário desinstala a aplicação, esses arquivos são removidos.

Outros metódos úteis

getFilesDir()
Obtém o caminho absoluto do diretório onde seus arquivos estão salvos.
getDir()
Cria (ou abre se existir) um diretório na memória interna.
deleteFile()
Apaga um arquivo salvo na memória interna.
fileList()
Retorna uma lista de arquivos salvos por sua aplicação.

Usando a memória externa

Os dispositivos compativeis com o Android suportam o uso de memórias externas onde você pode salvar arquivos. Essa memória pode ser uma mídia de armazenamento removível (como um cartõ SD) ou uma memória interna (não-removível). Os arquivos salvos na memória externa podem ser lidos por qualquer outro dispositivo ou aplicação e podem ser modificados pelo usuário quando ele ativar a transferência USB ao conectar o dispositivo com um computador.

Cuidado: Arquivos armazenados na memória externa pode disaparecer se o usuário montar a mídia em um computador ou remover o cartão, e não existe nenhuma medida de segurança sobre os arquivos salvos nesse tipo de memória. Todas as aplicações podem ler e escrever arquivos localizados em memórias externas e o usuário pode remove-los.

Verificando a disponibilidade da mídia

Antes que você possa executar qualquer ação com a memória externa, deve sempre chamar getExternalStorageState() para verificar que a mídia esta disponível. A mídia pode estar montada em um computador, não estar presente, montado como somente leitura, ou em algum outro estado. Por exemplo, abaixo segue uma maneira de verificar a disponibilidade da memória externa:

boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {
    // We can read and write the media
    mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    // We can only read the media
    mExternalStorageAvailable = true;
    mExternalStorageWriteable = false;
} else {
    // Something else is wrong. It may be one of many other states, but all we need
    //  to know is we can neither read nor write
    mExternalStorageAvailable = mExternalStorageWriteable = false;
}

Esse exemplo verifica se a memóri externa está disponivel para leitura e escrita. O metódo getExternalStorageState() retorna outros estados que talvez você queira checar, como se a mídia está sendo compartilhada com um computador, se não está presente no dispositivo, se foi removida de forma não segura, etc. Você pode usar essas checagens para fornecer ao usuário informações completar no momento que sua aplicação precisar usar a mídia.

Acessando arquivos na memória externa

Se você estiver usando a API no nível 8 ou superior, use getExternalFilesDir() para abrir umFile que representa o diretório da memória externa onde você quer salvar seus arquivos, Esse metódo pede um parametro ‘type’ que especifica o tipo de diretório que quer criar, como DIRECTORY_MUSIC e DIRECTORY_RINGTONES (passe o valor ‘null’ para obter a raiz do diretório de arquivos de sua aplicação). Esse metódo criará os diretórios apropriados se necessário. Especificando o tipo de diretório, você garante que o scanner de mídia do Android irá classificar corretamente seus arquivos no sistema (por exemplo, ringtones serão identificados como ringtones e não música). Se o usuário desinstalar sua aplicação, esse diretório e todo o seu conteúdo será removido.

Se estiver usando a API no nível 7 ou inferior, use getExternalStorageDirectory(), para abrir um File que represente a riz da memória externa. Você irá escrever seus dados no seguinte diretório:

/Android/data/<package_name>/files/

O nome <package_name> é o nome do seu pacote, como em “com.example.android.app”. Se o dispositivo do usuário estiver rodando a API nível 8 ou superior e a sua aplicação for desinstalada, esse diretório e todo o seu conteúdo será removido.

Salvando arquivos que devem ser compartilhados

Se você quiser salvar arquivos que não sejam específicos a sua aplicação e que não devem ser apagados quando sua aplicação for desinstalada, salve-os em um dos diretórios públicos da memória externa. Esses diretórios ficam na raiz da memória externa, como Music/, Pictures/, Ringtones/ e outros.

Se estiver usando a API nível 8 ou superior, use getExternalStoragePublicDirectory(), passando o tipo de diretório público que você quiser, como DIRECTORY_MUSIC, DIRECTORY_PICTURES, DIRECTORY_RINGTONES, ou outros. Esse metódo irá criar o diretório apropriado se necessário.

Se estiver usando a API nível 7 ou inferior, use getExternalStorageDirectory() para abrir um File que represente a raiz da memória externa, e então salve seus arquivos em um dos diretórios abaixo:

  • Music/
  • Podcasts/
  • Ringtones/
  • Alarms/
  • Notifications/
  • Pictures/
  • Movies/
  • Download/

Salvando arquivos de cache

Se você estiver usando a API nível 8 ou superior, use getExternalCacheDir() para abrir um File que represente o diretório da memória externa onde você irá salvar seus arquivos de cache. Se o usuário desinstalar sua aplicação, esses arquivos serão automaticamente removidos. Porém, durante o ciclo de vida de sua aplicaçã0, você deve gerenciar esses arquivos de cache e removê-los quando não forem necessários para liberar espaço na memória.

Se estiver usando a API nível 7 ou inferior, use getExternalStorageDirectory() para abrir um File que representa a raiz da memória externa, então escreva os dados de cache no seguinte diretório:

/Android/data/<package_name>/cache/

O <package_name> é o nome do pacote, como “com.example.android.app”.

Usando banco de dados

O Android fornece suporte completo a banco de dados SQLite. Qualquer banco de dados que você criar será acessível pelo nome por qualquer classe da aplicação, mas não fora da aplicação.

O metódo recomendado para criar um novo banco de dados SQLite é criar uma sub-classe de SQLiteOpenHelper e sobrecarregar o metódo onCreate(), onde você poderá executar um comando SQLite para criar tabelas no banco de dados. Por exemplo:

public class DictionaryOpenHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 2;
    private static final String DICTIONARY_TABLE_NAME = "dictionary";
    private static final String DICTIONARY_TABLE_CREATE =
                "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
                KEY_WORD + " TEXT, " +
                KEY_DEFINITION + " TEXT);";

    DictionaryOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DICTIONARY_TABLE_CREATE);
    }
}

Você pode então obter uma instância de sua implementação SQLiteOpenHelper usando o construtor que você definiu. Para escrever e ler do banco de dados, chame getWritableDatabase() e getReadableDatabase(), respectivamente. Ambas retornam um objeto SQLiteDatabase que representa o banco de dados e fornece metódos para operações SQLite.

Você pode executar consultaas SQLite usando os metódos SQLiteDatabase query(), que aceitam vários parâmetros de consulta, como a tabela de query, projeções, seleções, colunas, grupos e outros. Para queries complexas, como aquelas que requerem aliases de colunas, você deve usar SQLiteQueryBuilder, que fornece muitos metódos convenientes para a construção de queries.

Cada query  SQLite retorna um Cursor que aponta para todos os campos encontrados pela query. O Cursor é sempre o mecanismo com o qual você pode navegar pelos resultados da query e ler os campos e colunas.

Usando uma conbexão de rede

Você pode usar a rede (quando disponível) para armazenar e recuperar dados de seus serviços baseados e web. Para executar operações de rede, use classes dos seguintes pacotes:

Traduzido de developer.android.com

  • Alef

    Ajudou muito… vlw!