Páginas

Pesquisar neste blog

Mostrando postagens com marcador Android. Mostrar todas as postagens
Mostrando postagens com marcador Android. Mostrar todas as postagens

25 de abril de 2019

Como Customizar a Mensagem Toast no Android



A mensagem Toast exibida nos dispositivos Android é bem conhecida, trata-se daquela mensagem que o smartphone exibe quando executa algumas operações e avisa que finalizou ou que está em processo por exemplo, a mensagem que avisa que está enviando o e-mail. A mensagem Toast padrão tem uma cor de fundo cinza escuro com os caracteres em branco, mas e se você quiser usar a mensagem Toast e customizar a aparência como alterar a cor de fundo, o tamanho e a cor do texto e quem sabe até mesmo a aparência da mensagem.

Para customizar a mensagem de Toast precisamos criar uma variável que aponta para uma mensagem de Toast, obter a View padrão da mensagem e o TextView que armazena o texto da mensagem. Dependendo de quais customizações queremos fazer podemos precisar de cada uma destas variáveis. No exemplo abaixo a variável toast é usada para configurar o posicionamento da mensagem na tela, no caso a mensagem deve ser centralizada verticalmente, a variável toastMessage usamos para configurar a cor e o tamanho do fonte do texto, e a variável toastView usamos para configurar a cor de fundo da mensagem Toast.

Context context = getApplicationContext();
Toast toast = Toast.makeText(context, "Mensagem.....", Toast.LENGTH_LONG);

// Retorna a View padrão da mensagem
View toastView = toast.getView();

// Para customizar o texto da mensagem obter a View do componente do texto
// que no caso é um TextView
TextView toastMessage = (TextView) toastView.findViewById(android.R.id.message);
toastMessage.setTextSize(50);
toastMessage.setTextColor(Color.YELLOW);

// Centraliza a mensagem no centro da tela
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);

// Altera a cor de fundo da mensagem
toastView.setBackgroundColor(Color.BLUE);

// Exibe a mensagem
toast.show();

O código acima exibe uma mensagem Toast com a aparência mostrada na figura abaixo:

Figura 1 - Mensagem Toast Customizada
Além das customizações mostradas neste post é possível fazer mais customizações como por exemplo, alterar completamente o visual do componente Toast, veja mais informações de customização no site de desenvolvedores do Android
https://developer.android.com/guide/topics/ui/notifiers/toasts


4 de abril de 2019

Como Obter a Carga da Bateria Programaticamente no Android

Para obter a informação da carga da bateria no smartphone podemos criar um IntentFilter e chamar o registerReceiver para obter o estado atual da bateria.


IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = registerReceiver(null, ifilter);

int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

float batteryPct = level / (float)scale;

Toast.makeText(this, "Nível da bateria: " + String.valueOf(batteryPct * 100)
                + "%", Toast.LENGTH_LONG).show();

O exemplo acima exibe o nível de bateria atual usando as informações de nível e escala do estado da bateria.



A verificação do estado da bateria também acaba consumindo a carga da bateria, por este motivo a chamada desta informação deve ser feita com cuidado nos casos em que a bateria está baixa.

27 de março de 2019

Como Alterar o Tempo de Exibição da Mensagem Toast no Android



A mensagem Toast é aquela mensagem que aparece para confirmar alguma alteração, progresso de uma tarefa ou qualquer outra informação em dispositivos Android. A mensagem normalmente possui o texto em branco com um fundo cinza escuro.

A ideia por trás deste tipo de mensagem é passar uma informação para o usuário sem atrapalhar a atividade que ele estiver executando. A mensagem "aparece" por um curto espaço de tempo e "desaparece" sem a necessidade de interação do usuário.

A mensagem Toast como é conhecida no Android é uma View onde você pode definir a mensagem e o tempo de exibição, o intervalo de tempo pode ser curto - LENGHT_SHORT, dura em torno de 2 segundos ou longo - LENGHT_LONG, que dura em torno de 3,5 segundos. Mas e se você precisar que a mensagem fique visível por um intervalo de tempo maior, para o caso por exemplo, de uma mensagem mais longa.

A classe Toast não permite definir um intervalo de exibição da mensagem diferente dos valores pré-definidos, LENGHT_LONG e LENGHT_SHORT, então para aumentar este tempo podemos usar como uma possível solução a classe CountDownTimer. Esta classe permite definir um intervalo de tempo de exibição da mensagem durante um tempo pré-definido por exemplo, exibe a mensagem a cada 1 segundo durante 10 segundos. Segue o código exemplo para exibir uma mensagem Toast por 10 segundos:


final Toast toast = Toast.makeText(this, "Esta é uma mensagem Toast",
        Toast.LENGTH_LONG);

// Exibe a mensagem por 10 segundos
CountDownTimer toastCountDown;
toastCountDown = new CountDownTimer(10000, 1000) {
    public void onTick(long millisUntilFinished) {
        toast.show();
    }
    public void onFinish() {
        toast.cancel();
    }
};

// Exibe a mensagem
toast.show();
// Inicia a contagem do tempo
toastCountDown.start();

No método onFinish() da classe CountDownTimer cancelamos a exibição da mensagem quando atinge o tempo máximo.

Esta solução funciona porque a mensagem fica visível na tela pelo tempo definido e desaparece ao final do tempo máximo.

