dcsimg

Global Variables in Android Apps

Using the Application object to cure a case of the Android flip flops

Losing your religion

I love software — really I do.

I love to create stuff.

Some of my favorite words to hear are: "Would it be possible to…?"

The answer to this oft-spoken query is usually something between: "Why would you want to do that?" and "Of course, let’s see it in action."

I love the "Get it done" aspect to writing software. Creating proto-types to test out an idea is arguably my favorite thing to do professionally.

Production code is OK — if you can make a living writing it. It tends to get boring very quickly.

If the code can be written well, that is great too.

And if the code is easily maintained over time, that is even better. And usually, my code is. Except for the spurious comment that just says:

// punt

My development team often laughs at these lines and asks me just what I meant when I wrote it. If I remembered why I wrote it, I probably wouldn’t have a development team to back me up, but that is a story for another day!

I admit, I am probably a bit too loose with my programming style at times. Perhaps it is a character flaw but I have often had a difficult time when people take their programming languages (and themselves) too seriously.

One line I often hear is this: "I am a Java programmer". Great, welcome to the human race, Mr./Ms. Java Programmer.

I have a good friend who is always asking me if my code can be easily re-factored. Of course. Who doesn’t?

While I respect good programming practices, I shy away from people who “worship” one style of programming over another.

If you have been around programmers like these for any period of time, particularly “object oriented programmers”, you have likely heard some of these lines:

  • Never use globals. Never.
  • Your code will not be easy to maintain — break it into more classes.
  • Use hunGarian notation.
  • Encapsulate or perish.

Most of this advice is good — in reasonable doses. Some of it is just limiting the imagination — or the other evil — burdening us with excessive programming constructs. Heretical, I admit.

So, what does this have to do with Android you ask?

Simply that there are some things in Android which are quite happily solved through the use of the often maligned global variable — let’s have a look.

Activity Flip-Flopping

No, Android is not yet running for office, so we have little fear that the story will change over night.

We are concerned here with the funny behavior of our trusted friend Android when a device’s orientation is switched from Portrait to Landscape or vice versa.

In a prior article we learned how to take a photo with a simple Android application.

Taking a picture
Taking a picture

Unfortunately, if the phone is rotated, the Android Activity is re-created (onCreate() method is invoked) and our image is lost!

Losing the photo when rotating
Losing the photo when rotating

Placing a call to trace the execution of the onCreate method, we can actually see that the method is invoked again on each rotation.

05-10 23:15:23.601: INFO/com.msi.linuxmag.PhotoBooth2(7263): Activity Ready to Go!
05-10 23:15:24.481: INFO/ActivityManager(71): Displayed activity com.msi.linuxmag/.PhotoBooth2: 1180 ms (total 1180 ms)
05-10 23:15:27.361: DEBUG/ViewFlipper(134): updateRunning() mVisible=false, mStarted=true, mUserPresent=true, mRunning=false
05-10 23:15:30.401: INFO/WindowManager(71): Setting rotation to 1, animFlags=0
05-10 23:15:30.401: INFO/ActivityManager(71): Config changed: { scale=1.0 imsi=310/410 loc=en_US touch=3 keys=1/1/2 nav=3/1 orien=2 layout=34}
05-10 23:15:30.461: INFO/UsageStats(71): Unexpected resume of com.msi.linuxmag while already resumed in com.msi.linuxmag
05-10 23:15:30.641: INFO/com.msi.linuxmag.PhotoBooth2(7263): Activity Ready to Go!
05-10 23:15:34.171: INFO/WindowManager(71): Setting rotation to 0, animFlags=0
05-10 23:15:34.171: INFO/ActivityManager(71): Config changed: { scale=1.0 imsi=310/410 loc=en_US touch=3 keys=1/1/2 nav=3/1 orien=1 layout=34}
05-10 23:15:34.221: INFO/UsageStats(71): Unexpected resume of com.msi.linuxmag while already resumed in com.msi.linuxmag
05-10 23:15:34.291: INFO/com.msi.linuxmag.PhotoBooth2(7263): Activity Ready to Go!
05-10 23:15:37.301: INFO/WindowManager(71): Setting rotation to 1, animFlags=0
05-10 23:15:37.301: INFO/ActivityManager(71): Config changed: { scale=1.0 imsi=310/410 loc=en_US touch=3 keys=1/1/2 nav=3/1 orien=2 layout=34}

As a result of this "reload", any Activity-scoped variables are reset to their initial values — we need a solution to this obstacle.

In the log-listing above note the lines referring to "Config changed". This is at the root of what is happening — the configuration is changing.

Configuration here is somewhat broadly defined. It could refer to the keyboard layout changing — such as when a G1 or a Droid slides out its keyboard. Or a input language/locale changes. Or, in our case, the device is rotated.

An application can specifically declare within its AndroidManifest.xml which types of configuration changes it wants to handle. In absence of this declaration, the default behavior is for the currently running Activity to relaunch.

