Android Studio 2上利用NDK进行OpenCV 3.1开发

        本文主要分为两部分,第一部分采用实验性插件(Gradle Experimental Plugin)建立一个一般性的NDK应用,第二部分采用稳定版插件建立一个简单的灰度处理的OpenCV JNI应用。

        第一个初级NDK应用的代码托管在https://github.com/johnhany/NDKdemo

        第二个OpenCV NDK应用的代码托管在https://github.com/johnhany/OpenCV3JNI

        单纯为Android Studio配置OpenCV 3.1环境的方法请见《在Android Studio上进行OpenCV 3.1开发》


更新记录

2016.07.15 – 经@kennedywai的提醒,第二部分的代码只能运行于x86架构,而在armeabi-v7a会产生"libopencv_java3.so" not found的错误。解决办法是把app\src\main\jni\Application.mk文件中的“APP_STL := c++_static”改为“APP_STL := gnustl_shared”或“APP_STL := c++_shared”(gnustl_shared是考虑到APP_CPPFLAGS的-std=c++11标记)。


索引

        —开发环境

        —准备工作​

        —初级NDK应用

        ——实验性Gradle插件

        ——创建项目

        ——文件说明及修改

        ——编译及运行

        —OpenCV NDK应用

        ——创建项目

        ——文件的修改

        ——编译及运行

        —Instant Run

        —小结

        ——两次app\build.gradle文件的区别

        ——NDK,OpenCV Java API,OpenCV JNI的关系

        —如何减小项目文件夹的大小

        —参考资料


开发环境

        Windows 7 x64 旗舰版

        Android Studio 2.1.2

        JDK 1.8.0

        Android 6.0(API 23)

        OpenCV 3.1.0 Android SDK

        Android NDK r12b


准备工作

        1.按照《在Android Studio上进行OpenCV 3.1开发》环境配置Android模拟器两部分所介绍的步骤下载Android SDK并创建一个虚拟设备。

        2.打开Android Studio 2.1.2,点击sdk_manager_button图标打开SDK Manager。选择SDK Tools,勾选NDK如下图(我已经安装了NDK,所以细节上会有些不同,不过步骤是正确的):

ndk-tools

        再点击Apply,软件就会自动下载NDK。目前(2016.07.08)最新版本为r12b。下载完成后会自动保存在<Android SDK>\ndk-bundle目录下,比如我的是E:\dev-lib\android-sdk\ndk-bundle。也可以到官网手动下载所需的版本(https://developer.android.com/ndk/downloads/index.html),然后解压到一个合适的位置。此外,推荐一个开源的NDK:CrystaX NDK,据说在对C++11的支持方面以及与Boost的配合上更胜一筹(与Android NDK r10e相比,更新版本的比较情况暂时未知)。

        在ndk-bundle文件夹的CHANGELOG.md文件中可以查看目前的版本以及对应过去版本所产生的修改。几个月前我在使用Android Studio 1.5.1时,是不能直接通过SDK Manager下载软件包的。所幸,现在网络直连也可以了,而且下载速度不低:)


