最近有个需求,需要在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);

完整源码为:

http://download.csdn.net/detail/niosm/4409938

更多相关文章

  1. Android ADK开发包示例开源代码
  2. Android属性动画应用超简单代码打造酷炫扇形(卫星),圆形菜单
  3. Android studio中Git的学习和使用心得(二)在Android studio中如何
  4. Android Studio代码调试大全
  5. Android 实现闪屏页和右上角的倒计时跳转实例代码
  6. android语音识别方法示例代码
  7. Linux 3.3内核发布 融合Android源代码
  8. Android的代码都得自己一个个敲一遍吗?
  9. Android 电子书应用完全开源代码

随机推荐

  1. android java 文件的读写
  2. Android(安卓)ContextMenu和Listview配合
  3. Android之关于Intent的Flag属性的讲解
  4. How to fix the Android(安卓)AVD no tar
  5. OnclickListener与View.OnclickListener
  6. Android(安卓)studio3.1.2 坑——3rd-par
  7. Android(安卓)Event.getX 与getRawX的区
  8. Android调用系统播放器
  9. 在服务器上使用grandle打包android源码
  10. android 密码加密