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 (), и поэтому мы оставляем это поле пустым.

Другие вопросы по тегам