初级NDK应用

        实验性Gradle插件:

        Gradle Experimental Plugin基于Gradle的新特性开发,目的在于减少项目配置时间,并提供更好的NDK支持。由于仍然处在开发阶段,所以有些功能暂不支持,而且已有的功能也在频繁地修改。所以尝尝鲜就好,如果要结合OpenCV这种量级的函数库来进行NDK开发,目前我还是推荐采用稳定的Gradle Plugin,详见OpenCV NDK应用一节。

        实验性插件对Gradle版本的要求见下表(摘自http://tools.android.com/tech-docs/new-build-system/gradle-experimental):

gradle-experimental-plugin-version        Gradle的版本可以在File->Project Structure中看到:

gradle-version

        创建项目:

        1.打开Android Studio,新建一个项目,应用名(Application name)为NDKdemo,包名(Package name)为net.johnhany.ndkdemo。我的项目路径(Project location)为E:\projects\Android\NDKdemo,如下图所示:

new-project-1

        2.点击Next,保持默认不变,再点击Next

new-project-2        3.选择默认的Empty Activity,再点击Next

new-project-3        4.保持默认Activity和Layout不变,点击Finish,建立项目:

new-project-4        5.项目创建好后,在下图所示的位置选择Project

project-view        6.在源码目录创建一个jni文件夹。右击main文件夹,选择New->Directory

new-directory-1        在弹出的窗口中输入“jni”,然后点击OK

new-directory-2        7.在jni目录创建一个c文件。右击jni文件夹,选择New->C/C++ Source File

new-c-file-1        在弹出的窗口中输入“hello-jni”,并选择.c类型:

new-c-file-2

        此时项目的文件结构如下图所示,比较重要的文件用红色框标记:

ndk-project-structure       文件说明及修改:

       1.app\src\main\java\net\johnhany\ndkdemo\MainActivity.java包含主要的Java代码,内容修改为:

       2.app\src\main\jni\hello-jni.c包含主要的C代码,内容修改为:

       3.app\src\main\res\layout\activity_main.xml用来设置应用的Layout,内容修改如下:

       4.app\src\main\res\values\strings.xml规定了应用Layout中会引用的字符常量,比如应用名称、标题栏名称、按钮上的文字等等。可以不作修改。

       5.app\src\main\AndroidManifest.xml用来规定Activity之间的关系,以及申请摄像头、内存读写权限等。可以不作修改。

       6.app\build.gradle文件确定Android平台、编译工具及选项、依赖库等重要信息,修改如下:

       由于我在ndk-bundle\CHANGELOG.md中发现有这样一行'ndk-build' will default to using Clang in r13. GCC will be removed in a later release.,所以我这里工具链也采用了Clang。

       7.项目根目录下的build.gradle只需要修改一处,把buildscript.dependencies中的classpath改为'com.android.tools.build:gradle-experimental:0.7.0',表示采用实验性插件:

       8.gradle.properties文件暂时不需要修改。在某些情况下,Android Studio会提示你在该文件内添加android.useDeprecatedNdk=true,以启用老版本NDK的某些功能,不过我们这里给出的两个项目都不需要。

       9.local.properties文件规定了Android SDK和Android NDK的路径,默认不需要修改。如果是手动下载的NDK,则需要在这里设置NDK的路径:

       编译及运行:

       先点击一下sync_project_button按钮,检查一下Gradle配置是否正确。如果没有错误信息,确认虚拟设备已经在运行或者已经通过USB线连接了Android手机,则点击run_button按钮,Android Studio就会开始自动编译、打包、安装及运行。运行效果如下图:

hello-jni


OpenCV NDK应用

       创建项目:

       新建项目的过程与前文类似,这里就不赘述了。应用名称为OpenCV3JNI,包名为net.johnhany.opencv3jni,项目路径为E:\projects\Android\OpenCV3JNI。

       只不过要在jni文件夹中创建3个文件:Android.mkApplication.mk以及gray-process.cpp

opencv-ndk-project-structure       还要在app\src\main\res\drawable中准备一幅名为pic.png的图片,我使用的图片如下:

pic

       此外,需要注意的是,如果你的Java代码中没有出现任何OpenCV相关的变量和函数,则不需要向项目中导入OpenCV库,也不需要在设备上安装OpenCV Manager,在后续步骤中也不需要把OpenCV Android SDK中的opencv_java3.so手动拷贝到项目目录下。如果在Java代码中调用了OpenCV的Java接口,则请按照《在Android Studio上进行OpenCV 3.1开发》为项目配置OpenCV的完整过程将OpenCV库导入到项目中。

       文件的修改:

       1.app\src\main\java\net\johnhany\opencv3jni\MainActivity.java内容修改为:

       2.app\src\main\jni\Android.mk文件的内容为:

       其中,E:\\dev-lib\\OpenCV-android-sdk\\sdk\\native\\jni\\OpenCV.mk要指向你的OpenCV Android SDK中对应文件的位置。

       OPENCV_CAMERA_MODULES:=on说明要使用摄像头功能,我们的demo中虽然没有用到,但是平时写程序时经常会忘记在这里添加,所以一并写上了。

       OPENCV_INSTALL_MODULES:=on可以理解为,编译器自动把OpenCV-android-sdk\sdk\native\libs\x86\libopencv_java3.so拷贝并打包在最终的apk中(目标架构x86因目标设备而定),这也是不需要我们手动向项目内添加任何OpenCV相关库文件的原因。

       LOCAL_SRC_FILES是需要编译的C/C++源码文件,如果有多个文件,只需要用空格将文件名分隔,如果文件名太多需要换行,则在前一行行末添加一个“\”符号即可。

       LOCAL_MODULE是编译产生的.so库的名称,应该与MainActivity.java中通过System.loadLibrary("gray-process");调用的库名称一致。

       3.app\src\main\jni\Application.mk文件的内容为:

       其中,APP_CPPFLAGS中的-std=c++11表示开启C++11支持。

       APP_ABI规定了NDK编译的目标平台,由于我只想测试这两个架构,所以只写了两个,不过当然是越齐全越好:)

       APP_PLATFORM指定了NDK编译针对的平台,其取值应该尽量与app\build.gradle中的minSdkVersion相一致。参考这里:http://stackoverflow.com/a/21982908/3829845

       4.app\src\main\jni\gray-process.cpp文件内容如下:

       5.app\src\main\res\layout\activity_main.xml的内容修改为:

       6.app\src\main\res\values\strings.xml的内容为:

       7.app\build.gradle文件的内容改为:

       有些文章中在android.defaultConfig中添加了一个ndk{},用来声明本地库的名称,其实它的作用与Android.mk中的LOCAL_MODULE是相同的,这样不免有些重复,而且在修改文件名时容易出错,所以我把它去掉了。调用ndk-build.cmd的部分参考了NDK的官方样例。

       请注意文件末尾被注释掉的compile project(':openCVLibrary310'),这一点前面提到过,如果在Java中调用了OpenCV,这里就要取消掉注释,以编译项目中所导入的OpenCV Java部分。

       8.根目录的build.gradle文件中也只有一行需要注意,就是classpath那一行,如下:

       9.初级NDK应用中相同地,gradle.propertieslocal.propertiesapp\src\main\AndroidManifest.xml文件保持默认不变。

       编译及运行:

       与前一节相同,点击run_button按钮,开始编译和运行。运行效果如下图所示:

