0

I wanted to check whether specific set of packages are installed on the device in c++ ndk code as I don't wanted to check in Java code, so after research I had written code comparing code in java. My code checks packageinfo and if exception is thrown it treats it as package not found. Here is my code snippet

jboolean
checkpackages(JNIEnv *env, jobject context, char packagePaths[][MAX_STRING_SIZE], int size) {

    jstring packageName;
    jobject packageManagerObj;
    jobject packageInfoObj;
    jclass contextClass = env->GetObjectClass(context);
    jmethodID getPackageNameMid = env->GetMethodID(contextClass, "getPackageName",
                                                   "()Ljava/lang/String;");
    jmethodID getPackageManager = env->GetMethodID(contextClass, "getPackageManager",
                                                   "()Landroid/content/pm/PackageManager;");
    jclass packageManagerClass = env->FindClass("android/content/pm/PackageManager");
    jmethodID getPackageInfo = env->GetMethodID(packageManagerClass, "getPackageInfo",
                                                "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jclass packageInfoClass = env->FindClass("android/content/pm/PackageInfo");
    jfieldID versionCodeFid = env->GetFieldID(packageInfoClass, "versionCode", "I");
    packageManagerObj = env->CallObjectMethod(context, getPackageManager);
    for (int i = 0; i < size; i++) {
        const char *path = packagePaths[i];
        //packageName = env->NewStringUTF(path);

         jstring packageNamet = env->NewStringUTF("com.mypackgage");
        packageInfoObj = env->CallObjectMethod(packageManagerObj, getPackageInfo, packageNamet, 0x0);
        int versionCode = env->GetIntField(packageInfoObj, versionCodeFid);
        if(env->ExceptionCheck()) {
            env->ExceptionClear();

            __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NATIVE: Package manager: Exception");
        } else {
              return true;
        }
    }

    return false;
}

Here even after putting exception check my code crashes with pending exception

JNI DETECTED ERROR IN APPLICATION: JNI GetIntField called with pending exception android.content.pm.PackageManager$NameNotFoundException

My code works if I put existing package on device.I'm using Android studio 4.0.1 and ndk 21.3. Please help me in how can I handle this or any other way we can do.

1 Answer 1

0

As the documentation for getPackageInfo says, it can throw a NameNotFoundException.

You don't check for any exceptions until after GetIntField, which means that you might end up calling GetIntField with a pending exceptions, which isn't allowed.

Sign up to request clarification or add additional context in comments.

4 Comments

I had put code in try{}catch(std::exception){} but it was not working so I searched and got that to handle exception in ndk we should use if(env->ExceptionCheck()) { env->ExceptionClear(); //to clear exception before any other ndk code is run. } so used it in the code.
Like I said, you're not checking for Java exceptions until after GetIntField, but the CallObjectMethod just before it can throw an exception, and it is an error to call JNI functions with a pending Java exception. You need to check for and handle Java exceptions after every JNI call that can throw an exception.
Yes Michael, as I have mentioned in my above comment I have added code int versionCode = env->GetIntField(packageInfoObj, versionCodeFid); in try catch block but it was not going in catch block so after researching I came to know that to handle exception in ndk JNI c we have to check just below the statement that may result in exception if exception has occured by using statement env->ExceptionCheck(). try catch block doesn't get executed. Refered developer.com/java/data/exception-handling-in-jni.html
" in try catch block but it was not going in catch block" Because try/catch in C++ is for catching C++ exceptions. But what you're dealing with here are Java exceptions, which C++ has no idea about. Hence the need to use ExceptionCheck/Occurred/Clear. And again: checking for Java exceptions only after GetIntField is not enough. You need to do that after every single JNI call that might throw a Java exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.