We will examine this declarative configuration management in more detail in an upcoming article. For now, we’re going to solve our problem with one of the oldest programming techniques around — using the global variable space.

Application object to the rescue

By default, the Android application that is created with the “File->New” Android project does not contain an implementation of the android.app.Application class. To make use of this class, we must first sub-class it, as shown below.

package com.msi.linuxmag;

import android.app.Application;
import android.graphics.Bitmap;
import android.util.Log;

public class PhotoBoothApp extends Application {
	public Bitmap b = null;
	public PhotoBoothApp ()
	{
		super();
		Log.i("PhotoBooth2","PhotoBoothApp constructor()");
	}
}

In our case, the class is really very simple — we extend the android.app.Application class, declare a “global” variable named b which will hold our Bitmap, and implement the constructor. The constructor is trivial as we simply invoke super() to ask the parent class to do its initialization and we drop a line to the log for a sanity check that this code is being called.

Now, for those who would rather go to the dentist than write code that contains a public member variable, you can wrap that in a “getter” if you prefer and make the Bitmap instance Private.

package com.msi.linuxmag;

import android.app.Application;
import android.graphics.Bitmap;
import android.util.Log;

public class PhotoBoothApp extends Application {
	private Bitmap b = null;
	public PhotoBoothApp ()
	{
		super();
		Log.i("PhotoBooth2","PhotoBoothApp constructor()");
	}
	public Bitmap getBitmap()
	{
		return b;
	}
	public void setBitmap(Bitmap newBitmap)
	{
		b = newBitmap;
	}
}

Regardless of how much encapsulation you prefer, the key here is that this code is accessible to all of the Activity instances in our application. Let’s have a look at how we access this newly minted class from our Activity. And just for fun, I’m going to use the version which marks the Bitmap instance as Public!

Within an Activity, we call the getApplication() method to return an instance of the one and only Application object implemented in our application. Sorry for the multiple uses of the word “application”. The capitalized form refers to the android.app.Application class.

Our Activity code has been updated to no longer rely on a Bitmap object defined at the Activity level — we’re now going to rely on our “global” Bitmap instance.

In the onCreate() method, we now look to see if we have a good reference to a Bitmap object. If so, we display it by assigning it to the ImageView widget defined in our screen layout.

       public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.i(PhotoBooth2.class.getName(),"Activity Ready to Go!");

        final Button  btn = (Button) this.findViewById(R.id.TakePhoto);
        btn.setOnClickListener(new View.OnClickListener(){

        	public void onClick(View v){
        		Log.i(PhotoBooth2.class.getName(),"Button Clicked!");
        		try {
        			Intent action = new Intent("android.media.action.IMAGE_CAPTURE");
        			startActivityForResult(action,1);
        		} catch (Exception e) {
        			Log.e(PhotoBooth2.class.getName(),"Error occured [" + e.getMessage() + "]");
        		}
        	}
        });

        iv = (ImageView) this.findViewById(R.id.PictureFrame);
        PhotoBoothApp app = (PhotoBoothApp) getApplication();
        if (app.b != null) {
        	iv.setImageBitmap(app.b);
        }
    }

After successfully taking a photo, we want to store the image into our PhotoBoothApp object’s Bitmap instance.


    protected void onActivityResult(int requestCode,int resultCode,Intent data)
    {
    	try {
    		if (requestCode == 1) {
    			Log.i(PhotoBooth2.class.getName(),"resultCode is [" + resultCode + "]");
    			if (resultCode == RESULT_OK) {
	    			PhotoBoothApp app = (PhotoBoothApp) getApplication();
    				if (app.b != null) app.b.recycle();
	    			app.b = (Bitmap) data.getExtras().get("data");
	    			if (app.b != null) {
	    				iv.setImageBitmap(app.b);
	    			}
    			}
    		}
    	}catch (Exception e) {
    		Log.e(PhotoBooth2.class.getName(),"onActivityResult Error [" + e.getMessage() + "]");
    	}

    }

Now, we’re ready to handle orientation changes. Almost.

Modifying the code alone does not put the Application object into place for our application. We must also tell Android that our class has extended the android.app.Application. This takes place in the AndroidManifest.xml file — specifically as the android:name attribute of the Application tag.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.msi.linuxmag"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:name="PhotoBoothApp">
        <activity android:name=".PhotoBooth2"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Testing the application

Let’s test out the newly modified application by taking a photo. As further evidence that I’ve got lots of junk in my office, I’ll take a photo of an old mouse-pad and mouse:

Take another photo
Take another photo

What happens if we rotate the phone? Before making these code changes, we lost the image. Let’s see what happens now:

Rotation successful!
Rotation successful!

We still have our image!

Another item to consider is this — Android applications don’t casually terminate like a desktop application. If you take a phone call or switch to another application and then return to your application we need to be prepared to restore the state. Storing data in a global place like an Application object can be an appropriate tool for this task.

