【问题标题】:How to include *.so library in Android Studio?如何在 Android Studio 中包含 *.so 库?
【发布时间】:2023-03-17 17:30:01
【问题描述】:

我阅读了很多关于如何将 *.so 库添加到 Android Studio 的帖子,但它们都不起作用,尤其是在涉及到文本时:这不适用于较新的 xxx(Android Studio、gradle、. ..)

我们可以重新开始吗?我得到了:

Android Studio 0.6.0

从我看到的项目结构:

SDK 位置:

/usr/share/android-studio/data/sdk
/usr/lib/jvm/default-java

项目:

Gradle version 1.10
Android Plugin Version 0.11.+

模块/应用程序: 属性:

编译 SDK 版本 19 构建工具版本 19.1.0

依赖关系:

{dir=libs, include=[*.jar]} Compile

{dir=libs, include=[*.so]}  Provided

m com.android.support: appcompat -v7:19.+   Compile

我得到了预编译的 *.so 文件,并且在他们正在运行的演示应用程序中。我必须更改应用程序的源代码,因此我需要使用相同的 *.so 文件进行重建。

【问题讨论】:

标签: android android-studio


【解决方案1】:

在 Android Studio 1.0.2 中添加 .so 库

  1. 在“src/main/”中创建文件夹“jniLibs”
  2. 将所有 .so 库放入“src/main/jniLibs”文件夹中
  3. 文件夹结构看起来像,
    |--应用:
    |--|--src:
    |--|--|--主要
    |--|--|--|--jniLibs
    |--|--|--|--|--armeabi
    |--|--|--|--|--|--.so 文件
    |--|--|--|--|--x86
    |--|--|--|--|--|--.so 文件
  4. 无需额外的代码,只需同步您的项目并运行您的应用程序。

    参考
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

【讨论】:

  • 这不适用于 2015 年 6 月 16 日的 Studio 测试版
  • 这是正确的答案,在 Android Studio 1.2.2 中工作。检查和验证。
  • 使用 Android Studio 1.3.1。
  • 为我工作过。在 android studio 2.1.2 上 :)
  • 适用于 Android Studio 3.2.1,太棒了!仍然没有记录在任何地方!???
【解决方案2】:

当前解决方案

创建文件夹project/app/src/main/jniLibs,然后将您的*.so 文件放在该位置的abi 文件夹中。例如,

project/
├──libs/
|  └── *.jar       <-- if your library has jar files, they go here
├──src/
   └── main/
       ├── AndroidManifest.xml
       ├── java/
       └── jniLibs/ 
           ├── arm64-v8a/                       <-- ARM 64bit
           │   └── yourlib.so
           ├── armeabi-v7a/                     <-- ARM 32bit
           │   └── yourlib.so
           └── x86/                             <-- Intel 32bit
               └── yourlib.so

已弃用的解决方案

在您的模块 gradle.build 文件中添加两个代码 sn-ps 作为依赖项:

compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')

如何创建这个自定义 jar:

task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

同样的答案也可以在相关问题中找到:Include .so library in apk in android studio

【讨论】:

  • Compile 任务已被弃用。改用JavaCompile(来自相关答案)
  • 我应该把任务放在哪里?
  • 请先尝试jniLibs文件夹解决方案。此任务应放入您的应用程序/库 gradle.build 文件中。
  • 另见此处(列出不同的架构子文件夹):cumulations.com/blogs/9/…
【解决方案3】:

解决方案 1:创建 JniLibs 文件夹

在您的应用程序中创建一个名为“jniLibs”的文件夹,并在其中包含您的 *.so 文件夹。 “jniLibs”文件夹需要创建在与“Java”或“Assets”文件夹相同的文件夹中。

解决方案 2:修改 build.gradle 文件

如果您不想创建新文件夹并将 *.so 文件保存到 libs 文件夹中,这是可能的!

在这种情况下,只需将您的 *.so 文件添加到 libs 文件夹中(请尊重与解决方案 1 相同的架构:例如 libs/armeabi/.so)并修改应用的 build.gradle 文件以添加jniLibs的源码目录。

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

你会有更多的解释,这里有帮助你的截图(第6步):

http://blog.guillaumeagis.eu/setup-andengine-with-android-studio/

EDIT 必须是 jniLibs.srcDirs,而不是 jni.srcDirs - 编辑了代码。该目录可以是指向项目目录之外的 [相对] 路径。

