在棉花糖中获取蓝牙本地mac地址
Posted
技术标签:
【中文标题】在棉花糖中获取蓝牙本地mac地址【英文标题】:Get Bluetooth local mac address in Marshmallow 【发布时间】:2016-01-27 10:55:16 【问题描述】:Pre Marshmallow 我的应用程序将通过BluetoothAdapter.getDefaultAdapter().getAddress().
获取它的设备 MAC 地址
现在有了 Marshmallow,android 将返回 02:00:00:00:00:00
。
我看到一些链接(抱歉,现在不确定在哪里)说您需要添加额外的权限
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/>
能够得到它。但是它对我不起作用。
获取mac地址是否需要一些额外的权限?
我不确定这里是否相关,但清单中还包括
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
那么有没有办法获取本地蓝牙mac地址呢?
【问题讨论】:
【参考方案1】:对mac地址的访问被特意去掉了:
为了向用户提供更好的数据保护,从这个版本开始,Android 移除了使用 Wi-Fi 和蓝牙 API 的应用程序对设备本地硬件标识符的编程访问。
(来自Android 6.0 Changes)
【讨论】:
是的。我读过那个。但是 API 23 BluetoothAdapter 具有以下内容: /** * 默认 MAC 地址报告给没有 * android.permission.LOCAL_MAC_ADDRESS 权限的客户端。 * * @hide */ public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";所以这意味着有某种方法可以得到它。 (也许还没有实施?我抱有希望。) LOCAL_MAC_ADDRESS 权限只能由系统应用使用,Google 不太可能改变这一点。【参考方案2】:您可以从文件中访问 Mac 地址 "/sys/class/net/" + networkInterfaceName+ "/address",其中networkInterfaceName可以是wlan0或者eth1,但是它的权限可能是读保护的,所以可能无法在某些设备中使用。 我还附上了我从 SO 获得的代码部分。
public static String getWifiMacAddress()
try
String interfaceName = "wlan0";
List<NetworkInterface> interfaces = Collections
.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface intf : interfaces)
if (!intf.getName().equalsIgnoreCase(interfaceName))
continue;
byte[] mac = intf.getHardwareAddress();
if (mac == null)
return "";
StringBuilder buf = new StringBuilder();
for (byte aMac : mac)
buf.append(String.format("%02X:", aMac));
if (buf.length() > 0)
buf.deleteCharAt(buf.length() - 1);
return buf.toString();
catch (Exception exp)
exp.printStackTrace();
return "";
【讨论】:
谢谢。它适用于我尝试过的 Nexus 平板电脑。 Android N 及更高版本也将使用此方法返回错误的 MAC 地址。 我测试的两台设备都有两个甚至略有不同的 WiFi 和蓝牙 MAC 地址... 我在 android 10 上试过这个方法,效果很好,但是正如你所说,这是本地 wifi mac 地址,有没有办法使用这样的方法获取蓝牙 mac 地址?【参考方案3】:zmarties 是对的,但你仍然可以通过反射或 Settings.Secure 获取 mac 地址:
String macAddress = android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");
【讨论】:
wifi地址呢? ,你能处理一下mac地址吗? 这给出了不同的 bdaddr(但一个有效的 mac)。反射方法给出正确的 bdaddr。 @Rilwan 对隐藏/列入黑名单的 API 使用反射会使您的应用在下一次操作系统更新时崩溃,这永远不是正确的解决方案,只是临时解决方法。 android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address") 在 Android 10 中返回 null【参考方案4】:通过反射获取 MAC 地址如下所示:
private static String getBtAddressViaReflection()
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Object bluetoothManagerService = new Mirror().on(bluetoothAdapter).get().field("mService");
if (bluetoothManagerService == null)
Log.w(TAG, "couldn't find bluetoothManagerService");
return null;
Object address = new Mirror().on(bluetoothManagerService).invoke().method("getAddress").withoutArgs();
if (address != null && address instanceof String)
Log.w(TAG, "using reflection to get the BT MAC address: " + address);
return (String) address;
else
return null;
使用反射库 (net.vidageek:mirror),但您会明白的。
【讨论】:
代码不起作用。使用该库,它总是在具有不同 API 级别的服务器上返回 null 我只是在一些设备上尝试了代码,但总是得到一个 mac 地址(在 4.4、5.0、5.1 和 6.0 的设备上使用 targetSDK 22 进行了测试) 在 Android 8.0 Oreo 的 Pixel 2 版本上,此方法将不再有效。我收到 java.lang.reflect.InvocationTargetException 原因:java.lang.SecurityException:需要 LOCAL_MAC_ADDRESS 权限:用户 10141 和当前进程都没有 android.permission.LOCAL_MAC_ADDRESS。 Google 似乎已将“修复”推广到任何安装 Android 8.1 的设备。更新到 8.1 预览版的 Nexus 5X 也有例外。作为一个小小的安慰,Google 已经开始在蓝牙设置 UI 中显示自己的蓝牙 MAC,因此至少用户可以手动将其复制到需要它的应用中。 我可以确认手动输入然后使用 MAC 地址对我的应用程序建立无对连接有效。【参考方案5】:事实证明,我最终没有从 Android 获取 MAC 地址。蓝牙设备最终提供了 Android 设备 MAC 地址,该地址被存储并在需要时使用。是的,这似乎有点古怪,但在我参与的项目中,蓝牙设备软件也在开发中,结果证明这是处理这种情况的最佳方式。
【讨论】:
【参考方案6】:请使用以下代码获取蓝牙mac地址。如果有任何问题,请告诉我。
private String getBluetoothMacAddress()
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String bluetoothMacAddress = "";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
try
Field mServiceField = bluetoothAdapter.getClass().getDeclaredField("mService");
mServiceField.setAccessible(true);
Object btManagerService = mServiceField.get(bluetoothAdapter);
if (btManagerService != null)
bluetoothMacAddress = (String) btManagerService.getClass().getMethod("getAddress").invoke(btManagerService);
catch (NoSuchFieldException e)
catch (NoSuchMethodException e)
catch (IllegalAccessException e)
catch (InvocationTargetException e)
else
bluetoothMacAddress = bluetoothAdapter.getAddress();
return bluetoothMacAddress;
【讨论】:
提示:使用列入黑名单的 API 的反思从来都不是好的解决方案,它可能会在下一次 Android 更新时打击你【参考方案7】:首先必须将以下权限添加到 Manifest;
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
那么,
public static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
String macAddress = Settings.Secure.getString(getContentResolver(), SECURE_SETTINGS_BLUETOOTH_ADDRESS);
之后,必须使用 OEM / 系统密钥对应用程序进行签名。在 Android 8.1.0 上测试和验证。
【讨论】:
在 Android 10 中,还需要权限效果很好
private String getBluetoothMacAddress()
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String bluetoothMacAddress = "";
try
Field mServiceField = bluetoothAdapter.getClass().getDeclaredField("mService");
mServiceField.setAccessible(true);
Object btManagerService = mServiceField.get(bluetoothAdapter);
if (btManagerService != null)
bluetoothMacAddress = (String) btManagerService.getClass().getMethod("getAddress").invoke(btManagerService);
catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignore)
return bluetoothMacAddress;
【讨论】:
Field @Vinayak 的包名是什么我发现有很多 Field 类。 @Iqbalhossain 这是java.lang.reflect.Field
。【参考方案9】:
由于下面的方法为 android O 返回 null。
String macAddress = android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");
我找到了获取蓝牙Mac地址的新方法,您可以使用下面的命令行尝试。
su strings /data/misc/bluedroid/bt_config.conf | grep Address
注意:就我而言,我使用的是 root 设备,因此我的应用拥有超级用户权限。
【讨论】:
以上是关于在棉花糖中获取蓝牙本地mac地址的主要内容,如果未能解决你的问题,请参考以下文章