MOOC realitzat: “Android: Programación de Aplicaciones” de la UPV, a MiríadaX

Tot just he acabt el MOOC “Android: Programación de Aplicaciones” de la Universitat Politècnica de València, sobre la plataforma MiríadaX.

De moment, només dir que ja tinc el meu primer “badge“, que ve a ser el reconeixement de participació al MOOC que fa MiríadaX.EL reconeixement per badges admet graduacions i em temo que el que fa MiríadaX és el més bàsic. No té en compte, per exemple, les puntuacions obtingudes als tests, o els exercicis realitzats.

Per a un proper post queda pendent, ara des de l’experiència de primera ma que dona haver-ne fet un, explicar com ha anat la cosa. En un parell de setmanes, a més he d’acabar algun altre MOOC que també estic realitzant o sigui que, a més, podré donar també una opinió comparada.

En tot cas, he trobat aquesta experiència positiva i enriquidora. No era el primer cop que feia formacions online i tenia una idea prèvia del que em trobaria. Però ha superat les expectatives. He de dir que el curs de la UPV ha estat, amb diferència, el millor en que he participat en format online: 10 mòduls, amb abundants exercicis pràctics, tests i un examen per cada mòdul. Una novetat per mi: les “correccions” comunitàries d’exercicis als fòrums i , brillant, les classes de repàs amb àudio i vídeo en directe fent servir els hangouts de Google+. Déu n’hi do. Afegim bon material de vídeo i, potser, escàs material escrit, però enllaçat si més no.

Bé, ara ja soc un especialista en desenvolupament amb Android 😉 que era una mica la idea de fer aquest MOOC.

El MOOC. Un enorme camp de possibilitats d’auto-formació i de dissenyar un currículum a mida.

El següent pas: revisar l’oferta de Coursera.

Com preparar un entorn de desenvolupament per a Python for Android.

En un post anterior vaig presentar el Python for Android (Py4A), que és un python per a dispositius Android que funciona sobre l’Scripting Layer For Android (SL4A).

En aquell post presentava diversos scripts que es podien executar sobre el dispositiu Android. O sobre l’emulador d’Android que es troba disponible a l’Android SDK.

Tanmateix, en eaquell post no parlava dels entorns disponibles per a desenvolupar els scripts. Com puc desenvolupar amb Py4A de forma còmoda?

Prerequisits

Evidentment, és prerequisit tenir instal·lat a la tablet l’SL4A i el Py4A.
A l’ordinador que farem servir per desenvolupar cal tenir el JDK 1.6 de Java, com a mínim. El JDK permetrà instal·lar, a continuació l’Android SDK, el qual ens proporciona les eines que ens interessen: l’adb i el ddms. El DDMS és, en realitat, una aplicació Java.

L’Android SDK proporciona un parell d’eines que seran útils per a desenvolupar scripts Python: l’Android Debug Bridge (adb) i el Dalvik Debug Monitor Server (ddms).

Per a poder aprofitar les dues eines esmentades caldrà posar l’SL4A en “mode servidor”. Amb la combinació del “mode servidor”, l’adb, el ddms, i un cable usb serem capaços de desenvolupar scripts python al nostre ordinador i executar-los de forma immediata al dispositiu Android o a l’emulador de l’Android SDK.

Connectar el dispositiu per USB.

El que ve a continuació està basat en https://help.ubuntu.com/community/AndroidSDK

El primer pas ha estat aconseguir que l’adb i el ddms reconeixessin la meva tablet. Es tracta d’un model barat de fabricació xinesa: una tab-playtabpro de Point-of-View, que munta un sistema operatiu Android 4.0.3.

Activar depuració USB
Per a fer-ho, he connectat la tablet a l’ordinador amb el cable USB. NO he activat l’emmagatzematge USB. Quan s’activa l’emmagatzematge USB, per seguretat, hi han tot un seguit d’opcions que es desactiven a la tablet. En particular, es perd la visibilitat de sdcard. Repeteixo: NO he activat l’emmagatzematge USB. Aleshores he posat la tablet en mode de “depuració USB”. Per a fer això he anat a la configuració de la tablet, a les “opcions de desenvolupador” dins del submenú “Sistema” i allà he marcat “Depuració d’USB”, com es veu a la imatge:

