domingo, 12 de julho de 2015

Android - SplashScreen, Tela de Abertura de Sistemas




As denominadas SplashScreen (Tela de abertura) são normalmente utilizadas para mostrar ao usuário algum tipo de progresso antes do carregamento do aplicativo por completo como por exemplo, enquanto é carregado recursos como banco de dados ou arquivos. Também pode se tornar uma maneira de distrair o usuário durante alguns segundos enquanto é realizado este processo de carregamento. Normalmente o desenvolvedor utiliza o logotipo da empresa ou algo parecido. Quando programamos em Android devemos implementar esta funcionalidade via código, pois infelizmente não temos nenhum mecanismo embutido para esta tarefa. Neste artigo vou implementar todas as etapas necessárias para conseguirmos obter esta funcionalidade utilizando uma Activity para o “Splash” que implementa a classe “Runnable” (será comentado a seguir) e logo após o método “run” para inicialização da primeira Activity após esta apresentação.

Interface Runnable

Esta é uma interface pública a qual nossa Atividade irá implementar. Normalmente esta interface é utilizada para executar códigos em diferentes contextos. (Paralelamente, utilizando Threads). Esta interface está no pacote “java.lang” e o principal método é o “Run”, o qual é invocado internamente quando necessário. Assim, uma classe que implementa a mesma deverá obrigatoriamente redefinir este método, sem argumentos e fornecer a funcionalidade necessária. Outra informação importante que devemos saber é que esta interface é implementada pela classe Thread, ou seja, estando ativa significa que uma thread foi iniciada e ainda não finalizou sua tarefa.

Classe Handler

É uma classe, que traduzindo para o portugues significa algo como “manipulador”. Quando criamos um novo Handler, ele é destinado à fila de mensagens/threads do próprio thread que o criou. A partir daí toda mensagem que for destinada a ele será entregue para aquela fila de mensagens para serem executadas. Resumidamente ele fica responsável por entregar as mensagens para a fila de sua thread, executando-as em seguida. Podemos usá-las de duas maneiras, sendo: Para agendar mensagens e threads a serem executadas ou para enfileirar uma ação a ser executada em um segmento diferente do qual foi enviada. Na nossa tela iremos trabalhar com o segundo tipo. O principal método desta classe é o “postDelay”, sendo que o mesmo possui dois parâmetros sendo o contexto da aplicação e o tempo necessário de delay (em minisegundos), o qual executará o “Runnable” após este intervalo de tempo.

Exemplo:

Handler handler = new Handler();
handler.postDelayed(this, DELAYTEMPO);

Outros métodos

Achei interessante citar alguns métodos desta tão importante classe do Android, ressaltando que os mesmos poderão se adaptar conforme a necessidade do programador.

- Método “Post”

O mesmo será responsável por atualizar a interface gráfica recebendo um parâmetro, sendo: Runnable (será executado assim que for acionado). Importante saber que neste mesmo podemos inserir alguma ação para alteração dos componentes da tela.

Exemplo:

public void MetodoPost(View view)
{
    Handler handler = new Handler();
    handler.post(new AtualizarTextView("Post"));
}

-Método “PostSendMessage”

Este método irá atualizar a tela a partir de mensagens (método SendMessage). Quando ocorrer uma evolução neste processamento este mesmo método será acionado passando as informações úteis. Para exemplificar melhor teremos que criar uma classe, no caso será chamada de “ClasseProcesso” e dentro da mesma deveremos implementar o método “Run” e o “SendHandlerMessage”. Para utilizá-la devemos instanciar a classe “ClasseProcesso” passando o Handler e logo em seguida disparar a Thread.

O exemplo abaixo nos dá uma ideia clara deste processamento .

public class ClasseProcesso implements Runnable
{
    Handler handler;

Criação pública do objeto Handler.

    public ClasseProcesso(Handler handler)
    {
        this.handler = handler;
    }

Definimos o Handler do contexto o mesmo que acabamos de criar. 

    @Override
    public void run()
    {
      try {
             
            for(int i = 0; i < 5; i++)
            {
                Thread.sleep(2000);
                sendHandlerMessage(i);
            }  
        } catch(Exception e) {
          e.printStackTrace();
        }
    }

No método “Run”  faremos um laço seguido do método Sleep para simularmos algum tipo de processamento. Neste “For” invocaremos o método “sendHandlerMessage()”, o qual será responsável por atualizar a tela por etapas.
     
    private void sendHandlerMessage(int value)
    {
          Message msg = new Message();
          Bundle bundle = new Bundle();
bundle.putInt(ActionCode.ACTION,      ActionCode.ACTION_FEEDBACK_PROCESS);
          bundle.putInt(ActionCode.VALUE, value);
          msg.setData(bundle);
          handler.sendMessage(msg);
     }
}
   
public void MetodoHandlerPostSendMessage(View view)
{
     ClasseProcesso processo = new ClasseProcesso(handler);
     Thread t = new Thread(Classeprocesso);
     t.start();
}

