Accessing headers for NDK from Android Library Project - android

I'm currently implementing a custom Logging mechanism that I need to be accessible from both native and Java code. The fundamentals of the logging are implemented in C/C++ with a Java wrapper, and the two together are being built as an android Library Project.
The issue at hand is that while my Java code can access the Library project output, there doesn't seem to be a way for my native code to access the native .so or headers from the Library project. Is there an additional step I'm missing or is this just a limitation of the current ADT? More specifically, is there a makefile/eclipse configuration that will address the things I'm used to getting out of Library projects in general? (Build .so as needed, import rebuilt .so, import relevant headers for c/c++ compilation, etc.)

I don't think it's a limitation. We are supposed to declare native code dependencies in Android.mk and Application.mk

Worked out a way to get what I wanted - most of the information is (of course) in the NDK documentation, but what I was trying to do isn't 100% supported within the ADT. It should also be noted that I'm currently stuck developing in a windows environment, so much of this might be easier or unnecessary in Linux. The first key is the $(call import-module ...) macro. Within your library project, move the source files and the Android.mk folder into a named directory you can locate later. My Library project directory looked like this:
MyProject
> src
> res
v jni
- Application.mk
v MyLib
- source.cpp
- source.h
- Android.mk
I also had to edit my Application.mk to point to the project:
APP_PROJECT_PATH := <path-to-my-project>
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/jni/MyProject/Android.mk
Annoyingly, this broke my Android.mk in ways unforseen until I added a ./ to my source files. Also you need to export your includes for linking:
LOCAL_SRC_FILES := ./source.cpp
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
Ensure that the system path variable NDK_MODULE_PATH is set to include your library's JNI directory, e.g. <path-to-my-project>/jni (Note: I had to restart eclipse after I did this).
In the receiving application's Android.mk file (the one you'd like to link natively to your app), import the module:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyNativeProject
LOCAL_SRC_FILES := source.cpp
LOCAL_CFLAGS := -DANDROID_NDK -g -std=c99
LOCAL_SHARED_LIBRARIES := MyLib
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
$(call import-module, IntelLog)
At this point everything built perfectly, but the APK packager didn't like the generated .so binary being included twice (once from the Library project's natural import process, and again from the import-module call). To solve this, clean the library and don't build it again! the import-module call will build the .so and import it into your project. (Obviously, if your project only requires the Java API, you would need that .so file to be built). Congratulations! you have a functional (if not straightforward) build process with a hybrid native/Java Library

Related

How to integrate libcurl in native android project and build using ndk on windows?

I want to use libcurl in my native project. How can I integrate this library and build using ndk? Is there any post available that can guide me through the process?
I tried the docs from official site, but that's not working. FYI I am on windows platform.
Create a JNI folder within your project and add a folder for each architecture(arm, armv7,x86 etc). Place the corresponding libcurl.so files in the respective folders. Since this is a rebuilt shared binary you need to add this to your Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := <Curl> //add the module name here.
LOCAL_SRC_FILES := <libCurl.so> //add the .so file name here
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jni/include
include $(PREBUILT_SHARED_LIBRARY)
Create a JNI C file that uses the libraries from Curl and call the native code from Java source.
static {
System.loadLibrary("curl");
}
It shouldnt make a difference if you are on Windows platform. Adding open source liv files to Android NDK is pretty much the same process on all platforms.
No idea about windows, but as to the linker magic, see the links in
Integrating MuPDF as a library project (Android)

android ndk communicate different c++ project

