2015-10-02 89 views
5

花了数小时寻找解决我的问题和浏览各种论坛(包括这一个)后,我终于决定问我的问题,希望它没有在其他地方得到充分的答复。Android Studio - App + NDK模块库

我试图建立一个非常复杂的体系结构:

  • 我有我编译C程序源代码中分离静态库(.a)中
  • 我在一个模块库通过JNI使用它们
  • 我想在应用程序项目中使用此库。

我第一次成功地做了以下测试 - 我已经成功地使一个模块库,而不NDK和与应用程序编译。 - 我也设法使用静态库和JNI直接在应用程序,但

我通过以下几个步骤失败: - JNI的模块和应用程序调用该模块的类不起作用内的组合。

我认为问题在于包含aar,因为在aar处于库build/outputs目录中时,我无法在应用的构建目录中找到展开的aar。此外,所有以前的测试(包括使用 JNI都成功)。

我没有使用实验模型,因为它是实验性的,并且存在已知的静态库限制。

我的项目的结构是:

- App 
    - src 
     - main 
      - java 
       - activity 
- bar 
    - src 
     - main 
      - java 
       - class 
      - jni 
       - include 
        - *.h 
       - libs 
        - abis... 
         - libmod1.a 
         - libmod2.a 
       Android.mk 
       Application.mk 
       bar.c 
       bar.h 

该应用程序的build.gradle看起来是这样的:

apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 23 
    buildToolsVersion "23.0.0" 

    defaultConfig { 
     applicationId "com.test.foo" 
     minSdkVersion 10 
     targetSdkVersion 23 
     versionCode 1 
     versionName "1.0" 
    } 

    buildTypes { 

     release { 
      debuggable   false 
      jniDebuggable  false 
      minifyEnabled  false 
     } 
     unsigned { 
      debuggable   false 
      jniDebuggable  false 
      minifyEnabled  false 
     } 
     debug { 
      debuggable   true 
      jniDebuggable  true 
      minifyEnabled  false 
     } 
    } 


    productFlavors { 
     x86 { 
      ndk { 
       abiFilter "x86" 
      } 
     } 
     mips { 
      ndk { 
       abiFilter "mips" 
      } 
     } 
     armv7 { 
      ndk { 
       abiFilter "armeabi-v7a" 
      } 
     } 
     arm { 
      ndk { 
       abiFilter "armeabi" 
      } 
     } 
     fat 
    } 

    project.ext.versionCodes = ['armeabi':1, 'armeabi-v7a':2, 'arm64-v8a':3, 'mips':5, 'mips64':6, 'x86':8, 'x86_64':9] 

    android.applicationVariants.all { variant -> 
     variant.outputs.each { output -> 
      output.versionCodeOverride = 
        project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + defaultConfig.versionCode 
     } 
    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar']) 
    compile project(":bar") 
} 

模块的build.gradle看起来是这样的:

apply plugin: 'com.android.library' 

android { 
    compileSdkVersion 23 
    buildToolsVersion "23.0.0" 

    defaultConfig { 
     minSdkVersion 10 
     targetSdkVersion 23 
     versionCode 1 
     versionName "1.0" 

     ndk { 
      moduleName "module" 
     } 
    } 
    buildTypes { 

     release { 
      debuggable  false 
      jniDebuggable false 
      minifyEnabled false 
     } 
     unsigned { 
      debuggable  false 
      jniDebuggable false 
      minifyEnabled false 
     } 
     debug { 
      debuggable  true 
      jniDebuggable true 
      minifyEnabled false 
     } 
    } 

    productFlavors { 
     x86 { 
      ndk { 
       abiFilter "x86" 
      } 
     } 
     mips { 
      ndk { 
       abiFilter "mips" 
      } 
     } 
     armv7 { 
      ndk { 
       abiFilter "armeabi-v7a" 
      } 
     } 
     arm { 
      ndk { 
       abiFilter "armeabi" 
      } 
     } 
     fat 
    } 
    sourceSets.main { 
     jniLibs.srcDir 'src/main/libs' 
     jni.srcDirs  = [] 
    } 

    task ndkBuild(type: Exec) { 
     commandLine android.ndkDirectory.getAbsolutePath()+'/ndk-build', '-C', file('src/main').absolutePath 
    } 

    tasks.withType(JavaCompile) { 
     compileTask -> compileTask.dependsOn ndkBuild 
    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
} 

我的模块jni目录内的Android.mk为: LOCAL_PATH:= $(call my-dir)

#### Mod1 
include $(CLEAR_VARS) 
LOCAL_MODULE   := mod1 
LOCAL_SRC_FILES   := libs/$(TARGET_ARCH_ABI)/libmod1.a 
include $(PREBUILT_STATIC_LIBRARY) 

#### Mod2 
include $(CLEAR_VARS) 
LOCAL_MODULE   := pxnav 
LOCAL_SRC_FILES   := libs/$(TARGET_ARCH_ABI)/libmod2.a 
LOCAL_STATIC_LIBRARIES := pxfd 
include $(PREBUILT_STATIC_LIBRARY) 

##### Parser 
include $(CLEAR_VARS) 
LOCAL_MODULE   := module 
LOCAL_C_INCLUDES  := $(LOCAL_PATH)/include 
LOCAL_LDLIBS   += -landroid -llog 
LOCAL_SRC_FILES   := bar.c 
LOCAL_STATIC_LIBRARIES := mod1 mod2 
include $(BUILD_SHARED_LIBRARY) 
+0

我补充说,如果我直接使用生成的aar:新模块>导入.jar/.aar它可以完美地工作。我宁愿不必在每次编译时都将aar复制到指定的目录。 –

回答

0

我发现类似的任务简单的解决方法:我简单地设置jniLibs.srcDir应用模块。现在我不依赖爆炸aar以获得.so文件。顺便说一句,当您决定切换到实验插件(要使用本机调试,C++语法突出显示和交叉引用以及其他细节)时,请您检查define LOCAL_SRC_FILES in ndk{} DSL

+0

我不明白它有什么用处。您将应用程序中的jniLibs.srcDir设置为模块内的libs目录?在这种情况下,您如何设法让应用程序看到aar中的类?我的问题是,即使在酒吧模块库中的类不适用于应用程序。 –

+0

我尝试了你的解决方案,我确实在我的APK中链接了库,但AAR的类仍然从APK中丢失,无法在应用中实例化。 –

+0

该库不会构建其本机代码;它伪装成一个纯Java模块。你说你在你的一个初步实验中成功地使用了一个图书馆,不是吗? –