Mac地址获取(整理并测试)[亲测有效]

Mac地址获取(整理并测试)[亲测有效]Android6.0以下通过Wifi和Bluetooth广告api就能获取到,Android6.0到Android7.0之间通过cat /sys/class/net/wlan0/address获取,A

Mac地址获取(整理并测试)"

Mac地址获取(整理并测试)

使用WifiManager获取Mac(6.0以下)通过cat /sys/class/net/wlan0/address获取Address(6.0到7.0之间)通过ip地址来获取绑定的mac地址(7.0~10.0)扫描各个网络接口获取mac地址(7.0~10.0)Android10以下通用源码

结论先行: Android6.0以下通过Wifi和Bluetooth广告api就能获取到,Android6.0到Android7.0之间通过cat /sys/class/net/wlan0/address获取,Android7.0~Android10可以通过Ip和扫描网络接口获取,Android11起获取不到。

使用WifiManager获取Mac(6.0以下)

首先需要android.permission.ACCESS_WIFI_STATE权限。

 /**       * 通过WiFiManager获取mac地址       * @param context       * @return       */
     fun tryGetWifiMac(context: Context): String? {
         val wm =
             context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
         val wi = wm.connectionInfo
         if (ActivityCompat.checkSelfPermission(
                 context,
                 Manifest.permission.ACCESS_FINE_LOCATION
             ) != PackageManager.PERMISSION_GRANTED
         ) {
             Toast.makeText(context, "权限不够", Toast.LENGTH_SHORT).show()
         }
         if (wi == null || wi.macAddress == null) {
             return null
         }
         return if ("02:00:00:00:00:00" == wi.macAddress.trim { it <= ' ' }) {
             null
         } else {
             wi.macAddress.trim { it <= ' ' }
         }
     }

测试:

  • 使用Android 5.0的模拟器获取wi.macAddress是null。真机可以获取到。
  • Android6.0起需要ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION两个运行时权限。使用模拟器获取到的是”02:00:00:00:00:00″,为默认值。
  • 使用华为Mate 40 Pro也是获取到”02:00:00:00:00:00”

image-20220513125942155

结论:通过WiFiManager来获取Mac在Android6.0以上已经不可行了。

通过cat /sys/class/net/wlan0/address获取Address(6.0到7.0之间)

Android 6.0 API 23

为给用户提供更严格的数据保护,从此版本开始,对于使用 WLAN API 和 Bluetooth API 的应用,Android 移除了对设备本地硬件标识符的编程访问权。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法现在会返回常量值 02:00:00:00:00:00

现在,要通过蓝牙和 WLAN 扫描访问附近外部设备的硬件标识符,您的应用必须拥有 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 权限。

  • WifiManager.getScanResults()
  • BluetoothDevice.ACTION_FOUND
  • BluetoothLeScanner.startScan()

所以在Android6.0以上使用WifiManager或者Bluetooth获取mac地址不光获取到的是固定值,还需要用户运行时权限确认。没任何意义

该方法只在[6.0,7.0)之间可行。

上面通过WifiManager再6.0手机上获取不到Mac,通过这个方法可以获取到。

测试了下面两款机型:

image-20220513151102925

 /**       * android 6.0及以上、7.0以下 获取mac地址       *       * @param context       * @return       */
    private fun getMacAddress(context: Context): String? {
         var str = ""
         var macSerial = ""
         try {
             val pp = Runtime.getRuntime().exec(
                 "cat /sys/class/net/wlan0/address"
             )
             val ir = InputStreamReader(pp.inputStream)
             val input = LineNumberReader(ir)
             while (null != str) {
                 str = input.readLine()
                 if (str != null) {
                     macSerial = str.trim { it <= ' ' } // 去空格
                     break
                 }
             }
         } catch (ex: Exception) {
             Log.e("----- " + "NetInfoManager", "getMacAddress:$ex")
         }
         if (macSerial == null || "" == macSerial) {
             try {
                 return loadFileAsString("/sys/class/net/eth0/address")
                     .toUpperCase().substring(0, 17)
             } catch (e: Exception) {
                 e.printStackTrace()
                 Log.e(
                     "----- " + "NetInfoManager",
                     "getMacAddress:$e"
                 )
             }
         }
         return macSerial
     }
 ​
     @Throws(Exception::class)
     private fun loadFileAsString(fileName: String): String {
         val reader = FileReader(fileName)
         val text = loadReaderAsString(reader)
         reader.close()
         return text
     }
 ​
     @Throws(Exception::class)
     private fun loadReaderAsString(reader: Reader): String {
         val builder = StringBuilder()
         val buffer = CharArray(4096)
         var readLength: Int = reader.read(buffer)
         while (readLength == 0) {
             builder.append(buffer, 0, readLength)
             readLength = reader.read(buffer)
         }
         return builder.toString()
     }

