1

I'm working in Android, writing some JNI code, and I'm looking for a way to query the Mobile Equipment Identifier (MEID) from the device.

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

I'm trying to write C or C++ code that can run by itself on an Android device, so I don't think I can use Java (i.e., get MEID from TelephonyManager).

A search of StackOverflow finds: Is there an android shell or adb command that I could use to get a device's IMEI/MEID?

Okay great, dumpsys iphonesubinfo can get the info I need. And it works!

I couldn't find the source for dumpsys except as part of the source for Android. So I downloaded that... my hard disk filled up before the download finished, but I did get the source code to dumpsys. It is a surprisingly short C++ file. All it does is query Android's IBinder interface.

So, my questions:

0) Is there any way I can write a query against IBinder using just the stuff in the NDK? The include files used by dumpsys.cpp are not in the NDK, and grep in the NDK directory didn't find IBinder in any include files or code samples, so my guess is "no" (but I would like to be wrong).

1) Is there any other good way to get the MEID?

I'm seriously thinking I should just use system("dumpsys iphonesubinfo > /tmp/myprogname_dumpsys.tmp" and then open the resulting file and parse it. That should work, but I would hardly call it elegant... and I'm not sure if dumpsys is available on every Android device or not.

EDIT: The idea of using system() to run dumpsys will not work, because dumpsys needs android.permission.DUMP and Android no longer allows non-system apps to have that permission.

Dumpsys permission denial in java

valiano
  • 16,433
  • 7
  • 64
  • 79
steveha
  • 74,789
  • 21
  • 92
  • 117
  • `dumpsys` is a platform system file so I think its available on every android device. – user370305 Jul 25 '12 at 06:04
  • Also if you want to write a query like `dumpsys` you can trough **NDK** but also keep in my mind you have all permissions which needed. – user370305 Jul 25 '12 at 06:07
  • @user370305 -- How can I write a query like `dumpsys` through the NDK? – steveha Jul 25 '12 at 06:08
  • Use the same code, which `dumpsys` use. But I have doubt of `dumpsys` has all right to access all system files. – user370305 Jul 25 '12 at 06:13
  • I cannot use the same code which `dumpsys` uses, because `dumpsys` uses code that is not in the NDK. I don't want my code to have to depend on "secret" code that is part of the Android system source code but is not put into the NDK. – steveha Jul 25 '12 at 07:16

2 Answers2

1

I believe Dalvik implements all the same JNI interfaces that the JVM does, so while it's a bit fiddly, it's perfectly possible to make calls from native code through JNI to arbitrary Java classes and methods.

/* 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 */
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • My test app that calls into my JNI code crashes on the `CallObjectMethod()` line. I passed in the `jobject` instance that my JNI function got as an argument... is that the right thing to do? – steveha Jul 25 '12 at 07:14
  • I should have said this earlier: I like this approach and I hope I can get it to work. Thank you for suggesting it. – steveha Jul 25 '12 at 07:17
  • @steveha I forgot that `TelephonyManager#getDeviceId()` is not a method on `Context`; you need to `getSystemService(TELEPHONY_SERVICE)` first. I've not tested this either, but it should be closer now. – ephemient Jul 25 '12 at 18:05
  • I'm trying to make your idea work, and I have hit a roadblock. If you can, please look at my follow-on question: http://stackoverflow.com/questions/12103411/android-ndk-crash-in-callobjectmethod-calling-getsystemservice Thanks. – steveha Aug 24 '12 at 18:40
  • 1
    Thank you for answer, but why does `jclass cls = (*env)->FindClass(env, "android/context/Context");` return NULL all the time?(No problem with env) – Suge Sep 24 '13 at 03:00
  • Maybe a silly question, did you check your permission if it has READ_PHONE_STATE ? – Romulano Jun 23 '17 at 07:09
  • @ephemient I'm new to JNI and I wanna ask a question - Do you use defensive programming in your JNI code? I understand that you could skip error checks here for the sake of clarity, but do you normally check if FindClass or GetMethodID etc returned NULL? – Marcin K. Dec 03 '20 at 10:30
0

Retrieve the MEID on the Java side, then pass into your JNI function as a jstring parameter. It'll be cleaner than calling back to Java from C.

As to how to retrieve that, see Abhilasha's answer.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281