After a couple of years doing Node.js and React.js I've just come back to Android to do a refresh of an app I originally built in 2012 using OpenCV 2.4.5.

Since then OpenCV 3.0.0 has been released and I was full of hope that the static integration route would have gotten easier (it has, sort of) and that the OpenCV guys would have stopped pushing the insane OpenCV Manager integration approach (they haven't).

As it turns out things are easier now, but not because of changes in OpenCV - rather its because of changes in Android tooling. The relatively new Android Library format (.aar) means that it is very easy to create a reusable library that bundles OpenCV for Android, and the Gradle build system and its integration with Android Studio makes it super-simple to use a library once it is published somewhere, or to use it as local a module dependency if that's your thing.

I've made an example Android Studio project, and deployed the resulting .aar to bintray. I can't / won't stop anyone using my build, although of course it isn't an official build or anything ;)

I figured I'd document the steps I took, since I'll probably have forgotten by tomorrow otherwise.

  1. Download the OpenCV4Android bundle from sourceforge
  2. Unpack the bundle on your machine
  3. Fire up Android Studio and create a Library Project
  4. Copy the java sources from the OpenCV4Android bundle into src/main/java in your library project
  5. Copy the native library directories from the OpenCV4Android bundle into src/main/jniLibs
  6. Build the .aar

If you only want to integrate OpenCV into one application you could do the above steps as an additional module in your existing app project then include the .aar into your app module as a module dependency.

If you want to use the library in several apps or whatever, you'll probably want to push it to a maven repo - bintray gives you a nice free way of doing that.

Once you've published your .aar, using it is a doddle. First, reference your maven repo in the top-level build.gradle of your project:

allprojects {
  repositories {
    jcenter()
    maven {
        url  "http://dl.bintray.com/steveliles/maven"
    }
  }
}

Next, add the .aar dependency in your app's build.gradle file:

    dependencies {
      compile 'org.opencv:OpenCV-Android:3.0.0'
    }

Finally, bootstrap OpenCV in your Java code:

    if (OpenCVLoader.initDebug()) {
      // do some opencv stuff
    }

Awesome!

Bonus: Split your APK's per architecture

OpenCV includes native libraries for each of the possible device architectures, which means that if you bundle them all in one APK you'll be looking at a minimum 40MB download without counting any of your own assets, code, and what have you.

It is actually very easy to split your APK's by ABI so that the end-user download is kept as small as possible - around 8-9MB - and also the build+deploy time onto your development device is kept to a minimum if you only target your specific hardware architecture during development.

Setting up APK splitting is very easy with gradle. Just modify your app module's build.gradle file, adding the following to the 'android' directive:

splits {
  abi {
    enable true
    reset()
    include 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'arm64-v8a'
    universalApk false
  }
}

Enjoy!

Comment on this post

Update, 2015-03-27: Finally got around to having another look at this, attempting to take into account the feedback from commenters.

I just drafted a new version that tries to respond immediately using onStart/onStop when possible, and deals with edge cases like received phone-calls using a delayed Runnable posted to a Handler like the original.

This time I posted an AndroidStudio project as a new github repo rather than just a gist of the interesting bit.

I'm not convinced the defensive WeakReferences to Listeners are strictly necessary, but it seems pear cider brings out my cautious side (its Friday night, what can I say).

Fair warning: I haven't tested this exhaustively, YMMV.

Update, 2015-01-30: Lots of interesting discussion in the comments. Nobody, myself included, is particularly happy with the non-determinism inherent in posting runnables to a handler with an arbitrary delay.

Graham Borland pointed out that if you use onStart/onStop rather than onResume/onPause, you no longer need clever strategies or hacks to determine whether you really have gone background, but others have raised edge cases that complicate matters: phone calls trigger onPause but not onStop, and configuration changes (e.g. rotating the device) call onPause->onStop->onStart->onResume which would toggle our state from foreground to background and back to foreground again.

Original post:

Android doesn't directly provide a way to know if your app is currently foreground or background, by which I mean actively running an Activity (screen on, user present, and your app currently presenting UI to the user).

Obviously if you're coding in an Activity then for almost all of the time (e.g. in any callbacks other than onPause, onStop, or onDestroy) you already know you are foreground, however if you have Service's or BroadcastReceiver's that need to adjust their behaviour when the app is foreground vs. background you need a different approach.

Since API level 14 (Android 4, ICS) we can easily obtain this information by hooking into the activity lifecycle events using Application.registerActivityLifecycleCallbacks.

