Включить предварительно скомпилированную статическую библиотеку с использованием NDK
Я хочу включить статическую библиотеку, которая предварительно скомпилирована в моем проекте Android Studio NDK. Я использую Android Studio 1.0.1, и любые решения, которые пытаются решить эту проблему на SO, выглядят устаревшими (или связаны с созданием проекта библиотеки и включая его).
Структура выглядит следующим образом:
app
/--src
/--main
/--java
+--jni
+--jniLibs
/--armeabi
/--libpng.a
--armeabiv7
/--libpng.a
...(for each abi)
Я пытаюсь включить библиотеку libpng. Я попытался создать jniLibs (согласно ph0b (удивительный гид, кстати) и добавление libpng.a в соответствующую папку ABI. Это все еще дает мне ошибку - не может найти -llibpng, когда я пытаюсь скомпилировать код ниже:
ndk {
moduleName "game"
cFlags "-std=c++11 -fexceptions -DANDROID -I${project.buildDir}/../src/main/jni/include \
-I${project.buildDir}/../src/main/jni/include/png"
ldLibs "EGL", "GLESv3", "dl", "log", "android", "libpng"
stl "gnustl_static"
}
Ответы
Ответ 1
Теперь это работает правильно через экспериментальный плагин.
Полное описание см. в всей этой замечательной статье, из которой я беру это, но я также сам ее использую и он работает.
Это мой build.gradle
- обратите внимание, что в моем случае это для проекта библиотеки, и я использую статические ссылки, а не общие.
buildscript {
dependencies
{
classpath "com.android.tools.build:gradle-experimental:0.7.0-alpha3"
}
}
apply plugin: 'com.android.model.library'
model {
repositories {
libs(PrebuiltLibraries) {
v8_base {
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_base.a")
}
}
v8_libbase {
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libbase.a")
}
}
v8_libplatform {
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libplatform.a")
}
}
v8_nosnapshot {
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_nosnapshot.a")
}
}
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
sources {
main {
jni {
source {
srcDir "src/main/jni"
}
dependencies {
library "v8_base" linkage "static"
library "v8_libbase" linkage "static"
library "v8_libplatform" linkage "static"
library "v8_nosnapshot" linkage "static"
}
}
}
}
ndk {
moduleName "v8example"
cppFlags.add("-std=c++11")
cppFlags.add("-I${file("src/main/jni/include")}".toString())
cppFlags.add("-fexceptions")
ldLibs.add("log")
stl "stlport_static"
abiFilters.add("armeabi armeabi-v7a x86")
}
}
}
Альтернативой является то, что вы используете старый метод Gradle для вызова ndkBuild самостоятельно, используя при этом файлы .mk
. Это также отлично работает, но вы теряете хорошую интеграцию с Android Studio, например. ваши файлы jni
отображаются соответствующим образом.
Ответ 2
Добавление .so Library в Android Studio 1.0.2
- Создать папку "jniLibs" внутри "src/main/"
- Поместите все ваши библиотеки .so внутри папки "src/main/jniLibs"
- Структура папки выглядит,
| --app:
| - | --src:
| - | - | --main
| - | - | - | --jniLibs
| - | - | - | - | --armeabi
| - | - | - | - | - | - | -.
- Никакой дополнительный код не требует просто синхронизации вашего проекта и запуска вашего приложения.
Ссылка
https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main
Ответ 3
Поскольку поддержка ndk теперь ограничена в gradle, вы можете попробовать это для статических библиотек разных abi.
ndk {
moduleName "game"
....
ldLibs ..., file(projectDir).absolutePath+"/src/main/jniLibs/\$(TARGET_ARCH_ABI)/libpng.a"
....
}
Ответ 4
вы не можете просто включать файлы .so, вам также нужно иметь папки src, которые фактически предоставляют интерфейс для доступа к методам в этих .so файлах. Я бы рекомендовал не связывать ваш проект с библиотекой таким образом.
Лучший способ - включить его в качестве библиотечного модуля из студии android и отбросить jni-папки для отключения ndkbuild и указать jnilib в папку /libs, добавив следующее в файл build.gradle
jni.srcDirs = [] //disable automatic ndk-build call
jniLibs.srcDirs = [ 'libs' ] //no need to copy the .so files from /libs to /jniLibs folder
(проверьте, что каталог libs также был правильно импортирован с помощью студии android с .so файлами)
импортирование библиотеки в качестве модуля автоматически отслеживает
a) папка библиотеки yourlibrary в папке проекта и реструктурирована в соответствии с gradle конвенцией б) импортировал проект (включая ': yourlibrary' в settings.gradle) и
c) создала зависимости ( "Файл → Структура проекта → Выберите основной модуль приложения из левого нижнего окна → Зависимости (последняя вкладка) → Нажмите зеленый" + "справа → ваша библиотека в качестве зависимости от модуля → OK" )
Ответ 5
Это действительно уродливо, но оно работает! Вы можете обмануть Gradle, чтобы вы могли вводить код в сгенерированный файл Android.mk:
ndk {
abiFilter "armeabi-v7a"
// We need to inject the static library into the
// NDK build, and Gradle doesn't offer a way to directly
// modify the Android.mk file... So we hack it!
//
// You can see the end result at:
// build/intermediates/ndk/debug/Android.mk
moduleName "This_is_a_terrible_Gradle_hack\n" +
"include \$(CLEAR_VARS)\n" +
"LOCAL_MODULE := mystaticlib_prebuilt\n" +
"LOCAL_EXPORT_C_INCLUDES := mystaticlib/include\n" +
"LOCAL_SRC_FILES := mystaticlib/libmystaticlib.a\n" +
"include \$(PREBUILT_STATIC_LIBRARY)\n" +
"include \$(CLEAR_VARS)\n" +
"LOCAL_MODULE := MyActualModule\n" +
"LOCAL_STATIC_LIBRARIES += mystaticlib_prebuilt"
cFlags "-std=c++11 -fexceptions -frtti -pthread"
stl "gnustl_shared"
ldLibs "log", "OpenSLES", "z"
}