With Android Studio 2.2, and the new C++ support they added; can I now write and compile inside android studio, or do I need to compile and import my libraries separately
Short answer: Yes, you can.
Here is what you can do 1
1) In Android Studio, right click on your module ==> New ==> Package
2) name the package (folder) cpp (or you can name it jni)
3) you will see the cpp directory on the left.
4) You can create .cpp, .h and other files within that folder.
Nowm you have to tell gradle how to build that.
You need install CMake. 2
1) Go to Preferences ==> Android SDK ==> SDK Tools ==> CMake
2) Select that and click Apply and Ok
Now, you need to add a CMakeLists.txt file to your project.
Path: my_project/app/CMakeLists.txt
This is what the file should look like:
# https://developer.android.com/studio/projects/add-native-code.html#create-cmake-script
# Minimum version of CMake
cmake_minimum_required(VERSION 3.4.1)
# adding CEC library
# add_library structure: add_library(lib_name lib_type_STATIC_or_SHARED source_file_path)
add_library(my_lib_name SHARED src/main/jni/my_cpp_file.cpp)
# include_directories is to provide the path to you native lib code
# include_directories structure: include_directories(native_lib_folder_path)
include_directories(src/main/jni/)
# adding Android log library
# find_library is used to find NDK API libraries (built in NDK libs)
# find_library structure: find_library(name_you_want_to_call_the_lib lib_name_in_ndk_api)
find_library(log-lib log)
# linking log lib to our native lib
# once you find the library, you have to link that library with your native library
# target_link_libraries structure: target_link_libraries(you_native_lib lib_found_using_find_library)
target_link_libraries(my_lib_name ${log-lib})
And final step: add the following to your build.gradle:
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
You should be able to build it now.
th3pat3l's answer is works fine, but the official documentation for how to add C++ to a project is a little different. Here it is:
https://developer.android.com/studio/projects/add-native-code.html#create-sources
The main difference is the use of file->new->package. The package concept is for adding a java package and has a side effect of creating a folder.
You can do the same thing more directly by switching to project view and just creating the folder where you want it in the directory.
Related
I'm currently trying to compile OpenCV using Gradle and integrate it within my Android project, but I'm facing an issue and I don't know how to resolve it.
I have created a native library module within my project and created a few gradle tasks for downloading and unzipping the source code within the project. Then, using the CMakeLists.txt file provided in the OpenCV project, I import it using "add_subdirectory" within my application CMakeList.txt file.
With this, the OpenCV compilation complete correctly and generates the two required libraries, libopencv_core.so and libopencv_imgproc.so in the .cxx/RELEASE/buildHash/arm64-v8a/opencv/lib/arm64-v8a/ folder
However, only my own application .so library and the libopencv_imgproc.so are included in the final .aar file. The libopencv_core.so is missing. If I check in the Gradle build folder, located in build/intermediates/cxx/RELEASE/buildHash/obj/arm64-v8a/, I can see the same issue as in the .aar.
The funny thing is, if I only require to use the libopencv_core.so, it will be integrated within the final .aar correctly, and I don't understand why.
Here is my CMakeList.txt file:
cmake_minimum_required(VERSION 3.18.1)
project("myapp")
add_library(
myapp
SHARED
myapp.cpp )
find_library(
log-lib
log )
# OpenCV source code and CMakeList.txt are located in the opencv folder
add_subdirectory(opencv)
# Library opencv_core and opencv_imgproc are generated by the OpenCV CMakeList.txt
target_link_libraries(myapp opencv_core opencv_imgproc ${log-lib} )
target_include_directories(myapp PUBLIC
opencv/modules/core/include
opencv/modules/imgproc/include
)
include_directories (${CMAKE_BINARY_DIR})
My question is, what am I missing ? Is there something I must specify to force the inclusion of the libopencv_core.so ?
PS: Why I'm not simply integrating the binaries instead of compiling them ? Because the app is targeted for F-Droid, which requires to whole code to be compiled from the sources, so this is not an option for me.
I have finally managed to copy the libopencv_core.so in the correct folder and generate a complete aar.
I just had to add the following to my application CMakeLists.txt:
set_target_properties( opencv_core PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} )
I don't really get why I must add this line, but it's working !
For incorporating other opensource libs via CMake, I've checked similar questions such as this one:
Android Studio: Adding a library outside of the project root
but those are about incorporating Android-Studio lib projects instead of external libs.
In my case, I have a folder structure like this:
thirdparty
category
MyLib
src
MyAndroidStudioProject
build.gradle
settings.gradle
...
app
build
libs
src
build.gradle
...
In the project CMakeLists.txt, I then added this
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} MyLib)
set (MyLib_DIR ../../../thirdparty/category/MyLib)
# output lib binary
add_subdirectory (${MyLib_DIR} ./MyLib)
include_directories (${OBOE_DIR}/include)
I learned from sample code and assume that the CMake source root is at src/MyAndroidStudioProject/app, so MyLib is located using relative path accordingly.
However, building the project gives me
CMake Error at /path/to/src/MyAndroidStudioProject/app/src/main/cpp/CMakeLists.txt:53 (add_subdirectory):
add_subdirectory given source "../../../thirdparty/category/MyLib"
which is not an existing directory.
How should I fix this? Should I configure other settings in the project?
OK, solved it myself.
The relative path should be relative to the CMakeLists.txt file, located at
/path/to/src/MyAndroidStudioProject/app/src/main/cpp/CMakeLists.txt
So the correct relative path in my case should be
set (MyLib_DIR ../../../../../../thirdparty/category/MyLib)
i.e., CMakeLists.txt is 3 levels down the app folder.
I have a pre-built shared library (architecture ARM) which I exported as a conan package:
conan export-pkg .. ext/stable --force -pr android_19_arm_clang
Next I want to use this library in my Android project. I have Conan and CMake setup like this.
conanfile.txt:
[requires]
LibraryName/0.1#ext/stable
CMakeLists.txt
...
conan_basic_setup(NO_OUTPUT_DIRS)
...
target_link_libraries( # Specifies the target library.
myOwnAndroidLib-lib
android
${CONAN_LIBS}
)
...
Since the the pre-built library is a ".so" library I have to put it into the jniLibs Folder of my Android project. This part is missing in the conan/Android docs. How can I instrument conan to place the *.so files in the jniLibs folder?
Thank you
If you want to copy pre-built packages to a specific folder when building, you should use the feature imports:
https://docs.conan.io/en/latest/using_packages/conanfile_txt.html#imports
https://docs.conan.io/en/latest/reference/conanfile_txt.html#imports
I try to add a imported library to my project, and link it to another Library.
Here is some part of my code from CMakeLists.txt:
add_library(native-lib SHARED ${sources})
add_library(imported-lib SHARED IMPORTED)
set_target_properties(imported-lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/PathToLibs/${ANDROID_ABI}/imported-lib.so)
In my native-lib, I create an object of a Class which is placed in imported-lib but the app starts crash. (if I debug or run the app then make project works fine)
In the Gradle Console i get an Info: [org.gradle.api.Task] externalNativeBuildDebug: not building target imported-lib because there was no build command for it
How can I build it?
The shared lib currently need to packed into apk manually, one way is to route jniLibs to your shared lib directory. Hope later version could pack it automatically. One example is here,https://github.com/googlesamples/android-ndk/tree/master/hello-libs, it imports one shared lib, one static lib; shared lib is packed to APK with script in app/build.gradle:jniLibs.srcDirs = ['../distribution/gperf/lib']
As a workaround for me is so in the build.gradle. The 'make' must be in PATH.
externalNativeBuild {
cmake {
...
arguments "-GAndroid Gradle - Unix Makefiles",
"-DCMAKE_MAKE_PROGRAM=make"
}
}
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