【问题标题】:Make an Android library embedding JNI : No implementation found制作嵌入 JNI 的 Android 库:未找到实现
【发布时间】:2016-08-02 12:34:28
【问题描述】:

我的目标是构建一个嵌入 superpowered 库的 Android 库。该库提供 Android 静态库(.a 文件)和 C++ 头文件。

我已经创建了一个模块(类型为 Android 库),因此它使用 superpowered 库:

  • 我配置了 graddle,所以它允许 NDK / JNI
  • 我包含了与 superpowered 相关的 .a 文件和头文件
  • 在我的 Java 类中,我设置了映射到 cpp 方法的本地方法。

为了创建这个模块,我高度使用了 superpowered 提供的 Cross Example 示例。它是一个 Android 应用程序,现在作为第一步,我只想将它分成两部分:一个应用程序和一个 Android 库。

在我的 Android 应用程序中,我向该模块添加了依赖项。但是当我调用一个调用 JNI 方法的方法时,我得到这个错误:

E/art: No implementation found for void
  com.example.mylib.MyDSP.onPlayPause(boolean) 
  (tried Java_com_example_mylib_MyDSP_onPlayPause 
  and Java_com_example_mylib_MyDSP_onPlayPause__Z)

关于为什么它不起作用的任何想法?


来源:


在 Android 库中:

我的java类MyDSP(MyDSP.java):

package com.example.mylib;

public class MyDSP {

    public  void CallJniCppMethod() {

        this.onPlayPause(true);
    }

    private native void onPlayPause(boolean play);

    static {
        System.loadLibrary("SuperpoweredExample");
    }

}

在 cpp 文件中:SuperpoweredExample.cpp (SuperpoweredExample.cpp)

extern "C" JNIEXPORT void Java_com_example_mylib_MyDSP_onPlayPause(JNIEnv * __unused javaEnvironment, jobject __unused obj, jboolean play) {
    //example->onPlayPause(play);

    // We do nothing, but it's OK,
    // Just want to see if the JNI call does not throw exception
}

h 文件:SuperpoweredExample.h (SuperpoweredExample.h )

void onPlayPause(bool play);

lib (build.gradle) 的 graddle 配置:

应用插件:'com.android.model.library'

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def superpowered_sdk_path = properties.getProperty('superpowered.dir')

model {
    repositories {
        libs(PrebuiltLibraries) {
            superpowered { // this is where you declare the "superpowered" static library
                headers.srcDir "${superpowered_sdk_path}"
                binaries.withType(StaticLibraryBinary) { // attaching library files to each platform
                    def platformName = targetPlatform.getName()
                    if (platformName == "armeabi-v7a") {
                        staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidARM.a")
                    } else if (platformName == "arm64-v8a") {
                        staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidARM64.a")
                    } else if (platformName == "x86") {
                        staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidX86.a")
                    } else if (platformName == "x86_64") {
                        staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidX86_64.a")
                    }
                }
            }
        }
    }

    android {
        compileSdkVersion 24
        buildToolsVersion "24.0.1"

        defaultConfig {
            minSdkVersion.apiLevel = 21 // more than 95% of all active Android devices
            targetSdkVersion.apiLevel = 21
            versionCode 1
            versionName "1.0"
        }

    }


    android.ndk { // your application's native layer parameters
        moduleName = "SuperpoweredExample"
        platformVersion = 21
        stl = "c++_static"
        CFlags.addAll(["-O3", "-fsigned-char"]) // full optimization, char data type is signed
        cppFlags.addAll(["-fsigned-char", "-I${superpowered_sdk_path}".toString()])
        ldLibs.addAll(["log", "android", "OpenSLES"]) // load these libraries: log, android, OpenSL ES (for audio)
        abiFilters.addAll(["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]) // these platforms cover 99% percent of all Android devices
    }

    android.sources.main.jni {
        source {
            srcDir "jni"
            srcDir "${superpowered_sdk_path}/AndroidIO"
        }
        dependencies {
            library "superpowered" linkage "static" // this is where you attach the "superpowered" static library to your app
        }
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.1.1'
}

注意:

我所有的资源都可以在 Github 上找到:https://github.com/DelattreAdixon/Superpowered-Android-Lib

为了构建/运行它,您必须更改 le local.properties 内容,使其与您的 ndk/sdk/superpowered 路径匹配。

【问题讨论】:

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


    【解决方案1】:

    如果您使用experimental gradle,它会负责创建 cpp 文件,在此文件中创建函数并将其与您的 java 类链接。

    尝试删除cpp文件,点击private native void onPlayPause(boolean play)标记它,然后alt+intro,它会显示一个对话框来自动生成cpp文件和里面的函数。

    【讨论】:

    • 按照您的说明,它会生成一个 .c 文件(不带 .h),方法是(我保留为空)。并且在运行应用程序时,它可以正常工作(没有抛出异常)。现在,由于我想要一个 .cpp 文件(我的方法将包含 cpp 指令),我尝试使用 .cpp 扩展名重命名生成的文件。现在这导致了同样的异常:没有找到实现。
    • 你忘记了这个标志来构建 c++ 文件 cFlags "-std=c++11 -fexceptions"
    猜你喜欢
    • 1970-01-01
    • 2013-04-08
    • 2011-01-12
    • 2022-06-14
    • 2010-12-22
    • 1970-01-01
    • 2018-08-04
    • 2020-11-28
    • 2021-07-16
    相关资源
    最近更新 更多