Привет, Хабралюди!
В процессе работы с Android NDK я столкнулся с проблемой сборки уже существующих Linux библиотек на Android NDK. Так как материала не слишком много в этой статье поделюсь своим опытом. В Андроиде я новичек, так что если найдете ошибки — пишите:)
Чтобы пример был не самым простым и при том полезным — возьмём библиотеку libFLAC. Этот даст возможность декодировать .flac файлы. По данному мануалу, я надеюсь, соберутся большинство других библиотек.
Кроме неё нам понадобится:
Создаём стандартный Android проект, в нем создаём папку jni и распаковываем туда libogg, libvorbis, libflac.
Приступим к первому этапу. Для сборки я использовал такой скрипт:
Для libVorbis придется его немного изменить:
LDFLAGS будет таким:
а LIBS:
Для libflac изменим добавим в libs -lvorbis.
Рассмотрим структуру скрипта по порядку. Строка export CC — путь к компилятору Android NDK. Тут: export LDFLAGS можем задавать директории, где искать библиотеки, а в LIBS подключать их. В этой строке: export CPPFLAGS подключаем headers дополнительных библиотек.
Выполняете нужные скрипты в корне каждой из библиотек. После сборки, если все прошло успешно вы получаете библиотеки, которые уже можно компилировать на NDK.
Итак, для начала создадим Android.mk, вида:
include $(all-subdir-makefiles)
В папках: jni, jni/libogg, jni/libflac, jni/libvorbis
Этот скрипт означает, что будут подключены все Android.mk в поддиректориях.
Для создания Android.mk в папках jni/libogg/src, jni/libvorbis/lib, jni/libflac/src будем использовать все Makefile.am в тех же папках.
В Makefile.am ищем строки:
libogg_la_SOURCES = framing.c bitwise.c — это все что нам надо. Получаем стандартный Android.mk вида:
Думаю тут объяснять ничего не надо. Идём дальше.
Тут тоже все просто. Находим строку: libvorbis_la_SOURCES и подулючаем все файлы, что там есть. Получаем такой Android.mk:
Процесс тот же, но файлов намного больше и они в поддиректориях. Я решил все что есть собрать в одну библиотеку, чтоб было проще, поэтому получил такой скрипт:
И последнее:
Выполняем ndk-build (этот скрипт находится в папке NDK) и видим что все компилируется, но flac даёт следующую ошибку:
Проблема в том, что константа VERSION определена в makefile, который мы не подключали. Самым простым выходом я вижу создать эту константу в самом format.c вот так:
Все теперь ошибок нет. При компиляции получаем:
В каталогах должны появится такие файлы и папки:

Теперь осталось последнее — протестировать все ли работает. Я переделал на скорую руку из стандартных примеров декодирования аудио через libflac. Декодировал из flac файла в wav. Так как код скрипт великоват вы можете протестировать работу на этом apk:тестовый apk файл
(чтоб все сработало, надо чтоб в sdcard был файл output.flac с:
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, он будет перекодирован в test2.wav. При работе программы ничего писать не будет (только в логи). Протестировано на эмуляторе, HTC Wildfire и Samsung galaxy tab (везде Android 2.2). Процесс занял не более минуты при работе с 20 мегабайтным flac файлом. По окончанию работы отобразится Hello world.
Вот исходники всего проекта:
исходники
Удачи!
В процессе работы с Android NDK я столкнулся с проблемой сборки уже существующих Linux библиотек на Android NDK. Так как материала не слишком много в этой статье поделюсь своим опытом. В Андроиде я новичек, так что если найдете ошибки — пишите:)
Чтобы пример был не самым простым и при том полезным — возьмём библиотеку libFLAC. Этот даст возможность декодировать .flac файлы. По данному мануалу, я надеюсь, соберутся большинство других библиотек.
Кроме неё нам понадобится:
- Android NDK, r5b (http://developer.android.com/sdk/ndk/index.html)
- libOgg (http://www.xiph.org/downloads/)
- libVorbis (там же, где и libOgg).
Создание проекта
Создаём стандартный Android проект, в нем создаём папку jni и распаковываем туда libogg, libvorbis, libflac.
Сборка
Приступим к первому этапу. Для сборки я использовал такой скрипт:
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
Для libVorbis придется его немного изменить:
LDFLAGS будет таким:
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/"
а LIBS:
export LIBS="-lc -logg"
Для libflac изменим добавим в libs -lvorbis.
Рассмотрим структуру скрипта по порядку. Строка export CC — путь к компилятору Android NDK. Тут: export LDFLAGS можем задавать директории, где искать библиотеки, а в LIBS подключать их. В этой строке: export CPPFLAGS подключаем headers дополнительных библиотек.
Выполняете нужные скрипты в корне каждой из библиотек. После сборки, если все прошло успешно вы получаете библиотеки, которые уже можно компилировать на NDK.
Подготовка Android.mk
Итак, для начала создадим Android.mk, вида:
include $(all-subdir-makefiles)
В папках: jni, jni/libogg, jni/libflac, jni/libvorbis
Этот скрипт означает, что будут подключены все Android.mk в поддиректориях.
Для создания Android.mk в папках jni/libogg/src, jni/libvorbis/lib, jni/libflac/src будем использовать все Makefile.am в тех же папках.
jni/libogg/src
В Makefile.am ищем строки:
libogg_la_SOURCES = framing.c bitwise.c — это все что нам надо. Получаем стандартный Android.mk вида:
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) #В данном примере собираем динамические библиотеки
Думаю тут объяснять ничего не надо. Идём дальше.
jni/libvorbis/lib
Тут тоже все просто. Находим строку: libvorbis_la_SOURCES и подулючаем все файлы, что там есть. Получаем такой 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
Процесс тот же, но файлов намного больше и они в поддиректориях. Я решил все что есть собрать в одну библиотеку, чтоб было проще, поэтому получил такой скрипт:
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)
И последнее:
NDK BUILD
Выполняем ndk-build (этот скрипт находится в папке NDK) и видим что все компилируется, но flac даёт следующую ошибку:
/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Проблема в том, что константа VERSION определена в makefile, который мы не подключали. Самым простым выходом я вижу создать эту константу в самом format.c вот так:
#define VERSION "1.2.1"Все теперь ошибок нет. При компиляции получаем:
Install : libFLAC.so => libs/armeabi/libFLAC.so
Install : libogg.so => libs/armeabi/libogg.so
Install : libvorbis.so => libs/armeabi/libvorbis.soВ каталогах должны появится такие файлы и папки:

Теперь осталось последнее — протестировать все ли работает. Я переделал на скорую руку из стандартных примеров декодирования аудио через libflac. Декодировал из flac файла в wav. Так как код скрипт великоват вы можете протестировать работу на этом apk:тестовый apk файл
(чтоб все сработало, надо чтоб в sdcard был файл output.flac с:
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, он будет перекодирован в test2.wav. При работе программы ничего писать не будет (только в логи). Протестировано на эмуляторе, HTC Wildfire и Samsung galaxy tab (везде Android 2.2). Процесс занял не более минуты при работе с 20 мегабайтным flac файлом. По окончанию работы отобразится Hello world.
Вот исходники всего проекта:
исходники
Удачи!
