La fonctionnalité principale de l'application de notre client est de relayer fortement le suivi des appareils de ses clients, ils proposent des produits qui sont liés au téléphone spécifique (pas à son propriétaire). Cela a été possible en utilisant l'appareil imei, mais avec les changements de confidentialité dans Android 10, ils l'ont rendu inaccessible. ( https://developer.Android.com/about/versions/ 10/confidentialité/modifications ).
Android a une documentation sur l'identifiant à utiliser dans des cas d'utilisateurs spécifiques, mais ne correspond pas à notre cas car nous avons besoin qu'il soit unique, constant et lié à l'appareil (ou du moins difficile à changer). https://developer.Android.com/training/articles/user-data-ids . J'envisage Android ID d'être une solution possible, ou d'utiliser l'adresse mac en sachant qu'ils ne sont pas fiables à 100%.
Des pensées? recommandations? expériences? à ce stade, tout pourrait être une option
Je vous conseille de lire le blog officiel des meilleures pratiques de google pour voir ce que le cas d'utilisation correspond à vos spécifications: https://developer.Android.com/training/articles/user-data-ids.html
Pour moi, j'ai rencontré le même problème concernant l'unicité des identifiants Android et j'ai trouvé que la seule solution était d'utiliser l'API MediaDrm ( https://Android.googlesource.com/platform) /frameworks/base/+/Android-cts-4.4_r1/media/Java/Android/media/MediaDrm.Java#539 ) qui contient un identifiant d'appareil unique et peut survivre même lors de la réinitialisation d'usine et n'a pas besoin toute autorisation supplémentaire sur votre fichier manifeste.
Voici le couple de code, comment pouvons-nous récupérer l'identifiant unique sur Android 10:
import Android.media.MediaDrm
import Java.security.MessageDigest
import Java.util.*
object UniqueDeviceID {
/**
* UUID for the Widevine DRM scheme.
* <p>
* Widevine is supported on Android devices running Android 4.3 (API Level 18) and up.
*/
fun getUniqueId(): String? {
val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
var wvDrm: MediaDrm? = null
try {
wvDrm = MediaDrm(WIDEVINE_UUID)
val widevineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
val md = MessageDigest.getInstance("SHA-256")
md.update(widevineId)
return md.digest().toHexString()
} catch (e: Exception) {
//WIDEVINE is not available
return null
} finally {
if (AndroidPlatformUtils.isAndroidTargetPieAndHigher()) {
wvDrm?.close()
} else {
wvDrm?.release()
}
}
}
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
}
Pour Java utilisateurs intéressés par la solution par @Sofien, j'ai:
@Nullable
String getUniqueID() {
UUID wideVineUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
try {
MediaDrm wvDrm = new MediaDrm(wideVineUuid);
byte[] wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
return Arrays.toString(wideVineId);
} catch (Exception e) {
// Inspect exception
return null;
}
// Close resources with close() or release() depending on platform API
// Use ARM on Android P platform or higher, where MediaDrm has the close() method
}
Il y a deux différences clés par rapport à t. @ Code de Sophien.
MessageDigest
, ce qui donne un code plus simple. De plus, la méthode MessageDigest.update()
applique la fonction de hachage SHA-256
À son argument, ce qui introduit une probabilité extrêmement faible de perdre l'unicité UUID. Le seul inconvénient de ne pas hacher l'UUID est que vous n'avez pas d'UUID de longueur fixe, ce qui ne m'importe pas dans mon application.toHexString
(qui n'a pas d'équivalent sur une ligne en Java) j'utilise Arrays.toString
. Ce choix est sûr car (A) Il ne lance pas Exception
et (B) il conserve une correspondance biunivoque entre la wideVineId
et sa représentation String
. Si vous préférez vous en tenir à la conversion hexadécimale, la bibliothèque Apache Commons Codec propose une solution sur une seule ligne, voir cette réponse .Bien sûr, ces changements entraînent un UUID différent, inutile de dire que d'autres choix sont possibles. Notez également qu'un UUID généré avec Arrays.toString
Prend la forme
[92, -72, 76, -100, 26, -86, 121, -57, 81, -83, -81, -26, -26, 3, -49, 97, -24, -86, 17, -106, 25, 102, 55, 37, 47, -5, 33, -78, 34, 121, -58, 109]
Donc, si vous ne voulez pas de caractères spéciaux dans votre UUID, vous pouvez les supprimer avec String.replaceAll()
.
J'ai testé la persistance de l'UUID
sur les combinaisons appareil/système d'exploitation suivantes:
Dans tous les tests, le targetSdkVersion
est 29.
private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider(Context)
String mDeviceId = DeviceInfoProvider.getDeviceId(Context);
Log.d("DEVICE_ID" , mDeviceId);
String androidId = Settings.Secure.getString(getContentResolver(),
Settings.Secure.Android_ID);
Cependant, la valeur peut changer si une réinitialisation d'usine est effectuée sur l'appareil. Il existe également un bug connu avec un combiné populaire d'un fabricant où chaque instance a le même Android_ID. De toute évidence, la solution n'est pas fiable à 100%.
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);