is it possible to use a Android Studio Library (aar file) in a Qt app?
The problem is, that I want to implement a mobile App with Qt, but there is only a library for Android Studio. Is it possible to include the library in the Qt project or have I to write a wrapper class for it?
If I have to implement a wrapper, do I have to use the JNI and are there any examples for using it with C++ and a Java lib?
I found the answer, that worked for me.
First you have to unzip the aar file, so you can get your jar library file.
Then you can follow the instructions in this link to include the library to your apk:
http://doc.qt.io/qt-5/android3rdpartylibs.html
When you have finished this, you have to implement your own Java wrapper class to interact with the library. Therfore you have to use the QAndroidJniObject class from Qt. Here are more information about it.
http://doc.qt.io/qt-5/qandroidjniobject.html
You could also have a look at this example, where they use their own java class. http://doc.qt.io/qt-5/qtandroidextras-notification-example.html
You can add .aar files directly to your project
In gradle file add .aar folder to dependencies
compile project(':myAarFolder1.1')
and include it in gradle.settings
include ':myAarFolder1.1'
the aar file location in my project is like this
android/myAarFolder1.1/.aar
android/myAarFolder1.1/build.gradle
android/myAarFolder1.1/build.gradle file content
configurations.maybeCreate("default")
artifacts.add("default", file('myAarFolder1.1.aar'))
Ok incase anyone else comes across this I figured it out.
If you don't already have an android source folder add one by inserting this into your .pro file
android {
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources
}
Here is an example file structure:
project/android-sources
project/android-sources/settings.gradle
project/android-sources/build.gradle
project/android-sources/LibraryFolder
project/android-sources/LibraryFolder/Library.aar
project/android-sources/LibraryFolder/build.gradle
You might have to get your build.gradle file from ../build-Android/android-build/build.gradle and copy it into project/android-sources/ if it doesn't already exist.
Insert this into your build.gradle file within dependencies { }
api project(':LibraryFolder')
Insert this into your settings.gradle file at the bottom
include ':LibraryFolder'
Create the build.gradle file inside LibraryFolder and insert:
configurations.maybeCreate("default")
artifacts.add("default", file('Library.aar'))
and lastly if the library you are adding has other 3rd party dependencies you will have to add them to project/android-sources/build.gradle
For example I was adding ImagePicker and had to insert the below lines inside dependencies { } but above api project(':LibraryFolder')
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
from the library's source
Related
I've been struggling with this for a while, and although I have found many having similar problems, their fixes don't seem to work for me. Perhaps I am misunderstanding something though, regarding of where the shared library files go after installing an APK.
Setup: Android, using a build.gradle file, and CMakeLists.txt since I want to run some C++ code using JNI. I followed the tutorial basically from https://developer.android.com/studio/projects/add-native-code, along with other pieces here and there from other websites.
My C++ code works correctly (it only returns a number). The APK generated can be unzipped, and I see all the .so files under the lib directory. Inside /lib there are four directories, each one for a different arquitecture, including my target (ARM). However, when I install the APK and try to run my C++ code portion, it returns an unsatisfiedlinkerror with the message saying "We looked for your .so file on nativeDirs under /system/lib and /vendor/lib, but we didn't find it)."
Now, if I instead push the .so file from the unzipped APK, into the location they mention, everything will run correctly (so at least my code is compiled correctly). Am I misunderstanding something? I was also reading that it appears that the .so files are not extracted from the APK anymore, but still, it's not finding it. I actually can't find the .so file in the system at all, but again, if I extract the APK it will be there.
My CMakeLists.txt simply have the parameters based on: https://developer.android.com/studio/projects/configure-cmake
cmake_minimum_required(VERSION 3.4.1)
add_library(native SHARED
nativeCode.cpp)
target_link_libraries(native
android
log)
I'm loading my library as:
static {
System.loadLibrary("native");
}
My questions are:
First of all, where should the .so files exist in my device after installing the APK.
Should I specify in any way the location of where the .so files should be under CMakeLists.txt?
If I need to specify a path for the app to look for the .so files, where should this be?
Thank you for your help!
i'm answering your question one by one...
QUESTION : First of all, where should the .so files exist in my device after installing the APK ?
Starting From Android M, it supports uncompressed native libraries in APKs, which allows the platform to read the native libraries directly from the APK without having to extract them.It have the flag android:extractNativeLibs which is default false. This is why you don't see them in the "data/data/packagename/lib/" directory if you're testing on a device on Android M or later.
Ultimately for testing purpose you can use android:extractNativeLibs="true" in Application tag of AndroidManifest.xml, to see in "data/data/packagename/lib/" folder.
<application
android:extractNativeLibs="true">
...
</application>
QUESTION: Should I specify in any way the location of where the .so files should be under CMakeLists.txt?
Considering your nativecode.cpp in rootPath/app/src/main/cpp/nativecode.cpp, and your CMakeList.txt under roothPath/app , your CmakeList.txt add_library should be like below,
add_library( # Sets the name of the library.
nativecode
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/nativecode.cpp)
If you notice, i added relative path and i don't know about case Sensitive. please try with smallcase.
I noticed, you mentioned your lib name as "nativeCode" , but in Code you taken only (System.loadLibrary("native")), it should be nativeCode. make sure the name matches for your library.
Add path of your CMakeList.txt in build.gradle (App Level)
android{
...
externalNativeBuild {
cmake {
path "CMakeLists.txt" //consider this CMakeLists.txt inside rootPath/app/CMakeLists.txt
}
}
QUESTION : If I need to specify a path for the app to look for the .so files, where should this be?
If you follow above steps it will work, You no need to specify which is modern and easy way., but if you wish manually i'm sure it bit complex compared to above(atleast for me)
First you have to create .so files from your .cpp file. (for that,we can do with Android.mk and Application.mk)
Then, you can add following line in build.gradle app level.
android{
...
...
sourceSets {
main {
jniLibs.srcDir 'jniLibs' //consider this jniLibs folder under rootPath\app\src\main\jniLibs
}
}
}
Then, you have to add *.so files in rootPath/app/jniLibs/**/*.so.
You have to generate *.so files for all supported ARM like, ("x86", "x86_64", "armeabi", "armeabi-v7a", "arm64-v8a")
then your folder path something like ,
rootPath\app\src\main\jniLibs\arm64-v8a\libnativecode.so,
rootPath\app\src\main\jniLibs\arm64-v7a\libnativecode.so
and so on...
Hope, these clear your issues and your doubts aswell 🤞.
I use java instrument(premain) to change bytecode,i used losts of jars,like asm,spring,guava.When i package this agent to a jar and run this jar on a springboot's,it always tell me java.lang.NoClassDefFoundError.I know i can add Boot-Class-Path to the manifest file or use instrument's api to add jar,but is there an quick way to add jars to javaagent's classpath?
I added a jar file in my android application. The file is compiled well and working well.
However the jar file contains Json classes under the org.jason package, and it's the same Json package name provided with Android.
When I do an import, the system always choose the Json of Android package and me, I want the Json added with the jar file.
Is there a way to decide which package to import? Either the package provided with Android or the package added with the JAR?
You need to use exclude while importing the library.
compile (){
exclude group: 'x', module: 'y' //by both name and group
}
I tried to use some native library and received some Exception with underlying exception UnsatisfiedLinkError:
java.lang.UnsatisfiedLinkError: Couldn't load viblast: findLibrary returned null
I am using Android Studio + gradle.
It looks like android can't find the native library in APK file.
My projects tree:
I tried to put them in "jniLibs" directory, but it doesn't helped me. I think I forget to write something in gradle files, but I can't figure out what.
Create Folder "jniLibs" inside your "src/main/" and put all your .so files inside "src/main/jniLibs" folder. In your screenshot I can't find "jniLibs".
Please follow below steps :
Add the path of your NDK in the local.properties file, located to
the root directory of your project.
add these lines to your app build.grade files :
sourceSets {
main {
jni.srcDirs = ["libs"]
}
}
Remove old .so files from your app.
Go to the directory src/jni directory of your app project and run the command :
PATH_TO_YOUR_NDK/ndk-build
The project is compiling and your get your lib (.so) under the directory libs of your modules.
5.the libraries into your main app should be like below structure.
Please for reference visit this link..!!
Thanks..!!
I have a default Libgdx Gradle setup, and I need to add my simple text rendering library to it. It consists of a .jar file and native lib file.
This line of build.gradle script seems to work as I would expect, and what it does is add jfreetype.jar java library to my build path.
compile files('../local_lib/jfreetype.jar')
Is there a magic command like this to add native library (.dll to be exact) that is available on my file system and is not Mavenized?
natives "../local_lib/jfreetype32.dll"
This line of code just gives me an error saying that something cannot be found at some repo. I guess there should be a magical line like with .jar file to add native files that are available only on my file system and not on some repo.
The Gradle Natives plugin should do what you want.
You can specify a configuration that points at jar files that contain native dll/so. A gradle task "unpackNatives" will then unpack the dll/so into the build dirs.
Depending upon how you launch your application, you may still need to tell the Java runtime where to find the dll/so. There is some info about how this works at the project website:
https://github.com/cjstehno/gradle-natives
You can add a flat directory as a repository in this way, as mentioned in the dependency-management section in the Gradle User Guide.
repositories {
flatDir {
dirs '../local_lib'
}
}
If you want to create your own dependency-configuration natives, create it like this (more info on the same page):
configurations {
natives
}
Hope that helps.