Monday, March 09, 2009

Android Meenie early preview: more features described

In my previous post we've seen some basic features of Meenie, like adding placemarks to the map while you are on the road, but there's a more common use case when you are planning your trip in advance and want to add some placemarks, let's say the airport, hotel, office, restaurants, etc.

While it's perfectly possible to use the same use case as being on the road, it's much more confortable to add those placemarks and search for restaurants, hotels or whatever you are looking for in the comfort of your desktop computer. In those cases we will be using Google Maps to help us.
Google Maps has a feature called My Maps, where you can define map placemarks, lines and areas.


Then using a conversion utility which is running in Google Appengine to off-load the processing of the map in the android phone, we will be able to download this map and allow Meenie to show the same content. To locate the map we will be using the URL that appears in Link, in Google Maps top right.

This is the result.



Some details about Google Appengine being access from Android and using the Google Maps Link URL in Meenie and other Android applications were ommited for clarity and will be discussed on upcoming posts.



As always, comments are gladly welcome.

Wednesday, March 04, 2009

Android Meenie early preview

I was working on an Android application that scratchs a personal itch. As I'm traveling very frequently and visiting new cities all the time I always need some information readily available.
For example, the airport, station, hotel, office, venue, places to visit, restaurants, etc.
You need these information quickly accessible, while you travel.

This is an early preview of Android Meenie maps front end. I'm working on the server side now, so more information is coming soon.

Monday, March 02, 2009

Android emulator small bug

I wonder why Android SDK for Linux is distributed as a ZIP file, but anyway if you try to install the SDK in a multiuser environment you'll face some problems.
As usual, in a multiuser environment to avoid undesired changes to the software it should be installed as root.
Unpacking the SDK as root and then running as a normal user you receive this error

### WARNING: Cannot write user data file '/home/diego/.android/SDK-1.1/userdata-qemu.img'

if you check file permissions you can find that you can write to ~/.andrid/SDK-1.1 and userdata-qemu.img has been actually written.

So, what's the problem. Using strace to find out, we can see this

