📜 ⬆️ ⬇️

Build open-source libraries on Android NDK

Hi, Habraludy!

In the process of working with the Android NDK, I was faced with the problem of building existing Linux libraries on the Android NDK. Since the material is not too much in this article I will share my experience. I'm new to Android, so if you find mistakes, write :)

So that the example is not the easiest and yet useful - take the libFLAC library. This will give the opportunity to decode .flac files. According to this manual, I hope most of the other libraries will gather.

In addition to her, we will need:

Creating a project

')
Create a standard Android project, create a jni folder in it and unpack libogg, libvorbis, libflac there.

Assembly



We proceed to the first stage. To build, I used the following script:

PREBUILT=/home/user/android-ndk-r5b/toolchains/arm-eabi-4.4.0 PLATFORM=/home/user/android-ndk-r5b/platforms/android-3/arch-arm export CC="/home/user/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/bin/arm-eabi-gcc" export CFLAGS="-fPIC -DANDROID -nostdlib" export ANDROID_ROOT="/home/user/android-ndk-r5b" export LDFLAGS="-Wl,-rpath-link=$ANDROID_ROOT/platforms/android-3/arch-arm/usr/lib/ -L$ANDROID_ROOT/platforms/android-3/arch-arm/usr/lib/" export CPPFLAGS="-I$ANDROID_ROOT/platforms/android-3/arch-arm/usr/include/" export LIBS="-lc " ./configure --host=arm-eabi 


For libVorbis, you'll have to change it a bit:
LDFLAGS will be like this:
 export LDFLAGS="-Wl,-rpath-link=$ANDROID_ROOT/build/platforms/android-3/arch-arm/usr/lib/ -L$ANDROID_ROOT/build/platforms/android-3/arch-arm/usr/lib/ -L../../libs/armeabi/" 

and LIBS:
 export LIBS="-lc -logg" 


For libflac we will change add libs -lvorbis.

Consider the structure of the script in order. The export CC string is the path to the Android NDK compiler. Here: export LDFLAGS we can set the directories where to look for the libraries, and connect them in LIBS. In this line: export CPPFLAGS we connect additional libraries headers.

Execute the necessary scripts in the root of each library. After the build, if everything went well, you get libraries that you can already compile on the NDK.

Preparing Android.mk



So, first create an Android.mk, like this:
include $ (all-subdir-makefiles)
In folders: jni, jni / libogg, jni / libflac, jni / libvorbis
This script means that all Android.mk in the subdirectories will be connected.

To create Android.mk in jni / libogg / src, jni / libvorbis / lib, jni / libflac / src folders, we will use all Makefile.am in the same folders.
jni / libogg / src

In the Makefile.am look for the lines:
libogg_la_SOURCES = framing.c bitwise.c is all we need. We get the standard Android.mk of the form:
 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libogg LOCAL_C_INCLUDES := $(LOCAL_PATH) \ $(LOCAL_PATH)/../include/ LOCAL_SRC_FILES := framing.c bitwise.c include $(BUILD_SHARED_LIBRARY) #      

I think there is nothing to explain here. Go ahead.
jni / libvorbis / lib

Here, too, everything is simple. We find the line: libvorbis_la_SOURCES and subnet all the files that are there. We get the following Android.mk:
 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libvorbis LOCAL_C_INCLUDES := $(LOCAL_PATH) \ $(LOCAL_PATH)/../include \ $(LOCAL_PATH)/../../libogg/include # headers libogg LOCAL_SRC_FILES := mdct.c smallft.c block.c envelope.c window.c lsp.c \ lpc.c analysis.c synthesis.c psy.c info.c \ floor1.c floor0.c\ res0.c mapping0.c registry.c codebook.c sharedbook.c\ lookup.c bitrate.c\ LOCAL_SHARED_LIBRARIES := libogg #    LOCAL_LDLIBS := -ldl -lGLESv1_CM -llog include $(BUILD_SHARED_LIBRARY) 

jni / libflac / src

