Monday, November 2, 2009

Mobile Programming @HPU Spring 2010

I'm teaching a mobile programming course at Hawaii Pacific University (HPU) in the Spring. Will focus on iPhone and Android. Here's the link to sign up for single courses at HPU if you're not already enrolled there:

http://www.hpu.edu/index.cfm?contentID=373

I'll be teaching in HPU's mac lab so we'll cover both iPhone and Android programming. The plan is for every class member (or team) to have an app published in the iPhone app store and the Android marketplace by the end of the course.

Monday, October 19, 2009

Gravity thought experiments

For some reason (probably reading my son "The Magic School Bus Lost in the Solar System"), I started wondering about gravity. I was wondering why my sensation of gravity is just being pulled down, and not to the sides as well. I guess the mass to either side of me in the Earth is roughly equal and thus cancels itself out. Which made me wonder how something would fall if you happened to be standing on the edge of a hemisphere, or if there was a cylindrical space running through the center of the Earth. In the later case I would have thought that something might fall down past the Earth's center overshoot, and them fall back, oscillating until it eventually came to rest a the center. Not sure about the hemisphere example. Seems like something dropped might actually fall diagonally. Of course the natural rest state of objects large enough to have noticeable gravity is a sphere, so such toroidal or hemispherical objects would not occur without some kind of intervention. The funny thing about gravity is that all matter attracts other matter. I don't notice being sucked towards the computer because it has so little mass, but the mass of the Earth is huge and sucks me towards it. I wonder if there are objects in the universe massive enough for gravity to be noticed, but in different shapes so that the force of gravity is felt in directions other than straight down ...?

Tuesday, October 6, 2009

SmartFM Mobile Study Dictionary Upgrade

So I released an upgrade (1.0.1) of the SmartFM android client, adjusting the media type for audio uploads (although the AMR uploads are still only audible on the phone and not the main site) and disabling the voice input when the google speech recognition package is not available. This latter was in response to a marketplace comment from Zom-B about force closing on voice button.

Of course this makes me want to say a few things about the marketplace comments, which are potentially a great resource, but are kind of odd in that they can be signed under any name, and there is no way to reliably communicate back with the people who made the comments. For example, originally SuaveAfro made the comment that the app should support downloading other people's lists. I replied to SuaveAfro in my own comment explaining that that functionality was included. Subsequently SuaveAfro became Havoc, and so I updated my own comment accordingly, but that moved my comment away from the one it was referring to. I guess the solution is that I should update my comment to reflect whatever is my response to the most recent comment, but it seems less than optimal. Would be nice if the commenting framework could link directly to a discussion forum on that app, but I guess that's overkill. Comments are a simple solution - would be nice if they were at least linked to a user's email so I could have a fighting chance of getting responses back to users who are unlikely to look at the comments again after their first download ...

Thursday, September 17, 2009

SmartFM Mobile Study Dictionary live in Android Marketplace!

So shortly after my last blog post, I managed to get my SmartFm mobile study dictionary app live in the Android Marketplace. I think I finally managed to set it up so it won't conflict with the ADC version of the same app.

In less than 24 hours the app jumped into the the 100-500 downloads range, and we got some great feedback and ratings. Steve O's comment that it was "Very easy to use and definitions are very accurate. Excellent!" was music to my ears. I can't accept that praise without thanking Robert Brewer, George Lee, Viil Lid, Karhai Chu and Kim Binsted at the University of Hawaii for input on the developing interface, and huge thanks to the SmartFM team for their input on all aspects of application and various adjustments to the API to make everything connect up properly.

When I woke up this morning there was another comment from SuaveAfro, about wanting the app to allow the user to download other people's lists. I've commented back that other user's lists can be downloaded through the "Search Lists" function in the menu tab, although it is not an easy function to find, since you have to click "More" in the menu to get there. That is partly intentional, as the focus of the app is on items rather than lists, but I have to concede I haven't put up a help manual or anything that explains all that. I was so focused on the ADC submission that there is not much in the way of online support materials, and only a cursory help system on the app itself. I'll do my best to make better documentation available, but in the meantime I'll put as much as I can on this blog to help users of the application.

Tuesday, September 15, 2009

Video describing SmartFM Android Application

So the other week I submitted an android application to the second Android Developers Challenge (ADC). There's over a million dollars in prize money up for grabs from Google in the second such competition. Last time android was only available on emulators, but now the devices are out, so competition will be fierce.

I've put together a short video about my app, the SmartFM Mobile Study Dictionary, which shows you how I integrated the Google Speech Recognition component and got multimedia content creation working. I'm real excited about this application because now any user can create study content (focused on languages at the moment) on the go, uploading sounds and images. So say you learn a new word in the language you are studying you can check what it means using the dictionary, and if it doesn't exist, add the entry there and then. If it is there, you get helpful info on the word and its usage, and you can add new example sentences and usages you've discovered, with images and audio to illustrate.