open("/home/diego/.android/SDK-1.1/userdata-qemu.img", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0600) = 3
open("/opt/android-sdk-linux_x86-1.1_r1/tools/lib/images//userdata.img", O_RDONLY|O_NOCTTY|O_LARGEFILE) = -1 EACCES (Permission denied)
close(3) = 0
write(2, "### WARNING: Cannot write user d"..., 109### WARNING: Cannot write user data file '/home/diego/.android/SDK-1.1/userdata-qemu.img': Permission denied ) = 109 unlink("/home/diego/.android/SDK-1.1/userdata-qemu.img.lock") = 0
exit_group(3) = ?

qemu is reporting the wrong error, and the root of the problem is openning /opt/android-sdk-linux_x86-1.1_r1/tools/lib/images//userdata.img for reading.


Here is how to fix it

$ sudo chmod a+r /opt/android-sdk-linux_x86-1.1_r1/tools/lib/images//userdata.img
$ sudo chmod a+r /opt/android-sdk-linux_x86-1.1_r1/tools/lib/images//system.img

and everything will run smoothly.

Friday, February 27, 2009

Blacklisting kernels modules from command line

Sometimes the need to blacklist a module from the Linux kernel command line arise, though it's not very common, and it seems there's no a simple solution.

Well, most distributions support/etc/modprobe.d/blacklist kind of files stored in the filesystem, where you can list the modules to blacklist. But, what if this is not possible, mainly because you don't have a filesystem at all to change and reboot like happened to me while working in the new cult 3.1 thin client OS version ?

I'm listing te change here because it's very useful and can be used in other situations as well, like the one described here using Knoppix.

In the init file, while processing command line options, this snippet should be added

blacklist=*)
for m in $(echo ${x#blacklist=} | sed 's/+/ /g')
do
echo -e "# added by cult\nblacklist $m\n" >> \
/etc/modprobe.d/blacklist
done
;;
Here, the cult convention of separating multiple values in kernel command line options by '+' is used, but you can use ',' as well if you feel more comfortable.

Next time your kernel panics and you need to blacklist a module from the kernel command line you know.

Friday, January 02, 2009

Solved: Ubuntu 8.04 64 bit, Eclipse 3.4, Subclipse 1.4.7 and Subversion 1.5

A previous post, a possible solution to the problem of installing Subversion support in Eclipse 3.4 on Ubuntu 8.04 64 bit.
Although this worked much better Eclipse is still crashing under some operations. I've detected a problem while developing an android application, checked out from a subversion repository, when R.java is recreated causing Eclipse to crash.

This time, and convinced to find a solution or being forced to use Windows Vista as a development platform, I paid more attention to the crash log.

#
# An unexpected error has been detected by Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fbacc7e525a, pid=29545, tid=1098688848
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0-b23 mixed mode linux-amd64)
# Problematic frame:
# V [libjvm.so+0x1f125a]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

--------------- T H R E A D ---------------

Current thread (0x00000000401a7400): JavaThread "CompilerThread1" daemon [_thread_in_native, id=29552, stack(0x00000000416ca000,0x00000000417cb000)]

siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000000000000

Registers:
RAX=0x0000000000000000, RBX=0x00007fba8c561068, RCX=0x00007fba9a4ef5b0, RDX=0x0000000000000050
RSP=0x00000000417c6d70, RBP=0x00000000417c6de0, RSI=0x00007fba9a4ef5b0, RDI=0x00007fba8c561068
R8 =0x00007fba9a4ef608, R9 =0x00007fba9a4ef5b0, R10=0x00007fba9a4ef5b0, R11=0x0000000000000000
R12=0x00007fba8c561030, R13=0x0000000000000000, R14=0x0000000040162f50, R15=0x0000000000000001
RIP=0x00007fbacc7e525a, EFL=0x0000000000010246, CSGSFS=0x0000000000000033, ERR=0x0000000000000004
TRAPNO=0x000000000000000e

Top of Stack: (sp=0x00000000417c6d70)
0x00000000417c6d70: 00007fba9b0d1358 00000001ffffffff
0x00000000417c6d80: 00007fba9a4ef5b0 00000002cc789361
0x00000000417c6d90: 00007fba9b0d1350 00000007417c79a0
0x00000000417c6da0: 00000000417c7a68 01000000000005d2
0x00000000417c6db0: 00000000417c79a0 00007fbacce2e970
0x00000000417c6dc0: 00000000417c79a0 00000000417c6f30
0x00000000417c6dd0: 00000000417c6ef0 00000000417c6ec0
0x00000000417c6de0: 00000000417c7000 00007fbacc7e479c
0x00000000417c6df0: 00000000417c7a68 00000000417c6fb0
0x00000000417c6e00: 00007fba8c3e8010 00007fba8c000020
0x00000000417c6e10: 00000000417c6e80 00007fbacce47d70
0x00000000417c6e20: 00007fba8c104a50 0000000000000174
0x00000000417c6e30: 00000000417c7ac0 00007fbaccfe6c1c
0x00000000417c6e40: 00000000417ca950 00000000417c6e80
0x00000000417c6e50: 00007fbacce4a4e0 00007fba9a80ff90
0x00000000417c6e60: 0000000000000174 00007fbaccc1edf2
0x00000000417c6e70: 0000000040111030 00007fbaccc1eec1
0x00000000417c6e80: 00000000417ca950 00000000417c6ec0
0x00000000417c6e90: 00007fbacce4a4e0 0000000000007fe8
0x00000000417c6ea0: 00007fba8c39f620 00007fbaccc1edf2
0x00000000417c6eb0: 0000000040111030 00007fbaccc1eec1
0x00000000417c6ec0: 00007fbacce2e970 00007fba0000000e
0x00000000417c6ed0: 00000000417c9350 00000000417c79a0
0x00000000417c6ee0: 0000000000000a05 00000000401a79a0
0x00000000417c6ef0: 000000000000000d 00000000417c9350
0x00000000417c6f00: 00007fba8c5bad00 00007fbacc788d00
0x00000000417c6f10: 00007fba8c54f5a0 00000000000005d3
0x00000000417c6f20: 00000000417c6fb0 00007fba8c11dc70
0x00000000417c6f30: 000000000000000c 00000000417c9350
0x00000000417c6f40: 00007fba8c19c360 00007fba8c2d3790
0x00000000417c6f50: 00007fba8c0d9750 00007fba8c0da3b0
0x00000000417c6f60: 00007fba9bd08e60 00000000417c7ac0

Instructions: (pc=0x00007fbacc7e525a)
0x00007fbacc7e524a: 48 89 cf 41 ff 95 80 00 00 00 48 89 df 49 89 c5
0x00007fbacc7e525a: 8b 00 41 21 44 24 38 41 8b 45 04 21 43 04 41 8b

Stack: [0x00000000416ca000,0x00000000417cb000], sp=0x00000000417c6d70, free space=1011k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x1f125a]
V [libjvm.so+0x1f079c]
V [libjvm.so+0x2445f5]
V [libjvm.so+0x241105]
V [libjvm.so+0x1e05f7]
V [libjvm.so+0x248f98]
V [libjvm.so+0x248936]
V [libjvm.so+0x62a819]
V [libjvm.so+0x624ac1]
V [libjvm.so+0x50630a]


