Archive for the ‘Mobile’ Category.

Mobile Theme

I finally had some time to try out the WPtouch plugin, which now serves my blog using mobile friendly theme if you are using one of the recognized mobile browsers. I had tried mobile plugins before, but could never get them to work with WP Super Cache. Finally WPtouch had some instructions on how to make this work. In effect I ended up listing the mobile user agents in WP Super Cache settings so that the cache won’t be used for mobile UAs, and in addition modified the .htaccess entries needed by the cache to similarly exclude the same UAs. Not ideal, though, since if I want to add new UAs I need to edit 3 places: WPtouch, WP Super Cache and .htaccess.

d20 Ability Calculator for Android

I just released my second application for the Android platform, called d20 Ability Calculator for Android. Just in time for your weekend gaming session ;) It is again a tool to scratch a personal itch: while I like the ability point buy system for Dungeons & Dragons that I first saw with the 3rd Edition, for some reason it has always been annoying for me to calculate the ability scores that way. Especially when your campaign allows for lots of points, like we used in the Dead of Winter campaign. This application makes it easy:

d20 Ability Calculator for Android 1.0 screenshot

d20 Ability Calculator for Android 1.0 screenshot

The d20 Ability Calculator does not aim to be a full character generator. There is the venerable desktop application PCGen for that, although the learning curve to be able to use PCGen is pretty steep. But the Android application is a quick and easy helper when you don’t (or can’t) deal with PCGen and want to quickly create a new character. And let’s face it, you just about always will have your phone with you, which can’t be said about your laptop (even if you have one). There are already several dice applications available, so you can gather quite an arsenal of role playing utilities and tools for Android.

I was quite surprised that there does not appear to be anything like this available for the iPhone in the appstore: search for d20 with appshopper. You can use Cyrket and androidstats to keep track of how this application is doing in the Android Market:

From programming point of view the application presented some new challenges for me to overcome. I needed to launch the configurator Intent and inform the main calculator when that was done. The landscape layouts are also significantly different from portrait, which was not the case with the previous application. I became a fan of Toast, and will definitely consider using something similar for my other, non-Android applications as well. I also feel like I am slowly becoming a better Java developer. I still feel like my beginner Java skills are still the biggest hindrance in me getting anything done quickly on Android. Oh, and I definitely need to get better at making icons, and using custom buttons, backgrounds and so on to make esthetically pleasing applications.

I did the initial checkin on February 22nd, but didn’t really start working on it until March 1st. After that I spent probably 4 hours per evening, 6 days a week on it. So about 50 hours total I’d say.

There are lots of potential improvements and new features, but I’d like to get some user feedback first to see on which areas I should concentrate first. Drop me an email or leave a comment, and enjoy!

Caltroid Upgrade

I just pushed the 1.1 upgrade of Caltroid to the Android Market. The 1.1 release includes the upcoming March 2, 2009 timetable and ticket information.

While the free open source version got a few hundred downloads (as far as I can tell, since the distribution was picked up by sites I had not even informed about Caltroid’s existence) in about one and a half months, the 1.0 version on the Market got 12 happy customers during the first week. Everyone who bought it is still using it, and I heard no reports of any problems with it. Four people rated it with an average of 4.25 stars, and one person left a (positive) comment.

I hope my users will be able to upgrade without a problem. Caltroid does not use the “copy protection” scheme which seems to be causing problems for some, nor does it use a database which seems to be another problem area during upgrades.

Caltroid 1.0 in the Android Market

I have been working quite a bit on Caltroid, which is my Caltrain schedules application for Android. I have added new features like automatically scrolling to show the next train, displaying zones of travel and fares, improved the performance by a factor of 10, fixed crasher bug and many other improvements too numerous to mention here. I felt it was now solid enough to call it 1.0, and after all Caltroid is over a year old now.

Caltroid 1.0 screenshot

Caltroid 1.0 screenshot

