【问题标题】:Android Studio 2.2 doesn't package third party library to apkAndroid Studio 2.2 没有将第三方库打包到 apk
【发布时间】:2017-02-15 04:28:21
【问题描述】:

我使用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”。 然后我用工具(analyze apk)查看了apk,发现ffmpeg库没有打包。

【问题讨论】:

  • 我们有同样的问题。经过进一步调查,我们发现根本没有找到静态或共享库。您可以使用“find_library”和直接路径搜索来测试它。
  • 我使用 find_library(avcodec-lib NAMES avcodec-57 HINTS C:/Users/tony/Desktop/MyApplication/app/libs/armeabi/lib/) 但失败了。
  • 只是我们取消了进一步的调查,因为这似乎是与 Android Studio 相关的问题。我找到了code.google.com/p/android/issues/detail?id=211927
  • 您可以尝试在问题 211927 中报告并绕过参数。例如。 find_library(avcodec-lib NAMES avcodec-57 HINTS C:/Users/tony/Desktop/MyApplication/app/libs/armeabi/lib/CMAKE_FIND_ROOT_PATH_BOTH NO_DEFAULT_PATH) 但对我们来说这也行不通。我们现在将切换到使用 Android.mk 和 Application.mk 的旧方法
  • 它仍然无法工作。也许我只能切换到旧方法。

标签: android android-studio cmake


【解决方案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

并将这些行添加到在 Android Studio 中构建原生 .so 库的 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 的误解而导致的......

【讨论】:

    【解决方案2】:

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

    这里是 ffmpeg 中的 libavcodec 和 libavutil 示例。

    1- 将您的预构建库复制到 app/libs/[abi]/
    示例:app/libs/armeabi-v7a/libavcodec.so

    2- 将 include 复制到 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 是我能够将库捆绑到 apk 中的关键。

    请注意,我使用了 libs 文件夹,但您可能可以使用任何您想要存储预构建库的文件夹。

    在 github 上找到了一个工作示例(不是我的):https://github.com/imchenjianneng/StudyTestCase

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。 当我正确填写 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}。

        例如)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 {
          }
      }
      

      希望对你有帮助。

      附言我使用了自己构建的 FFMPEG 库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-09
        • 1970-01-01
        • 2016-10-09
        • 1970-01-01
        • 1970-01-01
        • 2016-10-16
        • 2018-06-05
        相关资源
        最近更新 更多