Import existing c++ library (.a or .so file) ndk android
Asked Answered
N

2

17

I just gone through native development in android. I am successful in getting my AndroidStudio 2.2.2 ready for native debelopment

I also build sample hello-jni project

What I am trying to achieve

I am trying to use an existing library designed in c++ (I will be provided with static library .a extension or .so file)

Few confusions regarding native developement

1) Shall I use the .cpp & .h files of the existing c++ library instead of .a or .so file ?

2) Do I need to make CMakeLists.text : So far as I googled my .a files is not generated using ndk-build , so I need to make it.

If I use .cpp & .h files , should I make Android.mk & Application.mk

Does CMakeLists.text compile my newly developed android project as library or my existing .a file ?

3) Where do I put the .a file in my project . Is it under jni folder?

4) Should my java class files should define methods with keyword native same like as implemented in c++ file (Example : In c++ file method name getData() , should java class contain public native getData() )

Novel answered 4/11, 2016 at 4:52 Comment(0)
B
24

Note: This answer does not show how you can use CMake after writing native (C++) code. For that setup, read the answer below to get full understanding of the setup and then look at this answer.


Ok so you have bunch of questions. Some of these questions are personal preference type but I will provide them as my personal choice.

#1 This is your choice. I, personally, would use the compiled .so file. This way I never have to worry about NDK and CMake and .mk files. If you have the file, all you have to do is add the file to the libs folder (not lib folder) and make a minor change to your build.gradle file. That's it.

Change to build.gradle:

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
        jniLibs.srcDirs = ['libs']
    }
}

#2 & 3 These would be irrelevant with this option.

#4 You would have to do something like this no matter if you use the files or the compiled libraries:

@SuppressWarnings("JniMissingFunction")
public class MyNativeMethods {
    static {
        System.loadLibrary("my_native_lib");
    }

    public native int native_method_1(int fd);
    public native int native_method_2(int fd);
    public native void native_method_3(int fd, int arr[]);
    public native int[] native_method_4(int fd);
}

And then, you can call those methods from your Activity/Fragment.

Hope this is clear enough.


EDIT (based on comment below):

  1. .so or .a files are your native libraries.

  2. the .cpp, .c, etc. files are just your native source code files. If you were to use those files in the project, you would have to use a build system (for example, CMake) to use them. CMake would take your source code files and make a .so library which is again the native library. This is why I suggested to use the .so files because why do the work of implementing CMake in your project when you don't need to?

If you want to try CMake or learn it in the future, check this answer: C/C++ with Android Studio version 2.2

  1. System.loadLibrary("my_native_lib");: Here you are telling the Java runtime to add this given library. This way you are creating a link between Java and the C++ code that is within the library. The methods below that line should have the same name as they do in the C++/C code. This way Java runtime will find and open the library and look for those method in the library you load. See more here
Broadcast answered 4/11, 2016 at 5:5 Comment(11)
Thanks a lot for this answer. I am very much confused with the word 'native library' . 1) The code I write for accessing the c++ methods from .so file (in 'jni' folder ) is called native library OR the methods I use from c++ library (like maths functions) is called native library OR my .so or .a file is called native library .... What this line says System.loadLibrary("my_native_lib"); what I am loading ?Novel
I've edited my answer to give you more details. See if that helpsJointless
My native Project is done using VisulaStudio . Any way to add the c++ source file to Android studio and generate .so ? . This would be great if this happensNovel
Yes to do that, look at this link. #40369882 It's the simplest solutionJointless
can u please help me how should be my Android.mk file ? as per ur patternNovel
You don't need Android.mk file if you use the method in the link above. CMakeLists.txt is the only thing you needJointless
Hi! @th3pat3l I am also in same kind of problem, Can you please help me to solve it. here is the link: #44282189Sarmiento
@Broadcast can you help me use some ".a" static library in my project, or is there any post that helps me use a static library in my project. I was able to use a shared library (.so file) in my project, but i am unable to use static library (.a file).Mehta
There were additional details in this answer that helped me. Until I moved my .so files into the correct architecture folder, Gradle did not package them into my APK. #24358187Trictrac
@Broadcast I think you should mention in your answer that the compiled native libraries should be for the same architecture as the target android device, or native libraries should be packaged for every ABI that android supports. Most build systems build libraries for just the host architecture by default, so there's ample possibility for confusion here.Schwitzer
@Broadcast If I go with option 1 of the compiled .so file, how do I use it from inside my project?Turnage
H
2

From here

Opening shared libraries directly from an APK

In API level 23 and above, it’s possible to open a .so file directly from your APK. Just use System.loadLibrary("foo") exactly as normal but set android:extractNativeLibs="false" in your AndroidManifest.xml. In older releases, the .so files were extracted from the APK file at install time. This meant that they took up space in your APK and again in your installation directory (and this was counted against you and reported to the user as space taken up by your app). Any .so file that you want to load directly from your APK must be page aligned (on a 4096-byte boundary) in the zip file and stored uncompressed. Current versions of the zipalign tool take care of alignment.

Note that in API level 23 and above dlopen(3) will open a library from any zip file, not just your APK. Just give dlopen(3) a path of the form "my_zip_file.zip!/libs/libstuff.so". As with APKs, the library must be page-aligned and stored uncompressed for this to work.

Holoblastic answered 27/1, 2017 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.