ID Vendor
(de http://developer.android.com/tools/device.html)
En un terminal he executat l’ordre lsusb (estic fent les meves proves amb un Linux Lubuntu 12.04).

albert@athena:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 003: ID 058f:6254 Alcor Micro Corp. USB Hub
Bus 003 Device 002: ID 1631:5400 Good Way Technology 
Bus 003 Device 003: ID 1631:5002 Good Way Technology 
Bus 003 Device 004: ID 045e:00f6 Microsoft Corp. Comfort Optical Mouse 1000
Bus 001 Device 008: ID 0781:5535 SanDisk Corp. 
Bus 002 Device 006: ID 18d1:0003 Google Inc. 

Observo el dispositiu Bus 002 Device 006: ID 18d1:0003 Google Inc. És la meva tablet. M’interessa l’ID 18dl. Aquest paràmetre el faré servir per a crear un fitxer de filtre amb

sudo leafpad /etc/udev/rules.d/51-android.rules

Si el fitxer no existeix, aleshores el crea. Cal afegir la línia següent. En negreta, el ID Vendor que he trobat amb lsusb

SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="plugdev"

i li donem els permisos adequats amb

sudo chmod a+r /etc/udev/rules.d/51-android.rules

Finalment, el fitxer que he creat:

albert@athena:~$ ls -al /etc/udev/rules.d/51-android.rules
-rw-r--r-- 1 root root 70 ago 17 19:25 /etc/udev/rules.d/51-android.rules
albert@athena:~$ 

Amb l’anterior ja hauria de tenir prou com per a poder activar el DDMS i l’ADB

Si tot ha anat bé, Engegant el DDMS (l’script ddms el trobaré a HOME_ANDROID_SDK/platform/tools/) el dispositiu apareixerà “online”, com a la imatge de sota.

En cas de no haver-se pogut establir la connexió, apareixeran ?????????.???. Caldrà revisar què és el que no hem fet bé.

En aquest moment, amb el DDMS ja podem fer coses com:
– còpies de la pantalla del dispositiu Android.
– enviar i rebre fitxers a i del dispositiu.
– analitzar el consum de memòria de les aplicacions del dispositiu
– analitzar el tràfic de xarxa de les aplicacions.
– emular l’entrada i sortida de trucades telefòniques, SMS, simular ubicació per a testejar el posicionament.
– …

Python en Server Mode

A continuació he posat l’SL4A en Server Mode. Primer de tot, obro SL4A

Per comoditat, preestableixo el port del Server Mode a 50000 (ha de ser un port lliure, i els port “alts”, per sobre de 32768 acostumen a estar-ho). Com alternativa, si poso 0 al valor del port, aleshores el SL4A és el que tria el port. En aquest últim cas, però, com em caldrà després, hauré de revisar quin port ha establert.

Per a fer-ho, primer de tot, al SL4A obro el menú de preferències:

Trio l’opció Server Port:

I l’estableixo a 50000.

A continuació, obro la vista d'”Interpreters”

Activo el mode Servidor (Start Server)

I l’inicio en mode “Privat”

En aquest moment, el SL4A – Py4A ja està iniciat en mode servidor, com podem veure a la notificació:

Vull confirmar que el port del servidor és el 50000. Si faig click a l’icona de l’SL4A s’obre la notificació que em mostra els scripts de SL4A que estan en funcionament:

I obtinc el port. Efectivament és el 50000.

Ja gairebé ho tinc tot a punt.

android.py

Finalment, he d’obtenir de la carpeta d’android el fitxer android.py i l’he de copiar a l’ordinador. Aquest android.py s’ha d’importar en els scripts de Py4A i, per tant, haurà de ser “visible” des de l’interpret de python de l’ordinador. Android.py actua com a proxy entre l’interpret de Python i l’SL4A. Aquesta comunicació quan el SL4A està en server mode es fa per RPC, de forma que realment no cal que l’interpret i el SL4A resideixin a la mateixa màquina. Aquest fet és el que permet desenvolupar a l’ordinador i executar a la tablet.

Per a obtenir el fitxer android.py de la tableta faré servir el File Explorer del ddms.

El fitxer es troba a /sdcard/com.googlecode.pythonforandroid/extras/python

Aleshores fent servir el botó “Pull File From Device”, El botó amb l’icona del disquet del File Explorer, puc copiar android.py a la carpeta de fonts python amb la que treballaré. En el meu cas l’he copiat a /home/albert/workspace/wk-python/prova-py4a

adb forwardind
Finalment, obro un terminal i em poso a la carpeta de fonts, i faig el següent:

albert@athena:~/workspace/wk-python/prova-py4a$ /home/albert/android-sdk-linux/platform-tools/adb start-server
albert@athena:~/workspace/wk-python/prova-py4a$ /home/albert/android-sdk-linux/platform-tools/adb forward tcp:9999 tcp:50000
albert@athena:~/workspace/wk-python/prova-py4a$ export AP_PORT=9999

El port 9999 és troba a la major part de la literatura sobre SL4A, però és per convenció.

Fixem-nos que les quatre línies anteriors sempre seran les mateixes, o sigui que les puc posar en un script.

Dit i fet, el meu script per engegar l’entorn d’sl4a és aquest.

#!/bin/bash

/home/albert/android-sdk-linux/tools/ddms &
/home/albert/android-sdk-linux/platform-tools/adb start-server
/home/albert/android-sdk-linux/platform-tools/adb forward tcp:9999 tcp:50000
export AP_PORT=9999
idle &

Li en dono els permisos d’execució (chmod a+x sl4a)

A L’script primer engego el ddms per si em cal passar scripts de l’ordinador a la tablet, o per si cal controlar l’us de memòria, comunicacions, o per si vull fer còpies de pantalla… Després engeo l’adb i li passo els ports 9999, i 50000 (el que he preestablert per al SL4A Server Mode). Finalment, exporto la variable AP_PORT i, finalment, engego IDLE, l’IDE de pyhton construit amb TkInter.

En cas que no el tingueu instal·lat, IDLE es pot instal·lar amb Synaptic, o des del Centre de Programari de l’Ubuntu

Finalment, des de l’IDLE faig la prova canònica:

I, com no podria ser d’una altre forma, funciona 😉

Hem construït un entorn de desenvolupament per a SL4A i Py4A amb:
Un cable USB
Un ordinador amb
Lubuntu 12.01
JDK1.6
Android SDK
IDE de Python IDLE
Una tablet barata.

Albert Baranguer – 26.08.2012

Els vídeos de la Google IO 2012

Aquesta setmana que tot just acaba ha vist una nova edició de la conferència Google IO d’enguany, al Moscone Center de San Francisco.

A la web de la Google IO 2012 ja han penjat molta informació útil.Per fer-se una idea general de la conferència, poden ser útils els vídeos de les sessions d’apertura (keynotes) dels dos primers dies.

Keynote Day 1

Keynote Day 2

La veritat és que l’ambient és fabulós. Fan venir ganes de ser-hi allà.

S’han presentat els nous productes i projectes de Google.

Per exemple, les Google Glasses

I la nova tablet Google Nexus 7 amb Android 4.1 Jelly Bean

També trobarem vídeos de les sessions tècniques. N’hi han un munt. Per exemple:

Novetats per a desenvolupadors Android:

Acrobàcies amb HTML5

SDK per a integrar aplicacions amb el Google Drive

Aplicacions HTML5 amb Google Chrome

Podeu trobar molts més vídeos de la Google IO al YouTube, al canal GoogleDevelopers, i a la mateixa web de Google Developers.

Algun any d’aquests caldrà fer un pensament i anar a veure què es cou a la Google IO.

Apunts d’HTML5

HTML5 és més que un llenguatge d’etiquetes. És el resultat de la convergència dels esforços del WWW Consortium i el WHATWG per a fer evolucionar l’HTML. Amb HTML5 podem parlar pròpiament de “programació”. A la vegada, es manté la compatibilitat cap enrere, Tot HTML previ a HTML5 “és també” HTML5. Ara bé, si fem servir les noves etiquetes, fulls d’estil i les noves APIs de javascript podrem arribar molt lluny.

Una demostració del que es pot arribar a fer amb HTML5 és aquest Mario Bros. El codi es pot descarregar. Només cal registrar-se gratuitament a codeproject.com.

Què ens proporciona HTML5? Sense ser exhaustius:

– Noves etiquetes amb nova semàntica per a organitzar millor la presentació de la informació
– Noves etiquetes per a afegir àudio i vídeo a les pàgines sense haver de dependre de plugins de terceres parts.
– Canvas, que ens permet dibuixar en 2D i 3D generant imatges tipus bitmap.
– SVG Scalable Vector Graphics. Per a generar imatges vectorials.
– Un mecanisme nou i consistent entre els diferents browsers per a emmagatzemar dades locals (Local Storage, més enllà de les cookies).
– Nous tipus de camps als formularis HTML amb, això és important, validació pel propi navegador.
– Geolocalització.
– Microdata (una eina per al posicionament a Internet).
– aplicacions offline.
– Base de dades SQL local
– …

Compatibilitat
HTML5 no està especificat del tot. No tots els navegadors dels diferents dispositius suporten HTML5, només els més moderns. No tots els navegadors moderns suporten “tot” l’HTML5. O el suporten exactament igual. En definitiva, res de nou.

Tanmateix, és una bona idea avançar poc a poc en la migració a HTML5. Tot l’HTML anterior a HTML5 és, també HTML5, per tant, la transició a HTML5 “heavy” es pot encetar gradualment.

Abans d’utilitzar una característica d’HTML5 caldrà determinar si està disponible al navegador de l’usuari. En entorns controlats, com intranets, on el navegador de l’usuari pot estar especificat, aquesta pot ser una tasca senzilla. En entorns més oberts una aproximació útil és fer servir llibreries javascript per a determinar les prestacions del navegador. Una de recomanada sovint als diferents manuals és la llibreria opensource Modernizr.

En general, fent servir Modernizr, seguirem el següent esquema:

if (Modernizr.CaracterísticaHTML5) {
    // puc fer servir HTML5
} else {
    // no puc fer servir HTML5
}

Anem a repassar amb més detall algunes opcions:

Noves etiquetes (algunes)
Noves etiquetes per a organitzar la informació, section, article… N’hi han moltes més!

<section>
una secció
<aside> 
informació addicional
</aside>
<header>la capcelera</header>
<article>un article</article>
<footer>el peu</footer>
</section>

Aquestes etiquetes permeten organitzar la informació de forma més propera a com s’està presentant habitualment. Un dels criteri en el desenvolupament d’HTML5 és “estandaritzar” allò que s’està fent. O si es vol, de regular les bones pràctiques. És dir, no s’inventa res si no cal, més aviat, s’afina. Les etiquetes section, article… anteriors es podien trobar abans d’HTML5 com els noms més habituals en DIVs, com va descobrir Google en analitzar milers de pàgines, fent les funcions d’organització que justament ara assumeixen.

CSS
Aquestes etiquetes no tenen, a priori, una representació gràfica predeterminada i això ens porta a l’altre element fonamental de’HTML5: el CSS3 (CSS level 3, acrtualment en desenvolupament).

A HTML5 es considera una mala pràctica (en realitat, des d’abans d’HTML5 que es considera una mala pràctica) l’ús dels atributs modificadors de la presentació a les etiquetes. Totes les característiques de presentació haurien d’anar a fulls d’estil CSS.

Etiquetes per a audio i video
Finalment, l’audio i el video es podran reproduir de forma nativa sense que calguin plugins (és la fi de Flash?). En realitat, la reproducció d’àudio i vídeo nativa dependrà dels còdecs disponibles. A més, no tots els navegadors suporten les etiquetes audio i video. Tot plegat, la següent estructura es pot utilitzar com a punt de partida:

Audio:

<audio controls>
    <source src="audio.ogg" type="audio/ogg">
    <source src="audio.mp3" type="audio/mpeg">
    <a href="http://player.swf?soundFile=audio.mp3">
    http://player.swf?soundFile=audio.mp3</a>
</audio>

L’explicació és la següent: la llista de sources ens permet proporcionar l’audio en diferents formats, amb l’esperança que algun d’ells serà nadiu al navegador dels usuaris (ogg és nadiu a firefox i chrome). El navegador reproduirà el primer de la llista per al que disposi de còdecs. Atenció, doncs, a l’ordre! En cas que el navegador no suporti l’etiqueta audio, aleshores, encara es podrà fer servir el plugin de flash. Si tampoc això funciona, es podrà descarregar el fitxer d’àudio amb un enllaç.

Vídeo:
És simètric a l’anterior:

<video controls 
width="360" height="240"
       poster="poster.jpg">
    <source src="video.ogv" type="video/ogg">
    <source src="video.mp4" type="video/mp4">
    <a href="http://player.swf?file=video.mp4">
    http://player.swf?file=video.mp4</a>
</video>

Com a comentari general, vàlid per a audio i video, indicar que cal especificar correctament els Content-type dels àudios i els vídeos. No A més, cal que els Content-types estiguin disponibles a la llista de Content-types del servidor web que serveis les pàgines.

Canvas
Canvas ens permet dibuixar. Això que sembla tan poca cosa, senzillament no es podia fer abans de forma fàcil. Ara es pot. l’etiqueta canvas determina una regió rectangular en la que es podrà, mitjançant javascript, dibuixar línies, rectangles, corbes… pintar de colors, amb diferents tipus de pinzells, aplicar transformacions…
Canvas és, en ell mateix, tot un món. Vegem-ne un petit exemple:

<!DOCTYPE html>
<html>
<head><title>Canvas</title>
<script>
function Pinta() {
    alert(Math.PI);
    var canvas = document.getElementById('idCanvas');
    var ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.moveTo(10,120);

    for(var x=10; x<=310; ++x) {
        y = 100*Math.sin(2*Math.PI*(x - 10)/300);
        ctx.lineTo(x, 120 - y);
    }
    ctx.stroke();
}
</script>
</head>
<body onload="Pinta()">

<canvas id="idCanvas" width="320" height="240">
</canvas>
</body>
</html>

Ens dibuixa la bonica corba sinusoïdal.

 

SVG
No només es poden crear programàticament imatges bitmap o raster. Tambés es poden crear imatges vectorials amb SVG. SVG ja és un vell conegut de diferents browser, com el Firefox, però ara passa a formar part de “l’especificació” d’HTML5. Per a il·lustrar, aquí mostro el que podria ser l’esquelet d’un petit joc:  proveu a fer click al cercle roig que batega i es mou ràpidament per la regió rectangular. Vet aquí una combinació de SVG i JavaScript.

Aquesta animació ha estat del tipus programàtic basada en setInterval de JavaScript, però és possible animar els objecte SVG de forma declarativa, amb l’element “animate”.

<!DOCTYPE html>
<html>
<head>
<meta charset="latin-1" />
<title>svg</title>
<script>
var xx=240;
var yy=160;
var rr=10;
var ix=1; var iy=1; var ir=1;
var obj=null;
var objClicks = null;
var totalClicks = 0;
function init() {
  obj = document.getElementById("idCercle");
  objClicks = document.getElementById("idScoring");
  setInterval("anima()",10);
}

function anima() {
  obj.setAttribute("cx", xx);
  obj.setAttribute("cy", yy);
  obj.setAttribute("r",rr);

  xx += ix; yy += iy; rr += ir;

  if (((xx + rr) > 480) || ((xx - rr) < 0)) {ix = -ix};
  if (((yy + rr) > 320) || ((yy - rr) < 0)) {iy = -iy};
  if ((rr > 20) || (rr < 5)) {ir = -ir};

  return true;
}

function ImA(whatiam) {
      ++totalClicks;
	  objClicks.innerHTML="jo soc un " + whatiam + "; total de clicks: " + totalClicks;
	  return true;
}
</script>
</head>
<body onload="init()">
<svg height="320" width="480" id="idSvgCanvas">
    <circle fill="#ff0000" onclick="ImA('cercle');" id="idCercle">
	</circle>
</svg>
<div id="idScoring">Click me!</div>
</body>
</html>

 

Nous tipus de camps de formulari

HTML5 afegeix nous camps de formulari. Pel que fa a la compatibilitat amb navegadors no HTML5, aquests representaran als nous camps com camps de text. De fet, aquest serà el comportament dels navegadors que suporten HTML5 però que no tenen un comportament específics per a aquests nous tipus.

Dit d’una altra forma, si preveiem que un camp d’un formulari s’adapta a algun dels nous tipus, és interessant fer servir el nou tipus, encara que el navegador no suporti HTML5 perquè, de totes formes, els seguirà presentant com una caixa de text.
En un futur aquests nous camps estaran.

Actualment ja hi han alguns navegadors que fan un tractament especial i validació “nadiua” per a determinats camps.

En el cas de Google Chrome, de moment hi ha representació gràfica especial per als type=”number”, type=”range” i s’ha afegit l’atribut “placeholder” en els input type de tipus text.

<!DOCTYPE html>
<html>
<head><title>Form</title>
</head>
<body ">
<form id="idForm">
data: <input type="date" name="data" placeholder="data"/><br />
hora: <input type="time" name="hora" placeholder="hora"/><br />
placeholder: <input type="text" placeholder="prova placeholder" name="texts" /><br />
email: <input type="email" name="email" placeholder="email" /><br />
url: <input type="url" name="url" placeholder="url"/><br />
Nombre: <input type="number" min="0" max="100" step="5" value="50" /><br />
Rang: <input type="range" min="0" max="100" step="5" value="50" /><br />
cerca: <input type="search" name="cerca" placeholder="cerca"><br />
color: <input type="color" name="color" placeholder="color"><br />
</form>
</body>
</html>

El codi anterior es presenta de la següent forma amb Google Chrome:

Geolocalització
Si està disponible en el navegador del dispositiu mòbil de l’usuari la geolocalització, geolocation, permet, si l’usuari dona el seu permís, que els llocs puguin conèixer l’ubicació del dispositiu del client. Depenent del dispositiu aquesta ubicació es determina de forma molt precisa, via gps, o no tant, per triangulació entre repetidors de telefonia, o de forma més burda, per rang d’IP del proveïdor. A priori, doncs hi ha indeterminació pel que fa a la precisió en la geolocalització, i en el temps de resposta. És més costosa, però molt més precisa, una localització per GPS que una localització per IP, que és immediata, però que pot tenir una “precisió” d’un radi de centenars de quilòmetres.

Un exemple de localització el tenim en el següent codi:

<!DOCTYPE html>
<html>
<head>
<meta charset="latin-1" />
<title>geoloc</title>
<script type="text/javascript">
function geoloc() {
	if (navigator.geolocation) {
	  var timeoutVal = 10 * 1000 * 1000;
	  navigator.geolocation.getCurrentPosition(
	    displayPosition, 
	    displayError,
	    { enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 }
	  );
	}
	else {
	  alert("Aquest navegador no suporta la geolocalització");
	}
}

function displayPosition(position) {
  var lLat = position.coords.latitude; 
  var lLong = position.coords.longitude
  var sText= "<b>Latitud:</b> " + lLat + 
             ", <b>Longitud:</b> " + lLong;
  document.getElementById("idPos").innerHTML = sText;
  var sImgSrc = "http://maps.google.com/maps/api/staticmap?" +
               "center=" + lLat + "," + lLong + "&zoom=14&size=512x512&maptype=roadmap&" + 
               "markers=color:blue%7Clabel:S%7C" + lLat + "," + lLong + "&sensor=false";
  document.getElementById("idImg").src = sImgSrc;
}

function displayError(error) {
  var errors = { 
    1: 'Permission denied',
    2: 'Position unavailable',
    3: 'Request timeout'
  };
  document.getElementById("idPos").innerHTML = "Error: " + errors[error.code];
}
</script>
</head>
<body onload="geoloc()" onunload="GUnload()">
Geolocalització.<br />
<div id="idPos">Calculant posició...</div>
<img id="idImg" src="" height="512" width="512" "alt="la meva ubicació"/>
</body>
</html>

Al provar la pàgina anterior al Mozilla Firefox, primer de tot observo que em demana permís:

Li en dono, i em mostra la meva posició.

Val a dir que no ha estat gens precís! Estic fent aquest experiment amb l’ordinador de sobretaula i, evidentment, la localització va per rang d’IP. Encara bo que ha trobat que és Barcelona! Evidentment, la potència de la geolocalització apareix quan la fem servir sobre dispositius mòbils que permeten una ubicació precisa.

Microdata
Les microdata permet afegir semàntica a les pàgines html. Això que sona molt críptic, i que segurament ho és X)), es pot traduir a “un sistema per afegir informació útil a la nostra pàgina web per a que cercadors i indexadors, o sigui Google, la trobin més interessant i la facin sortir més amunt o més destacada en les cerques”.

