Android Studio 2.2不会将第三方库打包到apk

时间:2016-10-06 12:18:22

标签: android android-studio cmake

我使用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库没有打包。

3 个答案:

答案 0 :(得分:3)

我发现了一种对我有用的方法,不确定它会对你有所帮助,但可能会有所帮助。我使用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

并将这些行添加到在Android Studio中构建本机.so-library的CMakeLists.txt中。也就是说,我从模板中的一个空项目开始调用本机代码(默认的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,我的jar的内容最终会在最后的apk中出现。不要问我为什么会这样,真的,我不知道,这是偶然的。

这对我来说意味着我编译空的libnative-lib.so,其唯一目的是诱骗Android Studio包含我的jar。

也许有人找到了一个更清洁的解决方案,并且可以指出我的解决方案是由于误解gradle和cmake导致的荒谬循环...

答案 1 :(得分:2)

我遇到了完全相同的问题。 Cmake不会自动将第三个库打包到apk中,你必须自己动手。

以下是来自ffmpeg的libavcodec和libavutil的例子。

1-将预先构建的lib复制到app / libs / [abi] /
例如:app/libs/armeabi-v7a/libavcodec.so

2-复制包含到app / 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

答案 2 :(得分:1)

我遇到了同样的问题。 当我正确填充CMakeLists.txt时,Gradle没有将.so文件打包到apk中,但最后我解决了它。

将JniLibs路径添加到本地build.gradle中的sourceSets中,如以下示例代码: https://github.com/googlesamples/android-ndk/blob/master/hello-libs/app/build.gradle 这是评论中提到的@Gerry

我做了:

  1. 将.so库复制到src / main / JniLibs / $ {ANDROID_ABI}。

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

    1. 编辑CMakeLists.txt
    2. 的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(app)
      2. 的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库。