A aplicação desenvolvida é algo muito simples e no mundo real ninguém criaria uma calculadora como esta. Lembre-se, o aplicativo foi criado apenas para estudar alguns conceitos (Principalmente o BroadcastReceiver).
Mas de que se trata o BroadcastReceiver?
Assim como as Activities podem ser chamadas por outras Activities através da utilização de Intents, Receivers também podem ser "chamados".
A principal diferença entre uma Activity e um Receiver é que o Receiver é executado em background e geralmente não deve realizar interação com o usuário (para evitar interrompe-lo). Além disso, um receiver possui um tempo máximo para executar alguma tarefa determinado em 10 segundos. Caso sua tarefa ultrapasse este tempo o Receiver é interrompido pelo sistema operacional.
Para as Activities que disponibilizamos, geralmente utilizamos um IntentFilter que diz o nome da Action e Category que permitem ao android encontrar nossa aplicação.
O exemplo clássico de um IntentFilter, é o que já é declarado quando criamos uma aplicação de HelloWorld no eclipse:
<activity android:name=".LivroAndroidCap7Activity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>Para um Receiver responder à uma Intent, o mesmo também precisa ser declarado com um IntentFilter. Um Receiver pode atender a várias Actions nativas como BOOT, recebimento de SMS, eventos relacionados à bateria além de poder atender a Actions customizadas (strings definidas pelo próprio desenvolvedor).
Criando a calculadora
Bom, então vamos logo para a criação da calculadora. A idéia aqui é criar um aplicativo que possui uma tela inicial que mostra apenas um botão com o rótulo Calcular conforme mostrado na figura abaixo:
Ao pressionar este botão, o usuário receberá um formulário com 3 campos dentro de um AlertDialog. O formulário poderia ter sido criado na mesma tela que o botão calcular, mas eu quis complicar um pouco mais só para brincar um pouco mais com outras funcionalidades do android (neste caso usar um AlertDialog).
Caso o usuário selecione o botão Calcular neste formulário, os dados para o cálculo são enviados para o sistema operacional através de uma Intent definida com o seguinte intent filter:
<intent-filter> <action android:name="CALCULO" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>Considerando este IntentFilter, outros aplicativos podem ser criados para enviar um broadcast com dados para CALCULO. Outros Receivers também podem ser criados para receber dados para calcular e efetuar estes cálculos de forma diferente (por exemplo algum tipo de cálculo alienígena).
A primeira coisa que criei neste projeto foram os layouts definidos no diretório res/layout do projeto.
main.xml (layout que possui apenas o botão calcular - tela inicial)
<?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:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/calculadora" /> <Button android:id="@+id/btCalcular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/calcular" /> </LinearLayout>layout_form.xml (layout que possui os campos do formulário - usado no AlertDialog)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/primeiro_numero" /> <EditText android:id="@+id/numero1" android:inputType="number" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/segundo_numero" /> <EditText android:id="@+id/numero2" android:inputType="number" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/operacao" /> <Spinner android:id="@+id/operacao" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>Após definir os layouts, criei as classes para a Activity e uma para o Receiver. CalculoReceiver.java
package br.com.livro.cap9; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; public class CalculoReceiver extends BroadcastReceiver { @Override public void onReceive(Context ctx, Intent intent) { // recupera os dados para calculo que qualquer Intent // recebida para este fim precisa enviar Bundle extras = intent.getExtras(); if (extras != null) { String n1 = extras.getString("numero1"); String n2 = extras.getString("numero2"); String op = extras.getString("operacao"); // recebe os valores // faz uma pequena validação // e então decide qual operaçao executar guardando o valor em resultado if (!isEmpty(n1) && !isEmpty(n2) && !isEmpty(op)) { int in1 = Integer.parseInt(n1); int in2 = Integer.parseInt(n2); int iop = Integer.parseInt(op); int resultado = 0; switch (iop) { case 0: // soma resultado = in1 + in2; break; case 1: // subtracao resultado = in1 - in2; break; case 2: // multiplicacao resultado = in1 * in2; break; case 3: // divisao resultado = in1 / in2; break; } // após efetuar o cálculo apenas gera um log // que poderá ser verificado pelo LogCat no eclipse. Log.i("CALCULO", "resultado do calculo: " + resultado); } } } private boolean isEmpty(String v) { return (v == null || v.length() == 0); } }CalculadoraActivity.java
package br.com.livro.cap9; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; public class CalculadoraActivity extends Activity implements OnItemSelectedListener, OnClickListener { protected static final int SOMA = 0; private int codigoOperacao = SOMA; // lista de operações disponíveis private String[] operacoes = { "Soma", "Subtração", "Multiplicação", "Divisão" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // adicionando o comportamento para o botão calcular Button btCalcular = (Button) findViewById(R.id.btCalcular); btCalcular.setOnClickListener(this); } /** * Ao selecionar um item no Spinner (famoso combobox em outras plataformas), * a posição da operação selecionada é guardada em codigoOperacao que podera ser * encaminhada através da Intent posteriormente quando o usuário solicitar o calculo. */ public void onItemSelected(AdapterView adapterView, View view, int position, long id) { codigoOperacao = position; } @Override public void onNothingSelected(AdapterView arg0) { codigoOperacao = SOMA; // operação padrao é a soma } @Override public void onClick(View v) { // criando a janela de dialogo AlertDialog.Builder alert = new AlertDialog.Builder(this); // Uma das coisas interessantes em utilizar este AlertDialog no exemplo, foi // utilizar também o LayoutInflater conforme mostrado abaixo. // O LayoutInflater cria uma instancia de View baseando-se // no layout informado em inflater.inflate LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View viewForm = inflater.inflate(R.layout.layout_form, null); // Desta forma é possivel definir o conteúdo do AlertDialog // como uma View ao invés de uma mensagem texto. alert.setView(viewForm); // Criamos entao os botoes para uma açao positiva e uma açao negativa // utilizando os devidos Listeners para click nos botoes. // Repare que a classe OnClickListener está dentro de DialogInterface // e não dentro de View como é utilizado para Buttons. alert.setPositiveButton("Calcular", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // aqui dentro recuperamos os dados registrados na view do formulário // por isso, para recuperar cada EditText, foi utilizado o viewForm.findViewById. // Pois apenas esta view possui os componentes registrados. // Tente utilizar findViewbyId apenas para ver o que acontece =P EditText txtNumero1 = (EditText) viewForm.findViewById(R.id.numero1); EditText txtNumero2 = (EditText) viewForm.findViewById(R.id.numero2); Bundle extras = new Bundle(); extras.putString("numero1", txtNumero1.getText().toString()); extras.putString("numero2", txtNumero2.getText().toString()); extras.putString("operacao", Integer.toString(codigoOperacao)); // Este é o ponto principal para o estudo do BroadcastReceiver. // É aqui que criamos uma intent para calculo que será // recebida pelo nosso Receiver CalculoReceiver. Intent itCalculo = new Intent(); itCalculo.setAction("CALCULO"); itCalculo.putExtras(extras); sendBroadcast(itCalculo); Toast.makeText(CalculadoraActivity.this, "calculo enviado para broadcast", Toast.LENGTH_SHORT).show(); } }); alert.setNegativeButton("Cancelar", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Toast.makeText(CalculadoraActivity.this, "calculo cancelado", Toast.LENGTH_SHORT).show(); } }); // carregando a lista de operações utilizando um ArrayAdapter // Existe muito conteúdo na net explicando o conceito de adapter para utilização em listas. ArrayAdapterPara entender o código, leia os comentários colocados no próprio código. Não vou detalhar o código aqui para não ficar repetitivo. Agora que criamos tudo que é necessário, é preciso registrar a Activity e o Receiver dentro no arquivo AndroidManifest.xmladapter = new ArrayAdapter ( this, android.R.layout.simple_spinner_item, operacoes); Spinner spnOperacoes = (Spinner) viewForm.findViewById(R.id.operacao); spnOperacoes.setAdapter(adapter); // guarda a posicao da operacao pois deve ser enviado para o broadcast receiver // o código da operação a ser realizada e não a descrição spnOperacoes.setOnItemSelectedListener(this); // exibindo o alert com o formulario para o usuário. alert.show(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="br.com.livro.cap9" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name="CalculadoraActivity" android:label="calculadora"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiver android:name="CalculoReceiver" android:label="calculo receiver"> <intent-filter> <action android:name="CALCULO" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> </application> </manifest>Ao executar a aplicação, teremos a seguinte saída no emulador:
E teremos a seguinte saída no LogCat:
Bom, é isso aí... o post acaba por aqui e espero que alguém também possa aprender algo com este exemplo simples.
Até a próxima.
tem como passar valores do BroadCastReceiver para uma Activity ?
ResponderExcluir