一、开发背景

有一个现有的Android Studio工程,之前直接调用OpenCV的Java接口编程,没有用到JNI编程,现需要利用OpenCV库实现底层算法,故尝试在原工程上加入CMake方式的JNI编程。

二、步骤

1、原工程在创建时没有选择“include C++”选项,故需要手动添加一些文件夹和文件以及修改某些文件。如下
(1)在main目录创建cpp文件夹,用以放置源代码
(2)在main目录下创建jniLibs文件夹,用以放置要调用的动态库文件。
(3)在app目录下创建CMakeLists.txt文件,作为顶层编译控制文件。
(4)修改app目录下的build.gradle文件,加入一些本地编译相关的配置信息。
以上为所有需要修改和添加的内容,具体细节下面叙述。

2、将OpenCV android-sdk目录下的include文件夹复制到cpp文件夹,作为供编写算法的OpenCV头文件,如图:

c 的android应用开发 android c++开发_android


3、将OpenCV android-sdk目录下的libs文件的对应平台的库文件复制到jniLibs文件夹下,如图(不是所有的库都用上,只是libopencv_java.so被用到,但全复制过来也无妨):

c 的android应用开发 android c++开发_android_02


4、编写CMakeLists.txt文件,内容如下

cmake_minimum_required(VERSION 3.4.1)  # CMake要求版本


include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include) # 头文件包含目录,CMAKE_SOURCE_DIR代表工程顶层目录,即CMakeList所在目录

add_library(libopencv_java SHARED IMPORTED)             #引入java动态库
set_target_properties(libopencv_java PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libopencv_java.so)

add_library(
        FaceRecognitionForAndroid
        SHARED
        src/main/cpp/facerecognition.cpp
        src/main/cpp/preprocess.cpp
        src/main/cpp/org_opencv_face_recognition_FaceRecognitionForAndorid)   #引入源文件生成动态库


find_library(  #引入Android NDK的log库
    log-lib
    log )


target_link_libraries( FaceRecognitionForAndroid  #链接所有的库生成最终库文件
                       libopencv_java
                       ${log-lib} )

5、更改app目录下的build.gradle文件,更改后内容如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "org.opencv.face.recognition"
        minSdkVersion 22
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {       //添加:cmake编译默认配置信息
            cmake {
                cppFlags " -frtti -fexceptions -stdlib=libstdc++"
                abiFilters 'armeabi-v7a'
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {    //添加:指定cmake文件的路径:和build.gradle同路径
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation project(':openCVLibrary249')
}

6、完成以上步骤,就可以在cpp文件夹内调用OpenCV的库编写C++算法了。当然,编写的算法想要被Java调用,还要根据JNI文件编写步骤编写对应的文件和Java类,从而调用自己编写的算法。

三、Bugfixed

在使用Android Studio编译依赖OpenCV2.4.9包的工程时,出现报错: ‘ext/atomicity.h’ file not found, 主要网上说时C++库的问题,要加入编译标志-stdlib=libstdc++, 但添加后问题并未解决。后来发现使用老版本的NDK就没有这个问题,而Android Studio的NDK时最新版本的。经测试,使用android-ndk-r14b-windows-x86_64版本的NDK即可解决问题。