Using this method we can register a single listener that will be called back whenever an activity lifecycle method is called on any activity in our application. We could call our listener class Foreground, and hook it in to the activity lifecycle methods by providing a custom Application class for our application:

class MyApplication extends Application {
    public void onCreate(){
        Foreground.init(this);
    }
}

Of course, we need to register this custom Application class in our Manifest.xml:

<application
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:name=".MyApplication">

So, what does our Foreground class look like? Let's begin by creating a class that implements ActivityLifecycleCallbacks and allows only one instance of itself to be created via a static method:

class Foreground
implements Application.ActivityLifecycleCallbacks {

    private static Foreground instance;

    public static void init(Application app){
        if (instance == null){
            instance = new Foreground();
            app.registerActivityLifecycleCallbacks(instance);
        }
    }

    public static Foreground get(){
        return instance;
    }

    private Foreground(){}

    // TODO: implement the lifecycle callback methods!

}

This approach of using Singleton's is used a lot in Android programming, as it is a technique recommended by Google.

OK, so we have a class that we can initialise from our Application and then retrieve from any code in our app using Foreground.get(). Now we need to implement the lifecycle callbacks to track the foreground/background status of our app.

To do that we'll use the onActivityPaused/onActivityResumed method-pair, using paused to signal a potential shift to background, and resumed to know we are in the foreground.

private boolean foreground;

public boolean isForeground(){
    return foreground;
}

public boolean isBackground(){
    return !foreground;
}

public void onActivityPaused(Activity activity){
    foreground = false;
}

public void onActivityResumed(Activity activity){
    foreground = true;
}

// other ActivityLifecycleCallbacks methods omitted for brevity
// we don't need them, so they are empty anyway ;)

Nice, so now from any code in our application we can test whether we're currently foreground or not, like this:

Foreground.get().isForeground()

Cool. Are we done? We-ell, depends.

There are three potential issues here:

  1. The app might go to background at any time, so it would be nice if we could get notified instead of having to continually poll the isForeground method.
  2. When an application transitions between two Activities there is a brief period during which the first Activity is paused and the second Activity has not yet resumed ... during this period isForeground will return false, even though our application is the foreground app.
  3. Application.registerActivityLifecycleCallbacks is only available from API-level 14 onwards.

Can we address both of these issues? You betcha!

First lets make it possible to get notified of foreground/background state transitions. We'll add a Listener interface to our Foreground class:

class Foreground
implements Application.ActivityLifecycleCallbacks {

    public interface Listener {
        public void onBecameForeground();
        public void onBecameBackground();
    }

    ...
}

We'll also need to manage any registered listeners and allow listeners to be added and removed. We'll manage registered listeners using a thread-safe and efficient List implementation from java.util.concurrent - CopyOnWriteArrayList:

private List<Listener> listeners =
    new CopyOnWriteArrayList<Listener>();

public void addListener(Listener listener){
    listeners.add(listener);
}

public void removeListener(Listener listener){
    listeners.remove(listener);
}

And, of course, we'll need to notify our listeners whenever we transition between foreground and background states, which we'll do by updating our onActivityPaused and onActivityResumed methods:

public void onPause(){
    foreground = false;
    for (Listener l : listeners){
        try {
            l.onBecameBackground();
        } catch (Exception exc) {
            Log.e("Foreground", "Unhappy listener", exc);
        }
    }
}

public void onResume(){
    foreground = true;
    for (Listener l : listeners){
        try {
            l.onBecameForeground();
        } catch (Exception exc) {
            Log.e("Foreground", "Unhappy listener", exc);
        }
    }
}

Allright, now we're able to register listeners with our Foreground class which will be called-back when we transition from foreground to background and vice-versa.

Bear in mind that the callback is invoked from the lifecycle callbacks and therefore on the main thread. Remember the golden rule of Android development: do not block the main thread. If you don't know what that means you should buy my book :)

Right, that's problem 1 sorted, what about problem 2? (What, you forgot it already? I mean the brief period between onPause being called in Activity A before onResume is called in Activity B).

OK, the issue here is that if we blindly update our foreground/background state in onActivityPaused and onActivityResumed we will always have a period where we're reporting incorrect values. Worse, if we're firing events we'll even tell everyone who's listening that we just went background when we didn't really!

Lets fix that by giving ourselves a brief period of grace before announcing that we've gone background. This is, like many things in engineering, is a compromise - in this case between immediacy and correctness. We'll accept a small delay in order not to falsely report that we went to background.

To do this we'll use one of the nice features of Android's Handler class - the ability to post a Runnable onto the main-thread's event-loop to be executed after a specified delay.