The process is the same, but the files are much larger and they are in subdirectories. I decided to collect all that is in one library to make it easier, so I got the following script:
 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libFLAC LOCAL_C_INCLUDES := $(LOCAL_PATH)/libFLAC/include/ \ $(LOCAL_PATH)/../include/ \ $(LOCAL_PATH)/../../libogg/include/ \ $(LOCAL_PATH)/../../vorbis/include/ \ $(LOCAL_PATH)/share/include/ \ $(LOCAL_PATH)/share/utf8/ \ $(LOCAL_PATH)/../include/ \ $(LOCAL_PATH)/../include/share/ \ $(LOCAL_PATH)/share/replaygain_synthesis/include/ \ $(LOCAL_PATH)/../../libogg/include/ \ $(LOCAL_PATH)/../../vorbis/include/ \ $(LOCAL_PATH)/metaflac/include/ \ $(LOCAL_PATH)/../include/ \ $(LOCAL_PATH)/../include/share \ $(LOCAL_PATH)/../../libogg/include/ \ $(LOCAL_PATH)/../../vorbis/include/ \ $(LOCAL_PATH)/flac/ \ $(LOCAL_PATH)/../include/ \ $(LOCAL_PATH)/../../libogg/include/ \ $(LOCAL_PATH)/../../vorbis/include/ \ LOCAL_SRC_FILES := libFLAC/bitmath.c \ libFLAC/bitreader.c \ libFLAC/bitwriter.c \ libFLAC/cpu.c \ libFLAC/crc.c \ libFLAC/fixed.c \ libFLAC/float.c \ libFLAC/format.c \ libFLAC/lpc.c \ libFLAC/md5.c \ libFLAC/memory.c \ libFLAC/metadata_iterators.c \ libFLAC/metadata_object.c \ libFLAC/stream_decoder.c \ libFLAC/stream_encoder.c \ libFLAC/stream_encoder_framing.c \ libFLAC/window.c \ libFLAC/ogg_decoder_aspect.c \ libFLAC/ogg_encoder_aspect.c \ libFLAC/ogg_helper.c \ libFLAC/ogg_mapping.c \ share/getopt/getopt.c share/getopt/getopt1.c \ share/grabbag/cuesheet.c \ share/grabbag/file.c \ share/grabbag/picture.c \ share/grabbag/replaygain.c \ share/grabbag/seektable.c \ share/replaygain_analysis/replaygain_analysis.c \ share/replaygain_synthesis/replaygain_synthesis.c \ share/utf8/charset.c share/utf8/iconvert.c share/utf8/utf8.c \ metaflac/main.c \ metaflac/operations.c \ metaflac/operations_shorthand_cuesheet.c \ metaflac/operations_shorthand_picture.c \ metaflac/operations_shorthand_seektable.c \ metaflac/operations_shorthand_streaminfo.c \ metaflac/operations_shorthand_vorbiscomment.c \ metaflac/options.c \ metaflac/usage.c \ metaflac/utils.c \ flac/analyze.c \ flac/decode.c \ flac/encode.c \ flac/foreign_metadata.c \ flac/local_string_utils.c \ flac/utils.c \ flac/vorbiscomment.c \ LOCAL_SHARED_LIBRARIES := libogg libvorbis LOCAL_LDLIBS := -ldl -lGLESv1_CM -llog include $(BUILD_SHARED_LIBRARY) 

And the last:

NDK BUILD



We execute ndk-build (this script is in the NDK folder) and see that everything compiles, but flac gives the following error:
/home/user/workspace/w/testOGG/jni/flac-1.2.1/src/libFLAC/format.c:60: error: 'VERSION' undeclared here (not in a function)
/home/user/workspace/w/testOGG/jni/flac-1.2.1/src/libFLAC/format.c:66: error: expected ',' or ';' before 'VERSION'
make: *** [/home/user/workspace/w/testOGG/obj/local/armeabi/objs/FLAC/libFLAC/format.o] 1

The problem is that the VERSION constant is defined in a makefile that we did not connect. The easiest way out is to create this constant in format.c itself like this:
#define VERSION "1.2.1"
Everything is now no errors. When compiling we get:
Install : libFLAC.so => libs/armeabi/libFLAC.so
Install : libogg.so => libs/armeabi/libogg.so
Install : libvorbis.so => libs/armeabi/libvorbis.so

The following files and folders should appear in the directories:
image
Now the last thing left is to test whether everything works. I rewrote a quick example of standard audio decoding via libflac. Decoded from flac file in wav. Since the script code is too large, you can test the work on this apk: test apk file
(so that everything works, it is necessary that the output.flac file in sdcard is with:
05-20 14: 18: 42.783: INFO / FLAC (427): sample rate: 44100 Hz
05-20 14: 18: 42.783: INFO / FLAC (427): channels: 2 Hz
05-20 14: 18: 42.783: INFO / FLAC (427): bits: 16 Hz, it will be recoded to test2.wav. When the program is running, nothing will be written (only in the logs). Tested on the emulator, HTC Wildfire and Samsung galaxy tab (everywhere Android 2.2). The process took less than a minute when working with a 20 megabyte flac file. At the end of the work, Hello world is displayed.
Here are the sources of the entire project:
source code
Good luck!

Source: https://habr.com/ru/post/119693/


All Articles