gray-process


Instant Run

       Instant Run的优势在于,对已经编译的项目,如果项目源码改动不大,重编译和部署到设备的时间就会显著缩短。只要在File->Project Structure中把Android Plugin Version设为2.1.2,Instant Run就会自动开启。不过这也意味着Instant Run与Gradle Experimental Plugin是不可兼得的。

       对于NDK开发,Instant Run的限制在于,NDK编译产生的.so库属于resource文件,而当resource文件或者Layout发生改变时,项目是需要强制重新编译的。所以对C++代码的任何改动都不属于Instant Run的支持范围,需要重新编译。


小结

       通过比较前面两个项目的配置文件你会发现app\build.gradle文件的区别:

       1.采用gradle-experimental:0.7.0时,启用实验性Gradle插件,此时:

       (1)apply plugin'com.android.model.application'

       (2)android{}被包含在model{}内;

       (3)ndk{}defaultConfig{}呈平等关系;

       (4)API版本需要用.apiLevel来指定;

       (5)属性和标记需要用.add().addAll()来添加;

       (6)可以直接指定工具链(toolchain);

       (7)可以直接指定ldLibscppFlagsstl等flag。

       2.采用gradle:2.1.2时,可以使用Instant Run,此时:

       (1)apply plugin'com.android.application'

       (2)没有model{},只有android{}

       (3)ndk{}被包含在defaultConfig{}内;

       (4)API版本用targetSdkVersion 23这样的语句来指定,不需要用.apiLevel

       (5)不能指定工具链,ldLibscppFlagsstl等,而且不能使用.add().addAll()等语句。

 

       关于NDK,OpenCV Java API,OpenCV JNI之间的关系可以这样理解:

       (1)Android项目的Java代码中调用了OpenCV,就需要使用OpenCV Java API,需要向项目中导入OpenCV-Android-SDK\sdk\java库,需要在设备上安装OpenCV Manager,需要在app\build.gradledependencies中添加compile project(':openCVLibrary310')来明确编译OpenCV的Java源码,在Java代码中需要用OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, mOpenCVCallBack);来明确调用OpenCV库;如果项目的Java代码中没有调用OpenCV,以上所有工作都不是必需的。

       (2)Android项目的C/C++代码中调用了OpenCV,就需要使用NDK对OpenCV的JNI进行编译,需要在build.gradleapp\build.gradle(根据需要,添加Android.mk以及Application.mk)中提供编译工具(ndk-build.cmd),工具链(Clang或GCC),依赖库(OpenCV.mk中定义),源码文件,库名称等信息。