Microdata afegeix la semàntica mitjançant uns atributs (itemscope, itemtype, itemid, itemprop, itemref) en les etiquetes de l’HTML.

Aquests atributs permeten identificar peces del contingut de la pàgina marcat per etiquetes HTML com valors de propietats definides en un vocabulari.

Els vocabularis són petits i estan relacionats amb un camp semàntic.

Les Microdata utilitzen vocabularis per a definir la semàntica que es volo afegir. Tothom pot crear els vocabularis que vulgui per al camp semàntic que li interessi, però ja n’hi han de fets. I els podeu examinar a http://www.data-vocabulary.org/

Per exemple, per al camp semàntic “persona” podem trobar el següent vocabulari a http://www.data-vocabulary.org/Person/

Property          Description
--------          ----------- 
name (fn)         Name
nickname          Nickname
photo             An image link
title             The person's title (for example, Financial Manager)
role              The person's role (for example, Accountant)
url               Link to a web page, such as the person's home page
                  affiliation (org) The name of an organization with
                  which the person is associated (for example, an
                  employer). If fn and org have the exact same value,
                  Google will interpret the information as referring
                  to a business or organization, not a person.
friend	          Identifies a social relationship between the person
                  described and another person.
contact	          Identifies a social relationship between the person
                  described and another person.
