Filnik
Filnik

Reputation: 138

NDK & Android Studio, compiling it crashes because of shared libraries

For code reusing I had to move some native code from the working directory to a shared library. This movement however causes a lot of troubles.

If I try to compile it in the old place, everything just clicks, instead if I try to compile it with the same data into the shared library foulder... it fails. No idea why.

Futhermore I can't even do it automatically with Android Studio because Android Studio for some weird reason doesn't recognize the ndk build command.

The .mk file is this:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := exam_filter
LOCAL_SRC_FILES := exam_filter.cpp
LOCAL_LDLIBS    := -lm -llog -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

And the error that I get when I try to compile it in the new foulder is:

ndk-build -C jni/
make: Entering directory `/home/fil/.../jni'
[armeabi] Compile++ thumb: exam_filter <= exam_filter.cpp
/home/fil/.../jni/exam_filter.cpp:4:28: fatal error: android/bitmap.h: No such file or directory
 #include <android/bitmap.h>
                            ^
compilation terminated.

Any idea? Thanks :)

Upvotes: 0

Views: 1258

Answers (1)

Filnik
Filnik

Reputation: 138

I post the guide that I have created for mantainance of how I fixed the problem. There may be some unrelated stuff, but they are still useful.

The main problem was that I had disabled the automatic building and that the name of the methods were slightly different. Furthermore, the error posted was caused by the fact that I wasn't targeting the APP_PLATFORM 8, as explained at the end.

Basic references:

The idea is that we have to match and compile the native methods to the java declarations. First of all there is a default foulder for the jni files. This foulder is in src/main/jniLibs. If you want to change that you can in this way:

sourceSets.main {
    jniLibs.srcDir 'src/main/libs'
}

Be careful not to use jni.srcDirs = [] otherwise the default jni compilation will be disabled and you have to do it by hand using tasks and other complicated stuff (there's no need for right now). There were also two .mk files... they will be just ignored since we have defined:

ndk {
    moduleName "exam_filter"
    ldLibs "log", "jnigraphics"
}

In the gradle file, that's the corresponding version for gradle. Every new change must be done both here and not using the makefiles. In order to make it work, every native function should match to every function declared in the java. To do so, it's better to automatically create the headers from the java. For this is useful to use javah in this way:

javah -classpath "/home/[...]/Android/Sdk/platforms/android-22/android.jar:./" -jni com.package.[...].NameOfTheClass

And this should be executed from src/main. Be careful that in windows the ":" before the ./ should be a ; instead (also the guides suggest the ; that in linux is wrong). In this way, you will get the header to copy and just use directly on your source code (in case you move functions or create new ones).

By hand

You can also compile by hand using this command:

ndk-build -C jni

However it won't work since the makefiles are missing. You should add an Android.mk file like this:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := exam_filter
LOCAL_SRC_FILES := exam_filter.cpp
LOCAL_LDLIBS := -lm -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)

And an Application.mk file like this:

APP_PLATFORM=android-8

However, there is no need now to do it by hand if you are using the automatic building by Android Studio.

Upvotes: 1

Related Questions