I am using OpenCV with Android Studio. I have a C++ module with ndk and java part. As it says in tutorial I placed opencv libs under ...src\main\jniLibs direcotry. When I buld my C++ code with ndk-build it generates the lbraries under ..src\main\libs folder ans so I have the following error:
Error:duplicate files during packaging of APK D:\AndroidStudioNDKProjects\Inpainting\app\build\outputs\apk\app-debug-unaligned.apk
Path in archive: lib/armeabi-v7a/libopencv_java3.so
Origin 1: D:\AndroidStudioNDKProjects\Inpainting\app\src\main\jniLibs\armeabi-v7a\libopencv_java3.so
Origin 2: D:\AndroidStudioNDKProjects\Inpainting\app\src\main\libs\armeabi-v7a\libopencv_java3.so
What I doing wrong?
problem is that you include 2 lib with same name and android is a bit racist about this (even if both are the same library). one may came from your c++ module and the other from your java part
basic solution : follow your dependencies and remove the extra library.
i would say, just remove the one in "jniLibs. but hard to be more precise without your project under the eyes....
Related
Android Studio 2.2 introduces cmake external build system. The problem is that documentation is really lacking and I do not know how should I link third party libraries? I've tried cmake directive target_link_libraries:
target_link_libraries(native-lib libs/libSomething.so)
And it "works" in that app compiles but then I get dlopen error at runtime because libSomething.so has not been packaged with application. The libs directory is under "app" if that changes anything and I've started with default JNI project generated by Android Studio 2.2...
[Update]
I've tried putting libSomething.so under app/src/main/jniLibs/armeabi-v7a but now the "main" (native-lib) library is not packaged.
[Update2]
I've added source set config that includes cmake output dir and this works but is ugly as hell and is not really a permanent solution...
sourceSet
{
main
{
jniLibs.srcDirs = [ "libs", ".externalNativeBuild/cmake/debug/obj"]
}
}
For now I ended up copying libSomething.so to cmake library output directory in a post build step. This works because it turns out that Android Studio copies into apk EVERYTHING that is in that directory.
Command in cmake is the following:
add_custom_command(TARGET native-lib POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI}/libSomething.so
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libSomething.so
)
For now, you could also put your shared libs into directory, and configure jniLibs to point to that directory, that will pack it. One sample is here: https://github.com/googlesamples/android-ndk/tree/master/hello-libs, follow gperf see if that helps. This way app not depending on the generated build folders. When android studio added packing libs, the jniLibs workaround is not necessary anymore
I am working on a project in which it has dependency on another library project. Library project has both java files and native SO files.
Accessing JAVA source files (APIs) from the Android project java source doesn't have any problem. But, my native code is dependent on native SO files present in the included library project of android as well.
Library Project Android Project
--------------- ---------------
src/Java files <-- Java files
libs/.so files <-- libs/.so files
.so files are part of the included library project. How can my current Android project native code try to use .so files of the included library project. Currently I am getting linking error of undefined reference to all the functions which are part of the library/libs/.so files.
Please let me know if any one has faced/resolved similar type of issue.
You probably have both projects imported into your Eclipse. But ndk-build knows nothing about Eclipse. If the library comes with its own .mk file that defines PREBUILT_SHARED_LIBRARY, it would be even better. One such example is OpenCV which includes sdk/native/jni/OpenCV.mk file.
But you can simply add path to the .so files to your Android.mk, e.g. put the following lines in the end of your file:
include $(CLEAR_VARS)
LOCAL_MODULE:=LibraryProjectSO
LOCAL_SRC_FILES:=/LibraryProject/libs/library.so
include $(PREBUILT_SHARED_LIBRARY)
Now you can add LibraryProjectSO to the list of LOCAL_SHARED_LIBRARIES.
I am trying to test OpenCV Android, on Android Studio, I am confused about how to include the NDK.
What I want to do is run the samples which come with OpenCV. Of the 6 samples provided I managed to run 4 successfully. The exceptions were face-detection and native-activity.
I suspect the reason is I have not set up my NDK correctly.
Googling I found a bunch of discussions but do not really understand them. This is my first time I am trying to work with both the NDK and OpenCV, and my Gradle understanding is limited.
I set an environment variable in my .bash_profile
export ANDROID_NDK=pathTo/android-ndk-r9
I do not understand how to get this to studio.
I see reference to jniFolder but do not understand what these are and should I care right now.
Stackoverflow.com/questions/17767557
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
pkgTask.jniFolders = new HashSet<File>()
pkgTask.jniFolders.add(new File(projectDir, 'native-libs'))
}
What am I supposed to do with this paste at the end of my build.gradle file ?
In summation, my questions are.
How do I get Android Studio to read the NDK variable ?
What exactly are the jniFolders ?
Is it enough just to paste at the end of my build.gradle file ?
Google Group Discussions on Gradle and NDK
For anyone coming across this this is how I resolved it apart from Xaviers anwser.
First I read OVERVIEW.html which comes with the NDK, in the docs directory.
I then compiled the .mk and .cpp files into an .so file. I did this inplace in the sample jni directory
This created the .so file in the libs folder which I copied to the destination as given by Xavier.
If you have libraries that you build with the ndk and want to put them in a gradle-enabled android project (using version 0.7.+ of the plugin), you can just put them in
src/main/jniLibs/<abi>/libfoo.so
for example:
src/main/jniLibs/armeabi-v7a/libfoo.so
src/main/jniLibs/x86/libfoo.so
and they'll get packaged automatically.
If you want to keep them in the native-libs folder you can put the following in your gradle file:
android {
sourceSets.main {
jniLibs.srcDirs = ['native-libs']
}
}
All this does really is tell gradle where the jniLibs folder for the main source set is (relative to the project root.)
The snippet you showed is doing something different. It's telling the package task to also include some native libraries. This was a hack that used to work in a previous version using undocumented API of the task that are no longer supported.
I've made an android library project that uses some native libraries.
I've made the jni wrapper and put the native libs (.so) in the libs// folders. The native libs are compiled using cmake, for armeabi, armeabi-v7a, x86 and mips.
I export this project to a jar and put this jar into a "normal" android project. I then export this project to an apk and can see that my libs are bundles into it.
However, when i install the apk, the libs corresponding to the device are not copied into /data/data/com.my.app/lib and obviously, running the app complains about not finding the libs (UnsatisfiedLinkError).
I've search through SO and everywhere i can but found no answer that solved my case.
i'm using Eclipse, btw
Thanks for your help
UPDATE
OK, i've read the doc in the ndk and seen the examples, and unfortunately, i can't see the solution.
The ndk build the c code into shared libs and places them into the appropriated location in the project. But it doesn't generate anything that says that the libs must be installed with the apk.
My goal is to provide an android library (so a jar), that can be included within an android application. I don't see the real difference between what i'm doing (compile the c libs using cmake and package the jni and java compiled classes into a jar) and what is done with android.mk
If you see what i'm missing, feel free to tell me (even if its obvious).
thanks
UPDATE
i've made a dirty hack: in the libs folder of my application, i've put the jar file containing my classes and my native libs and a copy of the .so files for each arch. Suprise, the libs are no installed in /data/data/com.me.myapp/lib
It seems to confirm that it's a packaging problem.
I export this project to a jar and put this jar into a "normal"
android project. I then export this project to an apk and can see that
my libs are bundles into it.
The issue is that the Android packaging system doesn't handle with binary assets in JARs. For your application project to find and include the generated .so files, you need it to reference the library project as an 'Android library project':
Did you call ndk-build command?
See description below for details.
http://developer.android.com/tools/sdk/ndk/index.html
You can build the shared libraries for the sample apps by going into /samples// then calling the ndk-build command. The generated shared libraries will be located under /samples//libs/armeabi/ for (ARMv5TE machine code) and/or /samples//libs/armeabi-v7a/ for (ARMv7 machine code).
I created a test project to understand how to build and run the tests using command line tool. I managed to create a project, updated it with
android update project -p .
and debug with
ant debug
When I added a library project to this test project, the ant debug started to fail because it couldn't find the build.xml of the library. The only solution I found atm is to update the library project as well (found here). Is this the correct way? I see pom.xml files in many of the libraries that I use. I know it is used by Maven (although I know nothing about it) and it might help me with another solution.
Ant is the official way to build android apk. Maven is an alternative way of doing it (not officially supported, but it works very well).
There are few differences regarding default project layout when working with maven or ant, but it's possible to have both build system working on the same source code if you do some additionnal configuration work (i.e. some information will be duplicated).
Default project layout with maven
java source files are under `/src/main/java``
dependencies are defined in the pom.xml (using the maven way of defining dependencies, with type apklib for android libraries)
Default project layout with ant (and eclipse ADT plugin)
java source files are under /src
dependencies are defined in /project.properties and are specified using relative path.
Here is an example of project.properties (it's a typical example of a library project referencing 2 other library project):
target=android-15
android.library=true
android.library.reference.1=../somelib
android.library.reference.2=../someOtherLib
(as you can see some additionnal information are stored in this file : the android target and the fact that the project is an library or an app. When you use maven, this information is in the pom.xml)
How to build a maven android lib with ant ?
The problems (when you need to build a maven-layout-android-library with ant) are the following:
having a proper /build.xml (it can be done through android update library-project ... here is the official doc about this command)
having a proper /project.properties (it is partially done by the android update ... command, but you may need to add some android.library.reference by hand or with eclipse ADT plugin)
telling ant that the java source files aren't at the default location, but are under /src/main/java
For this last point, here is how to do it:
create a file /ant.properties (in your maven-layout-android-library)
put the following entry in it:
source.dir=src/main/java
(Important : it is not always required because sometimes the java source files are already under /src in the maven-layout-project and in this case, the pom.xml contains the information that the source dir is /src)
And that's all. Now, your maven-layout-android-library can be build with ant debug