【问题标题】:Android -- get MEID from JNIAndroid -- 从 JNI 获取 MEID
【发布时间】:2012-07-25 05:51:01
【问题描述】:

我在 Android 中工作,正在编写一些 JNI 代码,并且正在寻找一种从设备查询移动设备标识符 (MEID) 的方法。

http://en.wikipedia.org/wiki/Mobile_equipment_identifier

我正在尝试编写可以在 Android 设备上自行运行的 C 或 C++ 代码,所以我认为我不能使用 Java(即从TelephonyManager 获取 MEID)。

搜索 StackOverflow 发现:Is there an android shell or adb command that I could use to get a device's IMEI/MEID?

好的,dumpsys iphonesubinfo 可以获得我需要的信息。它有效!

我找不到 dumpsys 的源代码,除非它是 Android 源代码的一部分。所以我下载了那个......我的硬盘在下载完成之前就已经装满了,但我确实得到了源代码到dumpsys。这是一个非常短的 C++ 文件。它所做的只是查询 Android 的IBinder 接口。

所以,我的问题:

0) 有什么方法可以只使用 NDK 中的内容编写针对 IBinder 的查询? dumpsys.cpp 使用的包含文件不在 NDK 中,并且 NDK 目录中的 grep 在任何包含文件或代码示例中都没有找到 IBinder,所以我的猜测是“否”(但我想错了)。

1) 还有其他获取 MEID 的好方法吗?

我在认真考虑我应该只使用system("dumpsys iphonesubinfo > /tmp/myprogname_dumpsys.tmp",然后打开生成的文件并解析它。这应该可行,但我很难称其为优雅......而且我不确定dumpsys 是否在每台 Android 设备上都可用。

编辑:使用system() 运行dumpsys 的想法行不通,因为dumpsys 需要android.permission.DUMP 而Android 不再允许非系统应用拥有该权限。

Dumpsys permission denial in java

【问题讨论】:

  • dumpsys 是一个平台系统文件,所以我认为它适用于所有安卓设备。
  • 另外,如果你想写一个像dumpsys 这样的查询,你可以通过 NDK 但我记得你拥有所有需要的权限。
  • @user370305 -- 如何通过 NDK 编写类似dumpsys 的查询?
  • 使用与dumpsys 相同的代码。但我怀疑dumpsys 有权访问所有系统文件。
  • 我不能使用 dumpsys 使用的相同代码,因为 dumpsys 使用的代码不在 NDK 中。我不希望我的代码必须依赖于作为 Android 系统源代码一部分但未放入 NDK 的“秘密”代码。

标签: android c++ c android-ndk java-native-interface


【解决方案1】:

我相信 Dalvik 实现了与 JVM 相同的所有 JNI 接口,因此虽然有点繁琐,但完全可以通过 JNI 从本机代码调用任意 Java 类和方法。

/* assuming you already have */
JNIEnv *env;
jobject context;
/* then call (with error-checking) */
jclass cls = (*env)->FindClass(env, "android/context/Context");
jmethodId mid = (*env)->GetMethodID(env, context_cls, "getSystemService",
    "(Ljava/lang/String;)Ljava/lang/Object;");
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "TELEPHONY_SERVICE",
    "Ljava/lang/String;");
jstring str = (*env)->GetStaticObjectField(env, cls, fid);
jobject telephony = (*env)->CallObjectMethod(env, context, mid, str);
cls = (*env)->FindClass(env, "android/telephony/TelephonyManager");
mid =(*env)->GetMethodID(env, cls, "getDeviceId", "()Ljava/lang/String;");
str = (*env)->CallObjectMethod(env, telephony, mid);
jsize len = (*env)->GetStringUTFLength(env, str);
char* deviceId = calloc(len + 1, 1);
(*env)->GetStringUTFRegion(env, str, 0, len, deviceId);
(*env)->DeleteLocalRef(env, str);
/* to get a string in deviceId */

【讨论】:

  • 调用我的 JNI 代码的测试应用程序在 CallObjectMethod() 行崩溃。我传入了我的 JNI 函数作为参数得到的 jobject 实例……这是正确的做法吗?
  • 我应该早点说:我喜欢这种方法,我希望我可以让它发挥作用。谢谢你的建议。
  • @steveha 我忘了TelephonyManager#getDeviceId() 不是Context 上的方法;你需要先getSystemService(TELEPHONY_SERVICE)。我也没有测试过,但现在应该更接近了。
  • 我正在努力实现您的想法,但遇到了障碍。如果可以,请查看我的后续问题:stackoverflow.com/questions/12103411/… 谢谢。
  • 谢谢你的回答,但是为什么jclass cls = (*env)->FindClass(env, "android/context/Context");总是返回NULL?(env没有问题)
【解决方案2】:

在 Java 端检索 MEID,然后将其作为 jstring 参数传递给您的 JNI 函数。它会比从 C 回调 Java 更干净。

至于如何检索,请参阅 Abhilasha 的回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2018-10-27
    • 2014-10-26
    • 1970-01-01
    相关资源
    最近更新 更多