ottaky@ottaky.com
 
HTML OK
CSS OK
 
 
ottaky.com supports..
ORG
no2id

SL4A (Scripting Layer for Android)

Author: sjb (Steve Brown) - ottaky@ottaky.com
Date: 19th July 2010
See also: HTC Desire
Scripting Layer for Android project home
Scripting Layer for Android at Google groups

What is it?

From the project website
Scripting Layer for Android (SL4A, formerly known as Android Scripting Environment or ASE) brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device. These scripts have access to many of the APIs available to full-fledged Android applications, but with a greatly simplified interface that makes it easy to get things done.

If you own an Android powered phone and you're a programmer who likes to get things done, as opposed to a programmer who uses Java, then you'll definitely want to take a look at SL4A which will allow you to write scripts in the languages you already know to make your phone do what you want it to do. In essence, it allows you to write scripts which have access to a subset of the Android functionality in a Real Language like Perl or Python.

Perl support is not great currently (r25). It works, but only for small values of "works". Messages between SL4A and the phone OS are sent and received as JSON, and the current implementation of the supplied JSON module lacks UTF-8 support, so any messages that contain anything other than basic ASCII will die.

Python works brilliantly, so I would definitely recommend Python over Perl. The Python distribution comes bundled with a ton of extra modules so it's easy to get things done with the minimum of effort.

Below you can find examples of Perl and Python scripts for SL4A, and there are some more here.

This Python script uses zxing's barcode scanner to scan a barcode, display the details and query the UPC Database as appropriate. The results are displayed using Android's native alert dialogue functionality.

SL4A Barcode
import xmlrpclib
import sys

import android

droid = android.Android()

api = xmlrpclib.ServerProxy('http://www.upcdatabase.com/rpc')

while True:

    scan = droid.scanBarcode().result

    if scan:

        response = ["Code: %s\nFormat: %s" % (scan['extras']['SCAN_RESULT'], scan['extras']['SCAN_RESULT_FORMAT'])]
    
        if scan['extras']['SCAN_RESULT_FORMAT'] == 'EAN_13' or scan['extras']['SCAN_RESULT_FORMAT'] == 'UPC_A':

            result = {}

            if scan['extras']['SCAN_RESULT_FORMAT'] == 'EAN_13':
            
                result = api.lookupEAN(scan['extras']['SCAN_RESULT'])
            
            else:
            
                result = api.lookupUPC(scan['extras']['SCAN_RESULT'])

            if result.has_key('found'):
    
                if result['found']:
    
                    if result.has_key('description'):
    
                        response.append('Item: %s' % (result['description']))
    
                    if result.has_key('size'):
    
                        response.append('Size: %s' % (result['size']))
    
                    if result.has_key('mfrName'):
    
                        response.append('Manufacturer: %s' % (result['mfrName']))
    
                    if result.has_key('mfrGLN'):
    
                        response.append('GLN: %s' % (result['mfrGLN']))
    
                    if result.has_key('mfrAddress'):
    
                        response.append('Address: %s' % (result['mfrAddress']))
    
                    if result.has_key('issuerCountry'):
    
                        response.append('Country: %s' % (result['issuerCountry']))
    
                else:
    
                    response.append('Not found in database')
    
            else:
    
                response.append('API error')
    
        else:
    
            response.append('Cannot lookup this format')

        content = "\n".join(response)

        while True:

            droid.dialogCreateAlert(scan['extras']['SCAN_RESULT'], content)
            droid.dialogSetPositiveButtonText('Again')
            droid.dialogSetNeutralButtonText('Copy');
            droid.dialogSetNegativeButtonText('Quit');
            droid.dialogShow()
            response = droid.dialogGetResponse().result
        
            if response.has_key('which'):

                if response['which'] == 'positive':

                    break

                if response['which'] == 'neutral':
        
                    droid.setClipboard(content)
                    droid.makeToast('Content copied to clipboard')
    
                elif response['which'] == 'negative':
    
                    sys.exit(0)

    else:

        break

This Perl script uses the most recent location information available on the phone to display a Google map with the nearest supermarkets (UK only, sorry) overlaid on top. The heavy lifting is actually carried out on this (ottaky.com) webserver which determines the store locations and generates KML that can be displayed on the map.

SL4A Markets
use Android;

my $droid = new Android;

my $lkl = $droid->getLastKnownLocation();

my $net_fix = $lkl->{'result'}->{'network'}->{'time'} || 0;
my $gps_fix = $lkl->{'result'}->{'gps'}->{'time'}     || 0;

if ($net_fix || $gps_fix) {

    my $fix_type = 'network';

    $fix_type = 'gps' if ($gps_fix > $net_fix);

    my $url = 'http://www.ottaky.com/cgi-bin/ase_markets_kml.cgi'.
              '?lat='.$lkl->{'result'}->{$fix_type}->{'latitude'}.
              '&lon='.$lkl->{'result'}->{$fix_type}->{'longitude'};

    $url =~ s|([^A-Za-z0-9])|sprintf("%%%02X", ord($1))|eg;
    $url =~ s| |+|g;
 
    $droid->viewMap($url);
}
else { die "No fix" }