Things are getting a bit more complex now, and we've some extra state to juggle. We're going to introduce another boolean to track whether we're paused or not, and we'll also need to keep a reference to the Runnable that we post to the main thread, so that we can cancel it when necessary.

private boolean foreground = false, paused = true;
private Handler handler = new Handler();
private Runnable check;

A quick note on Handler's: A Handler created with the no-arg constructor will perform all of its work on the thread that created it. Since we're instantiating this Handler inline in the Foreground class, and the Foreground instance is being created on the main thread during our Application's onCreate method callback, any work we post to this Handler will execute on the main thread.

Here's what our updated onActivityPaused and onActivityResumed methods look like:

@Override
public void onActivityResumed(Activity activity) {
    paused = false;
    boolean wasBackground = !foreground;
    foreground = true;

    if (check != null)
        handler.removeCallbacks(check);

    if (wasBackground){
        Log.i(TAG, "went foreground");
        for (Listener l : listeners) {
            try {
                l.onBecameForeground();
            } catch (Exception exc) {
                Log.e(TAG, "Listener threw exception!", exc);
            }
        }
    } else {
        Log.i(TAG, "still foreground");
    }
}

@Override
public void onActivityPaused(Activity activity) {
    paused = true;

    if (check != null)
        handler.removeCallbacks(check);

    handler.postDelayed(check = new Runnable(){
        @Override
        public void run() {
            if (foreground && paused) {
                foreground = false;
                Log.i(TAG, "went background");
                for (Listener l : listeners) {
                    try {
                        l.onBecameBackground();
                    } catch (Exception exc) {
                        Log.e(TAG, "Listener threw exception!", exc);
                    }
                }
            } else {
                Log.i(TAG, "still foreground");
            }
        }
    }, CHECK_DELAY);
}

A couple of things worth pointing out here:

  1. onActivityPaused schedules a Runnable to execute after CHECKDELAY milliseconds (CHECKDELAY is set to 500), and captures the Runnable in the check member variable so it can be cancelled if necessary
  2. onActivityResumed removes (cancels) the check callback if there is one, to cancel the pending notification of going background.

So now we have a nice neat mechanism for making direct checks for foreground/background status (Foreground.get().isBackground(), etc), and for being notified of changes to this status using the Listener interface.

To support API levels below 14 we'd need to hook our Foreground class more directly from the onPause and onResume methods of each individual Activity. This is most easily done by extending all activities in our application from a common base class and implementing the calls to Foreground from there.

For completeness, here's the github gist containing the full code for the Foreground class we've just explored.

Comment on this post

My book is published!

Its been an incredible learning experience - I read a lot of tech books, and find them invaluable, but if you really want to learn about something, try writing a book about it - the desire to deliver value to your readers with broad and deep coverage, and to not get things wrong, really focuses the mind!

Here's the cover and the marketing blurb I originally wrote, but which the publishers only used in part. I laboured over it for ages, so I figured I'd post it all here:

Asynchronous Android - Cover

With more than a million apps available from Google Play, it is more important than ever to build apps that stand out from the crowd. To be successful, apps must react quickly to user-input, deliver results in a flash, and sync data in the background. The key to this is understanding the right way to implement asynchronous operations that work with the platform, instead of against it.

Asynchronous Android is a practical book that guides you through the concurrency constructs provided by the Android platform, illustrating the applications, benefits, and pitfalls of each.

There's so much more to Android than Activities and Fragments. To get the best from modern Android devices, developers must look to unlock the power of multi-core CPU's. Concurrency is hard, but Google's engineers have worked miracles to build a platform that makes asynchronous programming natural and fun.

In this book you will:

Learn to use AsyncTask correctly to perform operations in the background, keeping user-interfaces running smoothly while avoiding treacherous memory leaks.

Discover Handler, HandlerThread and Looper, the related and fundamental building blocks of asynchronous programming in Android.

Escape from the constraints of the Activity lifecycle to load and cache data efficiently across your entire application with the Loader framework.

Keep your data fresh with scheduled tasks, and understand how Services let your application continue to run in the background, even when the user is busy with something else.

Key Points:

  • Understand Android's process model and its implications for your applications
  • Exercise multi-threading correctly to build well-behaved Android apps that work with the platform, not against it
  • Apply and control concurrency to deliver results quickly and keep your apps responsive to user-input
  • Avoid the common pitfalls that catch out even experienced developers
  • Discover Android-specific constructs that make asynchronous programming easy and efficient
  • Learn how, when, and why to apply Android's concurrency constructs to build smooth, response apps