acquaintance	  Identifies a social relationship between the person
                  described and another person.
address (adr)	  The location of the person. Can have the
                  subproperties 
                       street-address, 
                       locality, 
                       region, 
                       postal-code, 
                       and country-name.

Com funciona? el següent exemple esta extret de la Wikipedia

HTML original

<section> Hello, my name is John Doe, 
I am a graduate research assistant at 
the University of Dreams. 

My friends call me Johnny. 
You can visit my homepage at 
<a href="http://www.JohnnyD.com">www.JohnnyD.com</a>. 
I live at 1234 Peach Drive Warner Robins, Georgia.
</section>

Aquest HTML se li pot afegir semàntica, és dir, significat per als cercadors, de la següent forma:

<section itemscope itemtype="http://data-vocabulary.org/Person"> 
        Hello, my name is 
        <span itemprop="name">John Doe</span>, 
        I am a 
        <span itemprop="title">graduate research assistant</span> 
        at the 
        <span itemprop="affiliation">University of Dreams</span>. 
        My friends call me 
        <span itemprop="nickname">Johnny</span>. 
        You can visit my homepage at 
        <a href="http://www.JohnnyD.com" itemprop="url">www.JohnnyD.com</a>. 
        <section itemprop="address" itemscope itemtype="http://data-vocabulary.org/Address">
                I live at 
                <span itemprop="street-address">1234 Peach Drive</span> 
                <span itemprop="locality">Warner Robins</span>
                , 
                <span itemprop="region">Georgia</span>.
        </section>