Trivia time: One of the companies shown in the screen shot released a product named J++. Which one is it? The third person to answer this correctly will receive an electronic copy of Unlocking Android, Second Edition. Send your answer to fableson at msiservices.com.

Comments on "Global Variables in Android Apps"

One of our guests a short while ago advised the following website.

Every as soon as in a whilst we pick blogs that we study. Listed beneath are the most recent web sites that we pick.

Always a large fan of linking to bloggers that I like but really don’t get a good deal of link adore from.

Here are some hyperlinks to web-sites that we link to for the reason that we feel they are worth visiting.

We came across a cool web-site which you may well delight in. Take a look for those who want.

Here are some links to sites that we link to simply because we feel they’re really worth visiting.

Below you will discover the link to some sites that we feel you must visit.

Usually posts some incredibly interesting stuff like this. If you?re new to this site.

Every when in a while we choose blogs that we study. Listed beneath would be the most recent web-sites that we opt for.

The info mentioned within the post are a few of the most effective readily available.

I simply want to tell you that I’m very new to weblog and definitely loved this blog. Probably I’m planning to bookmark your blog . You surely have superb well written articles. Cheers for sharing your blog site.

Every after in a although we pick out blogs that we study. Listed beneath would be the latest sites that we select.

Here is a great Blog You might Discover Intriguing that we encourage you to visit.

We prefer to honor several other net internet sites around the net, even though they aren?t linked to us, by linking to them. Underneath are some webpages really worth checking out.

We came across a cool web page that you could possibly appreciate. Take a appear when you want.

We like to honor numerous other internet web pages on the net, even though they aren?t linked to us, by linking to them. Underneath are some webpages worth checking out.

Every when inside a when we pick out blogs that we read. Listed beneath are the most up-to-date sites that we choose.

The information and facts mentioned within the article are a few of the ideal obtainable.

Below you will come across the link to some web sites that we assume you need to visit.

Here is a good Blog You may Come across Exciting that we encourage you to visit.

Every once in a though we choose blogs that we study. Listed below are the latest web pages that we opt for.

Usually posts some very interesting stuff like this. If you are new to this site.

Always a significant fan of linking to bloggers that I enjoy but don?t get quite a bit of link like from.

The time to study or go to the subject material or web sites we have linked to beneath.

Below you?ll discover the link to some web sites that we assume you ought to visit.

Here are some hyperlinks to internet sites that we link to since we feel they’re worth visiting.

Every once in a even though we opt for blogs that we study. Listed below are the most up-to-date sites that we select.

We like to honor quite a few other online sites around the web, even though they aren?t linked to us, by linking to them. Beneath are some webpages worth checking out.

Just beneath, are quite a few entirely not related websites to ours, even so, they may be certainly really worth going over.

The details talked about in the write-up are a number of the ideal readily available.

Very handful of internet sites that take place to be comprehensive below, from our point of view are undoubtedly nicely really worth checking out.

The information talked about in the report are a number of the most beneficial readily available.

The time to read or stop by the content material or sites we’ve linked to beneath.

Here are a few of the web pages we advise for our visitors.

Check beneath, are some completely unrelated web-sites to ours, however, they are most trustworthy sources that we use.

That could be the finish of this article. Right here you?ll come across some sites that we think you will value, just click the hyperlinks.

Check below, are some absolutely unrelated websites to ours, however, they’re most trustworthy sources that we use.

Check below, are some totally unrelated sites to ours, nevertheless, they are most trustworthy sources that we use.

Just beneath, are various absolutely not related web-sites to ours, nonetheless, they’re certainly worth going over.

Just beneath, are a lot of entirely not related sites to ours, nevertheless, they’re certainly really worth going over.

We came across a cool web page which you may enjoy. Take a search in the event you want.

Here is a great Weblog You may Discover Exciting that we encourage you to visit.

Although websites we backlink to beneath are considerably not related to ours, we feel they’re essentially really worth a go through, so possess a look.

Although websites we backlink to below are considerably not related to ours, we feel they may be basically worth a go through, so have a look.

Please take a look at the internet sites we comply with, which includes this one particular, as it represents our picks from the web.

We came across a cool website that you could get pleasure from. Take a search in the event you want.

It’s going to be end of mine day, however before ending I am reading this impressive paragraph to improve my experience.

You actually allow it to be seem really easy with the presentation but I
find this matter to become actually something that I think I
might never understand. It appears to be too complicated and extremely broad for me.

I am just looking forward for your post, I’ll try to obtain the hang than it!

Also visit my web-site … WillRNeilsen

That may be the end of this article. Right here you will discover some sites that we feel you?ll enjoy, just click the links.

Check below, are some entirely unrelated internet sites to ours, having said that, they may be most trustworthy sources that we use.

Leave a Reply