如何在 Android Studio 中包含 * . so 库?

我读过很多关于如何添加 * 的文章。所以它们都不能工作,特别是当提到文本的时候: 这不能用于新的 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

* I got the * .所以文件预编译,并在演示应用程序他们正在工作。我必须更改应用程序的源代码,所以我需要用相同的 * 重建。文件。

246476 次浏览

当前解决方案

创建文件夹 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 文件中:

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)
}

同样的答案也可以在相关问题中找到: 在 android 工作室的 apk 中包含.so 库

这是我的 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')
}

在 Android Studio 1.0.2中添加. so 库

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

    参考文献
    Https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

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

此代码用于清除“ armeabi”目录并将“ so”文件复制到“ armeabi”,同时清除“ project”。

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

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

创建一个名为“ jniLibs”的文件夹到你的应用程序和包含 * . so 的文件夹中。 “ jniLibs”文件夹需要在与“ Java”或“资产”文件夹相同的文件夹中创建。

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

如果您不想创建一个新的文件夹并保留您的 * 。所以文件进入 libs 文件夹,这是可能的!

在这种情况下,只需添加您的 * 。因此,将文件放入 libs 文件夹(请尊重与解决方案1相同的架构: libs/armeabi/。并修改应用程序的 build.gradle 文件以添加 jniLibs 的源目录。

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

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

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

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

* . so 在 Android Studio 中的库

您必须在 android Studio 项目的 main 中生成 jniLibs 文件夹,并将所有。里面有文件。您还可以将这一行集成到 build.gradle 中

编译 fileTree (dir: ‘ libs’,include: [‘ 。罐’,’.so’])

效果非常好

应用程序:

| —— | —— src:

总部

| —— | —— | —— | —— jniLibs

阿米阿比

文件

这是项目结构。

我使用打包在 jar 文件中的外部本机库依赖项解决了一个类似的问题。有时这些体系结构依赖库被打包在一个 jar 中,有时它们被分割成几个 jar 文件。因此,我写了一些构建脚本来扫描本机库的 jar 依赖项,并将它们排序到正确的 android 库文件夹中。此外,这也提供了一种方法来下载依赖关系,没有发现在 maven 回购,这是目前有用的让 JNA 在 android 上工作,因为不是所有的本机 jars 发布在公共 maven 回购。

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'])

Android NDK 官方 hello-libs CMake 示例

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/app下看,libgperf.so也会在那里。

  • 在 C + + 代码上,使用: #include <gperf.h>

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

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

  • 如果只支持某些体系结构,请参见: 分级生成 NDK 目标只有 ARM

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

我有安卓工作室4.1.2,当我试图设置 NDK 路径在文件-> 项目结构-> Sdk 位置它会要求我下载 NDK,即使它已经安装,我设置 NDK _ HOME,ANDROID _ NDK _ HOME 和 PATH 环境变量和无。唯一对我有效的方法是在 local.properties 中手动设置 ndk 版本,使用 ABI 及其各自的名称创建一个 jniLibs (是的,就是这个名称)文件夹。因此,在 build.gradle 中指定 abi 过滤器和 ndk 版本。希望这能让别人不再头疼。

本地物业

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

建造,分级

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'
}

应用程序 src 总线

enter image description here

在 jniLibs 文件夹中

enter image description here