Trouble referencing a .so file in android studio - java

So I am trying to integrate CLE in Android and for this reason I have to add a few .so files. I am following a tutorial from here
Everything works fine till integrating the Star libraries, however when I run the program I get the following exception:
Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: library "/data/data/com.srplab.starcore/lib/libstar_java.so" not found
Now to include these .so files I have created a folder jniLibs and placed .so files for 3 architectures:
I ahve added the following lines of code to my build.gradle:
sourceSets
{
main
{
jniLibs.srcDirs = ['src/main/jnilibs']
}
}
However again when I run the below piece of code:
try {
//System.loadLibrary("mysharedlibrary");
System.load("/data/data/"+getPackageName()+"/libstar_java.so");
} catch (UnsatisfiedLinkError use) {
Log.e("JNI", "WARNING: Could not load libmysharedlibrary.so");
use.printStackTrace();
}
I am getting an exception, means the .so files did not load.
What is the proper way of doing this?

Your "armeabiv7a" folder must be renamed to "armeabi-v7a".
Also there is typo in :
jniLibs.srcDirs = ['src/main/jnilibs']
Your folder is with big L:
jniLibs.srcDirs = ['src/main/jniLibs']
By the way, "src/main/jniLibs" is used by default for native libraries and you do not have to specify it in your gradle scripts.
There is not full block of code above, but do you load your library from static initializer? like:
static
{
System.loadLibrary("star_java");
}
And look at your apk to be sure that your lib were successfully gathered. You can see it at app/build/outputs/apk/

Related

.so file not found (unsatisfiedlinkerror), but it exist

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 🤞.

Android loadLibrary path not found

I'm using System.loadLibrary("xxxx"); to load the library but I'm getting the error message again.
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.xxxxxxxxxxxxxxxxx/base.apk"],nativeLibraryDirectories=[/data/app/com .xxxxxxxxxxxxxxxxx/lib/arm64, /system/lib64, /product/lib64]]] couldn't find "libchilkat.so"
Java code:
static {
System.loadLibrary("chilkat");
}
My Libs
================================================
UPDATE
When you just enter Android Studio, it will create a folder named libs at the path <Project>\app\libs
I moved the libs folder to the path <Project>\app\src\main\
and extra gradle file
android {
....
sourceSets {
main.jniLibs.srcDirs = ['libs']
}
}
it worked fine for me

Android java.lang.UnsatisfiedLinkError with native library

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..!!

How do I specify an extra folder to be on the classpath for gradle's application plugin 'run' task?

I've successfully configured my gradle build script to create a zip distribution of my application with an extra 'config' folder at the root. This folder contains (at least right now) only one properties file in use by the application, and is on the classpath for the application.
What I'm looking for now, however, is a way to do the same with the 'run' task in the application plugin. When I try to run my application this way, (for testing), my program fails to run because of a class trying to access this properties file on the root of the classpath.
A bonus would be if I could get IntelliJ or Eclipse to also add this folder to its classpath just like the other folders (src/main/java, src/main/resources, ...) so I can run and debug my code from within the IDE without invoking a gradle task. I want to try to avoid as much as possible tying this code to any one IDE, so that when anybody needs to work on the project, they just need to import the build.gradle file and have the IDE make the appropriate config files it needs.
Here is my build.gradle file:
apply plugin: 'application'
mainClassName = "MainClass"
startScripts {
// Add config folder to classpath. Using workaround at
// https://discuss.gradle.org/t/classpath-in-application-plugin-is-building-always-relative-to-app-home-lib-directory/2012
classpath += files('src/dist/config')
doLast {
def windowsScriptFile = file getWindowsScript()
def unixScriptFile = file getUnixScript()
windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\config', '%APP_HOME%\\config')
unixScriptFile.text = unixScriptFile.text.replace('$APP_HOME/lib/config', '$APP_HOME/config')
}
}
repositories {
...
}
dependencies {
...
}
Likely what needs to happen is that I need to have the /src/dist/config folder to be copied into the build directory and added to the classpath, or have its contents be copied into a folder that is already on the classpath.
I ended up taking Opal's suggestion as a hint, and came up with the following solution. I added the following to my build.gradle file:
task processConfig(type: Copy) {
from('src/main/config') {
include '**/*'
}
into 'build/config/main'
}
classes {
classes.dependsOn processConfig
}
run {
classpath += files('build/config/main')
}
Alternatively, a simpler approach would be to add a runtime dependency to my project as such:
dependencies {
...
runtime files('src/main/config')
}
I didn't end up doing it this way, however, because my distribution package ended up having .properties files in the lib folder... and I'm just picky that way.
As you can see in the docs run is a task of type JavaExec. So classpath for it can be modified. Try to add config folder to the classpath. See here.

Unable to load .so file

I have an application which uses one native library "libSample.so" which is depend upon another .so file.I am trying to load that library using following code
File File1 = new File("libSample.so");
static
{
try {
System.load(File1.getAbsolutePath());
} catch (UnsatisfiedLinkError e) {
System.out.println("Link Error");
}
}
Before loading library I have tried setting up LD_LIBRARY_PATH where the library is located using command line.
export LD_LIBRARY_PATH=/home/usb:${LD_LIBRARY_PATH}
But still the library not get load.
What should I do now?
Please help.
static {
System.loadLibrary("libSample.so");
}
I assumed that you have your jars in /libs directory and .so file in /libs/armeabi directory so the system finds them. You do not have to add .so files in your eclipse build path.

Categories

Resources