Comprehensive Guide to Android Device Identifier Acquisition: From TelephonyManager to UUID Generation Strategies

Nov 28, 2025 · Programming · 10 views · 7.8

Keywords: Android Development | Device Identifier | UUID Generation | TelephonyManager | ANDROID_ID | Permission Management

Abstract: This article provides an in-depth exploration of various methods for obtaining unique device identifiers in Android applications. It begins with the basic usage of TelephonyManager.getDeviceId() and its permission requirements, then delves into UUID generation strategies based on ANDROID_ID, including handling known issues in Android 2.2. The paper discusses the persistence characteristics of different identifiers and their applicable scenarios, demonstrating reliable device identifier acquisition through complete code examples. Finally, it examines identifier behavior changes during device resets and system updates using practical application cases.

Introduction

Acquiring unique device identifiers is a common requirement in Android application development for user tracking, device management, and statistical analysis. However, due to Android system fragmentation and privacy protection requirements, this task has become quite complex. Based on high-quality Q&A data from Stack Overflow, this article systematically analyzes the advantages and disadvantages of various device identifier acquisition methods.

TelephonyManager.getDeviceId Method

The most direct method for obtaining device identifiers is through TelephonyManager's getDeviceId() method:

TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String uuid = tManager.getDeviceId();

This method returns the device's IMEI (International Mobile Equipment Identity) or MEID (Mobile Equipment Identifier), offering excellent uniqueness. However, several considerations are essential: First, the android.permission.READ_PHONE_STATE permission must be declared in AndroidManifest.xml; Second, starting from Android 6.0 (API level 23), this permission requires dynamic runtime request; Finally, on devices without cellular network capabilities (such as Wi-Fi tablets), this method may return null.

Permission Management and Runtime Requests

Since READ_PHONE_STATE is a dangerous permission, developers must properly handle the permission request process. After declaring the permission in AndroidManifest.xml, it's necessary to check permission status in the Activity and request user authorization appropriately:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_CODE);
}

Handle the user's authorization decision in the onRequestPermissionsResult callback, ensuring appropriate fallback solutions when permissions are denied.

ANDROID_ID and UUID Generation Strategy

Besides device ID, ANDROID_ID is another important source of device identifiers. Obtained through Settings.Secure.ANDROID_ID, this 64-bit number is generated when the device first boots up, but Android 2.2 has known issues: many devices return the same value 9774d56d682e549c, which is also the default value commonly used in emulators.

Based on this understanding, developers can adopt a layered strategy for generating device UUIDs:

public class DeviceUuidFactory {
    private static final String PREFS_FILE = "device_id.xml";
    private static final String PREFS_DEVICE_ID = "device_id";
    private static UUID uuid;
    
    public DeviceUuidFactory(Context context) {
        if (uuid == null) {
            synchronized (DeviceUuidFactory.class) {
                if (uuid == null) {
                    SharedPreferences prefs = context.getSharedPreferences(PREFS_FILE, 0);
                    String storedId = prefs.getString(PREFS_DEVICE_ID, null);
                    
                    if (storedId != null) {
                        uuid = UUID.fromString(storedId);
                    } else {
                        String androidId = Settings.Secure.getString(context.getContentResolver(), 
                            Settings.Secure.ANDROID_ID);
                        
                        if (!"9774d56d682e549c".equals(androidId)) {
                            uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                        } else {
                            TelephonyManager tm = (TelephonyManager) 
                                context.getSystemService(Context.TELEPHONY_SERVICE);
                            String deviceId = tm.getDeviceId();
                            uuid = deviceId != null ? 
                                UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) : 
                                UUID.randomUUID();
                        }
                        prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString()).apply();
                    }
                }
            }
        }
    }
    
    public UUID getDeviceUuid() {
        return uuid;
    }
}

Identifier Persistence and Reset Behavior

Different identifiers exhibit varying behaviors during device resets. UUIDs generated based on TelephonyManager.getDeviceId() remain unchanged after factory resets, while identifiers based on ANDROID_ID typically change after resets. Randomly generated UUIDs are only saved in application private storage and are lost after application uninstallation.

In environments supporting multiple users (Android 4.2 and above), each user has an independent ANDROID_ID, further complicating identifier management. Developers need to choose appropriate strategies based on specific business requirements: if tracking individual devices rather than installations is needed, device ID should be prioritized; if identifiers should reset when devices reset, dependency on device ID should be avoided.

Caching Issues in Practical Applications

The caching issues encountered by Retool Mobile applications, as mentioned in the reference article, remind us to pay attention to version management and cache clearance when handling device identifiers. When applications update or rename, old identifiers might be cached by the system, leading to inconsistent behaviors. Developers should ensure proper cleanup of relevant caches during application updates and implement version-compatible identifier migration strategies.

Best Practice Recommendations

Based on the above analysis, we recommend the following best practices: First, clarify business requirements, distinguishing between device tracking and installation tracking; Second, implement layered fallback strategies, prioritizing ANDROID_ID, falling back to device ID when problematic, and finally using random UUIDs; Third, properly handle permission requests and user denials; Finally, regularly evaluate identifier strategy effectiveness and adjust promptly to accommodate system version changes.

Conclusion

Acquiring Android device identifiers is a complex issue requiring comprehensive consideration of technical implementation, system compatibility, and user privacy. By reasonably combining TelephonyManager.getDeviceId(), ANDROID_ID, and UUID generation strategies, developers can build reliable device identification solutions that comply with privacy regulations. As the Android system continues to evolve, best practices in this field will keep updating, requiring developers to maintain awareness of new technologies and policies.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.