T#010 – Creiamo un browser per Android

Ciao a tutti, eccoci con un nuovo appuntamente con i nostri tutorial di programmazione Android. Dopo aver visto con i precedenti articoli vari aspetti legati al mondo dello sviluppo di un’applicazione per i nostri Google Phone, vediamo oggi, in questo nuovo tutorial, di mettere un po’ di cose insieme e creare un’applicazione completa. Nello specifico vedremo come costruire un mini browser che sfrutti una semplice WebView per mostrare una pagina web al suo interno.

Creazione del progetto su Eclipse

Per prima cosa avviamo Eclipse (se non l’avete ancora scaricato e configurato potete seguire la nostra guida). Creiamo un nuovo progetto cliccando sul menu File e selezionando New –> Project e infine Android Project nella finestra di dialogo che compare.
Nel primo passo dello wizard che permette di creare un progetto impostiamo:

  • nome del progetto e nome dell’applicazione: devAPP_browser
  • package principale: it.devapp.browser
  • versione di Android da usare: va bene una qualunque uguale o superiore alla 1.6
  • Activity da creare: MainActivity



Clicchiamo su Finish (gli altri passi dello wizard non ci interessano) ed Eclipse creerà per noi un progetto completo contenente una Activity che mostra semplicemente un messaggio. Il progetto è avviabile su un emulatore o su un device collegato, basta cliccare col tasto destro sul progetto e selezionare Run As –> Android Application.

Interfaccia grafica

La directory res all’interno di un progetto Android di Eclipse contiene tutte le risorse del progetto, in particolare abbiamo le sottodirectory:

  • drawable-hdpi, drawable-mdpi e drawable-ldpi: contengono le immagini per i device con densità dei pixel alta, media e bassa (per capirsi esempi di telefoni sono rispettivamente HTC Desire, Lg Optimus One e Sony Ericsson Xperia X10 Mini);
  • layout: contiene la definizione in file xml dei vari layout usati nell’applicazione. Anche in questo caso possiamo creare più directory che iniziano con layout- se vogliamo diversificare il layout in base alla densità del display;
  • values: contiene il file strings.xml con le stringhe usate nell’applicazione pronte per l’internazionalizzazione. Per aggiungere una nuova lingua basta creare una nuova cartella (per esempio values-it per l’italiano) contenente un altro file strings.xml.

Prima di modificare il layout creiamo la directory drawable dentro res e aggiungiamo dentro questa directory due immagini back.png e forward.png. Abbiamo creato una directory nuova e non abbiamo usato le tre directory esistenti per pigrizia, in realtà avremmo dovuto aggiungere 6 immagini scalate per adattarsi alle varie densità in modo da evitare immagini “distorte”.
Editiamo anche il file strings.xml per aggiungere le seguenti stringhe che ci serviranno nell’interfaccia grafica:

1
2
3
4
<string name="go">Go</string>
<string name="stop">Stop</string>
<string name="reload">Reload</string>
<string name="default_url">http://www.google.it</string>

Il layout dell’Activity creata in automatico è contenuto dentro il file main.xml nella directory res/layout del nostro progetto. Con un doppio click su questo file Eclipse aprirà l’editor delle interfacce che permette di modificare il layout sia in modo grafico che editando direttamente il codice xml.
Aggiungiamo nel layout un EditText per inserire l’url da mostrare nel browser, 5 Button (3 normali e 2 ImageButton contenenti le immagini con le frecce) e una WebView che mostrerà le pagine web. Il risultato finale è questo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<Button android:layout_height="wrap_content"
		android:layout_width="wrap_content" android:id="@+id/go"
		android:layout_alignParentRight="true" android:text="Go"
		android:layout_margin="2dip" />
	<EditText android:layout_height="wrap_content" android:text="@string/default_url"
		android:layout_toLeftOf="@id/go" android:layout_width="fill_parent"
		android:id="@+id/url" android:layout_margin="2dip" />
 
	<ImageButton android:layout_height="wrap_content"
		android:layout_width="wrap_content" android:layout_alignParentBottom="true"
		android:id="@+id/back" android:src="@drawable/back" />
	<ImageButton android:layout_height="wrap_content"
		android:layout_toRightOf="@id/back" android:layout_width="wrap_content"
		android:layout_alignParentBottom="true" android:id="@+id/forward"
		android:src="@drawable/forward" />
	<Button android:layout_height="wrap_content"
		android:layout_width="wrap_content" android:layout_alignParentBottom="true"
		android:layout_alignParentRight="true" android:id="@+id/stop"
		android:text="@string/stop" />
	<Button android:layout_height="wrap_content"
		android:layout_toLeftOf="@id/stop" android:layout_width="wrap_content"
		android:layout_alignParentBottom="true" android:id="@+id/reload"
		android:text="@string/reload" />
 
	<WebView android:id="@+id/webview" android:layout_width="fill_parent"
		android:layout_below="@id/url" android:layout_above="@id/back"
		android:layout_height="fill_parent" />
