Programar para Android - 08
Botões que lançam outras atividades
Começamos por criar um novo projeto
Try06 e retirar a string hello world, para ficar com um projeto vazio, mas já com a atividade já criada.
Desta vez vamos fazer algo um pouco mais longo e vamos ter o primeiro contacto com intents, permissões, obter dados do GPS e do Wifi e editar o
AndroidManifest.xml.
Vamos criar uma atividade com 6 botões que lançam atividades ou realizam outras ações, algumas mais simples outras mais complexas.
Começamos por criar seis strings no
strings.xml com nomes
app1 a
app6 e com o conteúdo:
Google,
Calculadora,
Notificação,
Vibrar,
GPS,
Wifi. Os botões irão:
- lançar o endereço http://www.google.pt;
- lançar a calculadora;
- mostrar uma notificação no écrã;
- vibrar o telemóvel;
- obter informação sobre o GPS;
- obter informação sobre a ligação Wifi.
No
main.xml vamos criar o layout. Adicionamos três LinearLayout horizontais dentro do LinearLayout vertical. Dentro de cada LinearLayout horizontal criamos dois botões, ficando assim com seis botões. Usando o botão "Distribute Weights Evenly", podemos fazer que os botões ocupem todo o écrã de forma equilibrada. O aspeto fica assim:
O xml do layout fica assim:
<?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" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp1"
android:text="@string/app1" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp2"
android:text="@string/app2" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp3"
android:text="@string/app3" />
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp4"
android:text="@string/app4" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<Button
android:id="@+id/button5"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp5"
android:text="@string/app5" />
<Button
android:id="@+id/button6"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:onClick="runApp6"
android:text="@string/app6" />
</LinearLayout>
</LinearLayout>
Já não vamos precisar de mexer mais no
strings.xml nem no
main.xml.
Vamos agora ver o
AndroidManifest.xml. Tal como o
strings.xml e o
main.xml, o Eclipse mostra uma interface gráfica, mas vamos editar diretamente o XML.
Este ficheiro contém informação sobre a aplicação que é usada, por exemplo, no Android Market (agora Play) para listar e identificar as aplicações.
Muitas das tags são óbvias. Desta vez vamos apenas acrescentar algumas linhas de texto, entre o
<uses-sdk ...> e o
<application ...>.
As linhas a acrescentar são estas:
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.wifi" />
<uses-feature android:name="android.hardware.location" />
<uses-feature android:name="android.hardware.location.network" />
<uses-feature android:name="android.hardware.location.gps" />
Os
uses-permission listam as permissões que a aplicação precisa de ter para poder funcionar, neste caso precisa de poder ligar a vibração (
VIBRATE), aceder aos dados de localização por GPS e pela rede (
ACCESS_FINE_LOCATION,
ACCESS_COARSE_LOCATION) e aceder a informação da ligação sem fios (
ACCESS_WIFI_STATE).
Esta informação também é mostrada ao utilizador no momento em que instala a aplicação e o utilizador tem de dar estas permissões à aplicação.
As linhas de
uses-feature informam que a aplicação só irá funcionar em dispositivos que tenham o hardware indicado (neste caso wifi e GPS). Esta informação é usada no market para filtrar as aplicações que não são compatíveis com o dispositivo do utilizador.
Finalmente vamos ao código e graças à separação que o Android faz ao colocar o layout e permissões em ficheiros XML, só temos de nos preocupar mesmo com o código.
O método
onCreate() que já existe não precisa ser mexido, apenas precisamos criar seis métodos novos, um para cada botão, com os nomes
runApp1() a
runApp6(). Estes foram os nomes definidos no
main.xml.
O primeiro botão lança um browser para aceder ao endereço http://www.google.pt. Isso consegue-se com este código:
public void runApp1(View v) {
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.google.pt/"));
startActivity(i);
}
Um intent é um objeto que, basicamente, contém uma mensagem que é passada ao sistema. Neste caso o intent é criado com a mensagem (ação)
ACTION_VIEW e com um parâmetro "http://www.google.pt". Um intent pode ter várias formas, mas este é uma das mais usadas. Contém dois parâmetros, o primeiro é a ação a executar (pode ser VIEW, PICK, EDIT, DELETE, etc) e o segundo parâmetro é um argumento para a ação. Neste caso estamos a dizer ao sistema que queremos ver (VIEW) o URL indicado. O sistema analisa o intent e escolhe a aplicação certa para executar a ação pedida. Pode haver mais que uma aplicação que possa executar essa ação, então o sistema pergunta ao utilizador qual a aplicação que pretende usar. Neste caso se houvesse dois browsers presentes no dispositivo o sistema iria perguntar que browser se pretendia usar.
O segundo botão lança a calculadora, usando também um intent.
public void runApp2(View v) {
Intent i = new Intent();
i.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");
startActivity(i);
}
Este intent é diferente. Começamos por criar um intent vazio e adicionamos um nome de classe. Este nome de classe é definido a partir do packagename da atividade. Por isso é importante que cada atividade tenha um nome único, porque esse nome vai ser utilizado para lançar a atividade e tem portanto de ser único.
O terceiro botão apenas mostra uma mensagem de notificação, que no Android é chamado um Toast.
public void runApp3(View v) {
String msg = "Hello World, again!";
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
O quarto botão liga a vibração durante 1 segundo (1000 milisegundos). Usa o serviço de sistema
VIBRATOR_SERVICE.
public void runApp4(View v) {
Vibrator vib;
vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vib.vibrate(1000);
}
O quinto botão obtém informação de localização do GPS ou da rede. Primeiro tenta obter a informação do GPS (
GPS_PROVIDER). Se a informção não estiver disponível (GPS desligado ou sem sinal) pede informação à rede (
NETWORK_PROVIDER). A informação obtida é mostrada num Toast.
public void runApp5(View v) {
LocationManager locator = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Location l = locator.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (l == null) {
// Fall back to coarse location.
l = locator.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
double alt = l.getAltitude();
double lat = l.getLatitude();
double lon = l.getLongitude();
long time = l.getTime();
float acc = l.getAccuracy();
float speed = l.getSpeed();
String prov = l.getProvider();
String msg =
"Lat: " + lat + "\n" +
"Long: " + lon + "\n" +
"Alt: " + alt + "\n" +
"Time: " + time + "\n" +
"Accuracy: " + acc + "\n" +
"Speed: " + speed + "\n" +
"Provider: " + prov + "\n";
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
O sexto e último botão obtém e mostra a informação sobre a ligação wifi atual. Usa o serviço de wifi do sistema (
WIFI_SERVICE). A informação obtida também é mostrada num Toast.
public void runApp6(View v) {
String msg;
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()) {
msg = "Wifi ligado\n";
WifiInfo winfo = wifi.getConnectionInfo();
int ipadd = winfo.getIpAddress();
String ip = String.format("%d.%d.%d.%d",
ipadd & 0xff,
ipadd >> 8 & 0xff,
ipadd >> 16 & 0xff,
ipadd >> 24 & 0xff);
msg +=
"BSSID: " + winfo.getBSSID() + "\n" +
"IP: " + ip + "\n" +
"Speed: " + winfo.getLinkSpeed() + "\n" +
"MAC: " + winfo.getMacAddress() + "\n" +
"RSSI: " + winfo.getRssi() + "\n" +
"SSID: " + winfo.getSSID();
} else
msg = "Wifi desligado";
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
O projeto necessita de uma lista relativamente longa de imports, que devem ser gerados pelo Eclipse, mas para referência aqui ficam:
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.widget.Toast;
Referências:
http://www.krvarma.com/2010/07/getting-ip-address-of-the-device-in-android/
http://www.damonkohler.com/2009/02/android-recipes.html
além do obrigatório:
http://developer.android.com/reference/packages.html