【讨论】:

  • 解决方案 2 对我不起作用。我收到一个构建错误:“在源集 'main' 上找不到属性 'jni'。”
  • 秘密是“需要在与“Java”或“Assets”文件夹相同的文件夹中创建“jniLibs”文件夹。谢谢!
  • 方法 1 让我能够正确编译,第二个在 AS 中创建了一个“cpp”文件夹并给了我关于缺少 C++ 编译器的错误
  • 解决方案 2 必须使用 jniLibs.srcDirs,而不是 jni.srcDirs 以允许指定本机库的位置(路径可以是相对的或绝对的,甚至可以指向项目目录之外)。
  • 对于解决方案 2,您需要将 source Sets { 代码放在 android { 部分下
【解决方案4】:

Android Studio 中的*.so 库

您必须在 android Studio 项目的 main 中生成 jniLibs 文件夹,并将所有 .so 文件放入其中。也可以在 build.gradle 中集成这一行

编译 fileTree(dir: 'libs', include: ['.jar','.so'])

效果很好

|--应用程序:

|--|--src:

|--|--|--main

|--|--|--|--jniLibs

|--|--|--|--|--armeabi

|--|--|--|--|--|--.so 文件

这是项目结构。

【讨论】:

  • compile fileTree(dir: 'libs', include: ['.jar','.so'])中添加.so 解决了我的prb。谢谢
  • 如果还是按照下面的解决方法,试试android ndk r10e
【解决方案5】:

这是我的 build.gradle 文件,请注意这一行

jniLibs.srcDirs = ['libs']

这将包括 libs 的 *.so 文件到 apk。

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
        jniLibs.srcDirs = ['libs']
    }

    // Move the tests to tests/java, tests/res, etc...
    instrumentTest.setRoot('tests')

    // Move the build types to build-types/<type>
    // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
    // This moves them out of them default location under src/<type>/... which would
    // conflict with src/ being used by the main source set.
    // Adding new build types or product flavors should be accompanied
    // by a similar customization.
    debug.setRoot('build-types/debug')
    release.setRoot('build-types/release')
}

