Включить предварительно скомпилированную статическую библиотеку с использованием 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"
    }