</RelativeLayout>

Le varie View sono organizzate in un RelativeLayout che permette di specificare per le View contenute in che relazione sono fra di loro e rispetto al layout principale. Per esempio abbiamo specificato che il pulsante Go è allineato sullo destra e che l’EditText dell’url è alla sinistra di questo Button. Avremmo potuto ottenere lo stesso layout anche usando più LinearLayout annidati.
Per accedere alle stringhe definite in precedenza abbiamo usato la sintassi android:text=”@string/default_url”, per accedere alle immagini abbiamo usato android:src=”@drawable/back”. Editando a mano il file xml Eclipse mette a disposizione un comodo autocomplete, premendo Ctrl+Spazio vengono mostrati una lista di tag o attributi utilizzabili. Nel caso in cui si prema Ctrl+Spazio dentro un attributo dopo aver scritto @string/ vengono mostrate tutte le proprietà definite nel file strings.xml.
Se eseguiamo nuovamente il nostro progetto possiamo vedere il layout sull’emulatore o sul telefono:



Ovviamente cliccando sui Button non succede niente, non c’è da lamentarsi visto che non abbiamo ancora scritto una riga di codice Java!

Activity principale

Modifichiamo l’Activity per aggiungere i metodi che poi collegheremo all’interfaccia grafica. Per prima cosa aggiungiamo due campi che contengono la WebView e l’EditText contenente l’url. Questi due campi sono popolati tramite il metodo findViewById a cui viene passato l’id della View da cercare. Gli id sono disponibili nella classe R creata automaticamente da Eclipse in base a tutte le risorse contenute nella directory res.

1
2
3
4
5
6
7
8
9
10
11
12
private WebView webView;
 
private EditText url;
 
@Override
public void onCreate(Bundle savedInstanceState)
{
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	webView = (WebView) findViewById(R.id.webview);
	url = (EditText) findViewById(R.id.url);
}

Aggiungiamo anche il metodo onResume in cui abilitiamo il javascript nella WebView e carichiamo l’url presente nel corrispondente campo:

1
2
3
4
5
6
7
@Override
protected void onResume()
{
	super.onResume();
	webView.getSettings().setJavaScriptEnabled(true);
	webView.loadUrl(url.getText().toString());
}

Eseguendo nuovamente il progetto vediamo che stavolta la WebView viene popolata all’avvio dell’applicazione. O meglio, prova a collegarsi a internet ma non ci riesce! Questo perchè dobbiamo specificare nel manifest della nostra applicazione che abbiamo bisogno di sfruttare la connessione. Il file AndroidManifest.xml contiene la configurazione dell’applicazione, fra le altre cose contiene anche i permessi di cui l’applicazione ha bisogno. Nel momento in cui un utente installa l’applicazione dal Market viene avvertito dei permessi di cui l’applicazione ha bisogno in modo da potersi difendere da applicazioni “troppo invadenti”. Nel nostro caso aggiungiamo questa riga prima della chiusura del tag manifest:

1
<uses-permission android:name="android.permission.INTERNET" />

Se rilanciamo il progetto vediamo finalmente comparire la home page di google!



I Button non hanno ancora associato un listener e quindi cliccandoli non viene eseguito niente. Definiamo i metodi da invocare per gestire i vari Button:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void go(View v)
{
	webView.loadUrl(url.getText().toString());
}
 
public void reload(View v)
{
	webView.reload();
}
 
public void stop(View v)
{
	webView.stopLoading();
}
 
public void goBack(View v)
{
	webView.goBack();
}
 
public void goForward(View v)
{
	webView.goForward();
}

