1

I have recently started working with NDK and am stuck with a problem. I basically want to use an external static library (.so) into my application. Here's what I've tried till now.

Create a library

1) Add a method in the Java class with native keyword

public native static void FibNR ();

2) In the terminal navigate to the project folder and run the following command

    mkdir jni
    javah -jni -classpath bin/classes/ -d jni/ com.example.fibonaccinative.FibLib

3) Refresh project and add a C file corresponding to the generated H file.

4) Create a Android.mk file in the JNI folder and add the following code in it

LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    OPENCV_LIB_TYPE :=STATIC
    LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.c
    LOCAL_MODULE := com_example_fibonaccinative_FibLib
    include $(BUILD_SHARED_LIBRARY)

5) Build the code using the following command

/Developer/android-ndk-r9b/ndk-build all

The above steps execute successfully and I'm able to view the results of the c code also. Now I want to create a new application and use the generated .so file (com_example_fibonaccinative_FibLib.so) into it. For this I do the following

Use the library

follow steps 1, 2 and 3 from above for the new application

4) Create a Android.mk file in the JNI folder and add the following code in it

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
LOCAL_LDLIBS := -L$(SYSROOT)/usr -llog
include $(BUILD_SHARED_LIBRARY)

5) Build the code using the following command

/Developer/android-ndk-r9b/ndk-build all

I'm not sure what to do next. What I think is I need to call the function of the library into com_example_usingstaticlibrary_LibraryTest.c. But doing so gives me an error saying

'com_example_fibonaccinative_FibLib' undeclared



EDIT 1:

1) In project 2 (where I want to use the Prebuilt Shared Library (.so)) I copied the library into the 'jni' folder

2) Changed the Android.mk file with the below text.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
include $(BUILD_SHARED_LIBRARY)

3) Added the .h file from the old project (com_example_fibonaccinative_FibLib.h) into the 'jni' folder

4) Changed the source of com_example_usingstaticlibrary_LibraryTest.c to

#include "com_example_usingstaticlibrary_LibraryTest.h"
#include "com_example_fibonaccinative_FibLib.h"

JNIEXPORT jlong JNICALL Java_com_example_usingstaticlibrary_LibraryTest_callLibraryFunction
(JNIEnv *env, jclass class) {
    Java_com_example_fibonaccinative_FibLib_fibNR(env, class, 500l);
    return -500l;
}

Clean/Build results into the following error

undefined reference to 'Java_com_example_fibonaccinative_FibLib_fibNR'


Edit 2:

With reference to this I've edited the Android.mk as follows

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)

The NDK build command compiles the code without error. When trying to load the library it gives the following error

Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/usingstaticlibrary/LibraryTest

When I remove LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib it works fine but I cannot use any function of the Prebuilt shared library.



Edit 3:

I tried a few more things including the suggestion by @jcm but nothing worked. I'm now attaching the source code. It has both the projects (Cleaned version to reduce size).

  1. FibonacciNative: Contains the first project.
  2. UsingStaticLibrary: Contains the second project. I intend to use the Prebuilt Shared Library of the first project into the second one.
Sahil Khanna
  • 4,262
  • 8
  • 47
  • 72

2 Answers2

4

You say you want to include a precompiled static library .a, but the file you reference is a shared library .so. If you still want to include a static library, here comes the solution and explanation:

LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so

You're trying to include the static library as a shared one, looks like an accidental slip from using the previous shared library entry as reference :).

Upon that, Android makefiles still requires you to actually make a module for the external library.

include $(CLEAR_VARS)
LOCAL_MODULE    := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.a
include $(PREBUILT_STATIC_LIBRARY)

Then you can simply add it as a dependency:

LOCAL_STATIC_LIBRARIES := com_example_fibonaccinative_FibLib

But if you're actually trying to include an external shared library. You would need to change the above to the following:

include $(CLEAR_VARS)
LOCAL_MODULE    := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)

and include it as a shared library.

LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib

Hope I helped!

Disclaimer: I have not actually tried to compile an example, simply referencing my knowledge and quick research.

References: Android NDK: Static library used is different than precompiled library specified

Community
  • 1
  • 1
  • Thanks for the good explanation. You helped me understanding lots of basic stuff which I had ignored earlier. I have updated the post with the changes you had explained. Can you please see "Edit 1" and correct me.. – Sahil Khanna Dec 06 '13 at 09:35
  • Java_com_kochartech_fibonaccinative_FibLib_fibNR is the function that was created as the native function in project 1. – Sahil Khanna Dec 06 '13 at 09:37
  • If you wan't to attach a header file which actually belongs to the library (.so). You should add LOCAL_EXPORT_C_INCLUDES := com_kochartech_usingstaticlibrary_LibraryTest.h before include $(PREBUILT_SHARED_LIBRARY) . This will cause the other library (which has the module as a dependency) to automaticly include the header file in it's build. – Patrick Engström Dec 06 '13 at 21:55
  • You should also read this [answer](http://stackoverflow.com/a/6166046/1103764) for some more details about the placement of the .so file. Which now occurs to me, seems to be the actual reason for your error (a bit hasty reading). Good luck! The JNI experience is not really pleasant. – Patrick Engström Dec 06 '13 at 22:00
  • I read the answer you had pointed to with a couple of more blogs, but nothing worked out. Please check "Edit 2" – Sahil Khanna Dec 07 '13 at 09:33
  • I think @jcm stated the solution to this problem in his answer, if that doesn't work for you, bake a zip-file with your test project for me and i'll give it a try! – Patrick Engström Dec 08 '13 at 20:48
1

As you're including libcom_example_fibonaccinative_FibLib.so as LibraryTest's shared library, in your java static method, you should load it before loading LibraryTest:

System.loadlibrary(com_example_fibonaccinative_FibLib);
System.loadLibrary(LibraryTest);

Update:

After checking your code, LibraryTest.java should look like:

package com.kochartech.usingstaticlibrary;

public class LibraryTest {

    public native static long callLibraryFunction();

    static {
        System.loadLibrary("com_kochartech_fibonaccinative_FibLib");
        System.loadLibrary("com_kochartech_usingstaticlibrary_LibraryTest");
    }

}
jcm
  • 2,568
  • 14
  • 18
  • @Sahil I modified what I told you and I've your code running. Please, check the update. – jcm Dec 09 '13 at 10:35