Android本机库链接到来自aar

时间:2015-07-23 19:33:16

标签: java android c++ android-ndk multiplatform

我有一个奇怪的问题。我有一个aar库,它包含并使用本机.so库。现在,我想编写另一个lib,它依赖于该库,并且还具有本机部分,具体取决于来自第一个lib的本机lib。依赖库使用第一个lib中的本机代码和java包装器。

我想知道,有没有办法,如何通过标准gradle依赖(使用第一个lib中复制的头文件)来做到这一点?或者我是否可以直接从源代码构建第二个库?

为什么我需要这个: 我们有一个具有基本功能的多平台lib,用于android as aar。这个lib可以在标准的android应用程序中使用,我们在多个项目中使用它,它没有其他本机代码。

但在一个应用程序中,我们想要编写多平台共享应用程序代码,具体取决于lib,我希望将这些库分开。

谢谢!

3 个答案:

答案 0 :(得分:6)

Here是基于CharAdapter.adapt("xyz").forEach(System.out::print) 的基本可行示例,您可以对OpenCV执行相同操作。

准备第一个lib如下

打包first libjar并导出*.so(请参阅链接项目中的文件headers如何将标题附加到aar)。

例如,您可以OpenCV4Android/opencv/build.gradle建立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

答案 1 :(得分:1)

正如你提到的Gradle,我假设你正在使用 最新的Android Studio。我使用1.2.2并且发现它很容易 从浮动的许多教程中构建简单的NDK项目 周围,​​但令人沮丧的难以建立一个NDK项目 任何复杂性。我会总结一下我的发现,但我非常高兴 建议阅读 this blogthis StackOverflow

我的项目与您的项目类似,但并不完全相同。我的诀窍 正在弄清楚如何让Android Studio使用我的Android.mk 找到正确的makefile变量。希望这会有所帮助。

股票Android Studio将完全忽略任何自定义 您创建的Android.mk文件,而不是自动生成自己的文件。 要更正此问题,您必须先破解 build.gradle 项目的脚本,位于project/app/build.gradle。 如果需要,您可能会破解顶级build.gradle。

这是我的黑客build.gradle。我建立在Windows机器上,所以我 仅针对Windows攻击它。如果您使用OSX,请取消注释行 或Linux。

<强>项目/应用/的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 -&gt; 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。

答案 2 :(得分:0)

从Android Studio 4.0开始,AGP(Android Gradle插件)支持一种称为Prefab的新机制。这使用了特别准备的AAR,可以像其他外部库一样在项目依赖项中列出该AAR,并且可以获得从CMake或ndk-build链接到该库所必需的头和构建标志。

这类似于@alijandro的exploded-aar approach,但得到官方支持,并且所需的样板更少。例如。您只需要

find_package(first REQUIRED CONFIG)
target_link_libraries(app first::libfirst)