2Lines Software
3Aug/100

Singletons and Services and Shutdowns Oh My

3662945409_1aca357b51

Passing data back and forth between activities on the Android platform is one of the more challenging aspects of understanding Android. Understanding how this data is managed by the OS is the difference between getting flooded with Error Reports and bad reviews and getting  glowing praise and eternal gratitude. Well maybe not to that extent, but having a good background in passing data can make your code much easier to manage and cleaner to read (and for that you have my gratitude) So in passing the data there are essentially two types Persistent and strangely enough, Non-Persistent data types. The Persistent types are best handled by preferences, files, databases or content providers and they are pretty detailed in their operation. If you need to keep data over the length of more that one session consider using Persistent data stores. On the other hand, there are often times where transient data needs to be stored for one session and passed between activities. To handle that there are a couple of ways to handle it. This page details some of the methods, and it is repeated here for convenience;

How do I pass data between Activities/Services within a single application?

It depends on the type of data that you want to share:

Primitive Data Types

To share primitive data between Activities/Services in an application, use Intent.putExtras(). For passing primitive data that needs to persist use the Preferences storage mechanism.

Non-Persistent Objects

For sharing complex non-persistent user-defined objects for short duration, the following approaches are recommended:

The android.app.Application class

The android.app.Application is a base class for those who need to maintain global application state. It can be accessed via getApplication() from any Activity or Service. It has a couple of life-cycle methods and will be instantiated by Android automatically if your register it in AndroidManifest.xml.

A public static field/method

An alternate way to make data accessible across Activities/Services is to use public static fields and/or methods. You can access these static fields from any other class in your application. To share an object, the activity which creates your object sets a static field to point to this object and any other activity that wants to use this object just accesses this static field.

A HashMap of WeakReferences to Objects

You can also use a HashMap of WeakReferences to Objects with Long keys. When an activity wants to pass an object to another activity, it simply puts the object in the map and sends the key (which is a unique Long based on a counter or time stamp) to the recipient activity via intent extras. The recipient activity retrieves the object using this key.

A Singleton class

There are advantages to using a static Singleton, such as you can refer to them without casting getApplication() to an application-specific class, or going to the trouble of hanging an interface on all your Application subclasses so that your various modules can refer to that interface instead. But, the life cycle of a static is not well under your control; so to abide by the life-cycle model, the application class should initiate and tear down these static objects in the onCreate() and onTerminate() methods of the Application Class [my emphasis]

Being as I come from a java EE background the first decision was to use the singleton class and allow the instance to be available across the VM. The singleton design pattern is fairly well-known and is a good easy way to manage control across many activities. In some previous projects I have used them to manage HTTP connections, image caching and global application configuration to much success. However, this is the important part to consider when using singletons which is very important; Android OS can and will terminate your singleton and not even tell you about it. I highlighted that in bold because if your design depends on singleton patterns you naturally assume they are going to stay persistent through the VM. These are frustrating errors and difficult to track down and even more frustrating for your users. For instance consider this piece of code: In your main activity;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SuperSingletonManager.create(this);
}

And your singleton;

private static SuperSingletonManager instance;
private SuperSingletonManager(Context context)
{
// do stuff once
}
protected static SuperSingletonManager create(Context context) {
instance = new SuperSingletonManager(context);
}
protected static SuperSingletonManager getInstance() {
if (instance == null)
throw new NastyException("Oh God Why?");
return instance;
}

Seemingly you should be able to call  SuperSingletonManager.getInstance() at any time and get access to the static instance. However, this isn't the case. If the launching  activity is removed by the OS (it happens, a lot) while you are on another activity, that static instance will be gone. So when you make that  SuperSingletonManager getInstance() call you are only going to get a nasty exception. This also means that if any of your functions in SuperSingletonManager make use of the Context those will throw errors. Ack. But I really, really like singletons. So do I. And far be it from me to tell you how to architect your code. The only stipulation is that the singleton should abide by the lifecycle model. We can do this by launching the singletons from a service and binding that service to the launching activity. To the Android purists, and common-sensists out there you might just say "Why not just use a service instead of a singleton?".  Sure, makes sense but this post is about singletons and how to get them working and not common-sense. So here is the class that will do all that;

