Adding OpenCV to Native C code through CMake on Android Studio

UPDATE 21-Oct-19: Deprecated Git/Simpler Way in favor of new AndroidOpenCVGradlePlugin

UPDATE 22-May-18: Added missing step number 6.

UPDATE 10-May-17: New solution provides proper integration of OpenCV into application with CMake and Android Gradle plugin 2.3.1. Tested using Android Studio 2.3.1.

UPDATE 11-May-17: An additional solution has been provided

There are two ways of including OpenCV.

Using AndroidOpenCVGradlePlugin

Visit https://github.com/ahasbini/AndroidOpenCVGradlePlugin for more details.

Git/Simpler Way

Visit https://github.com/ahasbini/Android-OpenCV for more details.

Manual/Advanced Way

To include OpenCV libraries into Android Studio Project, its best to create a new Library Module in the project and port the files from OpenCV Android SDK bundle into it:

  1. Create a new module by selecting File>New Module.
  2. Select "Android Library", and then enter the details:
    • Library name: OpenCV
    • Module name: opencv
    • Package name: org.opencv
  3. Once the new module created, copy the contents of path_to_opencv_sdk/sdk/java/src directory into path_to_your_project/opencv/src/main/java.
  4. Under main, create the following directly path: aidl/org/opencv/engine and move main/java/org/opencv/engine/OpenCVEngineInterface.aidl into it.
  5. Copy the contents of path_to_opencv_sdk/sdk/java/res into path_to_your_project/opencv/src/main/res.
  6. Create sdk folder inside path_to_your_project/opencv/src/ and copy path_to_opencv_sdk/sdk/native folder into it.
  7. Within the opencv module, create CMakeLists.txt file and add the following lines in the following order:

cmake_minimum_required(VERSION 3.4.1)
set(OpenCV_DIR "src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
include_directories(${OpenCV_INCLUDE_DIRS})

  1. Within the opencv module, edit the build.gradle file as such:

...
android {
    ...

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 25
        versionCode 3200
        versionName "3.2.0"

        ...

        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
    }
    buildTypes {
        ...
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
    sourceSets {
        main {
            jni.srcDirs = [jni.srcDirs, 'src/sdk/native/jni/include']
            jniLibs.srcDirs = [jniLibs.srcDirs, 'src/sdk/native/3rdparty/libs', 'src/sdk/native/libs']
        }
    }
}
...

  1. Within the app (application module, could be another name) module, create/edit CMakeLists.txt file and add the following lines in the following order (Note the different path set to OpenCV_DIR):

set(OpenCV_DIR "../opencv/src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
target_link_libraries(YOUR_TARGET_LIB ${OpenCV_LIBS})

  1. Within the app (application module, could be another name) module, edit the build.gradle file as such:

...    
android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
        }
    }
    buildTypes {
        ...
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    ...
    compile project(':opencv')
}

  1. Do a gradle sync, and now the OpenCV native libs, header files and Java wrapper classes are included.

When project is built and apk is launched, you could inspect the packaged apk under path_to_project/path_to_app_module/build/output/ (drag the apk onto the text editor tabs of Android Studio)

APK Inspection

You should see a libopencv_java3.so under each abi architecture folder.

Initialize the OpenCV SDK in your java class :

public class MyClass {

    static {
        if (BuildConfig.DEBUG) {
            OpenCVLoader.initDebug();
        }
    }

    ...
}

And you should see within logcat messages specifying the OpenCV has been loaded (the first error is normal):

05-10 10:42:31.451 D/OpenCV/StaticHelper: Trying to get library list
05-10 10:42:31.452 E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
05-10 10:42:31.452 D/OpenCV/StaticHelper: Library list: ""
05-10 10:42:31.452 D/OpenCV/StaticHelper: First attempt to load libs
05-10 10:42:31.452 D/OpenCV/StaticHelper: Trying to init OpenCV libs
05-10 10:42:31.452 D/OpenCV/StaticHelper: Trying to load library opencv_java3
05-10 10:42:32.031 D/OpenCV/StaticHelper: Library opencv_java3 loaded
05-10 10:42:32.031 D/OpenCV/StaticHelper: First attempt to load libs is OK
05-10 10:42:32.045 I/OpenCV/StaticHelper: General configuration for OpenCV 3.2.0 =====================================
05-10 10:42:32.045 I/OpenCV/StaticHelper:   Version control:               3.2.0
05-10 10:42:32.045 I/OpenCV/StaticHelper:   Platform:
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Timestamp:                   2016-12-23T13:04:49Z
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Host:                        Linux 4.8.0-25-generic x86_64
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Target:                      Linux 1 x86_64
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake:                       2.8.12.2
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake generator:             Ninja
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake build tool:            /usr/bin/ninja
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Configuration:               Release
05-10 10:42:32.045 I/OpenCV/StaticHelper:   C/C++:
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Built as dynamic libs?:      NO
05-10 10:42:32.045 I/OpenCV/StaticHelper:     C++ Compiler:                /usr/bin/ccache /opt/android/android-ndk-r10e/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-g++ (ver 4.9)

The manual method outlined by ahasbini worked (Reg. Adding OpenCV to Native C code through CMake on Android Studio), however some minor adjustments were required for the current version of Android Studio/SDK (3.1.3);

1 replace the occurrence of compile with implementation in (10) app build.gradle (Still getting warning : Configuration 'compile' is obsolete and has been replaced with 'implementation'). And in (9) app CMakeLists.txt ensure to replace YOUR_TARGET_LIB with your target lib (e.g. native-lib).

2 change the STL to gnustl_shared (Linking errors on Android with OpenCV 3.4.0 and NDK); edit (8) app build.gradle;

defaultConfig {
...
externalNativeBuild {
  cmake {
    ...
    arguments "-DANDROID_STL=gnustl_shared"
  }
}

This prevents referencing errors within linked opencv libraries (e.g. error: undefined reference to std:: ...)

3 To support C++11 (How to enable C++11 for Android Studio? / OpenCV Android native code build issue); edit (8) app build.gradle;

defaultConfig {
...
externalNativeBuild {
  cmake {
    ...
    cppFlags "-std=c++11"
  }
}

Then add the following to (9) app CMakeLists.txt before add_library();

set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")

This prevents the following error; relocation R_386_GOTOFF against preemptible symbol icv_ippJumpIndexForMergedLibs cannot be used when making a shared object.