</section>

Aquest tros de codi HTML5 (noteu l’us de l’etiqueta section) és interpretat per Google de la següent forma (es pot provar el resultats d’afegir Microdata a les pàgines amb el Google’s Rich Snippet Testing Tool.)

I una advertència: que Google pugui interpretar la Microdata NO vol dir, repeteixo, NO vol dir, que forçosament en millori el posicionament.

Database Storage
L’especificació del “Database storage” permet afegir una base de dades SQL local al navegador de l’usuari, per a utilitzar-la localment i com a magatzem persistent.
L’especificació no diu quina BD ha de ser, però almenys Chrome (també Chromium i Android) i Opera estan implementant SQLite i són les úniques implementacions a dia d’avui.

La tria d’SQLite no és casual. Aquesta eficient i potent BD opensource forma part de projectes com FireFox i Chrome des de fa molt de temps. La meva opinió és que disposar d’aquesta BD formant part del nucli del navegador i no posar-la a disposició del usuari era una provocació.

Que la BD triada a les implementacions disponibles sigui SQLlite permet entre d’altres coses, que la puguem examinar (i operar amb ella) fent us d’eines com SQLIteman. Això sí, cal saber on buscar: En el cas del Linux Ubuntu 12.04 que tinc instal·lat i amb el que faig els meus experiments, resulta que, per a Chrome, les bases de dades SQLite es troben, ben amagades, a /home/usuari/.config/google-chrome/Default/databases/file__0 i es van numerant. Amb una inspecció de la carpeta no es poden identificar per nom.

Cal repetir, però, que Database Storage no està present a tots els navegadors que suporten HTML5.

Tanmateix, és temptador disposar d’una BD SQL local.

El següent és un exemple d’agenda de telefons que vaig trobar a Internet (lamentablement, no em vaig guardar l’enllaç) i que he adaptat.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="latin-1" />
        <title>SQL Storage</title>
            
        <script>        
        var sCreate = "CREATE TABLE IF NOT EXISTS Agenda (id INTEGER PRIMARY KEY AUTOINCREMENT, Nom TEXT, cognom TEXT, telefon TEXT)";
        var sSelectAll = "SELECT * FROM Agenda";
        var sInsert = "INSERT INTO Agenda (Nom, cognom, telefon) VALUES (?, ?, ?)";
        var sUpdate = "UPDATE Agenda SET Nom = ?, cognom = ?, telefon = ? WHERE id = ?";
        var sDelete = "DELETE FROM Agenda WHERE id=?";
        var sDrop = "DROP TABLE Agenda";
        var db, dataset;        
        var resultats, id, Nom, cognom, telefon;
        
        function inicialitza() {
            resultats = document.getElementById('resultats');
            id = document.getElementById('id');
            Nom = document.getElementById('Nom');     
            cognom = document.getElementById('cognom'); 
            telefon = document.getElementById('telefon');
            db = openDatabase("AgendaTelefons.db", "1.0", "Agenda de Telefons", 200000);
            crearTaula();
        }
        
        function onError(tx, error) {
            alert(error.message);
        }
        
        function mostrarFiles() {
            resultats.innerHTML = '';
            db.transaction(function(tx) {
                tx.executeSql(sSelectAll, [], function(tx, result) {
                    dataset = result.rows;
                    for (var i = 0, item = null; i < dataset.length; i++) {
                        item = dataset.item(i);
                        resultats.innerHTML +=
                        '<li>' + item['cognom'] + ' , ' + item['Nom'] + 
                        ' <a href="#" onclick="carregarFila('+i+')">modificar</a>  ' + 
                        '<a href="#" onclick="esborrarFila('+item['id']+')">esborrar</a></li>';
                    }
                });
            });
        }
        
        function crearTaula() {
            db.transaction(function(tx) {
                tx.executeSql(sCreate, [], mostrarFiles, onError);
            });
        }
        
        function afegirFila() {
            db.transaction(function(tx) {
                tx.executeSql(sInsert, [Nom.value, cognom.value, telefon.value], carregar_i_reset, onError);
            });
        }
        
        function carregarFila(i) {
            var item = dataset.item(i);
            Nom.value = item['Nom'];
            cognom.value = item['cognom'];
            telefon.value = item['telefon'];
            id.value = item['id'];
        }
        
        function actualitzarFila() {
            db.transaction(function(tx) {
                tx.executeSql(sUpdate, 
                          [Nom.value, cognom.value, telefon.value, id.value], 
                          carregar_i_reset, 
                          onError);
            });
        }
        
        function esborrarFila(id) {
            db.transaction(function(tx) {
                tx.executeSql(sDelete, [id], mostrarFiles, onError);
            });
            netejaFormulari();
        }
        
        function esborrarTaula() {
            db.transaction(function(tx) {
                tx.executeSql(sDrop, [], mostrarFiles, onError);
            });
            netejaFormulari();
        }
        
        function carregar_i_reset() {
            netejaFormulari();
            mostrarFiles();
        }
        
        function netejaFormulari() {
            Nom.value = '';
            cognom.value = '';
            telefon.value = '';
            id.value = '';
        }
        </script>
    </head>
    
    <body onload="inicialitza();">   
        <br/><br/>
        <div align="center">
            <input type="hidden" id="id"/>
            Nom:<input type="text" id="Nom"/><br/>
            Cognom:<input type="text" id="cognom"/><br/>
            Telefon: <input type="text" id="telefon"/><br/>
            <button onClick="netejaFormulari()">Neteja Formulari</button>
            <button onClick="actualitzarFila()">Actualitzar</button>
            <button onClick="afegirFila()">Afegir</button>
            <button onClick="esborrarTaula()">Esborrar taula</button>
            <div id="resultats"> </div>
        </div>
    </body>