通过ip地址来获取绑定的mac地址(7.0~10.0)

必须声明android.permission.INTERNET权限。

 /**       * 根据IP地址获取MAC地址       *       * @return       */
     fun getMacAddressByIP(): String? {
         var strMacAddr: String? = null
         try {
             // 获得IpD地址
             val ip = getLocalInetAddress()
             val b = NetworkInterface.getByInetAddress(ip)
                 .hardwareAddress
             val buffer = StringBuffer()
             for (i in b.indices) {
                 if (i != 0) {
                     buffer.append(':')
                 }
                 val str = Integer.toHexString((b[i] and 0xFF.toByte()).toInt())
                 buffer.append(if (str.length == 1) "0$str" else str)
             }
             strMacAddr = buffer.toString().toUpperCase()
         } catch (e: java.lang.Exception) {
         }
         return strMacAddr
     }
 ​
     /**       * 获取移动设备本地IP       *       * @return       */
     private fun getLocalInetAddress(): InetAddress? {
         var ip: InetAddress? = null
         try {
             // 列举
             val en_netInterface = NetworkInterface
                 .getNetworkInterfaces()
             while (en_netInterface.hasMoreElements()) { // 是否还有元素
                 val ni = en_netInterface
                     .nextElement() as NetworkInterface // 得到下一个元素
                 val en_ip = ni.inetAddresses // 得到一个ip地址的列举
                 while (en_ip.hasMoreElements()) {
                     ip = en_ip.nextElement()
                     ip = if (!ip.isLoopbackAddress
                         && ip.hostAddress.indexOf(":") == -1
                     ) break else null
                 }
                 if (ip != null) {
                     break
                 }
             }
         } catch (e: SocketException) {
             e.printStackTrace()
         }
         return ip
     }
 ​
 ​

扫描各个网络接口获取mac地址(7.0~10.0)

必须声明android.permission.INTERNET权限。

     /**       * android 7.0及以上 (2)扫描各个网络接口获取mac地址       *       */
     /**       * 获取设备HardwareAddress地址       *       * @return       */
     private fun getMachineHardwareAddress(): String? {
         var interfaces: Enumeration<NetworkInterface?>? = null
         try {
             interfaces = NetworkInterface.getNetworkInterfaces()
         } catch (e: SocketException) {
             e.printStackTrace()
         }
         var hardWareAddress: String? = null
         var iF: NetworkInterface? = null
         if (interfaces == null) {
             return null
         }
         while (interfaces.hasMoreElements()) {
             iF = interfaces.nextElement()
             try {
                 hardWareAddress = bytesToString(iF!!.hardwareAddress)
                 if (hardWareAddress != null) break
             } catch (e: SocketException) {
                 e.printStackTrace()
             }
         }
         return hardWareAddress
     }
 ​
     /***       * byte转为String       *       * @param bytes       * @return       */
     private fun bytesToString(bytes: ByteArray?): String? {
         if (bytes == null || bytes.size == 0) {
             return null
         }
         val buf = java.lang.StringBuilder()
         for (b in bytes) {
             buf.append(String.format("%02X:", b))
         }
         if (buf.isNotEmpty()) {
             buf.deleteCharAt(buf.length - 1)
         }
         return buf.toString()
     }
 ​

