Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate .so file and the corresponding Java interface in Android Studio

I want to generate a SO file and its corresponding Java interface for using it into another project.

What I have done so far:

I have created a project in Android Studio 2.3.3 (the latest version of 2017-08-09) with 'Include C++ support' and wrote some C/C++ code and compile it and when I run the program it was successfully called and returned a "Hello from JNI" string.

So after that, I looked the output for the generated .so file, but there I did not find this file. After that, I found the generated APK file in the output folder and when I extracted it, inside I found these folders which all contain .so file:

  • arm64-v8a
  • armeabi
  • armeabi-v7a
  • mips
  • mips64
  • x86
  • x86_64

Now the question is, how can I use these .so files into another project, because of this I searched a lot on the internet, but unfortunately, I did not find any solution, the solution that they mentioned all was to create a folder in the main folder of the project name it jniLibs and after modify the Gradle file and so ..., but no one was working.

Here I want to know that how can we add the .so file and the corresponding Java interface to use them in the project?

It is the error that now I get to the new project when trying to call the JNI function in the .so file.

enter image description here

like image 946
Bahramdun Adil Avatar asked Aug 09 '17 06:08

Bahramdun Adil


2 Answers

I found a solution to this problem. I don't know if it is the good way to solve.

When you created a project with 'Include C++ Support'and wrote the Native (C/C++) code, then you run the app, if everything works well, then you can look to the generated .so files in the build folder in the following path: Open it and you will see the .so files for all the platforms in separate folders.

enter image description here

So now create a new project and change the project view to 'Project' perspective:

enter image description here

And copy and paste all the folders in libs folder of the 'app':

enter image description here

And then add the following code in the Gradle file:

task nativeLibsToJar(type: Zip, description: "create a jar archive of the native libs") {
    destinationDir file("$projectDir/libs")
    baseName "Native_Libs"
    extension "jar"
    from fileTree(dir: "libs", include: "**/*.so")
    into "lib"
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

After adding code the Gradle file looks like this:

enter image description here

After it done, sync the Gradle file:

enter image description here

And make the project from the Build menu:

enter image description here

After the process has been done, change the project view to Android, and you will see a 'jniLibs' folder and the generated .jar file inside this:

enter image description here

Now go to create a new project and do nothing just copy and paste the .jar file in the libs folder:

enter image description here

And now right click and select the 'Add As Library':

enter image description here

And select 'Native Library Location' and click on OK and also in the next dialog click again the OK.

enter image description here

And now create the same class in the same package as you wrote the C/C++ code in the first project. And load the lib by calling like this:

System.loadLibrary("native-lib");

And after that, the IDE, will give an error on the native method, do not care and do your work.

Note: The native method class must be the same name and in the same package as it was created, otherwise the method cannot be found.

Hope this helps someone who has the same problem with JNI.

like image 63
Bahramdun Adil Avatar answered Oct 03 '22 01:10

Bahramdun Adil


These .so files are in separate folders as different devices have different architectures, and linking a so that is incompatible will cause failures. How to find ARM processor version on android device? shows how to get android architecture using terminal (Also there is a internal api for Java).

  1. You can make your JNI project as an android library / module so that you can integrate it easily to other projects. You will need to write a wrapper. Most of the 3rd party libraries use this kind of approach.

  2. You can create another C++ project and then copy the build folders into new project lib folder. Then you will need to add these library dependencies in CMakeLists.txt. However you will still have to make a jni interface that will call your library. In CMakeLists you will need to include using

include_directories(path_to_your_include) add_library( lib_yourlib SHARED IMPORTED ) set_target_properties(lib_yourlib PROPERTIES IMPORTED_LOCATION path_to_your_abi_folders/${ANDROID_ABI}/yourlib.so)

GitHub project that showcases the first approach https://github.com/khedd/SimpleAndroidModule

like image 36
Hakes Avatar answered Oct 03 '22 00:10

Hakes