The results from the ADC won't be in till late November, and owners of android devices should be able to vote on the best apps later this month (please vote for me :-), but I'll release this to the market before then, once I've worked out a few bugs.

Please check out the video and let me know what you think:

SmartFmMobileStudyDictionary.mov

Friday, August 7, 2009

Android: displaying one dialog after another

So having got my progress bar dialog to appear I now find myself prevented from displaying a second dialog to announce the results of the long running action.

Here is the code:

   final ProgressDialog myOtherProgressDialog = new ProgressDialog(
     this);
   myOtherProgressDialog.setTitle("Please Wait ...");
   myOtherProgressDialog.setMessage("Adding item to study list ...");
   myOtherProgressDialog.setIndeterminate(true);
   myOtherProgressDialog.setCancelable(true);

   // TODO spinner not showing for some reason ...
   final AlertDialog dialog = new AlertDialog.Builder(this).create();

   final Thread add = new Thread() {
    public void run() {
     AddItemResult add_item_result = addItemToList(
       Main.default_study_list_id,
       (String) item.item_node.atts.get("id"));
     
     dialog.setTitle(add_item_result.getTitle());
     dialog.setMessage(add_item_result.getMessage());
     dialog.setButton("OK",
       new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
          int which) {
        
         return;
        }
       });
     
     myOtherProgressDialog.dismiss();
     //Looper.prepare();
     dialog.show();
    }
   };
   myOtherProgressDialog.setButton("Cancel",
     new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int which) {
       add.interrupt();
      }
     });
   OnCancelListener ocl = new OnCancelListener() {
    public void onCancel(DialogInterface arg0) {
     add.interrupt();
    }
   };
   myOtherProgressDialog.setOnCancelListener(ocl);
   closeMenu();
   myOtherProgressDialog.show();
   add.start();

The problem is that if I just try to show the second dialog I get this error:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

and if I try and edit the existing progress dialog to show the results of the long running action I am told:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Which is a bit frustrating. Is my only option to display results in a completely new activity?

Android dialog not appearing after menu action

So I have been having reasonable success getting progress dialogs to show up in android. It all seems to rely on showing the progress dialog and then starting whatever is the long running process in another thread, e.g.

 private void loadItem(Activity activity, final String item_id) {
ProgressDialog myProgressDialog = new ProgressDialog(activity);
myProgressDialog.setTitle("Please Wait ...");
myProgressDialog.setMessage("Loading item ...");
myProgressDialog.setIndeterminate(true);
myProgressDialog.setCancelable(true);

final ItemDownload item_download = new ItemDownload(activity,
myProgressDialog) {
public Vector downloadCall(SmartFmLookup lookup) {
return lookup.item(item_id);
}
};
myProgressDialog.setButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
item_download.interrupt();
}
});
OnCancelListener ocl = new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
item_download.interrupt();
}
};
myProgressDialog.setOnCancelListener(ocl);
myProgressDialog.show();
item_download.start();
}


I've even managed to support user cancellation. All good; however I have a more complex situation where the progress dialog is supposed to be displayed after hitting a menu button, and then replaced with another dialog that shows the results of the process; which is followed by a second progress dialog. In this case the first progress dialog never appears but the result dialog and second progress dialog do. I've tried removing all the other dialogs, but the initial progress dialog still never shows up - it gets stuck on the clicked menu button (see image).

Here's the code with subsequent dialogs stripped out:


public boolean onOptionsItemSelected(MenuItem menu_item) {
switch (menu_item.getItemId()) {
case ADD_TO_LIST_ID: {
// send command to add to list - need spinner?

final ProgressDialog myOtherProgressDialog = new ProgressDialog(
this);
myOtherProgressDialog.setTitle("Please Wait ...");
myOtherProgressDialog.setMessage("Adding item to study list ...");
myOtherProgressDialog.setIndeterminate(true);
myOtherProgressDialog.setCancelable(true);

// TODO spinner not showing for some reason ...

final Thread add = new Thread() {
public void run() {
AddItemResult add_item_result = addItemToList(
Main.default_study_list_id,
(String) item.item_node.atts.get("id"));

}
};
myOtherProgressDialog.setButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
add.interrupt();
}
});
OnCancelListener ocl = new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
add.interrupt();
}
};
myOtherProgressDialog.setOnCancelListener(ocl);
myOtherProgressDialog.show();
add.run();


break;
}
}
return super.onOptionsItemSelected(menu_item);
}


I think the solution must require programmatic closing of the menu popup. I did find this post on how to open it.   I was hoping to use that to open the menu bar at the beginning of my app, but calling that from the OnCreate method causes this error:

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

However it seems I can use something similar to close the menu panel:


    public void closeMenu(){
        this.getWindow().closePanel(Window.FEATURE_OPTIONS_PANEL);
    }

However, even after shutting the open menu panel, I still don't get to see the progress dialog.

Ah, found the problem, I was calling add.run() instead of add.start, so the new Thread was never spawned. Duh!!!