I'm aware that there are answers related to this, but they're old and outdated. I got Android Studio 1.3 and already downloaded Android NDK. When I run an app, it crashes and gives findLibrary returned null in Logcat. I figured out this was due to no .so library file (Correct me if I'm wrong). My question is - How do I generate a .so file in Android Studio?
What I have -
Android Studio 1.3 Stable version
Gradle 1.5
Android Experimental Plugin 0.2
Notice - If the library .so file has to be built from Cygwin or CMD, please tell me how to do it.
There are a few steps needed to get the NDK hooked up into Android Studio. Currently, support is marked as experimental and AS is starting to bundle the ability to download the NDK within the IDE. By default, AS uses a generic Android.mk and Application.mk when source and/or libs are placed in the jni or jniLibs folder. The instructions below override those defaults in order to provide more customization ability.
In short, you will need to:
Create the default jni and jniLibs directories for your source and libs.
Tell Android Studio where to find your NDK build chain
Tell gradle how to compile and where to place your libs
Create an Android.mk file to specify building and linking order
Create some source
Create directories
Inside /app/src/main create a jni and jniLibs directory.
Update local.properties
Inside your local.properties file, add a line similar to:
ndk.dir=/home/nathan/development/bin/android-ndk-r10e
Update build.gradle
This refers to the module level, not the application level. This ensures that we have defined the build path in the step above and removes the ability for Android Studio to automatically invoke ndk-build. Use the following example as a guide.
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.0"
defaultConfig.with {
applicationId = "com.example.hellojni"
minSdkVersion.apiLevel = 4
targetSdkVersion.apiLevel = 23
}
}
compileOptions.with {
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7
}
/*
* native build settings
*/
android.ndk {
moduleName = "hello-jni"
/*
* Other ndk flags configurable here are
* cppFlags += "-fno-rtti"
* cppFlags += "-fno-exceptions"
* ldLibs = ["android", "log"]
* stl = "system"
*/
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.txt')
}
}
android.productFlavors {
// for detailed abiFilter descriptions, refer to "Supported ABIs" #
// https://developer.android.com/ndk/guides/abis.html#sa
create("arm") {
ndk.abiFilters += "armeabi"
}
create("arm7") {
ndk.abiFilters += "armeabi-v7a"
}
create("arm8") {
ndk.abiFilters += "arm64-v8a"
}
create("x86") {
ndk.abiFilters += "x86"
}
create("x86-64") {
ndk.abiFilters += "x86_64"
}
create("mips") {
ndk.abiFilters += "mips"
}
create("mips-64") {
ndk.abiFilters += "mips64"
}
// To include all cpu architectures, leaves abiFilters empty
create("all")
}
}
Android.mk
You will need an Android.mk file inside the /app/src/main/jni directory
LOCAL_PATH := $(call my-dir)
# Builds a dylib out of test.cpp
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
test.cpp
Add some awesome C/C++ source code for your lib. These files will start in /app/src/main/jni and will be compiled and linked as specified in your Android.mk
Example file
#include <jni.h>
#include <android/log.h>
static const char *SOME_TAG = "MyAwesomeTag";
extern "C"
{
void
Java_com_something_something_1android_ClassName_some_fn(JNIEnv *env, jobject obj)
{
__android_log_print(ANDROID_LOG_VERBOSE, SOME_TAG, "Hello from NDK :)");
}
} // End extern
Compile and run.
Over a year later with Android Studio 2.2 and above, you can now get all of this done for you for free just by selecting "Include C++ Support" when creating a new project.
For more information check out: https://developer.android.com/studio/projects/add-native-code.html.
Related
I am trying to write a C++ file in Android Studio and I would like to use OpenCV in my project.
However, when I try to use the following includes, I get an error saying Cannot Find 'opencv2'.
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
To set up OpenCV in Android, you have to take the following steps, found here, to use the Java part of OpenCV in Android Studio.
To the best of my knowledge to use the C++ part of OpenCV in Android Studio, you have to add Android.mk and Application.mk to the folder containing your native code.
My Android.mk file looks like the following.
LOCAL_PATH := $(call my-dir)
CVROOT := C:/Users/Dan/Documents/Repos/Android-Studio/Assets/opencv-3.4.1-android-sdk/OpenCV-android-sdk/sdk/native/jni
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include $(CVROOT)/OpenCV.mk
LOCAL_MODULE := app
LOCAL_SRC_FILES := native-lib.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
My Application.mk file looks like the following.
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-27
Am I doing something wrong to set my project up to use the C++ part of OpenCV on Android?
Additional Information for if it makes a difference
My project outline looks like this.
My gradles look like the following
app module
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.test.test.esra"
minSdkVersion 24
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
// Room - Managing local databases
implementation 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
//Jetbrains Annotations
implementation 'org.jetbrains:annotations-java5:15.0'
implementation project(':openCVLibrary341')
}
openCVLibrary341 module
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 24
targetSdkVersion 27
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
project build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
For anyone else who arrives here with the same issue, the problem is fairly easy to fix.
You no longer need the .mk files so they can be deleted.
If you are starting a project from scratch, make sure you have Android NDK and CMake installed as well as enabling them for your project.
After following the initial steps posted in this answer to set up the Java part of OpenCV on Android. You will need to change your app module's build gradle to reflect the snippet below.
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
}
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
Then you want to edit the file CMakeLists.txt. In this file you want to include the following code underneath the cmake_minimum_required(VERSION X.X.X) line.
Also, you will need to add lib_opencv to the target_link_libraries near the bottom of CMakeLists.txt. This will help prevent undefined reference errors.
include_directories(your-path-to/OpenCV-android-sdk/sdk/native/jni/include)
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
...
target_link_libraries( # Specifies the target library.
native-lib
# OpenCV lib
lib_opencv
# Links the target library to the log library
# included in the NDK.
${log-lib} )
Make sure to replace your-path-to with your actual path to OpenCV for Android.
Finally, clean your project and refresh your linked C++ projects. This will remove the error.
I got this information from this really nice GitHub page. Credits to leadrien
Clarification on You no longer need the .mk files. This is true for Android Studio 3. I have not tested this on older versions of Android Studio or Eclipse, so you might need .mk files for those IDEs.
I am getting this error:
java.lang.UnsatisfiedLinkError: dlopen failed: file offset for the library "libopencv_java3.so" >= file size: 0 >= 0
when I am trying to link openCV native code with my java code. I tried a number of things but nothing resolved this error. Please suggest me any solutions.
Android.mk
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=STATIC
ifdef OPENCV_ANDROID_SDK
ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")
include ${OPENCV_ANDROID_SDK}/OpenCV.mk
else
include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk
endif
else
include C:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
endif
LOCAL_MODULE := Sample
LOCAL_LDLIBS += -llog
LOCAL_CFLAGS := $(OPTIMISATIONS)
LOCAL_SRC_FILES := \
Sample/Sample.cpp
build.gradle
defaultConfig
{
applicationId "com.example.app"
ndk
{
moduleName "Sample"
abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
}
}
externalNativeBuild {
ndkBuild {
path '../../../../../opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk'
path 'src/main/jni/Android.mk'
}
}
The error is occurring at System.loadLibrary("Sample");
I think that LOCAL_SRC_FILE name you given as Sample/Sample.cpp is not correct,check SRC_FILE name with full name like com_example_app_Sample.cpp for your cpp file.
And check ndkBuild path "../../../../../" if this path structure mismatch also the Opencv.mk will not load.
This error means the system cannot find the compile library (Sample.so). You need to make sure the library is at the right place, and that the system knows where to find it - I would suggest making sure jniLibs.srcDirs is set in the build.gradle file. For example, if the library is in 'libs' folder, you put this in the gradle file:
sourceSets {
main {
...
jniLibs.srcDirs 'libs'
I have an android application which is been using OpenGL libraries and PVRTC Tool.
This application was running perfectly on Eclipse till API 19. Now I want to move this till API 23 so think to port the application to Android Studio as well for future updates sync. I am facing problems in this porting please look up the screenshots to see the folder hierarchy I have in Eclipse running code
[
[
Following was my Android.mk file:
LOCAL_PATH := $(call my-dir)
PVRSDKDIR := $(LOCAL_PATH)
include $(PVRSDKDIR)/Tools/OGLES2/Build/Android/Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := nativeegl
LOCAL_CFLAGS := -DBUILD_OGLES2 -Wall -g
LOCAL_SRC_FILES := CCAppMain.cpp
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2# -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := \
ogles2tools \
android_native_app_glue
LOCAL_C_INCLUDES := \
$(PVRSDKDIR)/Builds/OGLES2/Include \
$(PVRSDKDIR)/Tools \
$(PVRSDKDIR)/Tools/OGLES2
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
And this is respective Application.mk file in Eclipse
# The ARMv7 is significanly faster due to the use of the hardware FPU
#APP_ABI := armeabi armeabi-v7a x86
#APP_OPTIM := release
APP_STL := stlport_static
I am using Android Studio Version 1.4 , Gradle Built 2.5
have set classpath as "classpath 'com.android.tools.build:gradle-experimental:0.2.0' "
My app module built.gradle looks like
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
defaultConfig.with {
applicationId = "xxx"
minSdkVersion.apiLevel = 14
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
compileOptions.with {
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7
}
android.ndk {
moduleName = "nativeegl"
//cppFlags += "-I${file("src/main/jni/native_app_glue")}".toString()
cppFlags += "-I${file("src/main/jni")}".toString()
cppFlags += "-I${file("src/main/jni/Tools")}".toString()
cppFlags += "-I${file("src/main/jni/Tools/OGLES2")}".toString()
cppFlags += "-I${file("src/main/jni/Tools/OGLES2/GLES2")}".toString()
ldLibs += ["android", "EGL", "GLESv2", "OpenSLES", "log"]
stl = "stlport_static"
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.txt')
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
}
I am really not able to configure the application at moment, On syncing it always giving errors such as
Error:Execution failed for task ':app:compileArmeabi-v7aDebugNativeeglSharedLibraryNativeeglMainCpp'.
> Multiple build operations failed.
C++ compiler failed while compiling PVRTPrint3D.cpp.
C++ compiler failed while compiling PVRTBackground.cpp.
C++ compiler failed while compiling PVRTShader.cpp.
C++ compiler failed while compiling PVRTPrint3DAPI.cpp.
C++ compiler failed while compiling PVRTPFXParserAPI.cpp.
See the complete log at: file:///E:/Android_Studio_Project/XXX/app/build/tmp/compileArmeabi-v7aDebugNativeeglSharedLibraryNativeeglMainCpp/output.txt
Can anyone look into it and make correction to my build.gradle file. I am guessing that PVRTC tool is been ignored in it.
Any help will be appreciated.
You are not obliged to forsake your carefully crafted Android.mk for the unpolished and limited DSL of the experimental gradle plugin. See more at define LOCAL_SRC_FILES in ndk{} DSL.
The specific problem in your case seems to be not that the PVRTC files are ignored, but that they are not compiled according to the rules and flags as configured in Tools/OGLES2/Build/Android/Android.mk.
TL;NR: append the following lines to you build.gradle:
def ndkBuild = android.ndkDirectory
import org.apache.tools.ant.taskdefs.condition.Os
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkBuild += '.cmd'
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
commandLine '$ndkBuild', '-C', 'src/main'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
commandLine '$ndkBuild', 'clean', '-C', 'src/main'
}
clean.dependsOn 'cleanNative'
tasks.all {
task ->
if (task.name.startsWith('compile') && task.name.contains('MainC')) {
task.enabled = false
}
if (task.name.startsWith('link')) {
task.enabled = false
}
if (task.name.endsWith("SharedLibrary") ) {
task.dependsOn buildNative
}
}
android {
sourceSets {
main {
jniLibs.srcDirs = ['src/main/libs']
}
}
}
So I want to modify one of the files in the OpenCV build for Android and I followed the instructions on their site to download the build and I was able to make it successfully. I modified one of the files (calibinit.cpp) and made it again and copied the files in the
opencv/platforms/build_android_arm/lib/
folder into the jniLibs folder of my AndroidStudio Project.
However, the changes I made are definitely not working. I already had a previous OpenCV library linked to my project, so I'm pretty sure it's still using the old code. How do I use the new build with my AndroidStudio Project?
Can you provide more details about how u use jni in Android Studio Project?
Did u try to clean and rebuild?
Do you have your own custom Android.mk? cause Android Studio will generate its own Android.mk, which can lead to unexpected result as u thought.
delete jniLibs folder and every so file, you don't need them.
define NDK path in local.properties file:
sdk.dir=D:\Android\SDK
ndk.dir=D:\Android\NDK
create a folder(i named it jni) and put Android.mk and Application.mk in it (and an empty dummy.c file for preventing future buggy errors)
as Roy said, Android Studio generates it's own Android.mk, we have our own Android.mk file and Android Studio must use it.jni.srcDirs = []prevents that generation!
Extract openCV sources somewhere, i put them here: D:\Android\Libs\OpenCV
here is my files, modify and use them
build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "your.package"
minSdkVersion 11
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
sourceSets {
main {
jni.srcDirs = [] /*disables automatic ndk-build call */
}
}
task ndkBuild(type: Exec) {
commandLine file('D:\\Android\\NDK\\ndk-build.cmd').absoluteFile,
'NDK_PROJECT_PATH='+file('src\\main\\jni').absolutePath,
'APP_BUILD_SCRIPT='+file('src\\main\\jni\\Android.mk').absolutePath,
'NDK_APPLICATION_MK='+file('src\\main\\jni\\Application.mk').absolutePath,
'NDK_LIBS_OUT='+file('src\\main\\jniLibs').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile project(':openCVLibrary300rc1')
}
Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-8
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#opencv
OPENCVROOT:= D:/Android/Libs/OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk
//I have a local source file, you can remove it
LOCAL_SRC_FILES := DetectionBasedTracker_jni.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS += -llog
LOCAL_MODULE := detection_based_tracker
include $(BUILD_SHARED_LIBRARY)
When you have
android {
defaultConfig {
ndk {
moduleName "yourlib"
stl "stlport_static"
ldLibs "log", "z", "m"
cFlags "-I/some/include/dir/"
}
...
}
...
}
in your build.gradle then Gradle will compile the files in src/main/jni/ and it will generate an Android.mk in build/ndk/debug/Android.mk.
However, in my case, I'm trying to compile some C++ files compiled against OpenCV.
I have this working when I manually create the Android.mk file and run the ndk-build command. But I want to do it via Gradle / Android Studio automatically.
When doing this manually, I include the libraries to link against. I do this, in the manually created Android.mk, with the line:
include /path/to/the/opencv/directory/sdk/native/jni/OpenCV.mk
However, in Android's Gradle plugin, I am unsure of how to add this 'include' directive in the generated Android.mk file.
Can anyone point me in the right Gradle-directive direction to add this line to the generate file? Thanks.
I've found that that the build process will pull everything in from below the ./src/main/jni folder. So, I've placed symlinks there to include and src folders elsewhere - the src files will be enumerated into the .mk file by the build process and the inc files will be scooped up by the compiler. Perhaps its a bit hacky:
android {
defaultConfig {
ndk {
moduleName "yourlib"
cFlags "-std=c99 -I${project.buildDir}/../src/main/jni/inc"
}
...
}
...
}
I also have different cFlags depending upon debug build. This seems to be valid gradle, but doesn't want to build with android-studio. It will build with the gradlew command tho:
android {
defaultConfig {
ndk {
moduleName "yourlib"
cFlags "-std=c99 -I${project.buildDir}/../src/main/jni/inc"
}
...
}
...
buildTypes {
release {
debuggable false
jniDebugBuild false
ndk {
moduleName "yourlib"
}
}
debug {
debuggable true
jniDebugBuild true
ndk {
moduleName "yourlib"
ldLibs "log"
cFlags "-g -D_DEBUG"
}
}
}
}
I hope it can help you (android-studio 0.8.6).