これは私が尋ねた別の質問のフォローアップです:Android-JNIからMEIDを取得します
Androidで携帯電話のIDを取得しようとしています。いくつかのJNIコードと、JNIコードを呼び出すための簡単なテストアプリがあります。これが私の簡単なテストアプリからのJavaコードです。
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String id = tm.getDeviceId();
文字列id
は、必要な電話ID値に設定されます。しかし、私はそれをJNIから取得する必要があり、上記のコードを使用してID値を渡すだけでは受け入れられない解決策です。(これは、一部のJNIコードをある程度改ざん防止するためであり、Javaレイヤーが正しいID値を送信することを信頼するべきではありません。)
これが私が書いたJNIコードですが、エラー処理が削除されているため、わかりやすくなっています。示された行まで機能し、その後アプリ全体がクラッシュします。
// "env" and "obj" are passed to a JNI function and are used unmodified in this code
// JNIEnv *env, jobject obj
jclass cls_context = NULL;
jclass cls_tm = NULL;
jobject tm = NULL;
jmethodID mid;
jfieldID fid;
jstring jstr;
jsize len_jstr;
cls_context = (*env)->FindClass(env, "android/content/Context");
fid = (*env)->GetStaticFieldID(env, cls_context, "TELEPHONY_SERVICE",
"Ljava/lang/String;");
jstr = (*env)->GetStaticObjectField(env, cls_context, fid);
mid = (*env)->GetMethodID(env, cls_context, "getSystemService",
"(Ljava/lang/String;)Ljava/lang/Object;");
tm = (*env)->CallObjectMethod(env, obj, mid, jstr); // THIS LINE CRASHES
cls_tm = (*env)->FindClass(env, "android/telephony/TelephonyManager");
mid = (*env)->GetMethodID(env, cls_tm, "getDeviceId",
"()Ljava/lang/String;");
jstr = (*env)->CallObjectMethod(env, tm, mid);
len_jstr = (*env)->GetStringUTFLength(env, jstr);
(*env)->GetStringUTFRegion(env, jstr, 0, len_jstr, buf_devid);
問題はそれが正しいことではないと思うobj
が、もしそうなら、私は何が正しいかわからない。それがJNI関数に渡されるのは、Javaコードobj
の場合と同じではありませんか?this
編集:さて、JNI関数に型の引数を追加し、その引数jobject
のコピーを明示的に渡しthis
てから、それをCallObjectMethod()
(上記のコードでクラッシュする引数)に渡すと、すべてが機能することがわかりました。 。インスタンスを取得しTelephonyManager
、電話ID値を照会できます。
ロギングマクロを使用して、obj
ポインターと渡されたポインターをログに記録しましたthis
。それらは類似した番号(互いに近いアドレス)ですが、同一ではありません。obj
したがって、JavaVM内からのある種のオブジェクト参照だと思います...実際には。と同じではありませんthis
。
JNI関数では、最初の2つの引数はとJNIEnv *env
ですjobject obj
。その2番目のものは何のためですか?私はそれで何ができますか?それを使用して呼び出す方法はありますか、それともgetSystemService
追加の引数を渡して渡す必要がありthis
ますか?