Android Studio中手机MAC与蓝牙地址均不可用时的读取方法咨询
Hey there! Let’s dig into this MAC address problem you’re hitting on Android. First, it’s important to understand why this is happening: starting from Android 6.0 (API 23), Google restricted access to WiFi MAC addresses (you’ll get the dummy value 02:00:00:00:00:00 instead of the real one), and Android 10+ added similar restrictions for Bluetooth addresses—unless your app is a system-level application with special permissions.
Here are the practical solutions you can try, depending on your app’s use case:
1. Check for System-Level App Privileges
If your app is signed with the system signature (e.g., pre-installed by the device manufacturer), you can use the android.permission.LOCAL_MAC_ADDRESS permission. This allows you to bypass the standard restrictions and retrieve real MAC addresses for both WiFi and Bluetooth interfaces.
Note: This permission is not available to regular third-party apps—it’s reserved for system applications only.
2. Read MAC Address from System Files (Limited Compatibility)
For regular apps, you can attempt to read the MAC address directly from the device’s sysfs filesystem. This works on older Android versions (pre-11) and some devices with looser restrictions, but it’s not guaranteed to work across all models or newer OS versions.
Here’s a code snippet to try this approach:
import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; private String getMacFromSysfs() { try { // Get all network interfaces except the loopback interface File netDir = new File("/sys/class/net/"); if (!netDir.exists()) return null; File[] interfaceFiles = netDir.listFiles(); if (interfaceFiles == null) return null; List<String> validInterfaces = new ArrayList<>(); for (File file : interfaceFiles) { if (!file.getName().equals("lo")) { validInterfaces.add(file.getName()); } } // Read the address file for each interface for (String iface : validInterfaces) { File addressFile = new File("/sys/class/net/" + iface + "/address"); if (!addressFile.exists()) continue; String mac = new String(Files.readAllBytes(addressFile.toPath())).trim(); // Skip the dummy MAC address if (!mac.equals("02:00:00:00:00:00")) { return mac; } } } catch (IOException e) { e.printStackTrace(); } return null; }
Important caveats: Android 11+ restricts access to sysfs paths for third-party apps, so this method may fail on newer devices. Also, interface names (like wlan0 or eth0) can vary between manufacturers.
3. Use Alternative Unique Identifiers
If you can’t retrieve the real MAC address (which is increasingly common on modern Android), consider using a substitute unique identifier that fits your use case:
- Android ID: Retrieve it using
Settings.Secure.ANDROID_ID. On Android 8.0+, this ID is unique per app and user profile, and resets if the device is factory reset.import android.content.Context; import android.provider.Settings; private String getAndroidId(Context context) { return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); } - Custom Persistent UUID: Generate a random UUID on first app launch and store it in
SharedPreferences. This stays consistent across app updates and device reboots (unless the app is uninstalled).import android.content.Context; import android.preference.PreferenceManager; import java.util.UUID; private String getPersistentUniqueId(Context context) { String uuid = PreferenceManager.getDefaultSharedPreferences(context) .getString("persistent_device_id", null); if (uuid == null) { uuid = UUID.randomUUID().toString(); PreferenceManager.getDefaultSharedPreferences(context) .edit() .putString("persistent_device_id", uuid) .apply(); } return uuid; } - Advertising ID: If your use case is related to advertising or analytics, you can use the Advertising ID. Users can reset this ID at any time, so it’s not suitable for device tracking.
4. Verify Required Permissions
Even though permissions won’t bypass the MAC restrictions on newer Android versions, make sure you’ve declared the necessary permissions in your AndroidManifest.xml to cover older devices:
<!-- For WiFi MAC access (pre-API 23) --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- For Bluetooth MAC access (pre-API 31) --> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- For Bluetooth access on Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Final Notes
For most third-party apps targeting modern Android versions, retrieving the real MAC address is no longer feasible due to privacy restrictions. Your best bet is to switch to one of the alternative unique identifiers mentioned above.
内容的提问来源于stack exchange,提问作者rezaj633




