Как включить *.so библиотеку в Android Studio?
Я прочитал много потоков, как добавить библиотеку *.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 Version 19
Build Tools Версия 19.1.0
Зависимости:
{dir=libs, include=[*.jar]} Compile
{dir=libs, include=[*.so]} Provided
m com.android.support: appcompat -v7:19.+ Compile
Я получил файлы *.so, предварительно скомпилированные, и в демонстрационном приложении они работают. Я должен изменить исходный код приложения, поэтому мне нужно перестроить с теми же файлами *.so.
Ответы
Ответ 1
Создайте новую папку project/app/src/main/jniLibs
, а затем поместите ваши файлы *.so
со своими папками abi в это местоположение.
Устаревшее решение
Добавьте оба фрагмента кода в свой файл gradle.build в качестве зависимости:
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.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)
}
Тот же ответ можно найти и в связанном с ним вопросе: Включить .so библиотеку в apk в андроид-студии
Ответ 2
Добавление .so Library в Android Studio 1.0.2
- Создать папку "jniLibs" внутри "src/main/"
- Поместите все ваши библиотеки .so внутри папки "src/main/jniLibs"
- Структура папки выглядит,
| --app:
| - | --src:
| - | - | --main
| - | - | - | --jniLibs
| - | - | - | - | --armeabi
| - | - | - | - | - | - | -.
| - | - | - | - | --x86
| - | - | - | - | - | - | -.
- Никакой дополнительный код не требует просто синхронизации вашего проекта и запуска вашего приложения.
Ссылка
https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main
Ответ 3
*. поэтому библиотека в Android Studio
Вам нужно создать папку jniLibs внутри main в проектах android Studio и поместить все ваши файлы .so внутри. Вы также можете интегрировать эту строку в build.gradle
compile fileTree (dir: 'libs', include: ['.jar', '. so'])
Он отлично работает
| --app:
| - | --src:
| - | - | --main
| - | - | - | --jniLibs
| - | - | - | - | --armeabi
| - | - | - | - | - | -. поэтому Файлы
Это структура проекта.
Ответ 4
Решение 1. Создание папки JniLibs
Создайте в своем приложении папку "jniLibs" и папки, содержащие ваш *.so внутри.
Папка "jniLibs" должна быть создана в той же папке, что и папки "Java" или "Assets".
Решение 2. Модификация файла build.gradle
Если вы не хотите создавать новую папку и сохраняете свои файлы *.so в папке libs, это возможно!
В этом случае просто добавьте файлы *.so в папку libs (пожалуйста, соблюдайте ту же архитектуру, что и решение 1: libs/armeabi/.so) и измените файл build.gradle вашего приложения, чтобы добавить исходный каталог jniLibs.
sourceSets {
main {
jni.srcDirs = ["libs"]
}
}
У вас будет больше объяснений со скриншотами, которые помогут вам здесь (шаг 6):
http://blog.guillaumeagis.eu/setup-andengine-with-android-studio/
Ответ 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
Чтобы использовать собственную библиотеку (так что файлы)
Вам нужно добавить некоторые коды в файл "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
Ответ 7
Я решил подобную проблему, используя внешние родственные зависимости lib, которые упакованы внутри файлов jar. Иногда эти библиотеки зависимостей архитектуры упаковываются все в одну банку, иногда они разбиваются на несколько файлов jar. поэтому я написал некоторый buildscript для сканирования зависимостей jar для родных libs и сортировки их в правильные папки Android для Android. Кроме того, это также обеспечивает способ загрузки зависимостей, которые не найдены в maven-репозиториях, которые в настоящее время полезны для работы JNA на андроиде, потому что не все родные банки публикуются в публичных репозиториях 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'])
Ответ 8
Официальный анонс 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
, key code части:
-
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
.
-
на С++-коде, используйте: #include <gperf.h>
-
расположение заголовка: hello-libs/distribution/gperf/include/gperf.h
-
Местоположение: distribution/gperf/lib/arm64-v8a/libgperf.so
-
Если вы поддерживаете только некоторые архитектуры, см. Gradle Создание только NDK-цели только ARM
Пример git отслеживает готовые совместно используемые библиотеки, но он также содержит систему сборки, чтобы фактически их создать: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs