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
}
- 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
-
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")) } } }
-
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") }
-
Create dir app/src/main/jniMy, this is place for yours .cpp files
-
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
-
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()); } }
-
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.