java.lang.UnsatisfiedLinkError:找不到布尔

时间:2016-12-16 06:17:09

标签: android java-native-interface unsatisfiedlinkerror

我用" .so"我的项目中的文件,但它出现以下错误" java.lang.UnsatisfiedLinkError:找不到布尔"的实现,我已经尝试重新创建" .so"使用Cygwin并将其放在 jniLibs 文件夹中,并使用它创建 jar ,但它也会出现同样的错误。

但同样的" .so"文件正在我现有的项目中工作。我尝试了很多方法,但它根本不起作用,我该怎么办?

  

com.amaze.filemanager E / art:找不到boolean com.amaze.filemanager.scanner.SignatureLib.InitScanner(java.lang.String,java.lang.String)的实现(尝试过Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner和Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner__Ljava_lang_String_2Ljava_lang_String_2)   12-19 11:47:07.463 4579-4934 / com.amaze.filemanager E / AndroidRuntime:FATAL EXCEPTION:Thread-5230                                                                        进程:com.amaze.filemanager,PID:4579                                                                        java.lang.UnsatisfiedLinkError:找不到boolean com.amaze.filemanager.scanner.SignatureLib.InitScanner(java.lang.String,java.lang.String)的实现(尝试过Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner和Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner__Ljava_lang_String_2Ljava_lang_String_2)                                                                            at com.amaze.filemanager.scanner.SignatureLib.InitScanner(Native Method)                                                                            在com.amaze.filemanager.scanner.SignatureLib.InitializeScanner(SignatureLib.java:42)                                                                            在com.amaze.filemanager.scanner.Signature。(Signature.java:62)                                                                            在com.amaze.filemanager.ScanForVirusActivity $ 1.run(ScanForVirusActivity.java:66)

public class SignatureLib {

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

    SharedPreferencesUtils spu;
    Context context;

    public SignatureLib(Context context) {
        this.context = context;
    }

    private native boolean InitScanner(String strDBPath, String dbPathTemp);

    private native boolean DeInitScanner();

    private native String checkVirus(String filepath);

    private native boolean UploadFile(String FilePath, String DeviceID, String path);

    private native boolean DownloadFile(String FilePath, String DeviceID, String path);

    private native boolean IsGameApp(String AppName);

    private native boolean SetUpdateInProgressStatus(boolean bStatus);

    public boolean InitializeScanner(String strDBPath) {

        spu = new SharedPreferencesUtils();
        String packageName = context.getPackageName();
        String dbPathTemp = "data/data/" + packageName + "/";

        return InitScanner(strDBPath, dbPathTemp);
    }

}

2 个答案:

答案 0 :(得分:2)

是的,需要完整的堆栈跟踪 - 你最初在一个毫无意义的地方打破了它。它的说法是你的.so文件没有InitScanner功能 - 你在C文件中错误地命名它,你的签名错误,或者根本就没有。或者,如果您使用C ++,则忘记了C函数的外部。

答案 1 :(得分:-1)

在我的java文件中,我已经在下面的静态块

中加载了名为“native-lib”的库名
package primeno.naval.com.primenumberusingndk;
static
{
  System.loadLibrary("native-lib");
}

这里我宣布了两个函数,它们的实现是在CPP文件中

public native String stringFromJNI();
public native boolean isPrime(int n);

带有上述功能实现的cpp文件

extern "C"
JNIEXPORT jstring JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jboolean JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_isPrime(JNIEnv *env,jobject ,jint no)
{
PrimeNumber primeNumber(no);
return primeNumber.isPrime();
}

或者你也可以这样做

extern "C" {

    JNIEXPORT jstring JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_stringFromJNI(
    JNIEnv *env,
    jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
    }

    JNIEXPORT jboolean JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_isPrime(JNIEnv *env,jobject ,jint no)
    {
    PrimeNumber primeNumber(no);
    return primeNumber.isPrime();
    }
}

如果函数和签名名称不匹配,则必须在cpp文件中的每个函数之前编写extern“C”, 所以命名约定的实际格式是

extern "C" JNIEXPORT <RETURN_TYPE> JNICALL Java_<PACKAGE_NAME>_<JAVA_CLASS>_<METHOD_NAME>(
JNIEnv *env, jobject obj, <METHOD_PARAMETERS>...) {
...
}

extern "C"

使C ++函数名具有C链接的语句。为了支持函数重载,C ++编译器破坏函数名称,这意味着C ++函数名称与C中的函数名称不同。没有extern“C”,您的本机函数的签名将与Java中的声明(在运行时)不匹配。简而言之,如果您正在编写本机C ++而不是C语言,那么每个方法都需要这个语句。

JNIEXPORT

包含确保正确导出函数所需的编译器指令。

<RETURN_TYPE>

返回JNI方法的类型,通常是Java类型的本机版本。例如,在上面刚编写的方法中,您将返回一个jstring,它是Java中String的本机等价物。

JNICALL:C

ontains编译器指令,以确保使用正确的JNI调用约定处理该函数。

<JAVA_CLASS>

此函数所依赖的连接Java类。在我们的示例中,这将是MainActivity,因为这是将使用此函数的Java类。

<PACKAGE_NAME>

先前定义的<JAVA_CLASS>所在的包名称。用下划线(_)替换点(。)。

<METHOD_NAME>

此名称应与您在连接中声明的名称相同。在我们的示例中,我们声明了本机方法getNativeString()。在这种情况下,也应该是getNativeString()。

JNIEnv *env

指向存储所有JNI辅助函数指针的结构(确切地说是函数表)的指针,包括我们在示例中调用的指针NewStringUTF(string)。为了能够使用这些功能,您需要#include。

jobject obj

与连接<JAVA_CLASS>对应的Java对象。

<METHOD_PARAMETERS>...:

逗号分隔本机方法应该采用的输入参数列表。在我们的示例中,我们的getNativeString()函数没有任何输入参数,因此留空。