I kept versions 0.1 through 0.3 Open Source and free to download, but I changed this for 1.0. I decided I wanted to make it easier to find the application as well as experiment with the Android Market, so I registered myself and paid the $25 registration fee. I have priced Caltroid at $1.99, which leaves me about a dollar per sale after Google takes 30% through the Market + 2% + $0.20 through Google Checkout. So if I get at least 25 people willing to buy it, I won’t feel like a fool for registering for the Market.

Update: Seems Google does NOT charge the usual Checkout fees on the Market, so it is just the 30%. Although several of my transactions seems to have $0.10 transaction fee instead, which is not 30% nor 2% + $.020. I have reported this to Google through some Market feedback page (couldn’t find any other contact form), but haven’t heard anything back. Basically it seems like Google is a black hole as far as trying to contact them or trying to get them to respond.

Multicolumn ListView in Android

Ever since I started programming on the Android platform, I have been wondering when the SDK would include a ready-made multicolumn ListView (or listbox as it is often called in other frameworks). One could of course construct such a thing by slapping regular ListViews side by side and then painfully adding code to keep them all in sync when scrolled and so on. It felt such a hack that I used GridView instead. GridView is not really a great list, though, because the cells will all be formatted the same. There are other issues besides that, but for me that was the main one.

I finally saw a blog post which customized ListView to put two TextViews vertically into one line. It was pretty simple going from there to one that would display three TextViews side-by-side. The main layout XML file could define ListView something like this:

<!-- main.xml -->
<ListView android:id="@+id/SCHEDULE" android:layout_width="wrap_content" android:layout_height="wrap_content">
</ListView>

Here is the XML for each row, main point being that we put three TextViews in LinearLayout with horizontal orientation:

<?xml version="1.0" encoding="utf-8"?>
<!-- row.xml -->
<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:paddingTop="4dip"
     android:paddingBottom="6dip"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal">
 
     <TextView android:id="@+id/TRAIN_CELL"
         android:layout_width="50dip"
         android:layout_height="wrap_content"/>
 
     <TextView android:id="@+id/FROM_CELL"
         android:layout_width="70dip"
         android:layout_height="wrap_content" android:layout_weight="1"/>
 
     <TextView android:id="@+id/TO_CELL"
         android:layout_width="60dip"
         android:layout_height="wrap_content"  android:layout_weight="1"/>
</LinearLayout>

Notice how you can format each TextView separately. There is no column separator, but something decent should not be too hard to whip up if desired. My understanding is that the screen width is supposed to be 160 dip, but for some reason I had to use width values that actually add up to more than that, as well as using layout weight to grow some fields proportionally so that when you switch to landscape mode things are still nicely aligned. I would have expected specifying widths in dip would have automatically done that.

Here is how you could populate that ListView with data:

ListView list = (ListView) findViewById(R.id.SCHEDULE);
 
ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map = new HashMap<String, String>();
map.put("train", "101");
map.put("from", "6:30 AM");
map.put("to", "7:40 AM");
mylist.add(map);
map = new HashMap<String, String>();
map.put("train", "103(x)");
map.put("from", "6:35 AM");
map.put("to", "7:45 AM");
mylist.add(map);
// ...
mSchedule = new SimpleAdapter(this, mylist, R.layout.row,
            new String[] {"train", "from", "to"}, new int[] {R.id.TRAIN_CELL, R.id.FROM_CELL, R.id.TO_CELL});
list.setAdapter(mSchedule);

The main point here is that the SimpleAdapter requires the data to be in a List, where each entry is a Map. In my case, I simulate the columns by putting in three entries into each of the maps, and the maps each have the same keys. The adapter then maps the key values (like "train") to the corresponding TextView (R.id.TRAIN_CELL).

Putting the above pieces of code into Caltroid produces results that look like this:

Multicolumn ListView in Android

Multicolumn ListView in Android

There is quite a bit of work to create the data structure for the adapter in this way, so for anything involving more than a trivial amount of data this is probably going to be too slow. With more data, a database is almost certainly involved and the SimpleCursorAdapter works almost exactly like SimpleAdapter, except that SimpleCursorAdapter maps column names from the query results to the appropriate views.

Android WebView Limitations

