≡ Menu

Smart Grids, part [x=2;y=6;x·y]: Moving to Android 4.0

I’ve been trying to gently refer to the Android SDK version when talking about the client-side application, in that the application development so far has been targeting Android 2.3 and not Android 4.x, which has slightly more stringent hardware requirements.

For the most part, this doesn’t affect the application much; I don’t use any features that require 4.x, and the API is certainly flexible enough for me to stick with the older revision of the SDK.

But I have an Android 4.x device, the Samsung Galaxy S3; what happens if I target the device I actually own?

Not much, really, but some. The main difference is in the threading model; another difference that affects the application is the required addition of a permission; the last difference is the modification of the deployment version.

Let’s walk through these in order.

First, we need to tell the deployment descriptor that we’re using a later SDK. The specific revision is 15 for Android 4.0; I can’t deploy to 4.1 yet as the S3’s stock ROM isn’t at that revision yet. (It’s supposed to deploy sometime in late October, perhaps November, although it’s not guaranteed for a specific date. I’m not yet running CM10.)

This revision is used in two places: AndroidManifest.xml and pom.xml. The pom.xml is for the packaging; the AndroidManifest.xml is for use by Dalvik at runtime.

The revision change is very simple: we change line 56 of the android-sensor/pom.xml file from:

<platform>10</platform>

to…

<platform>15</platform>

We also need to change the platform version in the properties section (at line 17) from:

<platform.version>2.3.3</platform.version>

to…

<platform.version>4.0.1.2</platform.version>

Next, we need to add a permission to allow the application to read the phone’s state.

Wait – how do I know this? Do I have magical Android ESP, or did an Android genie from the future in space communicate something to me?

Er…. no.

What I did was deploy the application with no changes, while watching the logs on the phone, via adb logcat.

What it showed me was this:

Note the text of the exception:

Requires READ_PHONE_STATE: Neither user 10181 nor current process has android.permission.READ_PHONE_STATE.

That’s… pretty darn useful. To fix it, all I need to do is add the following to AndroidManifest.xml:

<uses-permission
    android:name="android.permission.READ_PHONE_STATE"/>

With this added, we’ve now taken care of the permissions problem, but our application still won’t run properly; we’ll get an error telling us that network code can’t run in the application’s main thread.

We fix this by modifying our Connector implementation to use a separate thread to submit data.

We have a BaseConnector.java abstract class to work with, as described in “Wrapping a Data Transport.”

The publish() method is the jumping-off point for all of our publication processes; our first cut at making a multithreaded connector might (and does) look like this:

@Override
public void publish(final String data) {
    ExecutorService service = Executors.newSingleThreadExecutor();
    service.submit(new Runnable() {
        @Override
        public void run() {
            if (!isConnected()) {
                if (uri == null) {
                    throw new ConnectorException(ERROR_MESSAGE);
                }
                connect(uri);
            }
            doPublish(data);
        }
    });
    service.shutdown();
}

What we’re doing here is using a short-lived executor service to submit data, then telling that service to shut down so we don’t leak resources. It’s kludgy and may not be entirely suitable – we’ll see about that as we migrate to AMQP in subsequent chapters.