将静态库链接到Android中的JNI共享库

时间:2017-01-03 15:03:07

标签: android gradle android-ndk java-native-interface

我是Android新手,请原谅我,如果这看起来有点不成熟。我有两个预先构建的静态库,feta../../feta/build/libfeta.a)和mish../../mish/build/libmish.a),我有共享的JNI库。使用JNI库完全正常,但我试图通过JNI库访问fetamish。这两个库随着Android项目的不断变化和更新,因此每次构建它们时复制它们实际上都不是一个选项(如果这甚至可以解决链接问题),我不太喜欢简单地复制它们将源文件导入Android项目。

我尝试过搜索,但大多数答案都使用旧版本的系统,并希望我修改Android.mk,这是我没有的。我使用的是最新版本的Android Studio,它使用的是Gradle插件。

我尝试在各种设置中使用来自十几个教程和Stackoverflow答案的所有配置,但没有运气。

如果您回答,请提供完整且有效的build.gradle,这样我就不会遇到其他答案中遇到的同样问题(谢谢!)。

我刚刚在this教程之后问过这个问题,所以所有文件都会反映出来。

这是我得到的构建错误:

Error:A problem occurred configuring project ':app'.
> The following model rules could not be applied due to unbound inputs and/or subjects:
    android.sources { ... } @ app/build.gradle line 58, column 5
      subject:
        - android.sources Object [*]
    repositories { ... } @ app/build.gradle line 39, column 5
      subject:
        - repositories Object [*]
  [*] - indicates that a model item could not be found for the path or type.

这是build.gradle模块中的app文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.neonorb.mish_android"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++14 -Wno-implicit-exception-spec-mismatch"
            }
        }
        ndk {
            // ${targetPlatform.getName()}
            // ${buildType.getName()}
            stl "c++_static"
            abiFilters "x86_64"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

model {
    repositories {
        libs(PrebuiltLibraries) {
            feta {
                headers.srcDir "../../feta/include/"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("../../feta/build/libfeta.a")
                }
            }
        }
        libs(PrebuiltLibraries) {
            mish {
                headers.srcDir "../../mish/include/"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("../../mish/build/libmish.a")
                }
            }
        }
    }

    android.sources {
        main {
            jni {
                dependencies {
                    library "feta" linkage "static"
                    library "mish" linkage "static"
                }
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    compile 'com.google.android.gms:play-services-ads:10.0.1'
    compile 'com.android.support:design:25.1.0'
    testCompile 'junit:junit:4.12'
}

这是根(mish-android)目录之一:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

这是我的CMakeLists.txt

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             mish-android

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/mish.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       mish-android

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

这是我的目录结构,如果它有帮助的话。

enter image description here

1 个答案:

答案 0 :(得分:0)

事实证明,我需要升级我的Gradle插件。我能够删除CMakeLists.txt。我还需要将Gradle包装器版本升级到3.2以支持新的实验插件。

这是我的根build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        //classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'com.android.tools.build:gradle-experimental:0.9.0-beta1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

这是我的app build.gradle

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.2"
        defaultConfig {
            applicationId "com.neonorb.mish_android"
            minSdkVersion.apiLevel 15
            targetSdkVersion.apiLevel 25
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        ndk {
            moduleName "mish-android"
            ldLibs.add("log")
            cppFlags.add("-std=c++14")
            cppFlags.add("-Wno-implicit-exception-spec-mismatch")
            // ${targetPlatform.getName()}
            // ${buildType.getName()}
            stl "c++_static"
            abiFilters.addAll(["x86_64"])
            // only build for x86_64 because that's all Feta and Mish support atm
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file("proguard-rules.pro"))
            }
        }
        sources {
            main {
                jni {
                    source {
                        srcDir "src"
                    }
                    dependencies {
                        library "feta" linkage "static"
                        library "mish" linkage "static"
                    }
                }
            }
        }
    }
    repositories {
        libs(PrebuiltLibraries) {
            feta {
                headers.srcDir "../../feta/include/"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("../../feta/build/libfeta.a")
                }
            }
        }
        libs(PrebuiltLibraries) {
            mish {
                headers.srcDir "../../mish/include/"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("../../mish/build/libmish.a")
                }
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
}