I want to create a c++ project for android ndk.And I want to use it every project like dynamic library.I dont want to change /transport source code every time.I import *.so file and include it and use its class or whatever.
This is possible.If it possible how could import and use it.
Or i create java project and i use it to communicate c++ project with using jni and i compile it.After that i have a *.jar file and i use it instead of android ndk.
Which one of them possible or effective.
I'm not entirely sure if I understood the question correctly, but I assume you prefer to write your Android applications using solely/mostly C++ and have a core library/module that you want to re-use for every consecutive project WITHOUT including that libraries SOURCE files in each consecutive project.
You can omit including the source files and include the final built .so file in your new project by adding the required libraries into your makefile. Like so:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for libraryname)
LOCAL_MODULE := libraryname
LOCAL_SRC_FILES := libraryname.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
--- instructions for custom application code here ---
LOCAL_SHARED_LIBRARIES := libraryname
Where "libraryname" is the name of the library module and "libraryname.so" is the name of the library file. Note the path should be relative to the make file. Below the second "include $(CLEAR_VARS)" and above the final "LOCAL_SHARED_LIBRARIES" you add the instructions for building the source code of the application which is to use the shared library.
Don't forget to load all libraries in order on the Java side, i.e.:
System.loadLibrary( "libraryname" );
System.loadLibrary( "customlib" );

How to build multiple projects in the correct dependency order with Android NDK?

I have a series of existing libraries which I need to re-use in an Android application. The layout is similar to:
\Libraries\libOne
\Libraries\libTwo [Static library]
\Libraries\libThree
\Applications\MyApplication\ [Application]
libTwo depends on libOne, and libThree depends on libTwo. How can I get the build system to build all of the libraries in the correct order? I'm trying to use Eclipse, but if necessary I can use the command line.
All of these libraries will eventually be referenced by a Java application (and use JNI to interact with them). Any clues on how I setup the Android.mk / Application.mk files?
I've tried using BUILD_STATIC_LIBRARY for libTwo, but it doesn't actually output any files! I was expecting a libTwo.a file, but nothing gets compiled or built.
Do I write one Android.mk in the application? Or an Android.mk for each project?
OK, now I see your edit, and this makes it possible to answer the specific question.
You must have at least one Android.mk file for your application if you want to use Android NDK to build your native library/ies. This is not a requirement, though. It is OK to build it though Cmake, or a "standalone toolchain" with "traditional" makefiles, or with a MS Visual Studio plugin, or any other way. It is the result that matters. The result is a shared object built with a compatible compiler for a bionic runtime.
It makes goode sense to put the library in ${project_root}/libs/armeabi/ directory (for ARM v6 compatible devices, other subdirectories for x86, MIPS, arm v7a) to allow the APK builder pack it correctly, to allow app installer to unpack the correct version (compatible with the device processor) into /data/data/${package_name}/lib directory on the device, and finally to be able to use System.loadLibrary(short_name) to use it from Java. But it is also quite possible to pack the so file differently, unpack it manually, and load it from any place on the device file system (provided your app has permission to write and read this file).
But if we filter out exotic cases, it is much more comfortable to have an Android.mk in the ${project_root}/jni directory. In terms of ndk-build command, each library is a separate MODULE, but all three may be defined in one Android.mk file. On the other hand, if your libraries are isolated (e.g. come from separate 3rd parties), you will probably prefer to create three Android.mk files. Luckily, ndk-build is nothing but a wrapper around gnu make, and the simple include statement in Android.mk works as in any other makefiles.
In summary, your case is probably covered by a simple Applications/MyApplication/ [Application]/jni/Android.mk file:
include ../../Libraries/libOne/Android.mk
include ../../Libraries/libTwo/Android.mk
include ../../Libraries/libThree/Android.mk
I don't know what dependency you have between libOne and libTwo, but for libOne the file Libraries/libOne/Android.mk will look like
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
and Libraries/libThree/Android.mk
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
You should run ndk-build from Applications/MyApplication/ [Application] directory - either from command prompt, or through Eclipse ADT plugin.
update the same may be expressed by one Android.mk file in jni directory:
LOCAL_PATH = ../../Libraries/libOne
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH = ../../Libraries/libThree
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
There is an android section in the projects' properties, where you can edit the library dependencies. It can only be used, if libOne libTwo and libThree are marked as libraries, in their properties panel.

