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.

One thought on “Aplicacions Android amb Python

Deixa un comentari

Fill in your details below or click an icon to log in:

WordPress.com Logo

Esteu comentant fent servir el compte WordPress.com. Log Out /  Canvia )

Google photo

Esteu comentant fent servir el compte Google. Log Out /  Canvia )

Twitter picture

Esteu comentant fent servir el compte Twitter. Log Out /  Canvia )

Facebook photo

Esteu comentant fent servir el compte Facebook. Log Out /  Canvia )

S'està connectant a %s