public class SingletonService extends Service {

private final ISingletonService.Stub mBinder = new ISingletonService.Stub() {

public void startSingletons() throws RemoteException {

initializeSingletons();

}

public void stopSingletons() throws RemoteException {

shutdownSingletons();

}

};

public IBinder onBind(Intent intent) {

return mBinder;

}

protected void initializeSingletons() {

SuperSingletonManager.initialize(getApplicationContext());

}

private void shutdownSingletons() {

SuperSingletonManager.shutdown();

}

}

When you start your main activity bind the service using bindService() , and make a call to the startSingletons() method. This will launch your singletons under the lifecycle of the service. This will ensure they are active for the life of your application session. Also, make sure to unbindService when you are finished. Nobody likes developers that don't clean up after themselves. Good luck and if you actually use this method let me know! John

Posted via email from John Carpenter

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]
21Jan/0912

Programming with Android Part 4 – Finishing WikiWhere

Continuing from Part 3 we are going to spend the 30 minutes or so to finish the WikiWhere application. So far we have a mapping and location application on the device. The final step is integrating the Wiki sites and displaying them on the map.

1:45 Foosball, Reddit, Digg and Google Reader Break

1:55  Getting the XML feed for the Wiki sites

Now that you've had a long break we can get to the more complicated sections of the code. The Wiki information is collected and provided as a web service by Geonames.org. We will be using the wikipediaBoundingBox XML API to get the information from the service. By making a call to http://ws.geonames.org/wikipediaBoundingBox?north=51.1&south=50.1&east=-113&west=-115 you can get the XML feed of the Wiki Entries in the bounding box in the following format:

  1. <geonames>
  2.   <entry>
  3.   <lang>en</lang>
  4.   <title>Max Bell Centre</title>
  5.   <summary>The Max Bell Centre (often referred to as the Max Bell
  6.   Arena) is an ice hockey arena in Calgary, Alberta, Canada in the
  7.   community of Radisson Heights. It seats 2,121 for hockey with a
  8.   standing room capacity of over 3,000. It is named after George
  9.   Maxwell Bell, a philanthropist who helped fund the arena's
  10.   construction (...)</summary>
  11.   <feature>landmark</feature>
  12.   <countrycode>CA</countrycode>
  13.   <population>0</population>
  14.   <elevation>0</elevation>
  15.   <lat>51.0422</lat>
  16.   <lng>-114.0036</lng>
  17.   <wikipediaurl>http://en.wikipedia.org/wiki/Max_Bell_Centre
  18.   </wikipediaurl>
  19.   <thumbnailimg />
  20.  </entry>
  21. ...
  22. </geonames>

So to get our wiki items displayed on the map we need to:

1. Call the Geonames XML API

2. Parse the XML

3. Display the icons on a MapOverlay

4. Implement the "Search For Wiki Entries" Button

20Jan/0915

Programming with Android Part 3 – Building WikiWhere

We will continue from where we left off in the last instalment and extend our basic application into a more useful application. If you are keeping track, we're an hour and fifteen minutes into our development and we have our application environment setup and ready to program in Android.

Over the next hour we will create an application that will show the wiki entries near our location, display that information on a map and embed the wiki page into the application. This application highlights three key features of the Android platform;

  1. Focus on LBS that makes locative media easier to produce.
  2. Deep web integration from consuming web services to embedding web page.
  3.  Simple map integration via Google Maps.

What is WikiWhere

WikiWhere is a buzzword-compliant mobile application that gives you access to local wiki knowledge where ever you are. Using your Android phone, WikiWhere searches wiki for entries near your location and passes that information to you. Discover your neighbourhood or visit others. 

1:20 Back from Break. You aren't paid to sit there you know.

We are now going to get started with the WikiWhere application. Let's go through the first step and create an application shell using the Eclipse project builder. Just as in the previous part, select File >> New Project >> Android Project to launch a new project. Add the details for WikiWhere. I've attached a screenshot of the details below.