【讨论】:

    【解决方案6】:

    Android NDK 官方hello-libsCMake 示例

    https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs

    刚刚在 Ubuntu 17.10 主机、Android Studio 3、Android SDK 26 上为我工作过,所以我强烈建议您将项目基于它。

    共享库名为libgperf,关键代码部分为:

    • hello-libs/app/src/main/cpp/CMakeLists.txt

      // -L
      add_library(lib_gperf SHARED IMPORTED)
      set_target_properties(lib_gperf PROPERTIES IMPORTED_LOCATION
                ${distribution_DIR}/gperf/lib/${ANDROID_ABI}/libgperf.so)
      
      // -I
      target_include_directories(hello-libs PRIVATE
                                 ${distribution_DIR}/gperf/include)
      // -lgperf
      target_link_libraries(hello-libs
                            lib_gperf)
      
    • app/build.gradle:

      android {
          sourceSets {
              main {
                  // let gradle pack the shared library into apk
                  jniLibs.srcDirs = ['../distribution/gperf/lib']
      

      然后,如果您在设备上查看/data/applibgperf.so 也会在那里。

    • 在 C++ 代码上,使用:#include &lt;gperf.h&gt;

    • 标头位置:hello-libs/distribution/gperf/include/gperf.h

    • 库位置:distribution/gperf/lib/arm64-v8a/libgperf.so

    • 如果您只支持某些架构,请参阅:Gradle Build NDK target only ARM

    示例 git 跟踪预构建的共享库,但它也包含构建系统以实际构建它们:https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs

    【讨论】:

      【解决方案7】:

      我已经使用打包在 jar 文件中的外部本机 lib 依赖项解决了类似的问题。有时这些架构依赖库一起打包在一个 jar 中,有时它们被拆分为几个 jar 文件。所以我写了一些构建脚本来扫描原生库的 jar 依赖项并将它们分类到正确的 android lib 文件夹中。此外,这还提供了一种下载在 maven repos 中找不到的依赖项的方法,这对于让 JNA 在 android 上运行很有用,因为并非所有本机 jar 都发布在公共 maven repos 中。

      android {
          compileSdkVersion 23
          buildToolsVersion '24.0.0'
      
          lintOptions {
              abortOnError false
          }
      
      
          defaultConfig {
              applicationId "myappid"
              minSdkVersion 17
              targetSdkVersion 23
              versionCode 1
              versionName "1.0.0"
          }
          buildTypes {
              release {
                  minifyEnabled false
                  proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
              }
          }
      
          sourceSets {
              main {
                  jniLibs.srcDirs = ["src/main/jniLibs", "$buildDir/native-libs"]
              }
          }
      }
      
      def urlFile = { url, name ->
          File file = new File("$buildDir/download/${name}.jar")
          file.parentFile.mkdirs()
          if (!file.exists()) {
              new URL(url).withInputStream { downloadStream ->
                  file.withOutputStream { fileOut ->
                      fileOut << downloadStream
                  }
              }
          }
          files(file.absolutePath)
      }
      dependencies {
          testCompile 'junit:junit:4.12'
          compile 'com.android.support:appcompat-v7:23.3.0'
          compile 'com.android.support:design:23.3.0'
          compile 'net.java.dev.jna:jna:4.2.0'
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-arm.jar?raw=true', 'jna-android-arm')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-armv7.jar?raw=true', 'jna-android-armv7')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-aarch64.jar?raw=true', 'jna-android-aarch64')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-x86.jar?raw=true', 'jna-android-x86')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-x86-64.jar?raw=true', 'jna-android-x86_64')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-mips.jar?raw=true', 'jna-android-mips')
          compile urlFile('https://github.com/java-native-access/jna/blob/4.2.2/lib/native/android-mips64.jar?raw=true', 'jna-android-mips64')
      }
      def safeCopy = { src, dst ->
          File fdst = new File(dst)
          fdst.parentFile.mkdirs()
          fdst.bytes = new File(src).bytes
      
      }
      
      def archFromName = { name ->
          switch (name) {
              case ~/.*android-(x86-64|x86_64|amd64).*/:
                  return "x86_64"
              case ~/.*android-(i386|i686|x86).*/:
                  return "x86"
              case ~/.*android-(arm64|aarch64).*/:
                  return "arm64-v8a"
              case ~/.*android-(armhf|armv7|arm-v7|armeabi-v7).*/:
                  return "armeabi-v7a"
              case ~/.*android-(arm).*/:
                  return "armeabi"
              case ~/.*android-(mips).*/:
                  return "mips"
              case ~/.*android-(mips64).*/:
                  return "mips64"
              default:
                  return null
          }
      }
      
      task extractNatives << {
          project.configurations.compile.each { dep ->
              println "Scanning ${dep.name} for native libs"
              if (!dep.name.endsWith(".jar"))
                  return
              zipTree(dep).visit { zDetail ->
                  if (!zDetail.name.endsWith(".so"))
                      return
                  print "\tFound ${zDetail.name}"
                  String arch = archFromName(zDetail.toString())
                  if(arch != null){
                      println " -> $arch"
                      safeCopy(zDetail.file.absolutePath,
                              "$buildDir/native-libs/$arch/${zDetail.file.name}")
                  } else {
                      println " -> No valid arch"
                  }
              }
          }
      }
      
      preBuild.dependsOn(['extractNatives'])
      

      【讨论】:

        【解决方案8】:

        我有 android studio 4.1.2,当我尝试在 File -> Project Structure -> Sdk Location 中设置 ndk 路径时,即使它已经安装,它也会要求我下载 ndk,我设置了 NDK_HOME、ANDROID_NDK_HOME和 PATH 环境变量,什么都没有。唯一对我有用的是在 local.properties 中手动设置 ndk 版本,使用 ABI 及其各自的 .so 文件创建一个 jniLibs(是的,具有此确切名称)文件夹,并在构建中指定 abi 过滤器和 ndk 版本.gradle。希望这可以使其他人免于头痛。

        local.properties

        ndk.dir=C\:\\Users\\<user>\\AppData\\Local\\Android\\Sdk\\ndk\\22.0.7026061
        

        build.gradle

        plugins {
            id 'com.android.application'
        }
        
        android {
            compileSdkVersion 30
            buildToolsVersion "30.0.3"
        
            defaultConfig {
                applicationId "com.example.myapplication"
                minSdkVersion 22
                targetSdkVersion 30
                versionCode 1
                versionName "1.0"
                ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
        
                testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        
            }
        
            sourceSets {
                main {
                    jniLibs.srcDir 'jniLibs'
                }
            }
        
            buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
                }
            }
        
            compileOptions {
                sourceCompatibility JavaVersion.VERSION_1_8
                targetCompatibility JavaVersion.VERSION_1_8
            }
        
            ndkVersion '22.0.7026061'
        }
        

        ...\app\src\main\

        在 jniLibs 文件夹内

        【讨论】:

          【解决方案9】:

          使用本机库(so 文件) 您需要在“build.gradle”文件中添加一些代码。

          此代码用于在“清理项目”时清理“armeabi”目录并将“so”文件复制到“armeabi”中。

          task copyJniLibs(type: Copy) {
              from 'libs/armeabi'
              into 'src/main/jniLibs/armeabi'
          }
          tasks.withType(JavaCompile) {
              compileTask -> compileTask.dependsOn(copyJniLibs)
          }
          clean.dependsOn 'cleanCopyJniLibs'
          

          我是从下面提到的。 https://gist.github.com/pocmo/6461138

          【讨论】:

            猜你喜欢
            • 2016-08-02
            • 2016-08-19
            • 2016-09-04
            • 2016-02-10
            • 1970-01-01
            • 2013-05-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多