quarta-feira, 25 de abril de 2012

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_LOCATIONACCESS_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

1 comentário:

  1. Parabéns Ilídio Vicente, fiz e funcionou direitinho, só a Calculadora que quando chamo gera uma exceção, instalei num Galaxy Note 2. Mas você explicou muito bem.
    abraços,

    Amostra Grátis

    ResponderEliminar