Android的java端提供了非常丰富的库,我们可以在native代码中调用java的库。
以下为获取硬件IMEI信息的代码:
JNIEXPORT jstring JNICALL Java_com_sample_nativeGetDeviceId(JNIEnv *pEnv, jclass thiz, jobject context)
{
// IMEI
jstring imei = 0;
jclass cls_context = pEnv->FindClass("android/content/Context");
if( cls_context == 0){
LogMessage(ANDROID_LOG_ERROR, LOG_TAG, "cannot find context-class");
return imei;
}
jobject strServiceName = CJniHelper::getStaticFieldString(pEnv, cls_context, "TELEPHONY_SERVICE");
if( strServiceName == 0 ){
LogMessage(ANDROID_LOG_ERROR, LOG_TAG, "cannot find 'TELEPHONY_SERVICE'");
return imei;
}
jobject telephonymanager = CJniHelper::callObjectMethod(pEnv, cls_context, context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", strServiceName);
jclass cls_TelephoneManager = pEnv->FindClass( "android/telephony/TelephonyManager");
if( telephonymanager != 0 && cls_TelephoneManager != 0){
imei = (jstring)CJniHelper::callObjectMethod(pEnv, cls_TelephoneManager, telephonymanager, "getDeviceId", "()Ljava/lang/String;");
}else
LogMessage(ANDROID_LOG_ERROR, LOG_TAG, "cannot find TELEPHONY_SERVICE cls/object");
return imei;
}
其中,CJniHelper 实现的辅助几个函数如下:
CJniHelper::callObjectMethod 用来调用java类方法,返回对象,后面的变长参数用来传递 java方法的可变长参数
pEnv->CallObjectMethodV 这个函数返回一个java的对象。 如果需要返回其他函数,可类似调用pEnv的其他函数,如 CallStringMethodV等
jobject CJniHelper::callObjectMethod(JNIEnv *pEnv, jclass cls, jobject thiz, const char *methodName, const char *methodSign, ...)
{
jobject ret = 0;
jmethodID methodId = pEnv->GetMethodID(cls, methodName, methodSign);
if( methodId != 0 ){
va_list args;
va_start(args, methodSign);
ret = pEnv->CallObjectMethodV(thiz, methodId, args);
va_end(args);
}
return ret;
}
下面是获取类的静态字符串变量的函数,获取其他类型的静态变量,可类似使用 pEnv->GetIntObjectField 等函数
jstring CJniHelper::getStaticFieldString(JNIEnv *pEnv, const char *className, const char *fieldName)
{
jclass cls = pEnv->FindClass(className);
if( cls != 0 ){
return getStaticFieldString(pEnv, cls, fieldName);
}
return 0;
}
jstring CJniHelper::getStaticFieldString(JNIEnv *pEnv, jclass cls, const char *fieldName)
{
jfieldID fieldId = pEnv->GetStaticFieldID(cls, fieldName, "Ljava/lang/String;");
if(fieldId != 0){
return (jstring)pEnv->GetStaticObjectField(cls, fieldId);
}
return 0;
}
有了以上的辅助函数,可以很容易获取硬件信息,如设备序列号:
jstring serial = CJniHelper::getStaticFieldString(pEnv, "android/os/Build", "SERIAL");