vrijdag 3 juni 2011

Android hacking

So I bought an Android Archos 32 for my 5 year old daughter. A tiny device, ideal for fun things she can do (without spending money, it's wifi only).

I also want to see with it what is possible with python on this device, and if perhaps I can port a part of Gramps to there. Well, it will not be easy it seems, but something is possible. I'm thinking about an reader that can understand the Gramps xml fileformat.

So, what is needed to try things out?
  1. SL4A (scripting layer for android), so download it on your phone by clicking the barcode on : http://code.google.com/p/android-scripting/
    Then when downloaded, go to downloads on your android phone, and click the download to install it.
  2. Next, install python for SL4A, latest version of PythonForAndroid from http://code.google.com/p/android-scripting/downloads/list
    Again, click it in the Downloads to install it, then open run in and the app you see will have an install button at the top. Click that to install python and extra python modules/scripts
  3. You are now ready on your phone, click the SL4A app and you will see a list of scripts, click one to run it in a terminal or run it standalone
  4. To develop, you need to have a good PC/laptop, and install the android emulator there. Follow eg the walkthrough on this blog. So download the SDK, install it, and run it by typing in the tools directory ./android, then in the emulated phone, install again SL4A and python4android.
  5. Write a script on your PC. Eg, I write an application in
    ~/gramps/android
    push it to the open emulated android, go in the platform-tools directory from the SDK and run
    ./adb push ~/gramps/android/ /sdcard/sl4a/scripts/
  6. On the emulated phone, you will see the script in SL4A, and you can click it to run it.
  7. Once your script is not crashing your emulated phone anymore, you can push it to your actual phone: connect the phone to your PC in usb-mode, and move the file to /sdcard/sl4a/scripts/ on the phone. You can now run it in SL4A on the actual phone.
So, what is my first android script? A framework to read gramps xml files, so



#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 Benny Malengier
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

# $Id: gramps.py 17390 2011-05-03 14:38:54Z nick-h $

#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------

import android
import os
import sys


BASE_PATH = '/sdcard/gramps'
if not os.path.isdir(BASE_PATH):
os.mkdir(BASE_PATH)


#different states
ST_START = 0
ST_STOP = 1
ST_LOADXML = 2
ST_SELOBJTYPE = 3

class grampsA:
def __init__(self, droid ):
self.droid = droid
self.state = ST_START
self.error = None

def run(self):
while True:
if self.state == ST_STOP:
break
elif self.state == ST_START:
self.setxmlfile()
else:
print 'Unknown State'
break
#check if we have an error, if so alert user and exit
if self.error:
self.showerror(self.error)
break

def showerror(self, error):
self.droid.dialogCreateAlert('Error encountered: %s' % self.error)
self.droid.dialogSetPositiveButtonText('Close')
self.droid.dialogShow()
response = self.droid.dialogGetResponse().result

def setxmlfile(self):
title = 'Select Gramps xml file from %s' % BASE_PATH
files = [item for item in os.listdir(BASE_PATH)]
if not files:
self.droid.dialogCreateAlert('No files found in %s! Move a file there.'
% BASE_PATH)
self.droid.dialogSetPositiveButtonText('OK')
self.droid.dialogShow()
response = self.droid.dialogGetResponse().result
self.state = ST_STOP
return

self.droid.dialogCreateAlert('Select file')
self.droid.dialogSetItems(files)
self.droid.dialogSetNegativeButtonText('Stop')
self.droid.dialogShow()
response = self.droid.dialogGetResponse().result
if response.has_key('which') and response['which'] == 'negative':
self.state = ST_STOP
return

sel = self.droid.dialogGetResponse().result['item']
try:
self.xmlfile = files[sel]
self.droid.makeToast(self.xmlfile + ' chosen')
except:
self.error = 'Wrong response from file selection'
return
#next the xml file must be loaded, we import it in a dict database.


def main( ):
grampsA( android.Android( ) ).run()

if __name__ == '__main__':
main()