简体   繁体   中英

Get ANDROID_ID using Android NDK - stale local reference error

I'm developing an application for which one of the requirements is that I gather the device's ANDROID_ID through NDK.

After looking at countless threads, answers and references, I came up with a initial implementation that calls a static method on the class I use to do all interactions between the Java and Native layers. The only issue is it throws the following error right at the bottom, when retrieving the ANDROID_ID , and just exits after that.

JNI ERROR (app bug): accessed stale local reference 0x5d6892a9 (index 9386 in a table of size 11)

I know the error occurs on the last function call ( CallStaticObjectMethod ) because I've tried adding logs to it and it executes everything else. Here's the code I'm currently using:

SampleActivity.java

class SampleActivity {

    // ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        NativeService.initialize(this);

        // ...
    }
}

NativeService.java

public class NativeService {

    // ...

    public native static boolean initialize(Context ctx);
}

Native.cpp

JNIEXPORT jboolean JNICALL Java_com_company_mobile_NativeService_initialize(JNIEnv * env, jobject obj,
    jobject ctx
) {
    jclass contextClass = env->GetObjectClass(ctx);
    if (contextClass == NULL) {
        return false;
    }

    jmethodID getContentResolverMID = env->GetMethodID(contextClass, "getContentResolver", "()Landroid/content/ContentResolver;");
    if (getContentResolverMID == NULL) {
        return false;
    }

    jobject contentResolverObj = env->CallObjectMethod(ctx, getContentResolverMID);
    if (contentResolverObj == NULL) {
        return false;
    }

    jclass settingsSecureClass = env->FindClass("android/provider/Settings$Secure");
    if (settingsSecureClass == NULL) {
        return false;
    }

    jmethodID getStringMID = env->GetStaticMethodID(settingsSecureClass, "getString", "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;");
    if (getStringMID == NULL) {
        return false;
    }

    // Offending line
    jstring androidId = (jstring) env->CallStaticObjectMethod(settingsSecureClass, getStringMID, contentResolverObj, "android_id");
    if (androidId == NULL) {
        return false;
    }

    return (strcmp((char *)androidId, "0123456789ABCDEF") == 0);
}

The second argument to getString should be an instance of java/lang/String . The literal "android_id" is an array of char , which decays into a (const) char* .

To construct a java/lang/String instance from a const char* string you should use the JNI function NewStringUTF :

jstring idStr = (jstring) env->NewStringUTF("android_id");
// Do relevant error checking, and then:
jstring androidId = (jstring) env->CallStaticObjectMethod(settingsSecureClass, getStringMID, contentResolverObj, idStr);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM