我用" .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);
}
}
答案 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()函数没有任何输入参数,因此留空。