</html>

Local Storage
Local Storage és una alternativa als Cookies. És dir, és un mecanisme senzill i consistent entre els navegadors per a emmagatzemar parelles nom-valor de forma persistent (o sigui que entre sessions mantenim la informació).

Aquesta característica l’implementen tots els navegadors que suporten HTML5, des de Internet Explorer fins a Safari, passant pels Chrome, Android, Opera o FireFox. Com a curiositat, en el cas de FireFox resulta que la tecnologia amb que s’implementa Local Storage és, ves quina cosa, SQLite.

LocalStorage proporciona una API senzilla:
getItem(clau),
setItem(clau, valor),
removeItem(clau),
lenght: número de clausdeter
key(index): clau i-èssima

Els dos últims ens permeten implementar un iterador. Anem a repetir l’agenda de telefons fent servir LocalStorage:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="latin-1" />
        <title>Local Storage</title>
            
        <script>              
        var resultats, NomCognom, telefon;
        
        function inicialitza() {
            resultats = document.getElementById('resultats');
            NomCognom = document.getElementById('NomCognom');     
            telefon = document.getElementById('telefon');
            mostrarFiles();
        }
        
        
        function mostrarFiles() {
            resultats.innerHTML = '';
            for (var i = 0; i < localStorage.length; i++) {
            	item = localStorage.key(i);
               resultats.innerHTML +=
               '<li>' + item + "-" + localStorage[item] + 
               ' <a href="#" onclick="carregarFila(\''+ item +'\')">modificar</a>  ' + 
               '<a href="#" onclick="esborrarFila(\''+ item + '\')">esborrar</a></li>';
            }
        }
        
        
        function afegirFila() {
            localStorage[NomCognom.value] = telefon.value;
            mostrarFiles();            
        }
        
        
        function carregarFila(item) {
            NomCognom.value = item;
            telefon.value = localStorage[item];
        }
        
        
        function esborrarFila(item) {
            localStorage.removeItem(item);
            netejaFormulari();
        }
        
        
        function netejaFormulari() {
            NomCognom.value = '';
            telefon.value = '';
            mostrarFiles();
        }
        </script>
    </head>
    
    <body onload="inicialitza();">   
        <br/><br/>
        <div align="center">
            Nom i cognom: <input type="text" id="NomCognom"/><br/>
            Telefon: <input type="text" id="telefon"/><br/>
            <button onClick="netejaFormulari()">Neteja Formulari</button>
            <button onClick="afegirFila()">Afegir - Actualitzar</button>
            <div id="resultats"> </div>
        </div>
    </body>
</html>

I recordem que amb Chrome, podem repassar el contingut del localStorage (amb F12, eines de desenvolupador, a la pestanya resources).

Aplicacions Offline
Amb HTML5 podem fer aplicacions. Les aplicacions amb HTML5 són aplicacions web, és dir, connectades. Aplicacions que viuen a Internet. Tanmateix, característiques com Local Storage o Database Storage ens obren la possibilitat a desenvolupar aplicacions que puguin treballar desconnectades.

Les aplicacions desconnectades es descarregaran total o parcialment al nostre dispositiu, i seran funcionals quan el dispositiu no estigui connectat a Internet, és dir, físicament estaran al nostre dispositiu.

Fer una aplicació offline és tan senzill com afegir-li un fitxer de manifest de caché a una aplicació HTML5 “normal”, i que les pàgines de l’aplicació el declarin a l’etiqueta HTML

<html manifest="/cache.manifest">

El manifest té un content-type específic: “text/cache-manifest”. Cal assegurar que el servidor web serveix el content type correctament.

Què hi posarem en aquest manifest? ni més ni menys que la llista de pàgines i recursos que formaran l’aplicació offline. Un cop el navegador llegeixi el manifest procedirà a descarregar els diferents components. Per exemple:

CACHE MANIFEST
/index.html
/estils.css
/scripts.js
/imatge01.jpg
/imatge02.jpg
/imatge03.jpg

La primera línia ha de ser “CACHE MANIFEST”.

Tanmateix, també podem voler que hi hagin pàgines o recursos que explícitament no es descarreguin mai. Aleshores podem distingir entre recursos a la xarxa, i recursos a la caché

   
CACHE MANIFEST
NETWORK:
/comptador.php
CACHE:
/index.html
/estils.css
/scripts.js
/imatge01.jpg
/imatge02.jpg
/imatge03.jpg

Els recursos a la secció NETWORK no seran descarregats.

A més, por passar l’aplicació web hi hagin recursos que no estiguin definits ni a NETWORK, ni a CACHE. En aquest cas podem tenir una secció FALLBACK per a tractar aquests casos especials.

Per a saber-ne molt més
Hi han molts i molt bons manuals d’HTML5. I alguns d’ells es poden trobar lliures a Internet. En particular, jo m’he llegit, o m’estic llegint els següents:

http://diveintohtml5.info/. Aquesta web és la versió online i lliure del llibre “HTML5. Up and Running” de Mark Pilgrim, publicat per O’Reilly.

Un altre llibre interessant: Pro HTML5 Programming, publicat per Apress

Aquest és molt fàcil de llegir, és curtet i va al gra: HTML5 for Web Designers, publicat per “A Book Apart”.

Una cerca a la web us proporcionarà molts resultats. Els llibres que he citat són, simplement, alguns que he llegit i que, per tant, amb veig amb cor de recomanar.

A més, crec que és molt útil disposar des “xuletaris” o cheat sheets. Aquests estan molt bé:

HTML 5: http://webdesign.about.com/b/2012/05/01/html5-cheat-sheet.htm

Encara un altre d’HTML5: http://www.smashingmagazine.com/2009/07/06/html-5-cheat-sheet-pdf/

