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!

blog comments powered by Disqus