Search code examples
androidwindowsopencvcmakejava-native-interface

Can OpenCV for Android leverage the standard C++ Support to get native build support on Android Studio 2.2 for Windows?


There are many questions and answers surrounding getting native opencv for android building properly. Some use gradle, others use external tools. These numerous, complicated, and often conflicting descriptions for native OpenCV builds might be simplified with a consistent starting point; when creating an Android Studio 2.2 Beta project, there is an way to include C++ support: Include C++ Supportenter image description here

This feature was added around June of 2016. See Android tools technical docs for more information.

Using Android Studio 2.2 or higher with the Android plugin for Gradle version 2.2.0 or higher, you can add C and C++ code to your app by compiling it into a native library that Gradle can package with your APK. Your Java code can then call functions in your native library through the Java Native Interface (JNI). If you want to learn more about using the JNI framework, read JNI tips for Android.

Checking the Include C++ Support generates an external build file called CMakeLists.txt.

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       $\{log-lib} )

To recognize an Android project that uses native (C++) OpenCV code, the project will typically include a *.cpp file containing JNIEXPORT entries along with implementations that use #include <opencv...hpp> functionality. This, as opposed to importing the OpenCV module and copying the libs folder into jniLibs, which only allows calling OpenCV functionality from Java.

Is it possible to use this starting point to configure a OpenCV native 'hello world' app, proving the build is working?

ADDITIONAL INFORMATION 8/22
Since this puzzle is about CMake and less about OpenCV, I thought I'd give out a project starting point for those not interested in OpenCV. You could get the starting point project going reasonably quickly using the information in OpenCV in Android Studio.

Here is a youtube video that shows the creation of a new Android Studio project, importing OpenCV, configuring the native C++ build, resulting in the OpenCV "hello world" application that's equal to the one in gitHub.

ADDITIONAL INFORMATION 8/27
The version committed today, based on the answer from Bruno Alexandre Krinski does compile native OpenCV calls: https://github.com/sengsational/HelloCv . There is a separate problem concerning the "Installation Blocked" message, where, upon installation, Android warns the user "This app contains code that attempts to bypass Android's security protections." Since I am unsure that this is an issue with the build technique, I will not expand this question to include that issue (but if someone has input on that problem, please advise).

#Added 2 path definitions to support 20160825 additions
set(pathToProject C:/Users/Owner/AndroidStudioProjects/HelloCv)
set(pathToOpenCv C:/Users/Owner/OpenCV-3.1.0-android-sdk)

#Added by the IDE on project create
cmake_minimum_required(VERSION 3.4.1)

#Two sets suggested by Bruno Alexandre Krinski 20160825
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#Addition suggested by Bruno Alexandre Krinski 20160825
include_directories(${pathToOpenCv}/sdk/native/jni/include)

#Added by IDE on project create
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )

#Addition suggested by Bruno Alexandre Krinski 20160825
add_library( lib_opencv SHARED IMPORTED )

#Addition suggested by Bruno Alexandre Krinski 20160825
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToProject}/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)

#Added by IDE on project create
find_library( log-lib log )

#Added by IDE on project create, Removed and replace with additional parameter suggested by Bruno Alexandre Krinski 20160825
#target_link_libraries( native-lib $\{log-lib} )
target_link_libraries( native-lib $\{log-lib} lib_opencv)

Solution

  • It seems you already have imported the opencv module, now, open your CMakeList.txt and add the follow lines:

    set(CMAKE_VERBOSE_MAKEFILE on)
    
    add_library(lib_opencv SHARED IMPORTED)
    
    set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION
    path-to-your-project/MyApplication/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
    
    
    include_directories(path-to-opencv-directory/OpenCV-android-sdk/sdk/native/jni/include)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    

    and edit the:

    target_link_libraries( # Specifies the target library.
                       native-lib
                       lib_opencv
                       # Links the target library to the log library
                       # included in the NDK.
                       $\{log-lib} )
    

    to include your lib_opencv that you have created. To finish, you add the follow line:

    abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
    

    in your module app, like this:

    externalNativeBuild {
    
        cmake {
            cppFlags "-std=c++11 -frtti -fexceptions"
            abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
        }
    }
    

    and below of buildTypes you add:

    sourceSets {
        main {
            jniLibs.srcDirs = ['path to your application /MyApplication/app/src/main/jniLibs/']
        }
    }
    

    For more details, you can see this: https://github.com/googlesamples/android-ndk/tree/master/cmake/hello-libs