Instanciamos a classe para disparar a Thread.

Criando o Exemplo

Deveremos criar uma aplicação do início, no meu caso, utilizando a versão 4.1.2 do Android. Teremos dois arquivos de lay-out com suas respectivas atividades, sendo: uma para ilustrar a tela principal do sistema de exemplo e outra para a tela de SplashScreen. Iremos simular um delay de alguns segundos para abrir o sistema, para assim dar uma impressão agradável ao usuário. Figura 01.
Figura 01: Arquivos do Aplicativo.

Lay-out

Na tela inicial do sistema, para fins didádicos, irei adidicionar alguns buttons, Labels e EditTexts. Ver Imagem 02.

Figura 02: Tela Inicial do Sistema.

O código XML Correspondente: (Listagem 01)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button001"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView2"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="16dp"
        android:text="Botão 1" />

    <Button
        android:id="@+id/Button003"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/Button002"
        android:layout_below="@+id/Button002"
        android:layout_marginTop="38dp"
        android:text="Botão 3" />

    <Button
        android:id="@+id/Button002"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button001"
        android:layout_below="@+id/button001"
        android:layout_marginTop="30dp"
        android:text="Botão 2" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:text="Tela Inicial"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/editText1"
        android:layout_below="@+id/editText1"
        android:layout_marginTop="23dp"
        android:text="Label 2"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView3"
        android:layout_below="@+id/textView3"
        android:ems="10" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/Button003"
        android:layout_marginTop="24dp"
        android:layout_toLeftOf="@+id/textView2"
        android:text="Label 1"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>
Listagem 01: Código da tela Principal.

Já na Tela de Splash, eu particularmente sempre uso o Slogan da Empresa (no caso foi inserido o do The Club) e em seguida um texto informativo “Carregando o Sistema”. Ver Imagem 03.

 

Figura 03: Tela de SplashScreen.

Ver XML Correspondente: (Listagem 02)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/carregando_o_sistema_" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.12"
        android:src="@drawable/theclub" />

</LinearLayout>
Listagem 02: código da tela Splash.


Alterando o “AndroidManifest.xml”

Teremos que nos atentar para algumas alterações neste arquivo de configuração, não podendo esquecer que a tela que iremos chamar primeiro seria a de “Splash”. Para isto configure as propriedades da Activity da “Tag” intent-Filter o: “Action” (Para definir como atividade principal) e “category” (Para disparar no momento da execução). Já para a tela “MainActivity” (tela de início) apenas faremos a referência necessária. Ver listagem 03 para maiores detalhes.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.splashscreen"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.splashscreen.TelaSplashScreen"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <activity android:name="com.example.splashscreen.MainActivity"></activity>
    </application>
</manifest>
Listagem 03: Arquivo “AndroidManifest”.

Codificando o Exemplo

“SplashScreen.java”

No primeiro momento iremos importar algumas bibliotecas, Ver Listagem 04

package com.example.splashscreen;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;

Esta classe herda o tipo “Activity” e implementa a interface “Runnable” (como foi explicado no tópico anterior). Obrigatoriamente teremos que implementar o método “Run”.

public class TelaSplashScreen extends Activity implements Runnable
{

Foi necessário criar uma constante “DELAYTEMPO”, a mesma responsável por dar a impressão do sistema estar carregando algum tipo de dado. Esta constante irá ser utilizada no método “postDelay”.

       private final int DELAYTEMPO = 5000;
      
  @Override
       public void onCreate(Bundle savedInstanceState)
       {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.splashscreen);
Toast.makeText(this, "Abrindo o sistema . . .  ",   Toast.LENGTH_LONG).show();
           Handler handler = new Handler();
           handler.postDelayed(this, DELAYTEMPO);          
       }

No evento “OnCreate” usaremos a classe “Toast” para uma mensagem informativa e logo em seguida a “Handler” para nos orientar para a página principal.


     public void run()
     {
startActivity(new Intent(this MainActivity.class));
         finish();     
     }
O método “Run” irá chamar a tela “MainActivity”.

}
Listagem 04: SplashScreen.java.

“MainActivity.java”

Já na classe “MainActivity” não faremos nada de diferente, faremos referência apenas para o layout “Activity_main”. Ver Listagem 05.

package com.example.splashscreen;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity
{

     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
     }
}
Listagem 05: MainActivity.java.

Confiram o exemplo em Run-time. Ver Imagem 04.

 
Figura 04: Exemplo.
Conclusões

Pudemos implementar neste artigo a denominada SplashScreen (Tela de Abertura de Sistema). Um recurso muito util para incrementar e deixar nossos aplicativos mais atraentes ao usuário. Também descrevi as funcionalidades das classes “Handler” e “Runnable”, ambas de extrema importância para o aprendizado.
Espero que tenham gostado, um abraço e até a próxima.

 

Nenhum comentário:

Postar um comentário