Canvas: http://www.nihilogic.dk/labs/canvas_sheet/

Un bon xuletari de CSS també ajuda
CSS: http://coding.smashingmagazine.com/2009/07/13/css-3-cheat-sheet-pdf/

En aquest enllaç, fins i tot fan una recopilació de cheat sheets de CSS.

Finalment, si voleu veure exemples d’HTML5 en acció,aquesta web en proporciona molts: http://html5demos.com/

Aplicacions Android amb Python

Recentment hm’ha caigut a les mans una pissarreta Android (una tablet, per entendre’ns) molt senzilla i he aprofitat per a fer alguns experiments.

Realment, per a fer experiments amb Android no cal un dispositiu Android “físic” o “real”, doncs l’SDK d’Android proporciona emuladors que ens permetran provar els desenvolupaments. Ara bé, tot cicle de desenvolupament, que inicialment hauria de realitzar-se sobre els emuladors, hauria d’acabar amb proves sobre dispositius físics.

La primera pregunta que m’he fet és: Com es poden crear aplicacions per a la tablet? Abans que res, dir que el Sistema Operatiu Android és basa en una adaptació del nucli de Linux per a dispositius amb unes determinades característiques de hardware. És, doncs, programari de codi obert ben conegut.

L’opció més potent i més comú és amb l’Android SDK. L’Android SDK és un conjunt de classes Java que ens permetran desenvolupar aplicacions que aprofitin les diferents característiques del nostre dispositiu: els widgets de la UI, la geolocalització, la connexió Wi-Fi, la càmara… El llenguatge que farem servir serà Java. Jo crec que, en teoria, es podríen utilitzar altres llenguatges per a la JVM que generin bytecode (que es puguin compilar), per exemple Groovy, o Scala. Sobre aquests dos últims llenguatges dir que, a més, s’està realitzant un esforç per a convertir-los, també, en llenguatges d’script per a Android.

Tanmateix, la màquina virtual java dels dispositius Android està tunejada, es tracta de la màquina virtual Dalvik, amb un bytecode que no és directament compatible amb el de Java. Així que potser caldria, a la seva vegada, tunejar els compiladors de Groovy i Scala per a que poguessin generar bytecode compatible amb Dalvik. En fi.

Scripting per a Android? Sí. Una opció interessant de desenvolupament per a Android és amb llenguatges d’scripting, fent us de la plataforma “Scripting Layer for Android”(SL4A).

Amb SL4A podrem crear aplicacions per a Android fent us de llenguatges com Python (segurament l’opció més madura) o BeanShell, Perl, Lua o d’altres. Amb SL4A podem programar a la mateixa tablet, en la que disposarem d’un editor. Segurament, però, preferirem programar al nostre ordinador i passar els scripts a l tablet.

Encara hi ha una altre possibilitat de fer scripting fora del SL4A: Programar aplicacions amb HTML 5. En parlarem en un proper post.

Finalment, hi ha la possibilitat de programar amb C i C++, com no. Tanmateix aquesta opció, segons es diu a la mateixa web de descàrrega de l’Android NDK (Native Developer Kit), es considera un complement al desenvolupament amb l’Android SDK (Software Developer Kit), amb Java. La idea és que només s’haurien de programar amb C/C++ aquelles parts crítiques que requereixin estar optimitzades a baix nivell. O sigui, no es considera una opció per a desenvolupament d’aplicacions completes.

El resum de tot plegat és que el desenvolupament d’aplicacions Android que tinguin mes entitat que un simple script passa per l’Android SDK i Java.

En aquest post, però, faré experiments amb l’SL4A i Python.

Abans que res, advertir que a la web posa “SL4A is designed for developers and is alpha quality software.” S’ha entès, oi? Tanmateix, sembla que la plataforma SL4A és prou estable.

Tenint en compte l’anterior podem instal·lar l’SL4A i el Python for Android. Si busquem al Google Play, no trobarem aquestes apps. Cal descarregar-se-les de la web http://code.google.com/p/android-scripting/

En el moment que he començat a preparar aquest post, les versions eren aquestes:

SL4A: sl4a_r5.apk.
Python for Android: PythonForAndroid_r5.apk.
Potser ja n’hi han de més recents.

Per a instal·lar l’SL4A caldrà activar l’opció “Unknown sources” al menu “Application” de la tablet.

PythonForAndroid_r5.apk.és un instal·lador que en la seva primera execució instal·larà el Python connectant-se a Internet i descarregant el que li faci falta. A més, després podrem instal·lar mòduls addicionals diversos: per a bluetooth, interface amb Zope, criptografia… Els podem trobar a la wiki del python-for-android.

Per a llençar els scripts de Python cal punxar a l’icona de l’SL4A (no a la de “Python for Android”). En executar l’SL4A tindrem una llista dels scripts d’exemple i de test (a la meva tablet els trobo a /sdcard/sl4a/scripts).

Tots els programes en Python que vulguin fer servir el hardware específic del dispositiu Android hauran d’importar “android”:

import android; 
...
droid = android.Android()

droid serà l’objecte principal per accedir al dispositiu.

El tradicional Hello World es fa:

droid.makeToast('Hola! Bon dia a tothom!!')

makeToast mostra una notificació de curta durada.

De fet, també hauria pogut utilitzar print. Però es tracta de fer alguna cosa nova, no?

L’API completa es pot consultar en aquest enllaç. http://code.google.com/p/android-scripting/wiki/ApiReference.

La plataforma Android, a més del hardware específic, compta també amb un software específic de base. Entre el software de base hi ha SQLite3. Des de Python i SL4A la utilització d’SQLite3 segueix els mateixos procediments que amb un desktop.

Per exemple, crear la taula de prova “taula” i afegir-hi files

#!/usr/bin/python 
# coding: iso-8859-1 
# python i sqlite 

#import 
import sqlite3 

# es connecta a una base de dades 
conn = sqlite3.connect("./prova-sqlite.db") 

# obté un cursor. En realitat és més que un cursor. 
cursor=conn.cursor() 

# crea una taula 
cursor.execute("CREATE TABLE taula (Id INTEGER PRIMARY KEY, nom TEXT, valor TEXT)") 

# inserta files "A column declared INTEGER PRIMARY KEY will autoincrement." 
print "insereix 3 files" 
cursor.execute("insert into taula(nom, valor) values (?, ?)", ("nom 1","valor 1") ) 
cursor.execute("insert into taula(nom, valor) values (?, ?)", ("nom 2","valor 2") ) 
cursor.execute("insert into taula(nom, valor) values (?, ?)", ("nom 3","valor 3") ) 

