Customizing device identifiers on Android
PingOne Advanced Identity Cloud PingAM Android
The Device Binding module uses the Device ID module to generate a unique identifier for the device. This ID is used to store and retrieve the details of the device from the user’s profile on the server.
The Device ID supports multiple strategies for generating an identifier, such as Android ID and keystore-based identifiers, ensuring flexibility and security for various use cases:
DefaultDeviceIdentifier-
Uses the Android KeyStore for secure, persistent device identification.
This is the default option.
AndroidIDDeviceIdentifier-
Uses the Android system-provided device identifier.
LegacyDeviceIdentifier-
Provides compatibility with older device identification schemes.
The strategy you choose depends on your use case and requirements, as described in the following table:
| Feature | Default Device Identifier | Android ID Device Identifier | Legacy Device Identifier |
|---|---|---|---|
Identifier Source |
KeyStore-generated RSA key pair. |
|
KeyStore plus Android ID combination, or |
Uniqueness |
Unique to the app and device. |
Unique per app signing key, user, and device. (API 26+) |
Unique to the app and device. Compatible with legacy systems. |
Persistence |
Generates new ID when app reinstall. |
Persists across app reinstall. |
Depends on key existence, falls back to |
Behavior on New Device |
Different ID per device. |
Different ID per device. |
Different ID per device. |
Behavior on Reinstall |
Consistent if the KeyStore entries persist. However, in general, the OS removes the KeyStore when uninstalling the app. |
Consistent. (API 26+) |
Consistent if the KeyStore entries persist. However, in general, the OS removes the KeyStore when uninstalling the app. |
Behavior on Data Clear |
Change when clearing the KeyStore entries. |
Consistent. |
Change when clearing the KeyStore entries. |
Security |
Cryptographically secure, hardware-backed when available. |
System-managed, read-only. |
Combination of system ID and cryptographic material. |
Select your preferred method for obtaining a device ID below to see how to implement it in your Android apps:
-
Default identifier
-
Android ID
-
Legacy identifier
-
Custom identifier
The DefaultDeviceIdentifier provides a secure, persistent identifier using the Android KeyStore:
// Get the KeyStore-based identifier
val deviceId = DefaultDeviceIdentifier.id
The DefaultDeviceIdentifier method perform the following steps to return a unique identifier:
-
Creates and stores a key pair in the Android KeyStore
-
Uses the public key as the basis for the device identifier
-
Hashes the key data using SHA-256 for added security
-
Caches the result for efficient access
Use AndroidIDDeviceIdentifier to retrieve the Android ID. The ANDROID_ID is a 64-bit unique identifier for each device:
// Get the Android ID-based identifier
val androidId = AndroidIDDeviceIdentifier.id
The ANDROID_ID returned by AndroidIDDeviceIdentifier:
-
Is unique to each combination of app-signing key, user, and device, on devices running Android 8.0 (API level 26) and higher.
-
Persists across app re-installs but may change on factory reset.
For applications transitioning from older SDKs, the LegacyDeviceIdentifier provides compatibility:
// Get the legacy identifier (compatible with older implementations)
val legacyId = LegacyDeviceIdentifier.id
The LegacyDeviceIdentifier method perform the following steps to return a unique identifier:
-
Attempts to retrieve a key from the KeyStore using the Android ID as the key alias
-
If found, creates a composite identifier compatible with legacy systems
-
If not found, falls back to the
DefaultDeviceIdentifier
You can optionally define your own custom device identifier by implementing the DeviceIdentifier interface:
class CustomDeviceIdentifier : DeviceIdentifier {
override val id: String by lazy {
// Generate a custom identifier based on your specific requirements
val uniqueData = "your-unique-data-source"
MessageDigest.getInstance("SHA-256")
.digest(uniqueData.toByteArray())
.joinToString("") { "%02x".format(it) }
}
}
// Use your custom identifier
val customId = CustomDeviceIdentifier.id