转自:http://www.cnblogs.com/hibraincol/archive/2012/07/04/2575992.html
最近有个需求,需要在jni层获取android设备的mac地址,google了一圈,没看到现成的实现方法,所以就只好自己写一个了。
基本思路是,通过jni调用android java层的api,获取wifi的mac地址。理论上,所有的java代码都可以翻译成jni代码,所以应该可以实现。
首先来看看mac地址获取的java实现代码:
public String getLocalMacAddress(Context context) { WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo info = wifi.getConnectionInfo(); return info.getMacAddress(); }
代码相当简单。 就两个对象:WifiManager 和 WifiInfo对象,所以这个翻译成jni代码也不会有多复杂。
先在jni获取WifiManager 对象:
/* * 获取WifiManager 对象 * 参数: jCtxObj 为Context对象 */ jobject getWifiManagerObj(JNIEnv *env, jclass clz, jobject jCtxObj) { LOGI("gotWifiMangerObj "); //获取 Context.WIFI_SERVICE 的值 //jstring jstr_wifi_serveice = env->NewStringUTF("wifi"); jclass jCtxClz= env->FindClass("android/content/Context"); jfieldID fid_wifi_service = env->GetStaticFieldID(jCtxClz,"WIFI_SERVICE","Ljava/lang/String;"); jstring jstr_wifi_serveice = (jstring)env->GetStaticObjectField(jCtxClz,fid_wifi_service); jclass jclz = env->GetObjectClass(jCtxObj); jmethodID mid_getSystemService = env->GetMethodID(jclz,"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"); jobject wifiManager = env->CallObjectMethod(jCtxObj,mid_getSystemService,jstr_wifi_serveice); //因为jclass 继承自 jobject,所以需要释放; //jfieldID、jmethodID是内存地址,这段内存也不是在我们代码中分配的,不需要我们来释放。 env->DeleteLocalRef(jCtxClz); env->DeleteLocalRef(jclz); env->DeleteLocalRef(jstr_wifi_serveice); return wifiManager; }
然后,再获取WifiInfo对象:
/* * 获取WifiInfo 对象 * 参数: wifiMgrObj 为WifiManager对象 */ jobject getWifiInfoObj(JNIEnv *env, jobject wifiMgrObj) { LOGI("getWifiInfoObj "); if(wifiMgrObj == NULL){ return NULL; } jclass jclz = env->GetObjectClass(wifiMgrObj); jmethodID mid = env->GetMethodID(jclz,"getConnectionInfo","()Landroid/net/wifi/WifiInfo;"); jobject wifiInfo = env->CallObjectMethod(wifiMgrObj,mid); env->DeleteLocalRef(jclz); return wifiInfo; }
现在只差最后一步了,调用WifiInfo的getMacAddress()方法:
/* * 获取MAC地址 * 参数:wifiInfoObj, WifiInfo的对象 */ char* getMacAddress(JNIEnv *env, jobject wifiInfoObj) { LOGI("getMacAddress.... "); if(wifiInfoObj == NULL){ return NULL; } jclass jclz = env->GetObjectClass(wifiInfoObj); jmethodID mid = env->GetMethodID(jclz,"getMacAddress","()Ljava/lang/String;"); jstring jstr_mac = (jstring)env->CallObjectMethod(wifiInfoObj,mid); if(jstr_mac == NULL){ env->DeleteLocalRef(jclz); return NULL; } const char* tmp = env->GetStringUTFChars(jstr_mac, NULL); char* mac = (char*) malloc(strlen(tmp)+1); memcpy(mac,tmp,strlen(tmp)+1); env->ReleaseStringUTFChars(jstr_mac, tmp); env->DeleteLocalRef(jclz); return mac; }
只需要把这三个过程串起来就ok了
jobject wifiManagerObj = getWifiManagerObj(env, clz, jCtxObj);
jobject wifiInfoObj = getWifiInfoObj(env,wifiManagerObj);
char * mac = getMacAddress(env,wifiInfoObj);
完整源码为: