Android原生库链接到来自aar的另一个原生库
Android native library linking against another native library from aar
我有一个奇怪的问题。我有一个aar库,它包含并使用原生。so库。现在,我想写另一个库,它依赖于那个库,也有原生部分依赖于第一个库的原生库。依赖库同时使用第一个库中的本机代码和java包装器。
我想知道,是否有任何方法,如何通过标准gradle依赖(从第一个库复制头文件)做到这一点?或者我必须直接从源代码构建第二个库?
为什么我需要这个:我们有一个具有基本功能的多平台库,适用于android。这个库可以在标准的android应用程序中使用,我们在多个项目中使用它,这些项目没有其他本地代码。
但是在一个应用程序中,我们想编写多平台共享的应用程序代码,依赖于那个库,我想把这些库分开。
谢谢!
注意:此答案已弃用,因为Android Studio不再提供explored-aar
目录。
对于一个更好的解决方案,从aar
使用头,检查库androidNativeBundle
下面是OpenCV
的一个可行的例子,你可以为first lib
做同样的事情。
按如下方式准备第一个lib
将jar
, *.so
和导出的headers
打包(参见链接项目中的文件OpenCV4Android/opencv/build.gradle
如何将头文件附加到aar)。
例如,你从first lib
的建筑中得到first.aar
。
在其他项目中使用first lib
在你需要的时候添加first.aar
到你的其他项目。
allprojects {
repositories {
jcenter()
flatDir {
dirs '/path/to/aar'
}
}
}
// in your app's build.gradle
dependencies {
// ...
compile 'com.example:example-with-header@aar'
// ...
}
将本机库从本机构建系统链接到first.aar
。
如果你使用CMake
,它应该是这样的
add_library(first
SHARED
IMPORTED)
set_target_properties(
first
PROPERTIES IMPORTED_LOCATION
../../../../build/intermediates/exploded-aar/org.example/example-debug/jni/${ANDROID_ABI}/libfirst.so
# use find command to figure out the location of the first lib before use it, not sure if it's different in different build environment
# for android studio gradle plugin latest version use
# ../../../../build/intermediates/transforms/mergeJniLibs/debug/folders/2000/1f/main/lib/${ANDROID_ABI}/libfirst.so
)
# also use find command to figure the actual location of the exported header from aar
# this might be different in your environment for different version of gradle plugin
include_directories(build/intermediates/exploded-aar/com.example/example-debug/cpp/include)
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
first
${log-lib} )
正如您提到的Gradle,我假设您正在使用最新的Android Studio。我使用1.2.2,发现它很容易从浮动的许多教程中构建简单的NDK项目但令人沮丧的是,很难构建一个NDK项目任何复杂性。我将总结我的发现,但我高度建议阅读这个博客和这个StackOverflow。
我的项目与你的相似,但不完全相同。对我来说,诀窍是就是想办法让Android Studio使用我的Android。可,然后找到正确的makefile变量。希望这对你有帮助。
Android Studio将完全忽略任何自定义Android。Mk文件,而不是自动生成自己的。要纠正这个错误,你必须首先破解build.gradle脚本,位于project/app/build.gradle
。你也许能黑进顶级架构。Gradle,如果需要的话
项目/应用程序/build.gradle:
//import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sample.app"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ENABLE CUSTOM ANDROID.MK >>
sourceSets.main.jni.srcDirs= [] //Disable automatic ndk-build.
sourceSets.main.jniLibs.srcDir 'src/main/libs'
//Call regular ndk-build script from app directory
task ndkBuild(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd()
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
task cleanNative(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd(), 'clean'
}
clean.dependsOn cleanNative
}
//ENABLE CUSTOM ANDROID.MK <<
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.google.android.gms:play-services:7.5.0'
}
//ENABLE CUSTOM ANDROID.MK >>
def getNdkDir() {
if (System.env.ANDROID_NDK_ROOT != null)
return System.env.ANDROID_NDK_ROOT
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkdir = properties.getProperty('ndk.dir', null)
if (ndkdir == null)
throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file")
return (ndkdir)
}
def getNdkBuildCmd() {
def ndkbuild = getNdkDir() + "/ndk-build.cmd"
// def ndkbuild = getNdkDir() + "/ndk-build"
// if (Os.isFamily(Os.FAMILY_WINDOWS))
// ndkbuild += ".cmd"
return ndkbuild
}
//ENABLE CUSTOM ANDROID.MK <<
现在我可以创建我的多库Android.mk。这个构建两个静态链接库,然后构建最后的动态链接前两个中的库和链接。所涉及的目录是:
目录:
project/
app/
build.gradle
src/
main/
java/
jni/
Android.mk
include/
libmp3lame/
MiniMp3/
mp3_jni.c
mpglib/
Android.mk:
TOP_PATH := $(call my-dir)
LOCAL_PATH := $(TOP_PATH)/libmp3lame
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := libmp3lame
LOCAL_SRC_FILES :=
bitstream.c
...
version.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += libmp3lame
LOCAL_PATH := $(TOP_PATH)/mpglib
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_C_INCLUDES += $(TOP_PATH)/libmp3lame
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := mpglib
LOCAL_SRC_FILES :=
common.c
...
tabinit.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += mpglib
LOCAL_PATH := $(TOP_PATH)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := Mp3
LOCAL_STATIC_LIBRARIES := $(MY_LOCAL_STATIC_LIBRARIES)
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES :=
./mp3_jni.c
include $(BUILD_SHARED_LIBRARY)
你需要调整Android.mk.
从Android Studio 4.0开始,AGP (Android Gradle Plugin)支持一种名为Prefab的新机制。这使用了一个特别准备的AAR,可以在你的项目依赖关系中列出,就像你有其他外部库一样,你得到了从CMake或ndk-build链接到库所需的头和构建标志。
这类似于@alijandro的爆炸-aar方法,但它是官方支持的,并且需要更少的样板文件。例如,你只需要
find_package(first REQUIRED CONFIG)
target_link_libraries(app first::libfirst)
- Android Studio 中带有静态库的原生C++代码
- 如何在 Android Studio 4 中编译 C/C++ 原生代码
- Android Studio:如何在build.gradle中定义自定义宏(针对不同的构建变体),并让原生C / C++
- 在Android原生C++中使用Facemark opencv contrib
- 使用AAR的虚幻安卓开发
- CMake:Android Studio 原生活动项目无法在项目根目录之外找到第三方库
- Android NDK - C++ 异常会导致第三方原生库崩溃
- 如何在 gradle 原生项目中包含二进制库?
- 使用 Flutter 从 Android 上的原生编译共享库中调用函数
- exteranl原生构建问题,构建命令失败,android工作室
- build命令失败,外部原生问题android工作室
- 如何在electrolon项目中集成qt原生窗口
- Lua :在原生lua中编译,但在使用LuaJIT和sol2时C++出错
- 如何将.cpp C++原生库导入 Android Studio
- 原生 WebRTC 丢帧
- 如何使用 JNI 创建原生类?
- 如何为原生UI工具包扩展Ranorex?
- 如何从反应原生代码调用 C 函数?
- 安卓设备上的原生C++ WiFi P2P 网络是否可行?
- Android原生库链接到来自aar的另一个原生库