Android Studio 2.2 не упаковывает стороннюю библиотеку в apk

Я использую Android Studio 2.2 cmake для создания собственного кода, в собственном коде я вызывал ffmpeg api, поэтому библиотека ffmpeg должна быть упакована. Мой CMakelists.txt выглядит следующим образом:

cmake_minimum_required(VERSION 3.4.1)
include_directories(libs/arm/include)
link_directories(libs/arm/lib/)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp )


find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
add_library(avcodec-57 SHARED IMPORTED)
set_target_properties(avcodec-57 PROPERTIES IMPORTED_LOCATION C:/Users/tony/Desktop/MyApplication/app/libs/arm/lib/libavcodec-57.so)
target_link_libraries(native-lib avcodec-57)
target_link_libraries(native-lib avformat-57)

target_link_libraries(native-lib avutil-55)
target_link_libraries(native-lib avfilter-6)

В таком случае я могу сделать проект успешно, но когда я устанавливаю apk в эмулятор и запускаю, он не работает и показывает, что "libavcodec-57.so" не найден. Затем я использую инструмент (анализ apk), чтобы проверить apk, обнаружил, что библиотека ffmpeg не упакована.

Ответ 1

Я нашел способ, который работает для меня, но не уверен, что он поможет вам, но может. Я использую Android Studio 2.2, и столкнулся с вашей проблемой.

Я создал jar файл с предварительно созданными в нем библиотеками:

lib
--|armeabi
--|--|libMyLIb.so
etc.

просто создав папку lib с этим содержимым где-нибудь и выполнив команду

zip -r myjar.zip lib && mv myjar.zip myjar.jar

Затем я помещаю файл jar здесь:

app/libs/myjar.jar

И добавил эти строки в CMakeLists.txt, который создает собственную .so-библиотеку внутри Android Studio. То есть, я начал с пустого проекта с шаблона для вызовов на собственный код (по умолчанию libnative-lib.so):

# already there:
target_link_libraries( # Specifies the target library.
                   native-lib

                   # Links the target library to the log library
                   # included in the NDK.
                   ${log-lib} )

# my addition:
add_custom_command(TARGET native-lib POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs"
        $<TARGET_FILE_DIR:native-lib>)

И волшебным образом, теперь, если я построю apk, содержимое моей банки в конечном итоге окажется в последнем apk. Не спрашивайте меня, почему это работает, на самом деле, я понятия не имею, это было случайно.

Что для меня значит, это то, что я компилирую пустой libnative-lib.so, только для того, чтобы обмануть Android Studio, включив мою банку.

Возможно, кто-то найдет более чистое решение и может указать, где мое решение - это смешной цикл, который возник из-за недопонимания gradle и cmake...

Ответ 2

У меня была такая же проблема. Cmake не автоматически упаковывает третью библиотеку в apk, вы должны сделать это самостоятельно.

Вот пример libavcodec и libavutil из ffmpeg.

1- Скопируйте свой встроенный lib в приложение /libs/ [abi]/
Пример: app/libs/armeabi-v7a/libavcodec.so

2- Копировать в приложение /libs/include

Затем в вашем cmakelist.txt добавьте нужные библиотеки.

find_library( log-lib log )
set(ffmpeg_DIR ../../../../libs) #set path to libs folder

add_library( libavutil SHARED IMPORTED )
set_target_properties( libavutil PROPERTIES IMPORTED_LOCATION ${ffmpeg_DIR}/${ANDROID_ABI}/libavutil.so )

add_library( libavcodec SHARED IMPORTED )
set_target_properties( libavcodec PROPERTIES IMPORTED_LOCATION ${ffmpeg_DIR}/${ANDROID_ABI}/libavcodec.so )

include_directories(libs/include) #add include dir. don't know  why ../ not needed

add_library( native-lib SHARED src/main/cpp/native-lib.cpp )

target_link_libraries( native-lib libavcodec libavutil ${log-lib} )

Наконец, в вашем файле build.gradle jniLibsfolder:

sourceSets.main {
    jniLibs.srcDirs = ['libs']
}

Настройка jniLibs.srcDir была ключом для меня, чтобы иметь возможность связывать библиотеки lib в apk.

Обратите внимание, что я использовал папку libs, но вы, вероятно, можете использовать любую папку, в которой хотите сохранить ваши предварительно созданные библиотеки.

Нашел рабочий пример github (не мой): https://github.com/imchenjianneng/StudyTestCase

Ответ 3

У меня была та же проблема. Gradle не упаковывает .so файлы в apk, когда я правильно заполнял CMakeLists.txt, но, наконец, я разрешил его.

Добавьте путь JniLibs в sourceSets в local build.gradle, как этот пример кода: https://github.com/googlesamples/android-ndk/blob/master/hello-libs/app/build.gradle который @Gerry упоминается в комментарии.

Я сделал:


  • скопируйте .so библиотеки в src/main/JniLibs/${ANDROID_ABI}.

    ex) mobile/src/main/JniLibs/armeabi-v7a/libavcodec.so


  1. изменить CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

# project path (absolute), change it to yours.
set(projectDir C:/Users/Administrator/AndroidStudioProjects/TestApp1)

# headers
include_directories(${projectDir}/mobile/src/main/JniLibs/${ANDROID_ABI}/include)

# sample ndk lib
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )

# FFMPEG libraries
add_library( lib_avcodec SHARED IMPORTED )

set_target_properties(  lib_avcodec  PROPERTIES IMPORTED_LOCATION  ${projectDir}/mobile/src/main/JniLibs/${ANDROID_ABI}/libavcodec.so)

# ...
# (omitted) same codes with lib_avdevice, lib_avfilter, lib_avformat, lib_avutil, lib_swresample, and lib_swscale each.
# ...

target_link_libraries( # Specifies the target library.
                   native-lib

                   lib_avcodec
                   lib_avdevice
                   lib_avfilter
                   lib_avformat
                   lib_avutil
                   lib_swresample
                   lib_swscale
                   )

  1. в build.gradle(приложение)

build.gradle

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.2'
    defaultConfig {
        applicationId "your-application-Id"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti -fexceptions"
            }
        }

        ndk {
            // Specifies the ABI configurations of your native
            // libraries Gradle should build and package with your APK.
            abiFilters 'armeabi', 'armeabi-v7a'
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    # ADD THIS BLOCK.
    sourceSets {
        main {
            // let gradle pack the shared library into apk
            jniLibs.srcDirs = ['src/main/JniLibs']
        }
    }

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
    productFlavors {
    }
}

надеюсь, что это поможет вам.

p.s. Я использовал библиотеки FFMPEG, которые сами построили.