No primeiro post sobre escrita e leitura de arquivos no Android descrevi como ler e escrever na memória interna do Android. Este post descreve como escrever e ler em arquivos armazenados no cartão SD do dispositivo.
Antes de optar em gravar informações no cartão SD do dispositivo, lembre-se que o usuário terá acesso as informações deste arquivo e poderá apagá-lo a qualquer momento. Também não existe a garantia do arquivo não ser apagado durante a conexão ou desconexão do dispositivo com o microcomputador, caso o mesmo seja desconectado de forma incorreta.
Para demonstrar a leitura e escrita no cartão SD, vou utilizar o mesmo layout do projeto da parte I do post:
Antes de criar e escrever em um arquivo no cartão SD de um dispositivo, é necessário verificar se o cartão está inserido, quais são as permissões de escrita e leitura, se o sistema de arquivo é reconhecido pelo dispositivo, entre outras informações.
Foi criada a classe ManageFile com o método getStateSDcard() que verifica o estado do cartão SD, o método WriteFile() que faz a escrita do texto e o método ReadFile() que faz a leitura do texto armazenado no cartão SD.
public class ManageFile { private static final String TAG = "ManageFile"; private Context context; private boolean sdCardAvailable; private boolean sdCardWritableReadable; private boolean sdCardReadableOnly; public ManageFile(Context context){ this.context = context; } /** * Escreve no arquivo texto. * @param text Texto a ser escrito. * @return True se o texto foi escrito com sucesso. */ public boolean WriteFile(String text){ try { File file = new File(context.getExternalFilesDir(null), "romar.txt"); FileOutputStream out = new FileOutputStream(file, true); out.write(text.getBytes()); out.write("\n".getBytes()); out.flush(); out.close(); return true; } catch (Exception e) { Log.e(TAG, e.toString()); return false; } } /** * Faz a leitura do arquivo * @return O texto lido. * @throws FileNotFoundException * @throws IOException */ public String ReadFile() throws FileNotFoundException, IOException{ File textfile = new File(context.getExternalFilesDir(null), "romar.txt"); FileInputStream input = new FileInputStream(textfile); byte[] buffer = new byte[(int)textfile.length()]; input.read(buffer); return new String(buffer); } public void getStateSDcard(){ // Obtêm o status do cartão SD String status = Environment.getExternalStorageState(); if (Environment.MEDIA_BAD_REMOVAL.equals(status)) { // Midia foi removida antes de ser montada sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia removida."); } else if (Environment.MEDIA_CHECKING.equals(status)) { // Midia está presente e está sendo feita a verificação sdCardAvailable = true; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia sendo verificada."); } else if (Environment.MEDIA_MOUNTED.equals(status)) { // A midia está presente e montada neste momento com // permissão de escrita e leitura sdCardAvailable = true; sdCardWritableReadable = true; sdCardReadableOnly = false; Log.d(TAG, "Midia com permissão de escrita e leitura."); } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) { // A midia está presente e montada neste momento com // permissão somente de leitura sdCardAvailable = true; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia com permissão somente leitura."); } else if (Environment.MEDIA_NOFS.equals(status)) { // A midia está presente, mas está vazia ou utilizando um // sistema de arquivos não suportado sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia com sistema de arquivos não compatível."); } else if (Environment.MEDIA_REMOVED.equals(status)) { // A midia não está presente sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia não presente."); } else if (Environment.MEDIA_SHARED.equals(status)) { // A midia está presente, não montada e compartilhada // via USB sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia compartilhada via USB."); } else if (Environment.MEDIA_UNMOUNTABLE.equals(status)) { // A midia está presente mas não pode ser montada sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia não pode ser montada"); } else if (Environment.MEDIA_UNMOUNTED.equals(status)) { // A midia está presente mas não montada sdCardAvailable = false; sdCardWritableReadable = false; sdCardReadableOnly = false; Log.d(TAG, "Midia não montada."); } } public boolean isSdCardAvailable() { return sdCardAvailable; } public void setSdCardAvailable(boolean sdCardAvailable) { this.sdCardAvailable = sdCardAvailable; } public boolean isSdCardWritableReadable() { return sdCardWritableReadable; } public void setSdCardWritableReadable(boolean sdCardWritableReadable) { this.sdCardWritableReadable = sdCardWritableReadable; } public boolean isSdCardReadableOnly() { return sdCardReadableOnly; } public void setSdCardReadableOnly(boolean sdCardReadableOnly) { this.sdCardReadableOnly = sdCardReadableOnly; } }
No método WriteFile() foi utilizado o método getExternalFilesDir() do Android para obter o diretório do cartão SD. Foi passado o valor null como parâmetro, para que seja retornada a raiz do diretório da aplicação na área de armazenamento externa, no nosso caso o cartão SD (válido para a API 8, vide nota abaixo).
O arquivo vai ser escrito no diretório:
/Android/data/<nome_pacote>/files/
onde
nome_pacote
é o pacote da aplicação, no nosso caso br.com.romar.NOTA: O método getExternalFilesDir() deve ser utilizado em projetos que rodam a partir da API 8. Para projetos que rodam na API 7 ou inferior, deverá ser utilizado o método getExternalStorageDirectory(), que irá retornar a raiz do diretório do cartão SD. Neste caso o arquivo será gravado na raiz do cartão e não no diretório da aplicação. No caso da API 8, quando a aplicação for desinstalada os arquivos que estiverem no cartão SD no diretório /Android/data/<nome_pacote>/files serão apagados.
No método ReadFile() foi utilizado o mesmo método getExternalFilesDir() do Android para abrir o arquivo gravado anteriormente para leitura.
Na Activity principal do projeto foi criado um botão para escrita e leitura do arquivo. Segue o código que trata o click em cada um dos botões:
@Override public void onClick(View v) { try { switch (v.getId()) { case R.id.btnRead: // Faz a leitura do arquivo // Verifica se o sdcard tem permissão para leitura if (managefile.isSdCardAvailable() && (managefile.isSdCardReadableOnly() || managefile.isSdCardWritableReadable())) { managefile.getStateSDcard(); textRead.setText(managefile.ReadFile()); } else { Toast.makeText(this, "O cartão SD não está disponível, ou não permite" + " leitura", Toast.LENGTH_SHORT).show(); } break; case R.id.btnWrite: // Faz a escrita do arquivo // Verifica se o sdcard tem permissão para escrita if (managefile.isSdCardAvailable() && managefile.isSdCardWritableReadable()) { // Avisa o usuário se a gravação foi bem sucedida if(managefile.WriteFile(editText.getText().toString()) == true){ Toast.makeText(this, "Texto gravado com sucesso.", Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(this, "Não foi possível escrever o texto.", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "O cartão SD não está disponível, ou não permite" + " escrita.", Toast.LENGTH_SHORT).show(); } // Reseta o campo do texto editText.setText(""); break; default: break; } } catch (FileNotFoundException e) { Log.e(TAG, e.toString()); } catch (IOException e) { Log.e(TAG, e.toString()); } }
O cartão SD do dispositivo por padrão possui somente permissão de leitura. Para que seja possível escrever no cartão é necessário que no momento da instalação da aplicação o usuário dê a permissão de escrita na área de armazenamento externo. Para que a aplicação tenha a permissão de escrita é necessário inserir no arquivo AndroidManifest.xml da aplicação a seguinte tag:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />