Android的NDK崩溃CallObjectMethod调用getSystemService [英] Android NDK crash in CallObjectMethod calling getSystemService

查看:3627
本文介绍了Android的NDK崩溃CallObjectMethod调用getSystemService的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个后续行动的另一个问题,我问: Android的 - 从JNI得到MEID

This is a follow-up to another question I asked: Android -- get MEID from JNI

我想获得一个手机的ID在Android系统。我有一些JNI code和一个简单的测试程序来调用JNI code。这里是从我简单的测试应用程序的Java工作code:

I am trying to get the ID of a phone in Android. I have some JNI code and a simple test app to call the JNI code. Here is working Java code from my simple test app:

TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String id = tm.getDeviceId();

字符串 ID 设置为我想要的手机ID值。但是,我需要从JNI得到它,只是使用上述code和传递ID值不是一个可接受的解决方案。 (这是为了使一些JNI code稍微防篡改的,我不应该相信的Java层发出一个正确的ID值。)

The string id is set to the phone ID value that I want. But I need to get it from JNI, and just using the above code and passing the ID value in is not an acceptable solution. (This is to make some JNI code somewhat tamper-proof and I shouldn't trust the Java layer to send a correct ID value.)

下面是我写的JNI code,错误处理删除,因此很容易效仿。它的工作原理,直到指定行,然后整个应用程序崩溃。

Here is the JNI code that I have written, with error handling removed so it is easier to follow. It works until the indicated line, and then the whole app crashes.

// "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 不是通过正确的事情,但即便如此我不知道什么是正确的事情。是不是 OBJ 获取传递给JNI函数一样的东西这个在Java code?

I think the problem is that obj isn't the right thing to pass, but if so I have no idea what is the right thing. Isn't obj that gets passed to the JNI function the same thing as this in the Java code?

编辑:好的,我们已经想通了,如果我们添加类型的一个额外的参数 jobject 来JNI函数,并明确通过这个在这样的说法,然后传递到 CallObjectMethod()(一个在上面code崩溃),一切正常。我们得到了我们的 TelephonyManager 实例,我们可以查询电话ID值。

Okay, we have figured out that if we add an extra argument of type jobject to the JNI function, and explicitly pass a copy of this in that argument, and then pass that to CallObjectMethod() (the one that crashes in the above code), everything works. We get our TelephonyManager instance and we can query the Phone ID value.

使用记录宏,我记录了 OBJ 指针和传入的这个指针。它们是相似的号码(地址彼此接近的),但不完全相同。所以我觉得 OBJ 是某种来自Java VM内的对象引用的......它实际上不是一样的这个

Using a logging macro, I logged the obj pointer and the passed-in this pointer. They are similar numbers (addresses close to each other) but not identical. So I think obj is some sort of object reference from inside the Java VM... it is not actually the same as this.

在一个JNI功能,前两个参数是的JNIEnv * ENV jobject OBJ 。什么是第二个呢?我可以用它做什么?有什么办法,我可以用它打电话 getSystemService 否则我将不得不通过一个额外的参数,并在通过这个

In a JNI function, the first two arguments are JNIEnv *env and jobject obj. What is that second one for? What can I do with it? Is there any way I can use it to call getSystemService or will I have to pass an extra argument and pass in this?

推荐答案

这个问题似乎涉及到Java继承:在Java中,你可以叫 this.getSystemService()和它的作品,即使这个其实不是上下文的一个实例。当你的JNI调用,调用只是失败。

The problem seems to be related to Java inheritance: in Java, you can call this.getSystemService() and it works, even though this is not actually an instance of Context. When you make the JNI call, the call simply fails.

因此​​,我们的解决方案是有我们的Andr​​oid应用添加一个 .getApplicationContext()方法实际上功能作为自己的阶级的一部分。这反过来又调用实际 getSystemService()并返回结果。

So our solution was to have our Android app add a .getApplicationContext() method function actually as part of its own class. This in turn calls the actual getSystemService() and returns the result.

在code并没有改变:我们仍然呼吁

The code didn't change: we are still calling

mid = (*env)->GetMethodID(env, cls_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");

但现在它的工作原理,当有在呼吁我们的JNI函数的类 .getSystemService()方法。因此,在JNI调用,在 ENV 参数并重新present 这个(这是不一样......我印刷的价值这个为指针,并印 ENV ,和他们是不一样的,但他们肯定是相关的)。

but now it works, when there is a .getSystemService() method in the class that is calling our JNI function. So, the env argument in a JNI call does represent this (it's not identical... I printed the value of this as a pointer, and printed env, and they are not the same but they are definitely related).

这篇关于Android的NDK崩溃CallObjectMethod调用getSystemService的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