使用少量本机代码即可轻松构建和使应用程序正常工作。如果要使用本机库,其中有许多文件,则变得更加困难。困难在于,本机库是以需要针对所需处理器体系结构进行编译的源代码的形式分发的。以Opus音频编解码器为例,我将向您展示如何做到这一点。
Opus , Android, Opus, . - .so .a, , C/C++ . . Opus , NDK .so .a, Android-.
, C/C++, . Opus (.a).
C , . #include <fileWithHeaders.h>. C , (.a), #include <fileWithHeaders.h> . (.so), . , , , .
.so . , Opus , Android, . libjniopus.so , libopus.a, libopus.so.
NDK c 19 « ». , . , , , . , .
Opus
: (git clone), . Opus Autoconf — , . Autoconf toolchain , ENV-. Autoconf, , Unix . Windows, , , .
4 .a : armeabi-v7a, arm64-v8a, x86, x86-64.
ENV-. NDK, HOST_TAG TOOLCHAIN. Linux, ENV- , export:
export NDK=/home/vital/Android/Sdk/ndk/20.1.5948944
export HOST_TAG=linux-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
ENV- , , . , . ENV- , .bashrc, (~). .bashrc. , , . ENV-, :
export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
export CC=$TOOLCHAIN/bin/aarch64-linux-android21-clang
export CXX=$TOOLCHAIN/bin/aarch64-linux-android21-clang++
export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld
export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip
export AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
export AS=$TOOLCHAIN/bin/arm-linux-androideabi-as
export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang++
export LD=$TOOLCHAIN/bin/arm-linux-androideabi-ld
export RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
export STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip
export AR=$TOOLCHAIN/bin/i686-linux-android-ar
export AS=$TOOLCHAIN/bin/i686-linux-android-as
export CC=$TOOLCHAIN/bin/i686-linux-android21-clang
export CXX=$TOOLCHAIN/bin/i686-linux-android21-clang++
export LD=$TOOLCHAIN/bin/i686-linux-android-ld
export RANLIB=$TOOLCHAIN/bin/i686-linux-android-ranlib
export STRIP=$TOOLCHAIN/bin/i686-linux-android-strip
export AR=$TOOLCHAIN/bin/x86_64-linux-android-ar
export AS=$TOOLCHAIN/bin/x86_64-linux-android-as
export CC=$TOOLCHAIN/bin/x86_64-linux-android21-clang
export CXX=$TOOLCHAIN/bin/x86_64-linux-android21-clang++
export LD=$TOOLCHAIN/bin/x86_64-linux-android-ld
export RANLIB=$TOOLCHAIN/bin/x86_64-linux-android-ranlib
export STRIP=$TOOLCHAIN/bin/x86_64-linux-android-strip
arm64-v8a, .bashrc ENV- . , CC CXX 21, Android API level. , , minSdkVersion. 21, , . NDK 16 29 32- ABI (armeabi-v7a x86) 21 29 64- ABI (arm64-v8a x86-64).
, ENV-, toolchain , Opus. Readme Opus , - :
$ ./autogen.sh
$ ./configure
$ make
. , 4 .
NDK r19 « » toolchains. , ENV- ( .bashrc), , . configure host. arm64-v8a :
$ source ~/.bashrc
$ ./autogen.sh
$ ./configure --host aarch64-linux-android
$ make
source ~/.bashrc , «» .
, Opus .libs. , libopus.a.
.bashrc /, ENV- armeabi-v7a, host:
$ source ~/.bashrc
$ ./configure --host armv7a-linux-androideabi
$ make
./autogen.sh , configure, .
make . , - . , , , , ( configure host). , , , , , .
. , Opus. , .
- 4 ENV- . , bash-, . :
#!/bin/bash
export NDK=/home/vital/Android/Sdk/ndk/20.1.5948944
export HOST_TAG=linux-x86_64
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
if [[ $# -ne 3 && $# -ne 2 ]]
then
echo "You should specify at least minSdkVersion and path to Opus directory"
echo "Example ./buildOpus.sh 21 <pathToOpusDir> <pathToBuildDir>"
exit
fi
minSdk=$1
opusPath=$2
if [[ $# -eq 3 ]]
then
buildPath=$3
else
buildPath=./opus_android_build
if [[ -d $buildPath ]]; then
echo "opus_android_build directory already existed..."
echo "clearing opus_android_build directory..."
rm -rfv $buildPath && mkdir $buildPath
else
echo "creating opus_android_build directory..."
mkdir opus_android_build
fi
fi
echo "Executing autogen.sh"
$opusPath/autogen.sh
if [[ $minSdk -lt 21 ]]
then
triples=("armv7a-linux-androideabi" "i686-linux-android")
abis=("armeabi-v7a" "x86")
else
triples=("aarch64-linux-android" "armv7a-linux-androideabi" "i686-linux-android" "x86_64-linux-android")
abis=("arm64-v8a" "armeabi-v7a" "x86" "x86-64")
fi
BIN=$TOOLCHAIN/bin
cd $buildPath
for i in ${!triples[@]}
do
triple=${triples[$i]}
abi=${abis[$i]}
echo "Building $abi..."
if [[ $triple == "armv7a-linux-androideabi" ]]
then
export AR=$BIN/arm-linux-androideabi-ar
export AS=$BIN/arm-linux-androideabi-as
export CC=$BIN/$triple$minSdk-clang
export CXX=$BIN/$triple$minSdk-clang++
export LD=$BIN/arm-linux-androideabi-ld
export RANLIB=$BIN/arm-linux-androideabi-ranlib
export STRIP=$BIN/arm-linux-androideabi-strip
else
export AR=$BIN/$triple-ar
export AS=$BIN/$triple-as
export CC=$BIN/$triple$minSdk-clang
export CXX=$BIN/$triple$minSdk-clang++
export LD=$BIN/$triple-ld
export RANLIB=$BIN/$triple-ranlib
export STRIP=$BIN/$triple-strip
fi
mkdir $abi && cd $abi
$opusPath/configure --host $triple
make
cd ..
done
echo "Artifacts successfully built for minSdkVersion=$minSdk and ABIs:"
printf '%s ' "${abis[@]}"
echo ""
echo "Artifacts are located in .libs directory"
, ENV- .bashrc , .
, :
$ sudo chmod +x buildOpus.sh
NDK HOST_TAG, Linux ( linux-x86_64):
- 32-bit Windows: windows
- 64-bit Windows: windows-x86_64
- macOS: darwin-x86_64
:
$ ./buildOpus.sh 21 <pathToOpusDir> <pathToBuildDir>
minSdkVersion Opus. , . opus_android_build , buildOpus.sh.
. opus_android_build , , ABI, . , .libs, .
, 4 libopus.a , . Android- CmakeLists.txt, .so Opus.
app/src/main/cpp, C- (jniopus.c), external Kotlin. includes. include Opus. (.h). Opus C-. , , .
app/src/main/cpp libopus, 4 , ABI, Opus: armeabi-v7a, arm64-v8a, x86, x86-64. libopus.a, .
CmakeLists.txt, , Opus . «» . :
set(NATIVE_SOURCES_PATH "${PROJECT_SOURCE_DIR}/src/main/cpp")
set(OPUS_HEADERS_PATH "${NATIVE_SOURCES_PATH}/includes")
set(OPUS_LIB_PATH "${NATIVE_SOURCES_PATH}/libopus")
Opus :
add_library(
libopus
STATIC
IMPORTED)
add_library . , , STATIC(.a) SHARED(.so) , IMPORTED, . () :
set_target_properties(
libopus PROPERTIES
IMPORTED_LOCATION "${OPUS_LIB_PATH}/${ANDROID_ABI}/libopus.a")
ANDROID_ABI NDK toolchain , ABI.
-, external Kotlin, :
add_library(
jniopus
SHARED
${NATIVE_SOURCES_PATH}/jniopus.c)
, « » NDK :
find_library(
log-lib
log)
:
target_link_libraries(
jniopus
libopus ${log-lib})
, , . , Gradle, Run, . , Start call . , , .
, NDK toolchains ABI . , CmakeLists.txt . , Autoconf , pre-19 NDK, . , , .
« Android»: https://vk.com/@forasoft-kak-ispolzovat-nativnye-biblioteki-v-android
: https://gitlab.com/vitaliybelyaev/opus-android
Opus codec: http://opus-codec.org/, https://github.com/xiph/opus
Using the NDK with other build systems: https://developer.android.com/ndk/guides/other_build_systems
Android- CMake: https://developer.android.com/studio/projects/add-native-code#create-cmake-script
ABI Android: https://developer.android.com/ndk/guides/abis