在 android studio 中包含共享库 .so
Include Shared library .so in android studio
我在 ndk 的源文件夹中提取了 ffmpeg 然后在那里编译它只是为了我遵循这个:http://www.roman10.net/2013/08/18/how-to-build-ffmpeg-with-ndk-r9/ 并成功生成 android 文件夹 arm/lib 和 arm/include 个文件。
之后我在 $NDK/sources/ffmpeg/android/arm 中创建了一个 Android.mk 文件和一个 Android.mk在我的 android 项目中(src/main/jni 文件夹)。
我的src/main/jni/Android.mk是这样的:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tutorial01
LOCAL_SRC_FILES := tutorial01.c
LOCAL_LDLIBS := -llog -ljnigraphics -lz
LOCAL_SHARED_LIBRARIES := libavcodec
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-3.0.1/android/arm)
和$NDK/sources/ffmpeg/android/arm/Android.mk是:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-57.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
我像这样更新了我的 build.gradle 并使用 .so 文件成功生成了 jniLibs 但我得到 libavcodec/avcodec.h: No such file or directory在构建项目时。
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.example.spartan.hello"
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-android.txt'))
}
}
android.sources {
main {
jni {
source {
srcDirs = []
}
}
}
main {
jniLibs {
source {
srcDirs = ['src/main/libs']
}
}
}
}
android.ndk {
moduleName = "tutorial01"
stl = 'gnustl_shared'
}
}
task ndkBuild(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
}
并像这样将它们加载到我的 activity 中:
static {
System.loadLibrary("tutorial01");
System.loadLibrary("avcodec-57");
}
我是NDK的新手所以,如果我们手动将头文件粘贴到jni文件夹中可以吗?
如果您自己使用 ndk-build,则无需从 gradle 编译任何内容。
将您的 jni 源设置为不存在的文件夹或没有文件夹:
android.sources{
main.jni {
source {
srcDirs = [] // or ['src/main/none']
}
}
}
并删除此块:
// New code
android.ndk {
moduleName = "tutorial01"
}
我参考了第三方 google 示例 https://github.com/googlesamples/android-ndk/tree/master/hello-thirdparty,它基本上是针对 static lib(.a) 的,这就是我解决问题的方法使用 gradle 实验性插件:
我的 build.gradle 文件:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.example.spartan.hello"
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-android.txt'))
}
}
repositories {
libs(PrebuiltLibraries) {
libavcodec {
headers.srcDir "/home/spartan/AndroidStudioProjects/Hello/app/src/main/jni/include"
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/home/spartan/AndroidStudioProjects/Hello/app/src/main/jniLibs/${targetPlatform.getName()}/libavcodec-57.so")
}
}
}
}
android.ndk {
moduleName = "tutorial01"
def jniPath = "/home/spartan/AndroidStudioProjects/Hello/app/src/main/jniLibs"
cppFlags.add("-I${file(jniPath)}".toString())
file(jniPath).eachDirRecurse { dir ->
cppFlags.add("-I${file(dir)}".toString())
}
ldLibs.addAll(["log", "android","jnigraphics"])
stl = "gnustl_shared"
}
android.sources {
main {
jni {
dependencies {
library "libavcodec" linkage "shared"
}
}
}
}
android.productFlavors {
create ("armv7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
android.sources {
main {
jni {
source {
srcDirs = ['src/main/none']
}
}
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
}
在我的例子中,我在 jniLibs 中复制了 .so 并包含 .h 的文件夹jni 文件夹中的文件并且不需要在 android.ndk 中添加 -l 因为我已经在 headers.srcDir 中添加了(我只是在这里添加提及)。
所以我在这里用 repositories 替换了我的 Android.mk 并且它真的很简单。
我在 ndk 的源文件夹中提取了 ffmpeg 然后在那里编译它只是为了我遵循这个:http://www.roman10.net/2013/08/18/how-to-build-ffmpeg-with-ndk-r9/ 并成功生成 android 文件夹 arm/lib 和 arm/include 个文件。
之后我在 $NDK/sources/ffmpeg/android/arm 中创建了一个 Android.mk 文件和一个 Android.mk在我的 android 项目中(src/main/jni 文件夹)。
我的src/main/jni/Android.mk是这样的:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tutorial01
LOCAL_SRC_FILES := tutorial01.c
LOCAL_LDLIBS := -llog -ljnigraphics -lz
LOCAL_SHARED_LIBRARIES := libavcodec
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-3.0.1/android/arm)
和$NDK/sources/ffmpeg/android/arm/Android.mk是:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-57.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
我像这样更新了我的 build.gradle 并使用 .so 文件成功生成了 jniLibs 但我得到 libavcodec/avcodec.h: No such file or directory在构建项目时。
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.example.spartan.hello"
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-android.txt'))
}
}
android.sources {
main {
jni {
source {
srcDirs = []
}
}
}
main {
jniLibs {
source {
srcDirs = ['src/main/libs']
}
}
}
}
android.ndk {
moduleName = "tutorial01"
stl = 'gnustl_shared'
}
}
task ndkBuild(type: Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
}
并像这样将它们加载到我的 activity 中:
static {
System.loadLibrary("tutorial01");
System.loadLibrary("avcodec-57");
}
我是NDK的新手所以,如果我们手动将头文件粘贴到jni文件夹中可以吗?
如果您自己使用 ndk-build,则无需从 gradle 编译任何内容。
将您的 jni 源设置为不存在的文件夹或没有文件夹:
android.sources{
main.jni {
source {
srcDirs = [] // or ['src/main/none']
}
}
}
并删除此块:
// New code
android.ndk {
moduleName = "tutorial01"
}
我参考了第三方 google 示例 https://github.com/googlesamples/android-ndk/tree/master/hello-thirdparty,它基本上是针对 static lib(.a) 的,这就是我解决问题的方法使用 gradle 实验性插件:
我的 build.gradle 文件:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.example.spartan.hello"
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-android.txt'))
}
}
repositories {
libs(PrebuiltLibraries) {
libavcodec {
headers.srcDir "/home/spartan/AndroidStudioProjects/Hello/app/src/main/jni/include"
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/home/spartan/AndroidStudioProjects/Hello/app/src/main/jniLibs/${targetPlatform.getName()}/libavcodec-57.so")
}
}
}
}
android.ndk {
moduleName = "tutorial01"
def jniPath = "/home/spartan/AndroidStudioProjects/Hello/app/src/main/jniLibs"
cppFlags.add("-I${file(jniPath)}".toString())
file(jniPath).eachDirRecurse { dir ->
cppFlags.add("-I${file(dir)}".toString())
}
ldLibs.addAll(["log", "android","jnigraphics"])
stl = "gnustl_shared"
}
android.sources {
main {
jni {
dependencies {
library "libavcodec" linkage "shared"
}
}
}
}
android.productFlavors {
create ("armv7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
android.sources {
main {
jni {
source {
srcDirs = ['src/main/none']
}
}
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
}
在我的例子中,我在 jniLibs 中复制了 .so 并包含 .h 的文件夹jni 文件夹中的文件并且不需要在 android.ndk 中添加 -l 因为我已经在 headers.srcDir 中添加了(我只是在这里添加提及)。
所以我在这里用 repositories 替换了我的 Android.mk 并且它真的很简单。