大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说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_LOCATION
和ACCESS_COARSE_LOCATION
两个运行时权限。使用模拟器获取到的是”02:00:00:00:00:00″,为默认值。 - 使用华为Mate 40 Pro也是获取到”02:00:00:00:00:00”
结论:通过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_LOCATION
或 ACCESS_COARSE_LOCATION
权限。
WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
所以在Android6.0以上使用WifiManager或者Bluetooth获取mac地址不光获取到的是固定值,还需要用户运行时权限确认。没任何意义
该方法只在[6.0,7.0)之间可行。
上面通过WifiManager再6.0手机上获取不到Mac,通过这个方法可以获取到。
测试了下面两款机型:
/** * 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