Questi metodi richiamano semplicemente dei metodi sulla WebView. Per collegarli ai corrispondenti Button modifichiamo il file xml con il layout: aggiungiamo un attributo android:onClick con il nome del metodo dell’Activity da richiamare. Per esempio il pulsante Go diventa:

1
2
3
4
<Button android:layout_height="wrap_content" android:onClick="go"
	android:layout_width="wrap_content" android:id="@+id/go"
	android:layout_alignParentRight="true" android:text="Go"
	android:layout_margin="2dip" />

Riavviamo il progetto e stavolta funzionano anche tutti i pulsanti! Questo modo di associare i listener agli eventi funziona solo dalla versione 1.6 di Android, come già detto in un altro post questa cosa non è una limitazione troppo grossa in quanto i device 1.5 presenti sul mercato sono una minoranza.

Se volete importare il progetto nel vostro workspace di Eclipse potete scaricare lo zip con i sorgenti completi tramite il seguente indirizzo.

By Fabio Collini

Da agosto 2009 sono un freelance android developer, ho rilasciato due applicazioni nell'Android Market: Apps Organizer e Folder Organizer. Presso OmniaGroup ricopro il ruolo di Tech Leader nell'ambito di un progetto di rich internet application che utilizza JSF, JPA(EclipseLink) ed EJB3.

15 comments

  1. scusatemi, quando metto il java nell’activity mi dà errori di sintassi, però per il resto và bene…qualcuno può aiutarmi??

      1. Ciao, grazie per la guida ma sopratutto per lo zip. Ho importato lo zip all’interno di Eclipse (versione 4.2.0 Juno) ma da errore nel file MainActivity.java. Come si può risolvere? Grazie

  2. a ecco ho scaricato il main activity vostro ed ho preso da lì il java e ora nn mi dà problemi, ed ho capito anche l’errore,non lasciavo le 2 stringhe
    “import android.app.Activity;
    import android.os.Bundle;”

  3. Ciao a tutti e complimenti. Ho seguito alla lettera la vostra guida, tuttavia quando provo ad avviare il progetto mi appare il messaggio: “Could not find the main class”.

    Non riesco a capire dove e come modificare il sorgente.

    Grazie.

  4. Salve! Il progetto è molto interessante.. qualcuno sa suggerirmi se è possibile aggiungere una o alcune delle seguenti funzionalità:
    – salvare su file log le attività svolte mediante browser
    – inviare file log in remoto
    – impedire collegamento a siti inclusi in una blacklist (o, viceversa, permettere soltanto collegamento a siti inclusi in una whitelist)
    – salvare screenshot ogni volta che si apre una nuova pagina in maniera invisibile all’utente

    grazie!!!

  5. Ciao Ragazzi Ho Seguito Tutto Ma Volevo sapere Come Generare L’ Installazione ( Pacchetto .apk )

  6. ciao sto provando a seguire il tuo tutorial ma se la activity non è MAIN non riesce a caricare la pagina web..invece nessun problema se è la principale…come hai fatto tu….come è possibile???

    ho messo tutti i permessi nel manifest…

  7. Salve, volevo chiedervi un paio di cose:

    1) xke quando navigo nel webview quando clicco su un link mi apre il browser e non resta nell app? si puo evitare ??

    2) ho aggiungo @SuppressLint(“SetJavaScriptEnabled”) per evitare il warning dell abilitazione del java script. Ho fatto bene o potevo evitare?

    Grazie 1000

    1. ciao volevo chiederti in che modo hai risolto il primo punto. Grazie in anticipo…

  8. carino, funziona, ma occupa un botto di ram e non so perché….

  9. Perchè quando vado per esempio su google e schiaccio su campo dove inserire il testo non viene fuori la tastiera??
    Succede anche a voi?

  10. ciao ho una domanda…hop fatto tutto come dicevi e quando testo l’app si apre normalmente e i bottoni sn presenti ma quando li premo mi fanno l’interruzione imprevista dell’app stessa cosa devo rivedere forse qalche riga? nel progetto nn ci sono errori ma solo piccoli cartelli gialli con un punto esclamativo… Grazie in anticipo ti supplico di rispondere!!!

  11. Ciao, vorrei sapere perche riscontro un problema nella stringa ??”@Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    webView = (WebView) findViewById(R.id.webview);
    url = (EditText) findViewById(R.id.url);
    }

    ,in particolar modo in MAIN, WEBWIEW e URL.

Comments are closed.