如何减小项目文件夹的大小

       有时为了传阅及上传代码的方便,我们需要手动删除一些缓存文件,及减小项目所占用的空间。具体步骤如下:

       1.Build->Clean Project。但默认Clean之后会自动重新编译,所以这样做前后文件夹大小几乎没有区别。

       2.File->Invalidate caches。有时项目文件经过大量修改,缓存经过积累可能会产生一些意想不到的错误,这个操作可以强制重置缓存,当然对文件夹的大小不会产生太大变化。

       3.打开项目的文件夹,手动删除非必要的缓存文件,包括:

       (1).gradle文件夹内的所有文件夹及文件;

       (2)整个build文件夹及其子文件内的所有文件;

       (3)app\build文件夹内的所有文件夹及文件;

       (4)app\src\main\libs文件夹内的所有文件夹及文件;

       (5)整个app\src\main\obj文件夹及其子文件内的所有文件。

       这样,原本100多MB的文件夹就被精简到了几百KB。并且在下一次编译时,这些文件又会自动生成,不会对编译的应用产生影响。


参考资料

[1].googlesamples/android-ndk – https://github.com/googlesamples/android-ndk

[2].The new NDK support in Android Studio – http://ph0b.com/new-android-studio-ndk-support/

[3].Android Studio, gradle and NDK integration – http://ph0b.com/android-studio-gradle-and-ndk-integration/

[4].Experimental Plugin User Guide – http://tools.android.com/tech-docs/new-build-system/gradle-experimental

[5].Build and Run Your App – https://developer.android.com/studio/run/index.html#instant-run

[6].What is the relation between APP_PLATFORM, android:minSdkVersion and android:targetSdkVersion? – http://stackoverflow.com/q/21888052/3829845