Current CompileTask:
C2:1124 org.eclipse.core.internal.dtree.DataTreeNode.forwardDeltaWith([Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode;[Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode;Lorg/eclipse/core/internal/dtree/IComparator;)[Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode; (469 bytes)


--------------- P R O C E S S ---------------

Java Threads: ( => current thread )
0x00007fbaa47d7800 JavaThread "org.eclipse.jdt.internal.ui.text.JavaReconciler" daemon [_thread_blocked, id=30170, stack(0x0000000041d08000,0x0000000041e09000)]
0x0000000040347000 JavaThread "Worker-11" [_thread_blocked, id=30132, stack(0x0000000040e0c000,0x0000000040f0d000)]
0x00007fba9c43c400 JavaThread "Worker-10" [_thread_blocked, id=30131, stack(0x000000004100e000,0x000000004110f000)]
0x00007fba9bec9800 JavaThread "Worker-9" [_thread_blocked, id=29647, stack(0x0000000041210000,0x0000000041311000)]
0x00007fbaa69c5c00 JavaThread "SVN Kit 1.2 Connector" [_thread_blocked, id=29611, stack(0x000000004245a000,0x000000004255b000)]
0x00007fba9becf800 JavaThread "Thread-14" [_thread_blocked, id=29609, stack(0x0000000042359000,0x000000004245a000)]
0x00007fbaa623a000 JavaThread "Timer-1" [_thread_blocked, id=29607, stack(0x000000004110f000,0x0000000041210000)]
0x00007fbaa43b9000 JavaThread "Worker-8" [_thread_blocked, id=29602, stack(0x0000000042258000,0x0000000042359000)]
0x00007fba9dda5400 JavaThread "Worker-7" [_thread_blocked, id=29601, stack(0x0000000040f0d000,0x000000004100e000)]
0x00007fba9dcd9400 JavaThread "Worker-6" [_thread_in_vm, id=29600, stack(0x0000000041bcf000,0x0000000041cd0000)]
0x00007fba9beec800 JavaThread "Worker-4" [_thread_blocked, id=29598, stack(0x0000000042056000,0x0000000042157000)]
0x00007fbaa498d800 JavaThread "Timer-0" [_thread_blocked, id=29592, stack(0x000000004074d000,0x000000004084e000)]
0x00007fba9af2a800 JavaThread "Device List Monitor" daemon [_thread_in_native, id=29591, stack(0x0000000042157000,0x0000000042258000)]
0x00007fba9da2b800 JavaThread "Monitor" daemon [_thread_in_native, id=29574, stack(0x0000000041f55000,0x0000000042056000)]
0x00007fba9c3e5800 JavaThread "org.eclipse.jdt.internal.ui.text.JavaReconciler" daemon [_thread_blocked, id=29571, stack(0x000000004064c000,0x000000004074d000)]
0x00007fbaa5500800 JavaThread "Java indexing" daemon [_thread_blocked, id=29569, stack(0x0000000041e54000,0x0000000041f55000)]
0x0000000040378c00 JavaThread "Start Level Event Dispatcher" daemon [_thread_blocked, id=29561, stack(0x000000004054b000,0x000000004064c000)]
0x000000004031d800 JavaThread "Framework Event Dispatcher" daemon [_thread_blocked, id=29560, stack(0x0000000041ace000,0x0000000041bcf000)]
0x0000000040437400 JavaThread "State Data Manager" daemon [_thread_blocked, id=29559, stack(0x00000000419cd000,0x0000000041ace000)]
0x00000000401a9000 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=29553, stack(0x00000000417cb000,0x00000000418cc000)]
=>0x00000000401a7400 JavaThread "CompilerThread1" daemon [_thread_in_native, id=29552, stack(0x00000000416ca000,0x00000000417cb000)]
0x000000004019bc00 JavaThread "CompilerThread0" daemon [_thread_blocked, id=29551, stack(0x00000000415c9000,0x00000000416ca000)]
0x000000004019a400 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=29550, stack(0x00000000414c8000,0x00000000415c9000)]
0x0000000040176400 JavaThread "Finalizer" daemon [_thread_blocked, id=29549, stack(0x000000004097a000,0x0000000040a7b000)]
0x0000000040175000 JavaThread "Reference Handler" daemon [_thread_blocked, id=29548, stack(0x0000000040879000,0x000000004097a000)]
0x0000000040113000 JavaThread "main" [_thread_in_vm, id=29546, stack(0x00000000413c7000,0x00000000414c8000)]

Other Threads:
0x000000004016fc00 VMThread [stack: 0x0000000040b09000,0x0000000040c0a000] [id=29547]
0x00000000401ab000 WatcherThread [stack: 0x00000000418cc000,0x00000000419cd000] [id=29554]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
def new generation total 42496K, used 9220K [0x00007fbaa84d0000, 0x00007fbaab2e0000, 0x00007fbaada20000)
eden space 37824K, 14% used [0x00007fbaa84d0000, 0x00007fbaa8a53ac0, 0x00007fbaaa9c0000)
from space 4672K, 76% used [0x00007fbaaa9c0000, 0x00007fbaaad3d7b0, 0x00007fbaaae50000)
to space 4672K, 0% used [0x00007fbaaae50000, 0x00007fbaaae50000, 0x00007fbaab2e0000)
tenured generation total 94144K, used 48464K [0x00007fbaada20000, 0x00007fbab3610000, 0x00007fbab84d0000)
the space 94144K, 51% used [0x00007fbaada20000, 0x00007fbab0974090, 0x00007fbab0974200, 0x00007fbab3610000)
compacting perm gen total 86016K, used 85928K [0x00007fbab84d0000, 0x00007fbabd8d0000, 0x00007fbac84d0000)
the space 86016K, 99% used [0x00007fbab84d0000, 0x00007fbabd8ba3b8, 0x00007fbabd8ba400, 0x00007fbabd8d0000)
No shared spaces configured.

Dynamic libraries:
40000000-40009000 r-xp 00000000 08:05 424775 /usr/lib/jvm/java-6-sun-1.6.0.07/jre/bin/java
40108000-4010a000 rwxp 00008000 08:05 424775 /usr/lib/jvm/java-6-sun-1.6.0.07/jre/bin/java
4010a000-4054b000 rwxp 4010a000 00:00 0 [heap]
4054b000-4054e000 ---p 4054b000 00:00 0
4054e000-4064c000 rwxp 4054e000 00:00 0
4064c000-4064f000 ---p 4064c000 00:00 0

...

VM Arguments:
jvm_args: -Djava.library.path=/usr/share/java/ -Djava.library.path=/usr/lib/jni/ -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx256m -XX:MaxPermSize=256m
java_command: /opt/java/eclipse-3.4/plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar -os linux -ws gtk -arch x86_64 -showsplash -launcher /opt/java/eclipse-3.4/eclipse -name Eclipse --launcher.library /opt/java/eclipse-3.4/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.101.R34x_v20080731/eclipse_1115.so -startup /opt/java/eclipse-3.4/plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar -exitdata 1190018 -vm /usr/bin/java -vmargs -Djava.library.path=/usr/share/java/ -Djava.library.path=/usr/lib/jni/ -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx256m -XX:MaxPermSize=256m -jar /opt/java/eclipse-3.4/plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
Launcher Type: SUN_STANDARD

Environment Variables:
PATH=/home/diego/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
USERNAME=diego
LD_LIBRARY_PATH=/usr/lib/jvm/java-6-sun-1.6.0.07/jre/lib/amd64/server:/usr/lib/jvm/java-6-sun-1.6.0.07/jre/lib/amd64:/usr/lib/jvm/java-6-sun-1.6.0.07/jre/../lib/amd64:/usr/lib64/xulrunner-addons
SHELL=/bin/bash
DISPLAY=:0.0

Signal Handlers:
SIGSEGV: [libjvm.so+0x661750], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGBUS: [libjvm.so+0x661750], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGFPE: [libjvm.so+0x504550], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGPIPE: SIG_IGN, sa_mask[0]=0x00000000, sa_flags=0x00000000
SIGXFSZ: [libjvm.so+0x504550], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGILL: [libjvm.so+0x504550], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGUSR1: SIG_DFL, sa_mask[0]=0x00000000, sa_flags=0x00000000
SIGUSR2: [libjvm.so+0x5067c0], sa_mask[0]=0x00000000, sa_flags=0x10000004
SIGHUP: [libjvm.so+0x506520], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGINT: [libjvm.so+0x506520], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGTERM: [libjvm.so+0x506520], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
SIGQUIT: [libjvm.so+0x506520], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004


--------------- S Y S T E M ---------------

OS:lenny/sid

uname:Linux 2.6.24-22-generic #1 SMP Mon Nov 24 19:35:06 UTC 2008 x86_64
libc:glibc 2.7 NPTL 2.7
rlimit: STACK 8192k, CORE 0k, NPROC 12221, NOFILE 1024, AS infinity
load average:0.49 0.31 0.27

CPU:total 2 (2 cores per cpu, 1 threads per core) family 6 model 15 stepping 6, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3

Memory: 4k page, physical 1537752k(21980k free), swap 3148700k(3103580k free)

vm_info: Java HotSpot(TM) 64-Bit Server VM (10.0-b23) for linux-amd64 JRE (1.6.0_07-b06), built on Jun 10 2008 01:53:27 by "java_re" with gcc 3.2.2 (SuSE Linux)

time: Mon Dec 29 22:56:29 2008
elapsed time: 490 seconds



As we can see, the problem is not in subclipse or subversive but in the java virtual machine. It's true, that the problem only showed up when we use subversion, but this is another story.
So, to obtain the solution, download jdk-6u11-linux-x64.bin from Sun and install it.
Next step is to tell Eclipse to use this newly installed java.
Edit eclipe.ini and add these lines

-showsplash
org.eclipse.platform
-vm
/opt/java/jdk1.6/bin/java
-vmargs
-Djava.library.path=/usr/share/java/
-Djava.library.path=/usr/lib/jni/
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx256m
-XX:MaxPermSize=256m



Problem solved !
No crashes till now...

Android Intent Playground 2.0 (Installation)

These are the simplest steps to install Android Intent Playground using the emulator.


Download site
Go to http://codtech.com/downloads/android and download AndroidIntentPlayground.apk.
To be able to download it you need to attach an sdcard image to the emulator using -sdcard sdcard.img.

Install blocked
Click on the recently downloaded application to install it.
If you receive an Install blocked message you have to enable installation of applications form unknown sources, not only from Android Market.



Enable installation from unknown sources
Go to Settings and enable Unknown sources.

Install application
Once the settings are correct the application can be installed.



Launch the application
After being successfully installed launch the application and you will be presented with Android Intent Playground main screen.



Play with intents
Fell free to play with intents. Using Menu -> Random is a good way to get started.

Sunday, December 28, 2008

Ubuntu 8.04 64 bit, Eclipse 3.4, Subclipse 1.4.7 and Subversion 1.5

How to get these working together ?
Firstly, it's incredible that such a simple thing requires such a big amount of research, trial and error and frustration when should work out-of-the-box.
I'm writing this post hoping to save somebody else precious development time.

Introduction
Subclipse 1.4.7 requires Subversion 1.5 which is not available in normal Ubuntu repositories.
Eclipse just crashes using other combinations, in this environment.

Subversion 1.5
Install subversion 1.5 from Ubuntu backports. Just download the required packages and install them, there's no need to enable backports repository just for this.
Download the following packages:
  • subversion (> 1.5)
  • libsvn1 (>1.5)
  • libsvn-java (>1.5)
and install them using dpkg, for example in 64 bit

$ sudo dpkg --install libsvn-java_1.5.1dfsg1-1ubuntu2_amd64.deb \
libsvn1_1.5.1dfsg1-1ubuntu2_amd64.deb \
subversion_1.5.1dfsg1-1ubuntu2_amd64.deb

Subclipse 1.4.7
Add http://subclipse.tigris.org/update_1.4.x site to Eclipse and install Subclipse 1.4.7, Subversion Client Adapter 1.5.2 and Subversion Native Client Library Adapter (JavaHL) 1.5.5

Configuring Eclipse 3.4
If you try to use Subversion in Eclipse you will receive and error, because the Subversion JNI libraries are not detected.
To achieve thisd you have to edit eclipse.ini (the path depends on where you've decided to install it, as it's not installed from deb packages)
Add these two lines (this is the little magic)

-showsplash
org.eclipse.platform
-vmargs
-Djava.library.path=/usr/share/java/
-Djava.library.path=/usr/lib/jni/
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx256m
-XX:MaxPermSize=256m

and, after restarting Eclipse, you will be able to use Subversion.
Verify that under SVN Interface the correct JavaHL version is detected in Window -> Preferences -> Team -> SVN.

Android Intent Playground 2.0

Android Intent Playground 2.0 was released.


Check the previous post too: Diego Torres Milano's blog: Android: Playing with Intents which refers to a previous version.



This new version includes some extra features to help you understand and test Android intents.

Installation
Use the method described in Diego Torres Milano's blog: Android Intent Playground 2.0 installation or download AndroidIntentPlayground.apk and install it on the emulator using

adb install AndroidIntentPlayground.apk


Usage
After successful installation the launcher icon appear on the main screen


Launch Intent Playground and the main screen appears

we can tailor an Intent, filling some of its attributes, and then do something with it for example starting the corresponding application.
Among these Intent attributes we can set






















actionthe general action of the Intent, such as ACTION_VIEW, ACTION_EDIT, ACTION_MAIN, etc.
attributethe data to operate on, specified as an (attribute, value) pair.
Can be a

  • data uri
  • category
  • mime type

valuethe actual value to complete the (attribute, value) pair as specified in attribute
intentspecifies what to do with the intent

  • start an activity
  • broadcast the intent
  • start a service
  • resolve the activity

activitythe resolved activity


Random intents
There's a menu option to fill in random values, from a pre built list, of intent attributes

Wednesday, December 24, 2008

ge2adt new release

In this previous post, we reviewed Google Earth to Android ADT  (ge2adt) a simple application to convert Google Earth's KML routes to a format suitable to be loaded into Android ADT Emulator Control.
ge2adt has been updated to allow the conversion directly from Google Earth's KMZ routes, avoiding the unzipping step.

Friday, December 19, 2008

Android, Google Earth and KML routes

Whilst testing location based applications, the need to simulate routes is likely to appear.
This article shows you how to obtain KML routes using Google Earth, convert it to a suitable format to be loaded into Eclipse ADT plugin Emulator Control and be able to test location based applications.

Create the route
Using Google Earth, create the route using Directions.

Then right click on Route, at the end of the list of directions, and save it. Let's say, we save it as myroute.kmz.

Convert the route
To be used with the current version of Android ADT plugin (0.8.0) a slightly different format is needed as is not supported.
We have to convert the route to use multiple s.

The change is really simple and we could do it manually, but fortunately there's an application to automate this task.
ge2adt is hosted on Google Appengine and can be reached at http://ge2adt.appspot.com/.
Use your Google identifier to access it (i.e.: you gmail account).

Unzip kmz, extract doc.kml, rename it, upload myroute.kml, convert it, and save the result as myroute-adt.kml.

Test my location
Using Eclipse Android DDMS perspective, under Emulator Control, load the converted KML file myroute-adt.kml.


Once the route is loaded, use you location based application or launch Maps, select My Location on the menu, press the play button on Emulator Control and you will be able to appreciate the map moving along the route.



Wednesday, December 03, 2008

Android Development Workshop slides

I was a great opportunity to present this at Mobile Dev Camp, if you couldn't attend, 
presentation slides are available at http://www.slideshare.net/pr1001/android-development-workshop-presentation

Thursday, November 20, 2008

Android workshop at Mobile Dev Camp

I was kindly invited by Bubble Foundry's Peter Robinett to give a workshop on Android at Mobile Dev Camp this 29th November 2008 in Amsterdam.
We will be introducing the Android platform and how to start developing applications keeping an eye on Test Driven Development. 
More information and registration can be found at http://www.mobiledevcamp.nl/?p=41

Looking forward to seeing you.

Sunday, November 09, 2008

Android: Testing on the Android platform - ApiDemos tests











This document can be read in Google Docs (http://docs.google.com/Doc?id=ddwc44gs_49stmqs7hb), cut and paste link.





A previous post,Android: Testing on the Android platform - Unit tests, showed how to add your tests and run them from inside Eclipse. Although these are very useful tests in our quest to Test Driven Development, they cover only a small part of our needs.

Android 1.0 introduced a whole new world of tests cases like ActivityUnitTestCase to run isolated unit tests, ServiceTestCase to tests services and even functional test of activities like ActivityInstrumentatonTestCase.



ApiDemos provides a set of tests but you will not be able to easily run them unless in a non convoluted way as the way they are structured it's not supported by current Android Development Tools (ADT) Eclipse plugin and you would need other tools, but the solution is so simple that I wonder why they are not originally provided in the way we will be changing them.

Google documentation is not helping either.



ApiDemos tests


Tests are located in the tests/src folder and they have their corresponding AndroidManifest.xml.

Inside this folder, tests like this one are found










/*

 * Copyright (C) 2008 Google Inc.

 */



package com.example.android.apis;



import android.test.ActivityInstrumentationTestCase;



/**

 * Make sure that the main launcher activity opens up properly, which will be

 * verified by {@link ActivityInstrumentationTestCase#testActivityTestCaseSetUpProperly}.

 */

public class ApiDemosTest extends ActivityInstrumentationTestCase<ApiDemos> {



    public ApiDemosTest() {

        super("com.example.android.apis", ApiDemos.class);

    }



}







but we will not be able to run them not resorting to ant or maven, unless we make the following set of changes.

ApiDemosTest Android project




Create new project


Let's create a new Android project from within Eclipse, as usual New -> Project -> Android -> Android Project






Activity and Application name are set to Dummy because they are not used as we are seeing shortly.



Copy ApiDemos tests




Copy the tests/src folder from te original ApiDemos project and turn it into a source folder.

Fix the project setup to use original ApiDemos project to resolve references.






Copy AndroidManifest.xml


Again, from the original ApiDemos project copy AndroidManifest.xml overwriting the existing one






Build and run



If necessary, remove ApiDemos.apk if it has been already installed in the emulator.

Build ApiDemos and ApiDemosTests projects and install them.

Now, if you execute Dev Tools in the emulator and go to Instrumentation, you'll find Test for Api Demos. in the list.








Select it and you will obtain the tests results. Unfortunatelly by now, the reslts will be only visible in the logcat window









11-09 22:56:35.132: INFO/instrumentation(153): Test results for InstrumentationTestRunner=......................

11-09 22:56:35.132: INFO/instrumentation(153): Time: 6.739

11-09 22:56:35.132: INFO/instrumentation(153): OK (22 tests)






or alternativelly, from the command line

$ adb shell am instrument -w com.example.android.apis.tests/android.test.InstrumentationTestRunner

com.example.android.apis.ApiDemosApplicationTests:....

com.example.android.apis.ApiDemosTest:.

com.example.android.apis.app.ForwardingTest:...

com.example.android.apis.app.LocalServiceTest:.....

com.example.android.apis.os.MorseCodeConverterTest:.

com.example.android.apis.view.Focus2ActivityTest:....

com.example.android.apis.view.Focus2AndroidTest:....

Test results for InstrumentationTestRunner=......................

Time: 7.493



OK (22 tests)


Conclusion


So simple that I can't understand why they are not provided in this way by the original Android ApiDemos project.

Next time we will try to present test results in a more concise way inside the emulator as Electro did (video1, video2, video3).









Thursday, November 06, 2008

Android: Testing on the Android platform - Unit tests

This is the first installment of a series of articles about testing on the Android platform. Things have changed with the release of the version 1.0 of the SDK and will change in the future for sure, as there are still some lose ends.
Electron and Positron frameworks are not valid anymore in this new SDK, so let's back to base and start analyzing the possibilities featured in the Android platform as it is.


As with previous version of articles covering testing for different platforms we will be using our simple Temperature Converter (also analyzed in Test Driven Development and GUI Testing) example.

For a Test Driven Development approach you should
  1. create your Android project
  2. add the tests source folder (New -> Source Folder -> Folder name: tests/src)
  3. in the newly created folder add a Java Package. Its name should be the same as the project package with .tests appended
  4. in the 'tests' package create a new JUnit Test Case using JUnit 3 (New -> JUnit Test Case). Name it TemperatureConverterTest, leave class under test blank
  5. Copy this code into TemperatureConverterTest.java 
package com.codtech.android.temperatureconverter.tests;

      import junit.framework.TestCase;

          import java.util.HashMap;
            import java.util.Map;

                import com.codtech.android.temperatureconverter.TemperatureConverter;

                    /**
                       * @author diego
                         *
                           */
                            public class TemperatureConverterTest extends TestCase {

                                private static final Map conversionTable = new HashMap();

                                    static {
                                      // initialize (c, f) pairs
                                        conversionTable.put(0, 32);
                                          conversionTable.put(100, 212);
                                            conversionTable.put(-1, 30);
                                              conversionTable.put(-100, -148); conversionTable.put(32, 90);
                                                conversionTable.put(-40, -40);
                                                  conversionTable.put(-273, -459);
                                                    }

                                                        /**
                                                          * @param name
                                                            */
                                                              public TemperatureConverterTest(String name) { super(name);
                                                                }


                                                                      /**
                                                                        * Test method for {@link com.codtech.android.temperatureconverter.TemperatureConverter#celsiusToFahrenheit(int)}.
                                                                          */
                                                                            public void testCelsiusToFahrenheit() {
                                                                              for (int c: conversionTable.keySet()) {
                                                                                int f = conversionTable.get(c);
                                                                                  String msg = "" + c + "C -> " + f + "F"; int r = TemperatureConverter.celsiusToFahrenheit(c);
                                                                                    assertEquals(msg, f, r);
                                                                                      }
                                                                                        }
                                                                                          }

                                                                                          1. Accept Eclipse hints to create TemperatureConverter class and celsiusToFahrenheit method
                                                                                          2. Run -> Run As -> Run configurations and create a new JUnit configuration and select the previously created Test class
                                                                                          3. Run the tests and instead of the expected test results you'll get
                                                                                            # An unexpected error has been detected by Java Runtime Environment:
                                                                                              #
                                                                                                #  Internal Error (classFileParser.cpp:2924), pid=5364, tid=6644
                                                                                                  #  Error: ShouldNotReachHere
                                                                                                  1. That's because we are using Android's JUnit stub implementation. Go to Run -> Run As -> Run configurations again and in the recently created JUnit configuration Classpath's Bootstrap Entries remove Android Library
                                                                                                  2. Then Add Library, using Advanced... button, and add JRE System Library and JUnit 3
                                                                                                  3. Apply and Run
                                                                                                  4. And now our tests run, failing as expected. We haven't created the conversion method anyway





                                                                                                  So far so good, our tests are running. But as you may have discovered already, mainly when we changed the libraries, those tests are not Android platform tests so they are only useful as part of our Test Driven Development strategy and we must have always in mind that real Android implementation of some functionality may vary.

                                                                                                  1. Let's finish our TemperatureConverter class
                                                                                                  2. package com.codtech.android.temperatureconverter;

                                                                                                    /**
                                                                                                       * @author diego
                                                                                                         *
                                                                                                           */
                                                                                                            package com.codtech.android.temperatureconverter;
                                                                                                              public class TemperatureConverter {
                                                                                                                public static final int ABSOLUTE_ZERO_C = -273;

                                                                                                                    public static int celsiusToFahrenheit(int c) {
                                                                                                                      if (c < ABSOLUTE_ZERO_C ) {
                                                                                                                      throw new RuntimeException("Invalid temperature: " + c + " below absolute zero");
                                                                                                                      }
                                                                                                                      return (int)Math.round(c * 1.8 + 32);
                                                                                                                      }
                                                                                                                      }

                                                                                                                      Run the test again and it will success. A Test Suite can allso be added, however in this case as we have only one test it's not necessary.

                                                                                                                      Stay tuned. Next article will explore Android Instrumentation to run tests on the real platform.


                                                                                                                      Tuesday, September 16, 2008

                                                                                                                      Android thin client

                                                                                                                      Is Google Android suitable as a thin client operating system ?
                                                                                                                      I've been designing and developing thin client OSs during the last 7 years, and I was wondering if we can base a thin client OS on Android.
                                                                                                                      Let's find out.

                                                                                                                      Well, we need to change some source code to enable network booting so we have to wait, but watching this crude preview (from an 800x600 screen) perhaps begins our brainstorm...



                                                                                                                      Comments and suggestions are gladly welcome.

                                                                                                                      Thursday, September 04, 2008

                                                                                                                      from Z to A

                                                                                                                      Or from Zenity to Autoglade.
                                                                                                                      Gnome bug #412493 has been there for more than a year, it refers to the ability of handling forms with zenity. There are some proposals, but far too way too complex.
                                                                                                                      And sometimes, simple problems deserves simple solutions...

                                                                                                                      As usual, create your form in Glade, we will use the same example described in the bug report, a simple login window for a downloader pretending being connected to ftp.bli.org.
                                                                                                                      This is the running application.
                                                                                                                      The entry fields are annotated with autoglade as:
                                                                                                                      • username:auto:init:env
                                                                                                                      • password:auto:init:env
                                                                                                                      to initialize the values from the corresponding environment variables.

                                                                                                                      We use this simple script (login.sh) to call autoglade using login.glade

                                                                                                                      #! /bin/sh
                                                                                                                      export username=$LOGNAME
                                                                                                                      ${AUTOGLADE:-autoglade} ${0%.sh}.glade

                                                                                                                      That simple.

                                                                                                                      Tuesday, September 02, 2008

                                                                                                                      Lists meet autoglade

                                                                                                                      The latest autoglade (available from svn repository) now supports lists as a special case of a GtkTreeView widget usng a ListStore model with a single column. Remember, as always, it's a zero programming solution.

                                                                                                                      As other widgets, lists can be initialized from the environment using autoglade annotation to its name, for example:

                                                                                                                      treeview1:auto:init:env

                                                                                                                      will use the environment variable treeview1 to obtain list header and items

                                                                                                                      export treeview1='("Fruits" "Apples" "Bananas" "Hedge aple" "Kiwifruits" "Melons" "Oranges" "Pineapples" "Strawberries" )'

                                                                                                                      Using one of the tests also present in the svn repository

                                                                                                                      $ ./list.sh


                                                                                                                      and, after selecting one item and pressing OK

                                                                                                                      treeview1='("Kiwifruits")'
                                                                                                                      autoargs='$treeview1'

                                                                                                                      appears in application's stdout.

                                                                                                                      More information about autoglade can be obtained from http://autoglade.sf.net.

                                                                                                                      Google Chrome


                                                                                                                      This is taken from Google Chrome browser presentation.
                                                                                                                      There was ?

                                                                                                                      Fell free to interpret.

                                                                                                                      Monday, August 04, 2008

                                                                                                                      autoglade

                                                                                                                      This document can be read in Google Docs (http://docs.google.com/Edit?tab=view&docid=ddwc44gs_458qnjwvgr)


                                                                                                                      Introduction

                                                                                                                      This article will guide you through the steps needed to provide a graphical user interface (GUI) to some commands requiring almost no programming using autoglade.

                                                                                                                      As a real life example we will be using some commands to control cpu frequency scaling in Asus EeePC.
                                                                                                                      EeePC features a Celeron-M (4G) with On Demand Frequency Modulation (ODFM) originally set to performance, which actually disables ODFM and fixes CPU speed to 900 MHz (or 630 MHz, as it's underclocked in BIOS prior to 8804).

                                                                                                                      From some post in eeeuser forum:
                                                                                                                      "The cpu in the EEE consumes the same wattage running idle at 900mhz(630 real) as it does running idle at the 'scaled' frequency of 112.5mhz, because the actual frequency *does not change* it's just the forced execution of halt instructions. Halt instructions do save power; when a halt instruction is executed the cpu gets a bit of 'rest' where it consumes significantly less power than if it was executing a complex SSE2 instruction."

                                                                                                                      ODFM additionally provides ondemand mode. Available governors can be obtained using this command
                                                                                                                      $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
                                                                                                                      ondemand performance
                                                                                                                      current scaling governor can be obtained with
                                                                                                                      $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
                                                                                                                      performance
                                                                                                                      as well as maximum allowed frequency
                                                                                                                      $ cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
                                                                                                                      900000
                                                                                                                      While it's not completely clear if you can save some power and extend battery life using ondemand scaling or limiting the maximum frequency, we will be using this example to create a GUI around these commands and you can test for yourself. Anyway, our final objective is the creation of the GUI and analyzing the patterns used in order to be able to reproduce this with other commands lacking a GUI.

                                                                                                                      autoglade

                                                                                                                      autoglade is a tool that will take our GUI design and will automate most common usage patterns to be able to give the GUI functionality with no programming.

                                                                                                                      Design the GUI

                                                                                                                      We will be using another computer to design the GUI where glade user interface builder version 3 is installed. There's nothing wrong installing glade-3 on the EeePC, but the screen would be too small to confortably design the interface and you may need an external monitor.
                                                                                                                      glade-3 it's available for Linux and Windows, and because the GUI is described as an XML file it's platform independent.

                                                                                                                      This is an overview of the GUI, in this particular case using glade-3 on Windows Vista
                                                                                                                      our expanded widget tree should be something like this.

                                                                                                                      We can see some widget that have been highlighted. These widgets have received special names.

                                                                                                                      This is one of the way that autoglade uses to receive some messages from our design. Let's review them.
                                                                                                                      We have an horizontal scale widget whose name is freq:auto:init:env, that is our widget name is freq, because we are going to change the cpu frequency using it and we ask autoglade (auto) to initialize it (init) using the process environment (env) and by default autoglade will look for a variable named after the widget name (freq). Its value will be taken form the environment upon startup and the horizontal scale will be initialized having this value.

                                                                                                                      Next, we have two radio buttons to set the scaling governor to performance or ondemand.
                                                                                                                      Radio buttons are named as an incremental sequence, for example name1, name2, name3, ..., namen. In this particular case the name is governor.
                                                                                                                      In all but the first one we have to set the group property to be able to operate them as a group, that is only one can be active at a time.
                                                                                                                      As explained before the names are governor1:auto:init:env and governor2:auto:init:env, because they are the first (1) and second (2) radio buttons of the group, and we ask autoglade (auto) to initinalize (init) them using the process environment (env). In this case the variable will be governor and depending on its value (performance or ondemand) the corresponding radio will be activated on startup.

                                                                                                                      We need to send a message to autoglade to tell it how do we want to exit the event loop and thus closing the dialog and passing a value to its parent process. We do this by setting the response ID on OK and Cancel buttons to RESPONSE_OK (-5) and RESPONSE_CANCEL (-6).

                                                                                                                      Running with autoglade

                                                                                                                      Let's save it as cpufreq.glade and we are ready to test it.
                                                                                                                      $ autoglade cpufreq.glade
                                                                                                                      and most of the required behavior of our GUI is already there.

                                                                                                                      Specifying initial values

                                                                                                                      You can specify the initial value for frequency
                                                                                                                      $ freq=500 autoglade cpufreq.glade
                                                                                                                      or for both frequency and governor
                                                                                                                      $ freq=130 governor=ondemand autoglade cpufreq.glade

                                                                                                                      Obtaining return values

                                                                                                                      Running autoglade in one of the previously mentioned froms will give us these results
                                                                                                                      freq='225'
                                                                                                                      governor='ondemand'
                                                                                                                      autoargs='$freq $governor'
                                                                                                                      to standard output with the values we have selected in the GUI.

                                                                                                                      Shell wrapper

                                                                                                                      We are now in condition of putting everything togheter with a shell wrapper script.
                                                                                                                      Let's start with a simple one and then we can add more sophisticated features.
                                                                                                                      #! /bin/bash

                                                                                                                      AUTOGLADE=autoglade # set absolute path if autoglade is not installed

                                                                                                                      CPUFREQDIR=/sys/devices/system/cpu/cpu0/cpufreq

                                                                                                                      freq()
                                                                                                                      {
                                                                                                                      # get or set freqency
                                                                                                                      local F=$CPUFREQDIR/scaling_max_freq
                                                                                                                      local S=1000

                                                                                                                      [ -n "$1" ] && echo $(( $1 * $S )) > $F || export freq=$(( $(< $F) / $S ))
                                                                                                                      }

                                                                                                                      governor()
                                                                                                                      {
                                                                                                                      # get or set governor
                                                                                                                      local F=$CPUFREQDIR/scaling_governor

                                                                                                                      [ -n "$1" ] && echo "$1" > $F || export governor=$(< $F)
                                                                                                                      }

                                                                                                                      freq
                                                                                                                      governor

                                                                                                                      DUMP=$( $AUTOGLADE cpufreq.glade )
                                                                                                                      if [ $? -eq 0 ]
                                                                                                                      then
                                                                                                                      eval "$DUMP"
                                                                                                                      freq $freq
                                                                                                                      governor $governor
                                                                                                                      fi


                                                                                                                      Previous wrapper illustrates various common patterns.
                                                                                                                      Next time, we will be using more advanced features to finish our cpufreq application.

                                                                                                                      Monday, July 14, 2008

                                                                                                                      Vista on Asus EeePC


                                                                                                                      You can find tons of post about installing Vista on Asus EeePC, and some videos too. So, perhaps it works.
                                                                                                                      But, wait a minute !
                                                                                                                      What's the reason to install Vista ?
                                                                                                                      Because this Xandros sucks, because you can't configure it to your liking...
                                                                                                                      It's no news that AsusLauncher is very bad designed and, for example, instead of highlighting icons when the mouse is over it's using completely different images. So for every icon, you need a copy of it, highlighted multiplied by the number of themes. A total waste of disk space in such a limited environment.
                                                                                                                      Living with that limitations, and tweaking the glorious IceWM and some images and AsusLauncher XML comfiguration, you can obtain veeesta (a Vista looking EeePC running Xandros Linux).
                                                                                                                      I would have installed Ubuntu, but once that I have a Linux notebook where all of its hardware is working out-of-the-box, as if it was a Windows one, I don't want to start hunting for tweaks on how to make the wireless network work, how to make it sleep, or whatever.

                                                                                                                      If you want some instructions on how to do it, just drop me a message.
                                                                                                                      I think that this wallpapers and images cannot be redistributed due to Microsoft copyrights.

                                                                                                                      Enjoy veeesta !

                                                                                                                      Ohh, I almost forgot to show you the themed firefox and taskbar...