以上两种方式测试了Android 7.0(HTC)、Android8.0(小米 6)、Android9.0(Vivo)、Android10(华为Mate40)、

Android11(一加8T,小米4)崩溃。

通过busybox获取本地存储的mac地址

  • 不是通用方法。不可行

Android10以下通用源码

 package com.rongcheng.androidchanges
 ​
 import android.Manifest
 import android.content.Context
 import android.content.pm.PackageManager
 import android.net.wifi.WifiManager
 import android.os.Build
 import android.text.TextUtils
 import android.util.Log
 import androidx.core.app.ActivityCompat
 import java.io.*
 import java.net.InetAddress
 import java.net.NetworkInterface
 import java.net.SocketException
 import java.util.*
 import kotlin.experimental.and
 ​
 ​
 object MacAddressHelper {
     fun getMac(context: Context?): String? {
         var strMac: String? = null
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
             //6.0以下
             strMac = getLocalMacAddressFromWifiInfo(context)
             return strMac
         } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N
             && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
         ) {
             //6.0以上7.0以下
             strMac = getMacAddress(context!!)
             return strMac
         } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             //7.0以上
             strMac = getMacAddressByIP()
             if (TextUtils.isEmpty(strMac))
                 strMac = getMachineHardwareAddress()
             return strMac
         }
         return null
     }
 ​
 ​
     /**       * 通过WiFiManager获取mac地址       * @param context       * @return       */
     private fun getLocalMacAddressFromWifiInfo(context: Context?): String? {
         if (context == null) return null
         val wm =
             context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
         val wi = wm.connectionInfo
         if (ActivityCompat.checkSelfPermission(
                 context,
                 Manifest.permission.ACCESS_FINE_LOCATION
             ) != PackageManager.PERMISSION_GRANTED
         ) {
             Log.e("Frc", "缺少 ACCESS_FINE_LOCATION 权限")
         }
         if (wi == null || wi.macAddress == null) {
             return null
         }
         return if ("02:00:00:00:00:00" == wi.macAddress.trim { it <= ' ' }) {
             null
         } else {
             wi.macAddress.trim { it <= ' ' }
         }
     }
 ​
 ​
     /**       * android 6.0及以上、7.0以下 获取mac地址       *       * @param context       * @return       */
     private fun getMacAddress(context: Context): String? {
         var str = ""
         var macSerial = ""
         try {
             val pp = Runtime.getRuntime().exec(
                 "cat /sys/class/net/wlan0/address"
             )
             val ir = InputStreamReader(pp.inputStream)
             val input = LineNumberReader(ir)
             while (null != str) {
                 str = input.readLine()
                 if (str != null) {
                     macSerial = str.trim { it <= ' ' } // 去空格
                     break
                 }
             }
         } catch (ex: Exception) {
             Log.e("----- " + "NetInfoManager", "getMacAddress:$ex")
         }
         if (macSerial == null || "" == macSerial) {
             try {
                 return loadFileAsString("/sys/class/net/eth0/address")
                     .toUpperCase().substring(0, 17)
             } catch (e: Exception) {
                 e.printStackTrace()
                 Log.e(
                     "----- " + "NetInfoManager",
                     "getMacAddress:$e"
                 )
             }
         }
         return macSerial
     }
 ​
     @Throws(Exception::class)
     private fun loadFileAsString(fileName: String): String {
         val reader = FileReader(fileName)
         val text = loadReaderAsString(reader)
         reader.close()
         return text
     }
 ​
     @Throws(Exception::class)
     private fun loadReaderAsString(reader: Reader): String {
         val builder = StringBuilder()
         val buffer = CharArray(4096)
         var readLength: Int = reader.read(buffer)
         while (readLength == 0) {
             builder.append(buffer, 0, readLength)
             readLength = reader.read(buffer)
         }
         return builder.toString()
     }
 ​
     /**       * 根据IP地址获取MAC地址       *       * @return       */
     fun getMacAddressByIP(): String? {
         var strMacAddr: String? = null
         try {
             // 获得IpD地址
             val ip = getLocalInetAddress()
             val b = NetworkInterface.getByInetAddress(ip)
                 .hardwareAddress
             val buffer = StringBuffer()
             for (i in b.indices) {
                 if (i != 0) {
                     buffer.append(':')
                 }
                 val str = Integer.toHexString((b[i] and 0xFF.toByte()).toInt())
                 buffer.append(if (str.length == 1) "0$str" else str)
             }
             strMacAddr = buffer.toString().toUpperCase()
         } catch (e: java.lang.Exception) {
         }
         return strMacAddr
     }
 ​
     /**       * 获取移动设备本地IP       *       * @return       */
     private fun getLocalInetAddress(): InetAddress? {
         var ip: InetAddress? = null
         try {
             // 列举
             val en_netInterface = NetworkInterface
                 .getNetworkInterfaces()
             while (en_netInterface.hasMoreElements()) { // 是否还有元素
                 val ni = en_netInterface
                     .nextElement() as NetworkInterface // 得到下一个元素
                 val en_ip = ni.inetAddresses // 得到一个ip地址的列举
                 while (en_ip.hasMoreElements()) {
                     ip = en_ip.nextElement()
                     ip = if (!ip.isLoopbackAddress
                         && ip.hostAddress.indexOf(":") == -1
                     ) break else null
                 }
                 if (ip != null) {
                     break
                 }
             }
         } catch (e: SocketException) {
             e.printStackTrace()
         }
         return ip
     }
 ​
     /**       * android 7.0及以上 (2)扫描各个网络接口获取mac地址       *       */
     /**       * 获取设备HardwareAddress地址       *       * @return       */
     private fun getMachineHardwareAddress(): String? {
         var interfaces: Enumeration<NetworkInterface?>? = null
         try {
             interfaces = NetworkInterface.getNetworkInterfaces()
         } catch (e: SocketException) {
             e.printStackTrace()
         }
         var hardWareAddress: String? = null
         var iF: NetworkInterface? = null
         if (interfaces == null) {
             return null
         }
         while (interfaces.hasMoreElements()) {
             iF = interfaces.nextElement()
             try {
                 hardWareAddress = bytesToString(iF!!.hardwareAddress)
                 if (hardWareAddress != null) break
             } catch (e: SocketException) {
                 e.printStackTrace()
             }
         }
         return hardWareAddress
     }
 ​
     /***       * byte转为String       *       * @param bytes       * @return       */
     private fun bytesToString(bytes: ByteArray?): String? {
         if (bytes == null || bytes.size == 0) {
             return null
         }
         val buf = java.lang.StringBuilder()
         for (b in bytes) {
             buf.append(String.format("%02X:", b))
         }
         if (buf.isNotEmpty()) {
             buf.deleteCharAt(buf.length - 1)
         }
         return buf.toString()
     }
 ​
     /**       * android 7.0及以上 (3)通过busybox获取本地存储的mac地址       *       */
     /**       * 根据busybox获取本地Mac       *       * @return       */
     private fun getLocalMacAddressFromBusybox(): String? {
         var result: String? = ""
         var Mac = ""
         result = callCmd("busybox ifconfig", "HWaddr")
         // 如果返回的result == null,则说明网络不可取
         if (result == null) {
             return "网络异常"
         }
         // 对该行数据进行解析
         // 例如:eth0 Link encap:Ethernet HWaddr 00:16:E8:3E:DF:67
         if (result.isNotEmpty() && result.contains("HWaddr") == true) {
             Mac = result.substring(
                 result.indexOf("HWaddr") + 6,
                 result.length - 1
             )
             result = Mac
         }
         return result
     }
 ​
     private fun callCmd(cmd: String, filter: String): String? {
         var result: String? = ""
         var line = ""
         try {
             val proc = Runtime.getRuntime().exec(cmd)
             val `is` = InputStreamReader(proc.inputStream)
             val br = BufferedReader(`is`)
             while (br.readLine().also { line = it } != null && !line.contains(filter)) {
                 result += line
             }
             result = line
         } catch (e: java.lang.Exception) {
             e.printStackTrace()
         }
         return result
     }
 }

\

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13939.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注