Copy files to libs folder as a part of build script

I have an android application which uses jni and I'm trying to automate build process in Eclipse (using cdt plugin). I need to build my own static library, and I also need to use some precompiled libraries.
That means that I need to
a) build my own shared library (no problems here)
b) after build is complete, copy existing libraries into libs/armeabi folder (because this folder will be cleared during build process I must copy those files after every build)
I have some problems with b). What I'm trying to do is I'm inserting custom shell script (which works when executed as-is) after include $(BUILD_SHARED_LIBRARY) in Android.mk file. Unfortunately, this doesn't work, because apparently /libs/armeabi folder gets cleared only after Android.mk file is complete.
Is that true? Is there a way to insert post-build script into Android.mk? Is there any way I can execute bash script after jni code finished building but before whole build is complete (e.g. before java part is build and application starts executing?)? I though there must be some kind of "post-build" script in eclipse c/c++ project build settings, but there is no such thing.
Here's the complete Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_MODULE := player
LOCAL_SRC_FILES := player.c
include $(BUILD_SHARED_LIBRARY)
$(shell ./copy-libs.sh) #this script will get called, but the files will be erased right after
Well, it looks like there is an easier way to copy .so and .a libs without resorting to custom build scripts.
NDK supports prebuilt modules starting from ndk-r5, and they allow to copy .a or .so libraries into obj/lib folder during build process as needed.
Example and complete description are available in PREBUILTS.html file inside $NDK_INSTALLATION_FOLDER/docs/.

How to package prebuilt shared library inside an APK

This question seems to have been asked a lot but all were trying to use eclipse to package the library inside the APK.
However, my requirement is to package the library inside the APK (which will later be loaded using System.loadLibrary() through Java) using the Android build system, i.e. i want to write an Android.mk file that does this job.
Requirement:
1. Prebuilt shared library: libTest.so
2. Write an Android.mk file that will package this to libs/armeabi-7 inside the apk.
I don't know much about the build system I am using but the compilation is done using "mm" command after exporting the required environment variables.
When I provide libTest for LOCAL_JNI_SHARED_LIBRARIES, it tries to find it inside its exported paths and fails to find it there and hence build fails.
Can anyone please give any pointers on writing an Android.mk file that will package my prebuild shared library into the APK?
In order to prebuild your native library you have to
Create jni folder in your project folder
Create libs folder in your project folder
Add Adnroid.mk make file to the jni folder, it should looks like
this:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
Note 1: Test.cpp is the main library source file containing implementation of native methods. You can add more sources as a space separated list.
Note 2: Do not include headers, they are included automatically.
Note 3: If you need to enable C++ STL, then create another make file - Application.mk, add it to the jni folder and set APP_STL := stlport_static flag in it.
Then you will have to set up a builder. Refer to this article for how to do that:
After these steps, the builder will create your library in the libs folder which will be automatically packed into the apk when building the whole application.
Note: Your library name should be lowercase, it is a Linux convention. The "lib" prefix will be automatically added, so the final library name will be libtest.so.
Let's say there is one libxxx.so shared library under libs/armeabi/ of project which you want to pack into apk. There are 2 things you need to do in the Android.mk as below:
# 1. Copy .so to out/target/product/***/obj/lib
$(shell cp $(wildcard $(LOCAL_PATH)/libs/armeabi/*.so $(TARGET_OUT_INTERMEDIATE_LIBRARIES))
# 2. Make libxxx to be packed into apk
LOCAL_JNI_SHARED_LIBRARIES := libs/libxxxx
Then you can use apktool to unpack the built apk, you will find the libxxx.so will be located in libs/armeabi*/. It is indeed packed into the apk.
I had two LOCAL_JNI_SHARED_LIBRARIES that I wanted to build into my APK. I manage to do it by setting the following in my Android.mk:
LOCAL_MODULE_TAGS := samples
After re-compiling the module I was able to find both libraries inside the .apk under /lib/.

Categories

Resources