# amb un mapeig 
print "insereix 3 files més" 
item = {"nom": "nom 4", "valor": "valor 4"} 
cursor.execute("insert into taula(nom, valor) values (:nom, :valor)", item) 
item = {"nom": "nom 5", "valor": "valor 5"} 
cursor.execute("insert into taula(nom, valor) values (:nom, :valor)", item) 
item = {"nom": "nom 6", "valor": "valor 6"} 
cursor.execute("insert into taula(nom, valor) values (:nom, :valor)", item) 

# commit 
conn.commit() 

# a veure què ha fet... 
cursor.execute("select id, nom, valor from taula") 

# itera a través de les files 
# obtenir-ne només resultat un: 
print "estat inicial" 
for fila in cursor: 
	# recupera els valors 
	idnom, nom, valor = fila[0], fila[1], fila[2] 
	# els mostra 
	print "id: " + str(idnom) + "; nom: " + nom + "; valor: " + valor 

# tanca el cursor 
cursor.close() 

# tanca la connexió 
conn.close()

Puc copiar l’script anterior a la carpeta sl4a de la pissarreta. He connectat la pissarreta amb l’ordinador amb el cable USB i he creat una subcarpeta albert dins les carpeta sl4a/scripts per deixar-hi allí els meus experiments.

Aleshores, puc executar l’script des d’SL4A amb l’opció shell.

La versió de Python que s’instal·la és la 2.6.2. Però la versió no conté tots els mòduls estàndar de la distribució. En particular falta TkInter, el mòdul per a fer GUIs basat en Tk.

Ara bé, puc fer interfases gràfiques senzilles també a partir de l’objecte Android.

Per a donar un cop d’ull a aquestes possibilitats gràfiques, agafaré un dels scripts de prova que acompanyen P4A, el test.py, i en deixaré només la part gràfica.

Vet aquí la versió simplificada de test.py: test-gui.py

# coding: latin-1

import android
import time

droid = android.Android()

# mostra una notificació de curta durada
def test_make_toast():
  result = droid.makeToast('Hola món amb makeToast')
  return True

# mostra una notificació al zona de menú amb una icona
# i hi roman allà fins que hom hi fa click
def test_notify():
  result = droid.notify('Títol de prova', 'Hola, surto al menú!')
  return True 

# mostra una caixa de missatges amb un text i botó de seguir
def test_alert_dialog():
  titol = 'Interfície d\'usuari'
  missatge = 'Benvingut al test d\'integració.'
  droid.dialogCreateAlert(titol, missatge)
  droid.dialogSetPositiveButtonText('Seguir')
  droid.dialogShow()
  resposta = droid.dialogGetResponse().result
  print resposta
  return True

# mostra botons d'opció
def test_alert_dialog_with_buttons():
  title = 'Alert Box'
  message = ('Alert Box amb tres botons. Es quedarà aturat fins que en premis un.')
  droid.dialogCreateAlert(title, message)
  droid.dialogSetPositiveButtonText('Sí')
  droid.dialogSetNegativeButtonText('No')
  droid.dialogSetNeutralButtonText('Cancel·lar')
  droid.dialogShow()
  response = droid.dialogGetResponse().result
  return response['which'] in ('positive', 'negative', 'neutral')

# mostra un "spinner" una icona d'espera
def test_spinner_progress():
  title = 'Spinner'
  message = 'Exemple de "spinner".'
  droid.dialogCreateSpinnerProgress(title, message)
  droid.dialogShow()
  time.sleep(2)
  droid.dialogDismiss()
  return True

# mostra una barra de progrés horitzontal
def test_horizontal_progress():
  title = 'Horitzontal'
  message = 'Barra de progrés horitzontal'
  droid.dialogCreateHorizontalProgress(title, message, 50)
  droid.dialogShow()
  for x in range(0, 50):
    time.sleep(0.1)
    droid.dialogSetCurrentProgress(x)
  droid.dialogDismiss()
  return True

# mostra una llista
def test_alert_dialog_with_list():
  title = 'Alerta amb llista'
  droid.dialogCreateAlert(title)
  droid.dialogSetItems(['opció 1', 'opció 2', 'opció 3'])
  droid.dialogShow()
  response = droid.dialogGetResponse().result
  return True

# mostra una llista de radio button
def test_alert_dialog_with_single_choice_list():
  title = 'Alerta amb botó'
  droid.dialogCreateAlert(title)
  droid.dialogSetSingleChoiceItems(['opció 1', 'opció 2', 'opció 3'])
  droid.dialogSetPositiveButtonText('Sí!')
  droid.dialogShow()
  response = droid.dialogGetResponse().result
  return True

# mostra una llista de checkbox (multi-opció)
def test_alert_dialog_with_multi_choice_list():
  title = 'Alerta amb opció de sel·lecció múltiple'
  droid.dialogCreateAlert(title)
  droid.dialogSetMultiChoiceItems(['opció 1', 'opció 2 ', 'opció 3', 'opció 4', 'opció 5'], [])
  droid.dialogSetPositiveButtonText('Sí!')
  droid.dialogShow()
  response = droid.dialogGetResponse().result
  return True

def test_input():
	variable = droid.dialogGetInput('Input box','Escriu alguna cosa:').result
	droid.dialogCreateAlert('Mostra les dades','Has escrit: %s'%variable)
	droid.dialogShow()
	return True


# main
test_make_toast()
test_notify()
test_alert_dialog()
test_alert_dialog_with_buttons()
test_spinner_progress()
test_horizontal_progress()
test_alert_dialog_with_list()
test_alert_dialog_with_single_choice_list()
test_alert_dialog_with_multi_choice_list()
test_input()

Què més podriem fer ràpidament? Enviar correus, per exemple.

# coding: latin-1

import android

droid = android.Android()

adreces='abaranguer@gmail.es,stsoftlliure@gmail.com,albert.baranguer@josoc.cat'
subject='enviat des d\'android'
missatge='aquest és el missatge de prova que envio des de la pissarreta'

droid.sendEmail(adreces, subject, missatge, None)

El programet anterior obre l’aplicació que tinguem registrada per a enviar correus electrònics. En el meu cas es tracta de GMail. L’aplicació s’obre amb la pàgina del correu preparat per a enviar, amb els destinataris, el subject i el cos de missatge que hem preparat a la crida.

La plataforma SL4A i el Python for Android ofereixen moltes més possibilitats. El que he fet en el post només ha estat una aproximació. Per a aprofondir en el tema, ens podem adreçar al lloc web de SL4A, al lloc de Python-for-Android, als fòrums i també hi ha algun llibre: “Pro Android Python with SL4A.” d’Apress.