OpenCv with Android studio 1.3+ using new gradle - undefined reference

前端 未结 1 392
无人及你
无人及你 2020-11-30 03:02

I\'m having trouble using native OpenCv 2.4.11 (3.0.0 is also ok) with Android Studio 1.3+, with new ndk support. All tutorials about .mk files, but I want to use it with ne

相关标签:
1条回答
  • 2020-11-30 03:32

    After few weeks of pain, I succed. Here is my correct code for Android studio 1.3.1, OpenCv 2.4.11. First you should do this OpenCV in Android Studio (don't use paths which contains white space, both for project and opencv extraction folder) then, for opencv to be native:

    gradle-wrapper.properties:

    distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip 
    

    build.gradle(application):

    classpath 'com.android.tools.build:gradle-experimental:0.2.0'
    

    build.gradle(module):

    apply plugin: 'com.android.model.application'
    
    model {
        android {
            compileSdkVersion = 23
            buildToolsVersion = "23.0.0"
    
            defaultConfig.with {
                applicationId = "android.overloaded.nativetestv4"
                minSdkVersion.apiLevel = 18
                targetSdkVersion.apiLevel = 23
                versionCode = 1
                versionName = "1.0"
            }
        }
    
    
        android.ndk{
            moduleName = "mymodule"
            ldLibs += ['log']
            cppFlags += "-std=c++11"
            cppFlags += "-fexceptions"
            cppFlags  += "-I${file("C:/DevAndroid/OpenCV-android-sdk/sdk/native/jni/include")}".toString()
            cppFlags  += "-I${file("C:/DevAndroid/OpenCV-android-sdk/sdk/native/jni/include/opencv")}".toString()
    
    
    
    //        ldFlags += linkOpt
            ldLibs += ["android", "EGL", "GLESv2", "dl", "log", "z"]// , "ibopencv_core"
            stl = "gnustl_shared"//"gnustl_static"//"gnustl_shared"//"stlport_static"
        }
    
        android.buildTypes {
            release {
                minifyEnabled = false
                proguardFiles += file('proguard-rules.pro')
            }
        }
    
        android.productFlavors {
            create("arm") {
                ndk.with {
                    abiFilters += "armeabi"
    
                    File curDir = file('./')
                    curDir = file(curDir.absolutePath)
                    String libsDir = curDir.absolutePath+"\\src\\main\\jniLibs\\armeabi\\" //"-L" +
    
                    ldLibs += libsDir + "libnative_camera_r4.3.0.so"
                    ldLibs += libsDir + "libopencv_contrib.a"
                    ldLibs += libsDir + "libopencv_core.a"
                    ldLibs += libsDir + "libopencv_highgui.a"
                    ldLibs += libsDir + "libopencv_imgproc.a"
                    ldLibs += libsDir + "libopencv_info.so"
                    ldLibs += libsDir + "libopencv_java.so"
                    ldLibs += libsDir + "libopencv_legacy.a"
                    ldLibs += libsDir + "libopencv_ml.a"
                    ldLibs += libsDir + "libopencv_ts.a"
    
                }
            }
            create("armv7") {
                ndk.with {
                    abiFilters += "armeabi-v7a"
    
                    File curDir = file('./')
                    curDir = file(curDir.absolutePath)
                    String libsDir = curDir.absolutePath+"\\src\\main\\jniLibs\\armeabi-v7a\\" //"-L" +
    
                    ldLibs += libsDir + "libnative_camera_r4.3.0.so"
                    ldLibs += libsDir + "libopencv_contrib.a"
                    ldLibs += libsDir + "libopencv_core.a"
                    ldLibs += libsDir + "libopencv_highgui.a"
                    ldLibs += libsDir + "libopencv_imgproc.a"
                    ldLibs += libsDir + "libopencv_info.so"
                    ldLibs += libsDir + "libopencv_java.so"
                    ldLibs += libsDir + "libopencv_legacy.a"
                    ldLibs += libsDir + "libopencv_ml.a"
                    ldLibs += libsDir + "libopencv_ts.a"
    
                }
            }
            create("x86") {
                ndk.with {
                    abiFilters += "x86"
                }
            }
            create("mips") {
                ndk.with {
                    abiFilters += "mips"
                }
            }
            create("fat") {
    
            }
        }
    
    }
    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        compile 'com.android.support:appcompat-v7:23.0.0'
        compile project(':openCVLibrary2411')
    }
    

    .cpp

    #include <jni.h>
    #include <vector>
    #include <string>
    #include "helpers.h"
    #include <opencv2/core/core.hpp>
    
    using namespace std;
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    
    JNIEXPORT jstring JNICALL
    Java_android_overloaded_nativetestv4_MainActivity_FuncV1(JNIEnv *env, jclass type) {
    
        cv::Mat mat(33,22, 1);
    
        string s = "Cpp v1 - succ, rows#:" + Helpers::ToStringNum(mat.rows);
        Helpers::Log(s);
    
        return env->NewStringUTF(s.data());
    }
    
    }
    

    .java

    package android.overloaded.nativetestv4;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity
    {
        static {
            System.loadLibrary("mymodule");
        }
    
        public static native String FuncV1();
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toast.makeText(this, FuncV1(), Toast.LENGTH_LONG).show();
    
            ((TextView)findViewById(R.id.txtInfo)).setText(FuncV1());
        }
    

    Update for Android Studio 1.5.1, OpenCV 3.1
    1. First you should do this OpenCV in Android Studio (don't use paths which contains white space, both for project and opencv extraction folder), after that you should have normal working Java app
    2. Change build.gradle in project root:

    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath "com.android.tools.build:gradle-experimental:0.4.0"
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
    1. Change gradle-wrapper.properties:
    distributionBase=GRADLE_USER_HOME
    distributionPath=wrapper/dists
    zipStoreBase=GRADLE_USER_HOME
    zipStorePath=wrapper/dists
    distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
    
    1. Change build.gradle in opencv module:

      apply plugin: 'com.android.model.library'
      
      model {
          android {
              compileSdkVersion = 23
              buildToolsVersion = "23.0.2"
              defaultConfig.with {
                  minSdkVersion.apiLevel = 11
                  targetSdkVersion.apiLevel = 23
              }
      
      
          }
      
          android.buildTypes {
              release {
                  minifyEnabled = false
                  proguardFiles.add(file("proguard-rules.txt"))
              }
          }
      }
      
    2. Change build.gradle in app module:

      apply plugin: 'com.android.model.application'
      
      model {
          android {
              compileSdkVersion = 23
              buildToolsVersion = "23.0.2"
      
              defaultConfig.with {
                  applicationId = "android.overloaded.opencv31v1" //Name of package
                  minSdkVersion.apiLevel = 11
                  targetSdkVersion.apiLevel = 23
                  versionCode = 1
                  versionName = "1.0"
      
              }
          }
      
          android.ndk {
              moduleName = "native" // Name of C++ module, for System.loadLibrary("native")
              cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
              cppFlags.add("-fexceptions")
              // YOUR OPENCV DIRECTORY!!!
              cppFlags.add("-I${file("C:/DevAndroid/OpenCV-android-sdk/sdk/native/jni/include")}".toString()) 
              ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "z"])
              stl = "gnustl_shared"
          }
      
          android.buildTypes {
              release {
                  minifyEnabled = false
                  proguardFiles.add(file("proguard-rules.txt"))
              }
          }
      
          android.productFlavors {
              create("arm") {
                  ndk.with{
                      abiFilters.add("armeabi")
      
                      File curDir = file('./')
                      curDir = file(curDir.absolutePath)
                      String libsDir = curDir.absolutePath + "\\src\\main\\jniLibs\\armeabi\\"
      
                      ldLibs.add(libsDir + "libopencv_core.a")
                      ldLibs.add(libsDir + "libopencv_highgui.a")
                      ldLibs.add(libsDir + "libopencv_imgproc.a")
                      ldLibs.add(libsDir + "libopencv_java3.so")
                      ldLibs.add(libsDir + "libopencv_ml.a")
      
                  }
              }
              create("armv7") {
                  ndk.with {
                      abiFilters.add("armeabi-v7a")
      
                      File curDir = file('./')
                      curDir = file(curDir.absolutePath)
                      String libsDir = curDir.absolutePath + "\\src\\main\\jniLibs\\armeabi-v7a\\"
                      ldLibs.add(libsDir + "libopencv_core.a")
                      ldLibs.add(libsDir + "libopencv_highgui.a")
                      ldLibs.add(libsDir + "libopencv_imgproc.a")
                      ldLibs.add(libsDir + "libopencv_java3.so")
                      ldLibs.add(libsDir + "libopencv_ml.a")
                      ldLibs.add(libsDir + "libopencv_ts.a")
      
                  }
              }
          }
          android.sources{
              main{
                  jni{
                      source{
                          srcDirs += ['src/main/jniMy']
                      }
                  }
              }
          }
      }
      dependencies {
          compile fileTree(dir: "libs", include: [$/*.jar/$])
          compile "com.android.support:appcompat-v7:23.1.1" //Do not use 23.2.0 
          compile project(":openCVLibrary310")
      }
      
    3. Create dir app/src/main/jniMy, this is place for yours .cpp files

    4. Optionally create file chelper.c in jniMy, with this code:

      #ifndef OPENCV31V1_CHELPER_H
      #define OPENCV31V1_CHELPER_H
      
      #include <jni.h>
      #include <vector>
      #include <string>
      #include <sstream>
      #include <android/log.h>
      
      using namespace std;
      
      class Helpers{
      public:
          template <typename T>
          static string ToStringNum(T tNumber){
              ostringstream ostrStream;
              ostrStream << tNumber;
              return ostrStream.str();
          }
      
          static void Log(string s){
              __android_log_print(ANDROID_LOG_INFO, "My", s.data());
          }
          static void Log(std::exception ee){
              string s = "Exception: " + string(ee.what()) ;
              __android_log_print(ANDROID_LOG_INFO, "My", s.data());
          }
      
          static long Time(){
              struct timespec now;
              clock_gettime(CLOCK_MONOTONIC, &now);
              return (long)((int64_t)now.tv_sec * 1000LL + now.tv_nsec /1000000LL);
          }
          static string Time(long iTime){
              return ToStringNum(Time() - iTime) + "ms";
          }
      
      };
      #endif //OPENCV31V1_CHELPER_H
      
    5. Create file native_exporter.cpp in jniMy, with this code:

      #include <jni.h>
      #include <string>
      #include <opencv2/core/core.hpp>
      #include "chelper.h"
      
      extern "C"{
      JNIEXPORT jstring     JNICALLJava_android_overloaded_opencv31v1_MainActivity_FuncV1(JNIEnv *env,
      jclass type) {
      
          cv::Mat mat(33,22, CV_32FC2);
      
          string s = "Cpp v1 - succ, rows#:" +Helpers::ToStringNum(mat.rows);
          Helpers::Log(s);
          auto i = 5;
          for (int i2 : {1,3,5}){
              Helpers::Log(Helpers::ToStringNum(i2));
          }
      
          return env->NewStringUTF(s.data());
      }
      }
      
    6. Code in MainActivity.java:

      package android.overloaded.opencv31v1;
      
      import android.os.Bundle;
      import android.support.v7.app.AppCompatActivity;
      import android.util.Log;
      import android.view.SurfaceView;
      import android.widget.TextView;
      import android.widget.Toast;
      
      import org.opencv.android.CameraBridgeViewBase;
      import org.opencv.core.CvType;
      import org.opencv.core.Mat;
      
      public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2
      {
          private static void Log(String sMsg){Log.i("My", "MainActivity." + sMsg );}
      
          static{
              System.loadLibrary("opencv_java3");
              System.loadLibrary("native");
          }
      
          public native String FuncV1();
          JavaCameraViewCustom2 _javaCameraView; //Similar to JavaCameraView
      
          @Override
          protected void onCreate(Bundle savedInstanceState)
          {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              if(getSupportActionBar() != null)getSupportActionBar().hide();
              String sRes = FuncV1();
              Toast.makeText(this, sRes, Toast.LENGTH_LONG).show();
      
              ((TextView)findViewById(R.id.txtInfo)).setText(sRes);
      
              _javaCameraView = (JavaCameraViewCustom2)findViewById(R.id.cameraView);
              _javaCameraView.setVisibility(SurfaceView.VISIBLE);
              _javaCameraView.setCvCameraViewListener(this);
      
          }
      
          @Override
          protected void onResume()
          {
              super.onResume();
              _javaCameraView.enableView();
          }
      
          @Override
          protected void onPause()
          {
              super.onPause();
              _javaCameraView.disableView();
          }
      
          Mat _imgBgrTemp;
          @Override
          public void onCameraViewStarted(int width, int height)
          {
              _imgBgrTemp = new Mat(height,width, CvType.CV_8UC4);
          }
      
          @Override
          public void onCameraViewStopped()
          {
              _imgBgrTemp.release();
          }
      
          @Override
          public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
          {
              _imgBgrTemp = inputFrame.rgba();
              return _imgBgrTemp;
          }
      }  
      

    Android Studio will ask you to change jdk, also it will install new gradle, you should do everything it ask.

    0 讨论(0)
提交回复
热议问题