Reputation: 27021
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);
}
Upvotes: 3
Views: 2544
Reputation: 58517
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);
Upvotes: 1