共有55条评论

  1. 您好,非常感谢你的分享。我按照你的步骤去实现,在编译时出现这个错误:prebuilt-library.mk: Error:(45) *** Android NDK: Aborting    .  Stop.一直没有找到问题在哪,你能指点一下我吗?

  2. Error:Execution failed for task ':app:ndkBuild'.
    > Process 'command 'D:\sdk\ndk-bundle/ndk-build.cmd'' finished with non-zero exit value 2

  3. 你好博主,第二个OpenCV NDK应用在你的教学下我在模拟器上成功运行,apk导入手上就无法运行,是需要安装opencv manager 吗?

    1. 你好,如果手机上运行出错时在logcat里面提示的信息类似于找不到库或找不到某个库函数的话,就是缺少单独的opencv manager引起的。

  4. 楼主,按步骤来出现了这个问题,请问怎么解决

     Could not get unknown property 'Os' for task ':app:ndkBuild' of type org.gradle.api.tasks.Exec.  

  5. 楼主,请教一个问题:

    参考纯java实现OpenCV Demo时,我们可以import new module将OpenCV-android-sdk\sdk\java\作为依赖库导入,这样涉及到OpenCV api时AS有提示。那么在Android studio上能否实现Native层当涉及到OpenCV的函数时出现提示呢???比如如下Jni函数实现:

    JNIEXPORT jintArray JNICALL Java_com_ckt_eirot_opencv4jni_GrayProcess_grayProcess(JNIEnv *env, class obj,jintArray buf,jint w, jint h) {
        jboolean ptfalse = false;
        jint *srcBuf = env->GetIntArrayElements(buf, &ptfalse);
        if (srcBuf == NULL) {
            return 0;
        }
        int size = w * h;

        Mat srcImage(h, w, CV_8UC4, (unsigned char *) srcBuf);
        Mat grayImage;

        // 加粗字符想实现像java层一样给出代码提示  cvt….
        cvtColor(srcImage, grayImage, COLOR_BGRA2GRAY);
        cvtColor(grayImage, srcImage, COLOR_GRAY2BGRA);

        jintArray result = env->NewIntArray(size);
        env->SetIntArrayRegion(result, 0, size, srcBuf);
        env->ReleaseIntArrayElements(buf, srcBuf, 0);

        return result;
    }

     

    期待回复,O(∩_∩)O谢谢

    1. https://developer.android.com/studio/projects/add-native-code.html#existing-project
      关于Native层使用OpenCV API时没有提示的问题已经找到解决方案,那就是用cmake编译工程。具体操作步骤如下:

      1. 新建src/main下新建cpp目录并创建CMakeLists.txt,添加一句:
      # add OpenCV Library
      include_directories(/home/eirot/MyDev/Opencv/OpenCV-android-sdk/sdk/native/jni/include/)

      2. 修改app/build.gradle配置,添加cmake 支持:
      defaultConfig {
      /*
      * 前面的不变,这里省略了…
      */
      externalNativeBuild {
      // we use ndkBuild for our exist ndk project
      ndkBuild {
      abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
      }
      }
      }

      然后在同级层添加:
      externalNativeBuild {
      /*cmake {
      path "src/main/cpp/CMakeLists.txt"
      }*/
      // For ndk-build, instead use ndkBuild {} not cmake{}
      ndkBuild {
      /**
      https://developer.android.com/studio/projects/add-native-code.html#link-gradle
      * Manually configure Gradle
      * Gradle also includes the Application.mk file if it is located in the same directory as your Android.mk file.
      * path "src/main/jni/Application.mk"
      */

      path "src/main/jni/Android.mk"
      }
      }

      3. Sync project, 编译就OK了!

    1. 借楼一问  首先楼主写的是我一年来所看的cv4android最好的一篇  有一个问题 使用java层的库在不使用cv库管理的情况下 ,需要一个opecv_java3.so 8m左右  我想知道的是这个是怎么编译出来的  不知道楼主知否  这个库应该是jar层涉及到的本地层的总动态库  

  6. 楼主我想问下,Android.mk下的文件配置的LOCAL_MODULE 和项目中加载library的名字是一样的,会报这个错,有什么解决方法吗

     

     java.lang.UnsatisfiedLinkError: Couldn't load NdkJniDemo from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.zy.fengchun.jnidemo-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.zy.fengchun.jnidemo-2, /vendor/lib, /system/lib]]]: findLibrary returned null

  7. 大神,要在java代码中使用opencv的东西,就必须安装那个manager吗?,有没有不用安装就可以解决的办法

  8. 大神,您好,我按您的代码来的,运行报这个错误

    Error:(32, 0) Could not find property 'Os' on task ':app:ndkBuild'.
     

    1. 上个Os问题解决了,往下运行报Error:Execution failed for task ':app:ndkBuild'.
      > A problem occurred starting process 'command 'null/ndk-build.cmd''

      1. 这个解决了,没绑定NDK,但是运行成功够提示couldn't find "libgray-process.so。

        具体错误信息
        java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-support-annotations-23.4.0_bf99cbbcb03da316a29f4c7b1f5b2657391f3be7-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-internal_impl-23.4.0_2e678c86932c7de0b10a656c8192c85d4d9e6011-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-com.android.support-support-vector-drawable-23.4.0_064739ea104b1de4079826b085858db5cf7e2d70-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-com.android.support-support-v4-23.4.0_89f82c0a84e067843f7c117be9e90c44b8642a95-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.4.0_18ac785552ffffcd83d9b357b38d5a86f6d3ebf8-classes.dex", dex file "/data/data/opencv3jni.johnhany.net.opencv3jni/files/instant-run/dex/slice-com.android.support-animated-vector-drawable-23.4.0_b96794d24d3c9f9eeb29c9cfba3e8474caedfc71-classes.dex"],nativeLibraryDirectories=[/data/app/opencv3jni.johnhany.net.opencv3jni-1/lib/x86_64, /data/app/opencv3jni.johnhany.net.opencv3jni-1/base.apk!/lib/x86_64, /vendor/lib64, /system/lib64]]] couldn't find "libgray-process.so"

      1. 在报错的那个gradle中加入

        导包

  9. 大牛你好

    我的jni里include opencv2/stitching/stitcher.hpp用ndk build编译找不到文件 但是在opencv的纯c++却可以 这怎么解决?

    1. 大牛我刚刚看了 在opencv4android的include.stitching文件夹下没有stitcher,我可以用win下的stitcher来替代么?

      1. 一般是可以直接把opencv库的头文件拿给opencv4android用的,只不过需要注意文件名和路径关系的问题,因为不同版本的某些文件的位置和依赖关系都会发生一些变化,就要靠自己阅读hpp文件中的内容来寻找正确的包含文件。

  10. 看了楼主的文章很有启发,按照楼主的Demo我这AS2.1+ndk12b运行发现有几个问题:

    1、OpenCVJNI3中Application.mk中第一行APP_STL := APP_STL := gnustl_shared 多了一个APP_STL :=,不然ndk编译会报错;

    2、Android.mk中的include E:\\dev-lib\\OpenCV-android-sdk\\sdk\\native\\jni\\OpenCV.mk我这一直编译不过,尝试将sdk整个目录复制到main目录下,和jni目录同一级别,然后这一句改成:

    subdirs += $(LOCAL_PATH)/../sdk/native/jni/OpenCV.mk
    include $(subdirs)

    1. 多谢分享!

      1.笔误已更正:)

      2.原来Eclipse+ADT做Android开发的时候会有这个问题,谁料现在as在某些环境下也会出现这种问题。朋友的探索态度值得称赞!

  11. Error:(168) *** Android NDK: Aborting.    .  Stop.
    Android NDK: : Cannot find module with tag '' in import path    
    Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined ?    
    Android NDK: The following directories were searched:    
    Android NDK:         
    make: Entering directory D:/Android/project/OpenCV3JNI/app/src/main/jni'
    make: Leaving directory
    D:/Android/project/OpenCV3JNI/app/src/main/jni'
    :app:ndkBuild FAILED
    Error:Execution failed for task ':app:ndkBuild'.
    > Process 'command 'D:\Android\sdk\ndk-bundle/ndk-build.cmd'' finished with non-zero exit value 2   

    博主我也遇到这个问题了

    1. 我遇到了同样的问题。请按照前文提到的方法进行修改,修改后重启AS,可以解决。同时请问博主,为什么这样修改能能解决?

      2、Android.mk中的include E:\\dev-lib\\OpenCV-android-sdk\\sdk\\native\\jni\\OpenCV.mk我这一直编译不过,尝试将sdk整个目录复制到main目录下,和jni目录同一级别,然后这一句改成:

      subdirs += $(LOCAL_PATH)/../sdk/native/jni/OpenCV.mk
      include $(subdirs)

  12. 大神,我按照你的第一个NDK初级应用,app的gradle里ldlibs和cppFlags是灰色的,而且构建失败,提示Plugin with id‘com.android.applicaion’not found ,我的AS是1.5.1版本的

  13. 楼主,你好,请问opencv运行在手机上面会卡吗?opencv对硬件的要求挺高的,不知道手机的硬件能否处理过来,或者运作这么大的opencv程序对手机的损害大吗?

    1. 如果在主UI线程执行很复杂的算法,就会比较卡了。如果在C++部分利用Boost等库做一些多线程优化,在Java部分利用AsyncTask将计算转移到其他线程上,即使计算量很大也不容易在画面上体现出卡顿。

      长时间执行高强度运算肯定会使手机发热,但opencv对硬件资源的利用和某些手游还是比不了的,况且现在某些智能手机的计算能力已经超过几年前的电脑了,也不必太担心opencv程序会对手机硬件造成很大负担:)

  14. 您好,我运行您的程序出现以下错误

    Android NDK: ERROR:C:/Users/rzhu/Desktop/OpenCV3JNI/app/src/main/jni/Android.mk:opencv_java3: LOCAL_SRC_FILES points to a missing file

    Android NDK: Check that /Android//OpenCV-android-sdk//sdk//native//jni//../libs/x86/libopencv_java3.so exists  or that its path is correct

    而且gray-process.cpp文件无法sync

    1. Android.mk文件中#include …OpenCV.mk的路径是完整正确的吗?在这个文件中,当OPENCV_LIB_TYPE为SHARED时,会通过OPENCV_LIBS_DIR寻找libopencv_java3.so。再确认一下libopencv_java3.so也存在于OpenCV-android-sdk/sdk/native/libs/x86目录中

  15. 谢谢楼主分享,刚接触OpenCV,想把PC上的一个程序移植到手机端。按照你写的步骤,出现了以下的问题,麻烦问一下楼主这是什么原因?

    Error:(168) *** Android NDK: Aborting.    .  Stop.
    Android NDK: : Cannot find module with tag '' in import path    
    Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined ?    
    Android NDK: The following directories were searched:    
    Android NDK:         
    make: Entering directory D:/Android/project/OpenCV3JNI/app/src/main/jni'
    make: Leaving directory
    D:/Android/project/OpenCV3JNI/app/src/main/jni'
    :app:ndkBuild FAILED
    Error:Execution failed for task ':app:ndkBuild'.
    > Process 'command 'D:\Android\sdk\ndk-bundle/ndk-build.cmd'' finished with non-zero exit value 2

      1. 我使用你github上的demo依然会出现下面的问题

        Error:(45) *** Android NDK: Aborting    .  Stop.

        make: Leaving directory `D:/AndroidProject/OpenCV3JNI-master/app/src/main/jni'

        :app:ndkBuild FAILED

        Error:Execution failed for task ':app:ndkBuild'.
        > Process 'command 'D:\Android\sdk\ndk-bundle/ndk-build.cmd'' finished with non-zero exit value 2

  16. 博主你好,我发现按照你昨天(7月15日)更新的修改Application.mk的方法

    还是会出现"libopencv_java3.so" not found的错误,

    我现在参考了这篇博客http://blog.csdn.net/yanzi1225627/article/details/50644903的做法

    通过修改Android.mk:把

    OPENCV_CAMERA_MODULES:=on
    OPENCV_INSTALL_MODULES:=on
    OPENCV_LIB_TYPE:=SHARED

    放在导入opencv.mk路径之前,就可以编译通过,正常运行(初学opencv、Android,不是很清楚具体原因…)

    看了博主之前的很多博客,很是收益,期待博主这个系列的更新!

    1. 多谢分享!虽然用之前的格式在我的机器上可以运行,但是像你这样修改确实有一定的道理,如果看一下opencv android sdk里面的OpenCV.mk,会发现文件里需要判断OPENCV_INSTALL_MODULES和OPENCV_LIB_TYPE的值来执行一些操作,但是值的声明对这个过程的影响可能和ndk相关的插件和库的版本有关吧。

      如果感兴趣,可以试一下:在OpenCV.mk里面搜索“OPENCV_LIB_TYPE”,会找到这样的语句:

      ifeq ($(OPENCV_LIB_TYPE),SHARED)
          OPENCV_LIB_SUFFIX:=so
      else
          OPENCV_LIB_SUFFIX:=a
          OPENCV_INSTALL_MODULES:=on
      endif

      把它改成:

      ifeq ($(OPENCV_LIB_TYPE),SHARED)
          OPENCV_LIB_SUFFIX:=so
          OPENCV_INSTALL_MODULES:=on
      else
          OPENCV_LIB_SUFFIX:=a
          OPENCV_INSTALL_MODULES:=on
      endif

      因为OPENCV_LIB_TYPE的默认值是SHARED(可能与版本有关,请找ifeq ($(OPENCV_LIB_TYPE),)处进行判断),这样就完全不需要在Android.mk中添加OPENCV_INSTALL_MODULES:=on和OPENCV_LIB_TYPE:=SHARED,也能自动把libopencv_java3.so拷贝到apk中。

      再次感谢你的支持!

  17. 对了楼主 我跑了您的例子 在armebai v7a的模拟器和平板都无法正常运行,但在x86结构的模拟器没问题,想问是哪里代码有兼容问题吗? 错误如下:

                                                                             
                                                                             
                                                                             ——— beginning of crash
    07-14 11:35:56.197 23357-23357/net.johnhany.opencv3jni E/AndroidRuntime: FATAL EXCEPTION: main

    Process: net.johnhany.opencv3jni, PID: 23357

    java.lang.UnsatisfiedLinkError: dlopen failed: library "libopencv_java3.so" not found 

    at java.lang.Runtime.loadLibrary(Runtime.java:372) 

    at java.lang.System.loadLibrary(System.java:1076) 

    at net.johnhany.opencv3jni.MainActivity.<clinit>(MainActivity.java:22)
                                                                               

    at java.lang.Class.newInstance(Native Method)
                                                                                 

    at android.app.Instrumentation.newActivity(Instrumentation.java:1067)
                                                                                 

    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2317)
                                                                                 

    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                                                 

    at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                                 

    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                                                 

    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                 

    at android.os.Looper.loop(Looper.java:148)
                                                                                 

    at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                                 

    at java.lang.reflect.Method.invoke(Native Method)
                                                                                 

    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                                 

    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

    1. 你好!把app\src\main\jni\Application.mk第一行的“APP_STL := c++_static”改为“APP_STL := c++_shared”就可以解决这个问题。我试验了一下,在x86的模拟器和armeabi-v7a的小米4上都可以运行:)

发表评论

电子邮件地址不会被公开。 必填项已用*标注