java.lang.UnsatisfiedLinkError: Реализация для Boolean не найдена
Я использую файлы ".so" в своем проекте, но он выдает следующую ошибку "java.lang.UnsatisfiedLinkError: Реализация для Boolean не найдена", я уже пытаюсь воссоздать ".so" с помощью Cygwin и поместить его в папку jniLibs, а также с помощью create баночка этого, но это дает ту же ошибку.
Но тот же файл ".so" работает в моем существующем проекте. Я пытаюсь так много способов, но это не работает вообще, что я могу сделать?
com.amaze.filemanager E / art: не найдена реализация для логического значения com.amaze.filemanager.scanner.SignatureLib.InitScanner(java.lang.String, java.lang.String) (пробовал:07.463 4579-4934/com.amaze.filemanager E/AndroidRuntime: ФАКТИЧЕСКОЕ ИСКЛЮЧЕНИЕ: Thread-5230 Процесс: com.amaze.filemanager, PID: 4579 java.lang.UnsatisfiedLinkError: Реализация не найдена для логического значения 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) на 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 ответа
Да, нужна была полная трассировка стека - вы изначально прервали ее в месте, которое не имело смысла. Он говорит о том, что в вашем.so-файле нет функции InitScanner - либо вы неправильно назвали его в C-файле, либо неправильно установили сигнатуру, либо ее вообще нет. Или, если вы использовали C++, вы забыли расширить функцию C.
В моем 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();
}
}
Если несоответствие имени функции и сигнатуры не имеет места, то вы должны написать extern "C" перед каждой функцией в файле cpp, поэтому фактический формат соглашения об именах
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, которая является нативным эквивалентом String в Java.
JNICALL
: C
содержит директивы компилятора, необходимые для обеспечения того, чтобы функция обрабатывалась с соответствующим соглашением о вызовах JNI.
<JAVA_CLASS>
:
Связывающий класс Java, к которому привязана эта функция. В нашем примере это будет MainActivity, так как это класс Java, который будет использовать эту функцию.
<PACKAGE_NAME>
:
Имя пакета, где ранее определено <JAVA_CLASS>
находится в. Замените точки (.) подчеркиванием (_).
<METHOD_NAME>
:
Это имя должно совпадать с тем, которое вы объявляете внутри соединения. В нашем примере мы объявили нативный метод getNativeString(). В этом случае также должно быть getNativeString().
JNIEnv *env
:
Указатель на структуру (точнее, таблицу функций), в которой хранятся все указатели вспомогательных функций JNI, включая тот, который мы вызываем в нашем примере, NewStringUTF(string). Чтобы использовать эти функции, вам нужно #include.
jobject obj
:
Java-объект, соответствующий подключению<JAVA_CLASS>
,
<METHOD_PARAMETERS>...:
Разделенный запятыми список входных аргументов, которые должен принимать нативный метод. В нашем примере у нас нет входных аргументов для нашей функции getNativeString (), и поэтому мы оставляем это поле пустым.