WikiWhere Project Dialog

Step 1. Create the MapView

The main user interface will be a MapView so we want to change the interface of our WikiWhere class from Activity to MapActivity and implement the onRouteDisplayed method.

  1. package demo.WikiWhere;
  2.  
  3. import com.google.android.maps.MapActivity;
  4. import android.app.Activity;
  5. import android.os.Bundle;
  6.  
  7. public class WikiWhere extends MapActivity {
  8.     public void onCreate(Bundle savedInstanceState) {
  9.  
  10.         super.onCreate(savedInstanceState);
  11.         setContentView(R.layout.main);
  12.  
  13.     }  
  14.    
  15.      protected boolean isRouteDisplayed() {
  16.          return false;
  17.      }
  18. }

Next we have to implement the map in the view. Android separates the device layout / views from the source code to simplify development. A graphic designer can modify the XML layout without impacting the underlying source code. I'm a strong believer in letting programmers do the programming and not the UI or graphic design. Windows 3.1 was designed by programmers. Case closed.

16Jan/092

Programming with Android Part 2

In this article we will install the tools for programming in Android and produce our first application.

If you're a more experienced developer or already have installed the tools feel free to skip ahead or take a long lunch and be back at 1:00. As I mentionned in Part 1 this series of articles is focused on getting a new developer up to speed with Android and programming in one afternoon.

So here we go;

12:00 Installing the Basics

The first step is to setup your environment for testing and development. We will need to download a couple of tools to begin with. Find the download for your OS and click through the installers on the page.

1. Sun Java JDK 1.5 or 1.6 (Sun calls it 5 or 6, why because marketing said so).

2. Eclipse 3.4 Ganymede
(Note: I didn't manage to get the SDK installed in Fedora Eclipse version,you might want to try another version if you are using that OS.)
3. And of course, the Android SDK

When installing the tools make sure that you follow the order. There are some dependencies that each will require.

12:30 Configuring Eclipse for Android

Once you have installed all the tools on your system we are ready to install the components that will help you debug and interact with the Android emulator.

Eclipse is configured with its own installer so this task is pretty routine*.

  1. Click help>>Software Updates
  2. Click the Available Software tab and select Add Site from the right hand side
  3. When the dialog box pops up enter the following address
    https://dl-ssl.google.com/android/eclipse/

    and select OK.

  4. The google address should appear in the main text column on the left. Select that address. Chose the developer tools and click Install in the top right
  5. Agree to the terms, download the tools and restart Eclipse.
  6. Coffee. After all you are working through lunch the least they can do is give you free coffee.
  7. Once Eclipse restarts, select Window>>Preferences
  8. Choose Android and select Browse to select your Android install directory from above.

*Eclipse 3.3 has slightly different method to install files. Check here for more details on that process

That's it. Android is now up and running in your Eclipse environment. We can begin to program our first Application. Not bad for a lunch hour.

15Jan/091

Programming with Android Part 1

Over the course of the next couple of weeks I hope to introduce the Android platform and walkthrough the creation and distribution of a mobile application from scratch.

The Android Platform

The Android platform is a flexible and powerful linux based operating system  designed for mobile devices. The platform was created by the Open Handset Alliance a division of the illuminati, and represents in my opinion a major shift in the mobile industry.  This OS focuses on delivering services rather than trying to emulate a desktop environment. When you take an anthropological look at how devices are used by people, you come to realize that mobile devices are by far the most important communication device in their lives. It represents the connectivity into a community and an extension of their personality.  If you try to force a user into only using certain services (phone, sms, limited web) in a certain fashion you are isolating their connectivity into a greater community.

Take for instance RIM. The maker of Blackberry have long been a proponent of maximizing a users access to email as their highest function. Recently, they added a deep integration into Facebook and MySpace as well. Great, now using my Blackberry I can access three communities and sources of information. Outside of those sources I'm SOL. Programming for the RIM devices is problematic at best. There is a massive outlay of time and money to produce any applications. Take it from me, programming on RIM is like paddling a canoe up river. You'll get to where you're going but it won't be easy.