8 de março de 2019

Como Compilar o Aplicativo WiFiDirectDemo no Android Studio

A partir da API 14 (Android 4.0) é possível fazer a comunicação entre dispositivos Android, que possuem o hardware adequado, através do WiFi, sem a necessidade de usar um equipamento intermediário, tipo um access point (ponto de acesso). Para testar essa funcionalidade, existe um código exemplo que o Google fornece que está no link WiFiDirectDemo, mas o projeto está no formato do Eclipse, e para compilar e rodar através do Android Studio precisa importar o projeto no ambiente de desenvolvimento, antes de conseguir compilar.

Como compilar

Após baixar o arquivo do projeto é possível abrir no Android Studio, mas infelizmente o Android Studio não apresenta nenhuma indicação que o projeto está em Eclipse, ele abre o projeto, mas não é possível compilar e rodar o exemplo.

Para compilar e rodar o exemplo é necessário fazer a importação do projeto Eclipse para o projeto Android Studio. Para importar o projeto use a opção Import Project na tela inicial do Android Studio, onde aparecem as opções para criar um projeto novo, abrir um existente, importar um projeto, dentre outras opções.

Tela Inicial do Android Studio

A importação do projeto demora um pouco, mas depois que importar, o projeto compila e roda com sucesso.

Tela do Aplicativo WiFiDirectDemo

OBS: Caso você precise rodar o aplicativo em uma API inferior a 23 (Marshmallow), vai dar erro de compilação na biblioteca do FileProvider que foi inserido na API 22, portanto para usar toda a funcionalidade do aplicativo a API mínima deve ser a 23.

Links com mais informações sobre o WiFi Direct:
Connect devices wirelessly
Wi-Fi peer-to-peer overview


28 de fevereiro de 2019

Escrita e Leitura de Arquivo no Android – Parte I

Os dispositivos com o Android permitem a escrita e leitura de arquivos na memória interna. Este post descreve como criar um arquivo texto, escrever e visualizar o conteúdo do arquivo no próprio dispositivo e como exportar o arquivo do emulador do Eclipse para o computador.

Como cada aplicação do Android roda em seu próprio contexto, o arquivo só pode ser manipulado pela própria aplicação que criou o arquivo. O arquivo não é visualizado por outras aplicações e não pode ser manipulado pelo usuário.

O projeto utilizado para demonstrar a escrita e leitura do arquivo possui uma Activity com o seguinte layout:
arquivo1
Foi criada uma classe chamada ManageFile com os métodos WriteFile e ReadFile, que fazem a escrita e leitura do arquivo.


/**
* Classe responsável pela escrita e leitura de arquivo.
* @author Romar Consultoria
*
*/
public class ManageFile {
private static final String TAG = "ManageFile";
private Context context;

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 {
// Abre o arquivo para escrita ou cria se não existir
FileOutputStream out = context.openFileOutput("romar.txt",
Context.MODE_APPEND);
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 file = context.getFilesDir();
File textfile = new File(file + "/romar.txt");

FileInputStream input = context.openFileInput("romar.txt");
byte[] buffer = new byte[(int)textfile.length()];

input.read(buffer);   

return new String(buffer);
}
}



Observe que no construtor da classe foi passado o argumento context da aplicação para que seja possível manipular o arquivo no contexto da aplicação.

O método writeFile tem como argumento o texto a ser escrito e utiliza o método openFileOutput para criar se o arquivo não existir ou abrir o arquivo anteriormente criado.

O método readFile busca pelo arquivo (romar.txt) criado anteriormente, faz a leitura do arquivo e retorna uma String com o conteúdo.

Na Activity do projeto foram criados dois botões Ler e Escrever que fazem a chamada dos métodos de escrita e leitura do arquivo:



@Override
public void onClick(View v) {

try {
switch (v.getId()) {
case R.id.btnRead:
// Faz a leitura do arquivo
ManageFile fileread = new ManageFile(this);
textRead.setText(fileread.ReadFile());
break;

case R.id.btnWrite:
ManageFile filewrite = new ManageFile(this);

// Avisa o usuário se a gravação foi bem sucedida
if(filewrite.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();
}

// 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());
}

}



A aplicação funcionando apresenta a seguinte tela:

arquivo2

É possível exportar o arquivo (romar.txt) para o computador, através do emulador do Eclipse utilizando a perspectiva DDMS, na aba File Explorer que exibe o conteúdo nos diretórios do dispositivo.

arquivo3

No diretório data/data/nome_do_pacote/files fica localizado os arquivos, criados dentro do contexto da aplicação. Para exportar o arquivo selecionar o botão indicado pela seta e gravar o arquivo no computador. Mas lembre-se o acesso a este arquivo só é possível via emulador, no dispositivo real não é possível acessar este arquivo.

Escrita e Leitura de Arquivo no Android–Parte II

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:
arquivo1
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 getStateSDcard() foi utilizado o método getExternalStorageState() da classe Environment do Android que retorna o estado do cartão SD. Para cada estado retornado é setado um flag para indicar se o cartão está disponível, se permite escrita e leitura, ou se permite somente somente leitura.

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());
}

}

Antes de fazer a escrita ou leitura no arquivo, o código verifica primeiro se o cartão SD está disponível e permite escrita ou leitura dependendo do caso.

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" />