I was trying to figure out how to display HTML help page for my Caltrain schedules application using WebView. I don’t want my application to require internet connection, so the HTML needs to ship with the application. Since help obviously needs to be localized, I tried to put the HTML into a string resource. This turned out to be tricky.

If string resources contain the quote (") or apostrophe (') characters, you need to either be able to wrap the whole string in either quote or apostrophe, or if you use both in the string then you need to espace with backslash (\). You will also need to replace less than (<) with &lt;. But even after this loadData() was giving me a blank page. By reducing my markup I found out I could not use any CSS styles. And even after that I still run into a problem where having hash (#) in the data meant nothing after the hash would show up (including the hash character). Using backslash to escape that or using a numeric entity &#35; instead did not help. At this point I gave up on localizing help, and went looking for ways to just include the HTML help file in the apk and load it using a file URL.

There are seemingly two locations to put “raw” resources in: /assets and /res/raw. It wasn’t clear to me how I could load HTML from /res/raw, so I went with /assets:

        browser.loadUrl("file:///android_asset/help.html");

Hopefully new SDK versions will make internationalizing HTML resources easier.

Garmin Nüvi 760

I got a Garmin Nüvi 760 for Christmas. It was quite a surprise, since my Garmin iQue 3600 still works, although it had some stability problems in the summer.

The iQue is a hybrid Palm/Garmin navigator, which means that it has the benefit of being able to run most Palm software. The killer application for a navigator turned out to be Fastfinger, which let’s you record macros for anything, and run a macro with a single touch. I configured the REC key to open the Fastfinger quick launch screen where I configured 11 actions for things like: route home, next gast station on route, next Starbucks on route, cancel next via point, nearest parking, nearest hospital and so on. Combined with the highly configurable navigator options, the possibilities were basically endless. The downsides include short battery life (and needing to restore from a computer once this happens), needing to use the stylys to write, long time to acquire satellites, and no custom points-of-interest support. I also haven’t tried it with Linux, but I doubt I would be able to synchronize the map data.

The 760 is obviously more advanced, but it took me a while to start liking it. It uses Garmin proprietary OS for which there does not seem to be many hacks, meaning you are stuck with whatever Garmin put on the device. The screen has different orientation, the UI is really dumbed down (to a stage where I had to read the manual to figure out how to add a via point), text-to-speech (TTS) can be somewhat hard to understand (although it beats having to look at the navigator for the name of the street you need to turn next to) and it shows the current speed limit. Out of the box the 760 comes with two options for sound: either use the FM transmitter and turn your car radio to the channel, or use the builtin speakers. The former does not work well in areas that have lots of radio stations available like the Silicon Valley, nor is it convenient on long drives where you pass through areas that use different frequencies. The volume level from the device itself has been configured a tad too low, although it seems there is an easy hack to make it louder.

The 760 also comes with a free 60 day subscription to traffic alert service. Supposedly you can buy a lifetime subscription for an additional $60. It seems to have worked pretty well on my freeway commute (101), but it doesn’t seem to include support for small roads. When it works it is pretty nifty: you get a little alert icon in the display that tells you how much traffic is going to slow you down, and automatically calculates you the fastest route taking traffic into account.

I haven’t really confirmed it, but it seems to me the 760 isn’t giving me as accurate driving information. For example, it gave me directions to a restaurant but failed to inform me that to get to the restaurant I needed to drive one more block and make a U-turn. I think the iQue has always told me to do a U-turn if needed to get to the right side of the road.

I was pleasantly surprised that my system running Ubuntu Linux recognized the 760 as a USB storage device when I hooked it up. I can access the SD card via this way as well. Of course, since the system is so locked down there isn’t much you can do besides uploading music to the SD card.

Caltroid 0.3 – Now with All Trains

It turned out Caltroid 0.2 shipped with an error that showed the times for only the 30 first trains for the day. Fixed that, and since I had already made some internationalization fixes and localized it to Finnish and Spanish (Google Translation only for now, since I don’t speak Spanish), I decided to include those fixes and call it 0.3.

The Android internationalization documentation is pretty good. The only issue I had was that trying to use getText() to get string with rich text styling caused application startup crashes, so I had to go back to using getString().