Asynchronous Android will help you to build well-behaved apps with smooth, responsive user-interfaces; delight your users with speedy results and data that's always fresh; and keep the system happy and the battery charged by playing by the rules.

Right now you can get the book direct from Packt Publishing, and Barnes and Noble.

The links for Amazon US, Amazon UK, OReilly, and Safari aren't active yet, but should be by the time you read this.

A free sample chapter should be available from the Packt page soon - I believe it will be Chapter 7, Scheduling work with AlarmManager.

The source code for all of the examples is available from GitHub, and if you can download a pre-built app that runs all of the examples from Google Play.

Comment on this post

A really handy method since API-level 11 is isChangingConfigurations(). When you need to make a decision about which objects to tear down, observers to unregister, etc., you really want to know if your Activity is restarting, going onto the back-stack, or finishing for good.

isFinishing() differentiates between going to the back-stack or one of the other two cases, but doesn't help us to figure out if we're finishing for good or coming right back following a configuration change, say.

At API-level 11 we got a new method to help address that - isChangingConfigurations(). This is great - in lifecycle methods (typically onPause) we can check to see why we're pausing and potentially leave some of our long lived objects alone, being careful to avoid memory leaks, of course!

What options do we have prior to API-level 11? Not a whole lot, actually. The best I could come up with was to create a base Activity class (sub-classing FragmentActivity, obviously) and override two methods:

  1. onSaveInstanceState - overridden to set a boolean property isConfigChange to true.
  2. isChangingConfigurations - overridden to either invoke the super-class method or return the value of isConfigChange, depending on the API level running the app.

There is one big downside - onSaveInstanceState is not invoked until after onPause has completed, so isChangingConfigurations() will only return a correct value when invoked from onStop pre API-level 11.

Full source code below.

Comment on this post

I hit a problem in Android, trying to talk HTTPS with an Apache web-server that has an SSL certificate purchased from Dynadot/AlphaSSL:

javax.net.ssl.SSLHandshakeException: 
  java.security.cert.CertPathValidatorException: 
    Trust anchor for certification path not found.

The code to talk to the server looks something like this:

...
HttpsURLConnection _conn = null;
try {
    _conn = (HttpsURLConnection) 
        new URL(aUrl).openConnection();
    if ((_conn.getResponseCode() >= 200) && 
        (_conn.getResponseCode() < 300)) {
        return handleSuccessResponse(_conn);
    } else if (...) {
        ...
    } else {
        return handleErrorResponse(_conn);
    }
finally {
    _conn.disconnect();
}
...

I googled the message "Trust anchor for certification path not found". Unsurprisingly, StackOverflow shows up several times in the results, but several of the top hits I got suggest reaching immediately for a custom trust manager as the preferred solution.

This set off alarm bells for me, ranging from "that sounds like a lot of effort" through "so, why does connecting to another https site (e.g. my bank) work?".

You do need a custom trust manager if you signed your own certificate.

I haven't thought about it much, but the extra effort actually seems to outweigh the cost of buying a certificate.

You do not need a custom trust manager if you bought your certificate!

If you bought a certificate, building a custom trust manager is a complicated, slow, high-effort workaround for your actual problem, and - worse - you'd have to repeat the workaround on each client (imagine you are building apps for Android, iOS and Windows Mobile).

Certificates are signed in a "chain", where the chain eventually leads back to a set of root authority certificates that are known and trusted by Android. The point is to be able to trace a certificate back to a trusted signing authority without having to have any advance knowledge of the certificate.

So why is my certificate not trusted?

It turns out the server I was connecting to was misconfigured. It was returning its own certificate, but it was not returning the intermediate certificate, so there was no chain, and Android was unable to verify its authenticity, hence "trust anchor not found". Happily I was able to get access to the server to fix up the configuration.

One way to investigate your certificate chain is with openssl client:

openssl s_client -debug -connect www.thedomaintocheck.com:443

This lists some useful information about your cert, including the chain. If you are experiencing a trust anchor not found, your chain will probably only contain one element, like this:

Certificate chain
  0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
    i:/O=AlphaSSL/CN=AlphaSSL CA - G2

.. and openssl will finish its output with something like

Verify return code: 21 (unable to verify the first certificate)

A server configured correctly with intermediate certificates will return a complete chain, like this:

Certificate chain
  0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
    i:/O=AlphaSSL/CN=AlphaSSL CA - G2
  1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
    i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
  2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
    i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

.. and Android's HttpsURLConnection will happily accept the certificate - no custom trust manager keystore nonsense here, thank you.

Comment on this post