Android: 用jni 获取MAC地址

129 篇文章 0 订阅

首先来看看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);

获取安卓设备的IMEI和Mac地址需要使用Android NDK来编写C++代码,因为IMEI和Mac地址是由操作系统提供的,而操作系统是用Java或者Kotlin编写的。以下是获取IMEI和Mac地址的示例代码: ```c++ #include <jni.h> #include <android/log.h> #include <string> #include <sstream> using namespace std; extern "C" { JNIEXPORT jstring JNICALL Java_com_example_android_deviceinfo_DeviceInfoActivity_getIMEI(JNIEnv *env, jobject instance) { jclass clazz = env->FindClass("android/telephony/TelephonyManager"); jmethodID getIMEIMethod = env->GetMethodID(clazz, "getDeviceId", "()Ljava/lang/String;"); jobject telephonyManager = env->CallObjectMethod(instance, env->GetMethodID(env->GetObjectClass(instance), "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"), env->NewStringUTF("phone")); jstring imei = (jstring) env->CallObjectMethod(telephonyManager, getIMEIMethod); const char *imeiChars = env->GetStringUTFChars(imei, NULL); string result = string(imeiChars); env->ReleaseStringUTFChars(imei, imeiChars); return env->NewStringUTF(result.c_str()); } JNIEXPORT jstring JNICALL Java_com_example_android_deviceinfo_DeviceInfoActivity_getMacAddress(JNIEnv *env, jobject instance) { jclass clazz = env->FindClass("java/net/NetworkInterface"); jmethodID getHardwareAddressMethod = env->GetMethodID(clazz, "getHardwareAddress", "()[B"); jclass inetAddressClazz = env->FindClass("java/net/InetAddress"); jmethodID getByAddressMethod = env->GetStaticMethodID(inetAddressClazz, "getByAddress", "([B)Ljava/net/InetAddress;"); jobjectArray networkInterfaces = (jobjectArray) env->CallStaticObjectMethod(clazz, env->GetStaticMethodID(clazz, "getNetworkInterfaces", "()Ljava/util/Enumeration;")); jstring result = env->NewStringUTF(""); while (env->CallBooleanMethod(env->CallObjectMethod(networkInterfaces, env->GetMethodID(env->FindClass("java/util/Enumeration"), "hasMoreElements", "()Z")), env->GetMethodID(env->FindClass("java/util/Enumeration"), "nextElement", "()Ljava/lang/Object;"))) { jobject networkInterface = env->CallObjectMethod(networkInterfaces, env->GetMethodID(env->FindClass("java/util/Enumeration"), "nextElement", "()Ljava/lang/Object;")); jbyteArray hardwareAddress = (jbyteArray) env->CallObjectMethod(networkInterface, getHardwareAddressMethod); if (hardwareAddress == NULL) { continue; } jbyte *hardwareAddressBytes = env->GetByteArrayElements(hardwareAddress, NULL); jint hardwareAddressLength = env->GetArrayLength(hardwareAddress); stringstream ss; for (int i = 0; i < hardwareAddressLength; i++) { ss << hex << (int) hardwareAddressBytes[i]; if (i != hardwareAddressLength - 1) { ss << ":"; } } string macAddress = ss.str(); if (macAddress != "") { result = env->NewStringUTF(macAddress.c_str()); break; } } return result; } } ``` 在Java代码中,需要声明native方法,并且使用System.loadLibrary来加载C++库。以下是在Java代码中调用上面定义的native方法的示例代码: ```java public class DeviceInfoActivity extends AppCompatActivity { static { System.loadLibrary("deviceinfo"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_device_info); String imei = getIMEI(); String macAddress = getMacAddress(); TextView imeiTextView = findViewById(R.id.imeiTextView); imeiTextView.setText(imei); TextView macAddressTextView = findViewById(R.id.macAddressTextView); macAddressTextView.setText(macAddress); } public native String getIMEI(); public native String getMacAddress(); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值