Skip to content

@DmitrySkiba /gist:1017293
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
JNIpp: getting IMEI from native code on Android
/* There is no native way to get IMEI, so we have to call
* Java classes through JNI.
*
* But fear not: JNIpp (github.com/DmitrySkiba/itoa-jnipp) makes
* this task much easier.
*
* To get IMEI we need to perform the following calls:
*
* TelephonyManager telephony=(TelephonyManager)
* context.getSystemService(Context.TELEPHONY_SERVICE);
* String id=telephony.getDeviceId();
*/
/* This is 'quick'n'dirty' way of doing the task. JNIpp was designed for
* creating wrapper classes, and is not very well suited for ad-hoc
* calls. See next file for 'proper' way.
*/
/* There will little explanations, see dmitryskiba.github.com/itoa-jnipp/
* for help and examples.
*/
/* Function GetDeviceId() is at the end.
*/
/**************************************/
/* First, implement GetSystemService() function to perform
* Context.getSystemService().
*/
#define JB_CURRENT_CLASS Context
JB_DEFINE_ACCESSOR(
"android/content/Context"
,
NoFields
,
Methods
(
GetSysSvc,
"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"
)
)
static java::PObject GetSystemService(java::PObject context,const char* serviceName) {
return java::PObject::Wrap(
JB_CALL(ObjectMethod,context,GetSysSvc,java::PString::New(serviceName))
);
}
#undef JB_CURRENT_CLASS
/**************************************/
/* Then implement TelephonyManager.getDeviceId().
*/
#define JB_CURRENT_CLASS TelephonyManager
JB_DEFINE_ACCESSOR(
"android/telephony/TelephonyManager"
,
NoFields
,
Methods
(
GetDeviceId,
"getDeviceId","()Ljava/lang/String;"
)
)
static java::PString GetDeviceId(java::PObject telephony) {
return java::PString::Wrap(
JB_CALL(ObjectMethod,telephony,GetDeviceId)
);
}
#undef JB_CURRENT_CLASS
/**************************************/
/* And finally, put it all together.
* 'contextObject' is a Context instance, typically an Activity
* (if you have NativeActivity object, it is nativeActivity->clazz).
*/
void GetDeviceId(jobject contextObject) {
java::PObject context=java::PObject::Wrap(contextObject);
java::PObject telephony=GetSystemService(context,"phone");
if (!telephony) {
// Oops, no service.
} else {
java::PString idString=GetDeviceId(telephony);
if (!idString) {
// We've got NULL
} else {
const char* id=idString->GetUTF();
// Work with id.
}
}
}
/* This correct (as per JNIpp) way of working with Java classes:
* you create wrappers for all classes you are interested in
* and then your code reads much close to the Java original Java.
*/
void GetDeviceId(jobject contextObject) {
PContext context=PContext::Wrap(contextObject);
PTelephonyManager telephony=java::Cast<TelephonyManager>(
context->GetSystemService(Context::TELEPHONY_SERVICE));
if (telephony) {
java::PString id=telephony->GetDeviceId();
if (id) {
const char* idUTF=id->GetUTF();
// Work with id.
}
}
}
/**********************************************************/
/* First, declare wrapper classes. This should go in a header file.
*/
class Context: public java::Object {
JB_WRAPPER_CLASS(Context);
public:
static const char* const TELEPHONY_SERVICE;
public:
Context(const jni::LObject& context);
java::PObject GetSystemService(const char* name) const;
};
typedef java::ObjectPointer<Context> PContext;
class TelephonyManager: public java::Object {
JB_WRAPPER_CLASS(TelephonyManager);
public:
TelephonyManager(const jni::LObject& telephony);
java::PString GetDeviceId() const;
};
typedef java::ObjectPointer<TelephonyManager> PTelephonyManager;
/**********************************************************/
/* Then implement wrapper classes. This should go in cpp file (or files).
*/
/**************************************/
#define JB_CURRENT_CLASS Context
JB_DEFINE_WRAPPER_CLASS(
"android/content/Context"
,
NoFields
,
Methods
(
GetSysSvc,
"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"
)
)
const char* const Context::TELEPHONY_SERVICE="phone";
Context::Context(const jni::LObject& context):
java::Object(context)
{
}
java::PObject Context::GetSystemService(const char* name) const {
return java::PObject::Wrap(
JB_CALL_THIS(ObjectMethod,GetSysSvc,java::PString::New(name))
);
}
#undef JB_CURRENT_CLASS
/**************************************/
#define JB_CURRENT_CLASS TelephonyManager
JB_DEFINE_WRAPPER_CLASS(
"android/telephony/TelephonyManager"
,
NoFields
,
Methods
(
GetDeviceId,
"getDeviceId","()Ljava/lang/String;"
)
)
TelephonyManager::TelephonyManager(const jni::LObject& telephony):
java::Object(telephony)
{
}
java::PString TelephonyManager::GetDeviceId() const {
return java::PString::Wrap(
JB_CALL_THIS(ObjectMethod,GetDeviceId)
);
}
#undef JB_CURRENT_CLASS
@firexel

Just for a great justice. You, actually, can get IMEI from native witout JNI calls. See here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.