At the end of my post on how to Setup GoogleCL on WinXP I joked about running GoogleCL, Google's new command line tool for accessing Google service, on the Android OS. Trying to make that joke a reality, I found the Android Scripting Environment project which allows running Python scripts on Android - step one: accomplished.
Warning: this is not for the faint of heart. The instructions that follow will require you to not only install software on your Android device, but also to download and modify Python source code. I will assume that you are capable of using SVN to get source code from code.google.com and applying a .patch file. And you'll probably end up having to type on a really tiny keyboard at some point. Don't say I didn't warn you.
Install Android Scripting Environment (ASE)
The easiest way to install ASE is to open up the ASE home page on your PC and scan the barcode.
Hack GoogleCL
Note: this change is now in trunk and won't be necessary in the 0.9.8 release.
Now grab the source code for GoogleCL (see here).
I needed to apply a small patch to get my setup to work with the 0.9.7 release.
The Patch
Index: src/googlecl/__init__.py =================================================================== --- src/googlecl/__init__.py (revision 299) +++ src/googlecl/__init__.py (working copy) @@ -156,7 +156,7 @@ import pickle token_path = os.path.join(GOOGLE_CL_DIR, TOKENS_FILENAME_FORMAT % user) if os.path.exists(token_path): - with open(token_path, 'r') as token_file: + with open(token_path, 'rb') as token_file: token_dict = pickle.load(token_file) try: token = token_dict[service.lower()] @@ -184,7 +184,7 @@ token_path = os.path.join(GOOGLE_CL_DIR, TOKENS_FILENAME_FORMAT % user) success = False if os.path.exists(token_path): - with open(token_path, 'r+') as token_file: + with open(token_path, 'rb+') as token_file: token_dict = pickle.load(token_file) try: del token_dict[service.lower()] @@ -236,12 +236,12 @@ import stat token_path = os.path.join(GOOGLE_CL_DIR, TOKENS_FILENAME_FORMAT % user) if os.path.exists(token_path): - with open(token_path, 'r') as token_file: + with open(token_path, 'rb') as token_file: token_dict = pickle.load(token_file) else: token_dict = {} token_dict[service] = token - with open(token_path, 'w') as token_file: + with open(token_path, 'wb') as token_file: # Ensure only the owner of the file has read/write permission os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) pickle.dump(token_dict, token_file)
I made it small on purpose because it's hard to read anyway. Hopefully, this way you'll be able to select it all and copy it easily. Apply the patch to your GoogleCL code.
The patch makes GoogleCL open the auth token file in binary mode. I needed this because later I'll be copying a token file from my desktop to my phone. Without the patch, the phone rejected token the file.
Install GoogleCL
Now you need to copy your GoogleCL source onto the phone. Your Android phone may vary. On mine, I just connect to my desktop computer via USB and select "Disk Drive" as the USB connection type. This mounts the phone's storage as two removable disks. You can also remove the SD card from your phone and put it in a reader connected to your computer, since it's the card we're putting files on.
Find ase/extras/python/ on your SD card. This directory should contain a number of Python modules already, such as gdata and xml. Copy your googlecl/src/googlecl in next to them. Also copy googlecl/src/google to ase/scripts/google.py. You'll use this later when you write your talking calendar scripts.
Write a Script to Call GoogleCL
This script changes your HOME dir to /sdcard so that GoogleCL can write your .googlecl configuration file. I wasn't able to figure out how to let GoogleCL write to the default HOME location. The other settings are what ASE uses when it runs Python scripts. I don't know how many of them are required to actually make this work, and I haven't felt like fiddling with it too much since it's working.
Replace [USERNAME] with your Google account username and save it as ase/scripts/calendar_today.sh.
#!/bin/bash export HOME=/sdcard export TEMP="/sdcard/ase/extras/pythontmp" export PYTHONHOME="/data/data/com.google.ase/python" export PYTHONPATH="/sdcard/ase/extras/python:/sdcard/ase/scripts/" /data/data/com.google.ase/python/bin/python /sdcard/ase/scripts/google.py --user [USERNAME] calendar list --date `date +%Y-%m-%d`
Make It Talk
I love this part because it's so easy with Android. This script calls the one above and passes the output to the phone's text-to-speech service. Save it as ase/scripts/say_calendar.py.
import android import subprocess p = subprocess.Popen( ['/system/bin/sh', '/sdcard/ase/scripts/calendar_today.sh'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, errors = p.communicate() print errors print output droid = android.Android() droid.ttsSpeak(output)
Important Note for Windows Users: be sure to convert any files written on Windows to UNIX line endings before copying them to your phone. If you need to, you can also open up the files on your phone and remove the extra line end characters there. ASE has a file editor built in and I use ASTRO for editing other files.
Preauthentication
I couldn't get the GoogleCL OAuth process to work on my phone. When I returned to ASE from completing the auth process in the browser the script had already stopped running, interrupting the authentication. I got around that by preparing a auth token file on my desktop and copying it to the phone.
Using your modified copy of GoogleCL on the desktop, authenticate to each of the services you want to use from your phone. Then take the access_tok_[username] file from the .googlecl directory under your home directory and put that file in /sdcard/.googlecl/ on your phone.
Dismount your phone's drives from your desktop, or reinstall the SD card in your phone.
Make It So
Now, assuming you've followed my instructions exactly and I haven't left out anything important, you should be able to:
- Open up ASE on your phone
- Select Menu->View->Interpreters
- Select Menu->Add->Python
- Press back to return to the list of scripts
You should see a number of scripts listed, including the ones you just wrote. Select say_calendar.py. Your calendar entries for today should be displayed and the phone should speak them soon after. Now, it may not sound the way you expect - the TTS isn't perfect. But I think that's pretty good for a few minutes setting up some free scripting tools.
I would like to extend a very big thank you to Jason Holt and Tom Miller. Their encouragement and advice made this possible. Thanks, guys.