Les appareils Android ont-ils un identifiant unique et, dans l'affirmative, quel moyen simple d'y accéder via Java?
Settings.Secure#Android_ID
retourne l'ID Android sous la forme unique pour chaque utilisateur chaîne hexagonale de 64 bits.
import Android.provider.Settings.Secure;
private String Android_id = Secure.getString(getContext().getContentResolver(),
Secure.Android_ID);
UPDATE: depuis les dernières versions d'Android, de nombreux problèmes liés à Android_ID
ont été résolus et j'estime que cette approche n'est plus nécessaire. S'il vous plaît jeter un oeil à réponse d'Anthony .
Divulgation complète: mon application utilisait à l'origine l'approche ci-dessous, mais ne l'utilise plus. Nous utilisons maintenant l'approche décrite dans le Blog du développeur Android entrée que la réponse d'emmby liens (à savoir, générer et enregistrer une UUID#randomUUID()
).
Il existe de nombreuses réponses à cette question, dont la plupart ne fonctionneront que "certaines" fois, et malheureusement cela ne suffit pas.
Sur la base de mes tests de périphériques (tous les téléphones, dont au moins un n'est pas activé):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
(comme prévu)Android_ID
Android_ID
et TelephonyManager.getDeviceId()
- tant que un compte Google a été ajouté lors de l'installation.Donc, si vous voulez quelque chose d'unique sur le périphérique lui-même, TM.getDeviceId()
devrait suffira. Il est évident que certains utilisateurs sont plus paranoïaques que d'autres. Il peut donc être utile de hacher un ou plusieurs de ces identificateurs, de sorte que la chaîne reste pratiquement unique pour le périphérique, mais n'identifie pas explicitement le périphérique réel de l'utilisateur. Par exemple, en utilisant String.hashCode()
, associé à un UUID:
final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" + Android.provider.Settings.Secure.getString(getContentResolver(), Android.provider.Settings.Secure.Android_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
pourrait aboutir à quelque chose comme: 00000000-54b3-e7c7-0000-000046bffd97
Cela fonctionne assez bien pour moi.
Comme Richard le mentionne ci-dessous, n'oubliez pas que vous avez besoin de l'autorisation pour lire les propriétés TelephonyManager
, ajoutez ceci à votre manifeste:
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
importer des libs
import Android.content.Context;
import Android.telephony.TelephonyManager;
import Android.view.View;
Après avoir lu chaque article de Stack Overflow sur la création d'un identifiant unique, du blog de développeur Google et de la documentation Android, j'ai l'impression que le "pseudo-identifiant" est la meilleure option possible.
Code Psuedo:
_if API >= 9/10: (99.5% of devices)
return unique ID containing serial id (rooted devices may be different)
else
return the unique ID of build information (may overlap data - API < 9)
_
Merci à @stansult pour avoir posté toutes nos options (dans cette question de débordement de pile).
Email Email - Logiciel
<uses-permission Android:name="Android.permission.GET_ACCOUNTS" />
_ ou<uses-permission Android:name="Android.permission.READ_PROFILE" />
_ _<uses-permission Android:name="Android.permission.READ_CONTACTS" />
_ ( Comment obtenir l'adresse e-mail principale du périphérique Android )Numéro de téléphone de l'utilisateur - Logiciel
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
_ IMEI - Matériel (téléphones uniquement, nécessite Android.permission.READ_PHONE_STATE
)
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
_Android ID - Hardware (peut être nul, peut changer lors de la réinitialisation d'usine, peut être modifié sur un appareil enraciné)
Adresse MAC WLAN - Matériel (nécessite Android.permission.ACCESS_WIFI_STATE
)
<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE "/>
_ Adresse MAC Bluetooth - Matériel (appareils avec Bluetooth, nécessite Android.permission.BLUETOOTH
)
<uses-permission Android:name="Android.permission.BLUETOOTH "/>
_Pseudo-Unique ID - Logiciel (pour tous les appareils Android)
Je sais qu’il n’existe aucun moyen "parfait" d’obtenir un identifiant unique sans utiliser les autorisations; Cependant, nous n'avons parfois que vraiment besoin de suivre l'installation de l'appareil. Lorsqu'il s'agit de créer un identifiant unique, nous pouvons créer un "pseudo identifiant unique" basé uniquement sur les informations fournies par l'API Android sans utiliser d'autorisations supplémentaires. De cette façon, nous pouvons montrer le respect de l'utilisateur et essayer de lui offrir une bonne expérience.
Avec un pseudo-identifiant unique, vous ne rencontrez que le fait qu'il peut y avoir des doublons en raison du fait qu'il existe des périphériques similaires. Vous pouvez modifier la méthode combinée pour la rendre plus unique. Cependant, certains développeurs ont besoin de suivre les installations de périphériques et cela fera l'affaire ou la performance basée sur des périphériques similaires.
Si leur périphérique Android est une API 9 ou plus, il est garanti que cela est unique du fait du champ 'Build.SERIAL'.
SOUVENEZ-VOUS, techniquement, il ne manque que 0,5% environ des utilisateurs qui ont une API <9 . Vous pouvez donc vous concentrer sur le reste: 99,5% des utilisateurs!
Si le périphérique Android de l'utilisateur est inférieur à API 9; espérons-le, ils n'ont pas fait de réinitialisation d'usine et leur "Secure.Android_ID" sera préservé ou non "null". (voir http://developer.Android.com/about/dashboards/index.html )
Si tout échoue, si l'utilisateur a une valeur inférieure à l'API 9 (inférieure à Gingerbread), a réinitialisé son appareil ou si 'Secure.Android_ID' renvoie 'null', alors simplement l'ID renvoyé sera basé uniquement sur leur Android informations sur le périphérique. C'est là que les collisions peuvent se produire.
Changements:
S'il vous plaît jeter un oeil à la méthode ci-dessous:
_/**
* Return pseudo unique ID
* @return ID
*/
public static String getUniquePsuedoID() {
// If all else fails, if the user does have lower than API 9 (lower
// than Gingerbread), has reset their device or 'Secure.Android_ID'
// returns 'null', then simply the ID returned will be solely based
// off their Android device information. This is where the collisions
// can happen.
// Thanks http://www.pocketmagic.net/?p=1662!
// Try not to use DISPLAY, Host or ID - these items could change.
// If there are collisions, there will be overlapping data
String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// Thanks to @Roman SL!
// https://stackoverflow.com/a/4789483/950427
// Only devices with API >= 9 have Android.os.Build.SERIAL
// http://developer.Android.com/reference/Android/os/Build.html#SERIAL
// If a user upgrades software or roots their device, there will be a duplicate entry
String serial = null;
try {
serial = Android.os.Build.class.getField("SERIAL").get(null).toString();
// Go ahead and return the serial for api => 9
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
// String needs to be initialized
serial = "serial"; // some value
}
// Thanks @Joe!
// https://stackoverflow.com/a/2853253/950427
// Finally, combine the values we have found by using the UUID class to create a unique identifier
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
_
À partir de la console de Google Play Developer:
À compter du 1er août 2014, les règles du programme pour développeurs de Google Play exigent que tous les nouveaux téléchargements et mises à jour d'applications utilisent l'identifiant publicitaire au lieu de tout autre identifiant persistant à des fins publicitaires. Apprendre encore plus
Implementation :
Autorisation:
_<uses-permission Android:name="Android.permission.INTERNET" />
_
Code:
_import com.google.Android.gms.ads.identifier.AdvertisingIdClient;
import com.google.Android.gms.ads.identifier.AdvertisingIdClient.Info;
import com.google.Android.gms.common.GooglePlayServicesAvailabilityException;
import com.google.Android.gms.common.GooglePlayServicesNotAvailableException;
import Java.io.IOException;
...
// Do not call this function from the main thread. Otherwise,
// an IllegalStateException will be thrown.
public void getIdThread() {
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException exception) {
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesAvailabilityException exception) {
// Encountered a recoverable error connecting to Google Play services.
} catch (GooglePlayServicesNotAvailableException exception) {
// Google Play services is not available entirely.
}
final String id = adInfo.getId();
final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
}
_
Source/Docs:
http://developer.Android.com/google/play-services/id.htmlhttp://developer.Android.com/reference/com/google/Android/gms/ ads/identifiant/AdvertisingIdClient.html
Il est prévu que l'ID de publicité remplace complètement l'utilisation existante d'autres identificateurs à des fins publicitaires (telles que l'utilisation d'Android_ID dans Settings.Secure) lorsque les services Google Play sont disponibles. Les cas où les services Google Play ne sont pas disponibles sont signalés par une exception GooglePlayServicesNotAvailableExot levée par getAdvertisingIdInfo ().
http://fr.kioskea.net/faq/34732-Android-reset-your-advertising-id
J'ai essayé de référencer chaque lien pour lequel j'ai pris des informations. Si vous manquez et devez être inclus, veuillez commenter!
Comme Dave Webb le mentionne, le Android Developer Blog contient un article qui couvre cela. Leur solution préférée consiste à suivre les installations d'applications plutôt que de périphériques, ce qui fonctionnera bien dans la plupart des cas d'utilisation. L'article de blog vous montrera le code nécessaire pour que cela fonctionne, et je vous recommande de le vérifier.
Cependant, l'article de blog continue pour discuter des solutions si vous avez besoin d'un identifiant de périphérique plutôt que d'un identifiant d'installation d'application. J'ai parlé à quelqu'un chez Google pour obtenir des éclaircissements supplémentaires sur quelques éléments au cas où vous en auriez besoin. Voici ce que j'ai découvert sur les identificateurs de périphérique, qui n'est PAS mentionné dans l'article de blog susmentionné:
Sur la base des recommandations de Google, j'ai implémenté une classe qui générera un UUID unique pour chaque périphérique, en utilisant Android_ID comme source, le cas échéant, en recourant à TelephonyManager.getDeviceId () si nécessaire, et en cas d'échec, en recourant à un UUID unique généré de manière aléatoire. qui persiste lors des redémarrages d'applications (mais pas les réinstallations d'applications).
Notez que pour les périphériques qui doivent se replier sur l'ID de périphérique, l'ID unique PERSISTERA lors des réinitialisations d'usine. C'est quelque chose à prendre en compte. Si vous devez vous assurer qu'une réinitialisation d'usine réinitialisera votre ID unique, vous voudrez peut-être envisager de vous replier directement sur l'UUID aléatoire au lieu de l'ID de périphérique.
Encore une fois, ce code concerne un ID de périphérique, pas un ID d'installation d'application. Dans la plupart des situations, un ID d'installation d'application est probablement ce que vous recherchez. Mais si vous avez besoin d'un ID de périphérique, le code suivant fonctionnera probablement pour vous.
import Android.content.Context;
import Android.content.SharedPreferences;
import Android.provider.Settings.Secure;
import Android.telephony.TelephonyManager;
import Java.io.UnsupportedEncodingException;
import Java.util.UUID;
public class DeviceUuidFactory {
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
protected volatile static UUID uuid;
public DeviceUuidFactory(Context context) {
if (uuid == null) {
synchronized (DeviceUuidFactory.class) {
if (uuid == null) {
final SharedPreferences prefs = context
.getSharedPreferences(PREFS_FILE, 0);
final String id = prefs.getString(PREFS_DEVICE_ID, null);
if (id != null) {
// Use the ids previously computed and stored in the
// prefs file
uuid = UUID.fromString(id);
} else {
final String androidId = Secure.getString(
context.getContentResolver(), Secure.Android_ID);
// Use the Android ID unless it's broken, in which case
// fallback on deviceId,
// unless it's not available, then fallback on a random
// number which we store to a prefs file
try {
if (!"9774d56d682e549c".equals(androidId)) {
uuid = UUID.nameUUIDFromBytes(androidId
.getBytes("utf8"));
} else {
final String deviceId = (
(TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE))
.getDeviceId();
uuid = deviceId != null ? UUID
.nameUUIDFromBytes(deviceId
.getBytes("utf8")) : UUID
.randomUUID();
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// Write the value out to the prefs file
prefs.edit()
.putString(PREFS_DEVICE_ID, uuid.toString())
.commit();
}
}
}
}
}
/**
* Returns a unique UUID for the current Android device. As with all UUIDs,
* this unique ID is "very highly likely" to be unique across all Android
* devices. Much more so than Android_ID is.
*
* The UUID is generated by using Android_ID as the base key if appropriate,
* falling back on TelephonyManager.getDeviceID() if Android_ID is known to
* be incorrect, and finally falling back on a random UUID that's persisted
* to SharedPreferences if getDeviceID() does not return a usable value.
*
* In some rare circumstances, this ID may change. In particular, if the
* device is factory reset a new device ID may be generated. In addition, if
* a user upgrades their phone from certain buggy implementations of Android
* 2.2 to a newer, non-buggy version of Android, the device ID may change.
* Or, if a user uninstalls your app on a device that has neither a proper
* Android ID nor a Device ID, this ID may change on reinstallation.
*
* Note that if the code falls back on using TelephonyManager.getDeviceId(),
* the resulting ID will NOT change after a factory reset. Something to be
* aware of.
*
* Works around a bug in Android 2.2 for many devices when using Android_ID
* directly.
*
* @see http://code.google.com/p/Android/issues/detail?id=10603
*
* @return a UUID that may be used to uniquely identify your device for most
* purposes.
*/
public UUID getDeviceUuid() {
return uuid;
}
}
Voici le code utilisé par Reto Meier dans la présentation Google I/O cette année pour obtenir un identifiant unique pour l'utilisateur:
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
public synchronized static String id(Context context) {
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
}
}
return uniqueID;
}
Si vous associez ceci à une stratégie de sauvegarde pour envoyer des préférences vers le nuage (également décrit dans le message talk de Reto, vous devez avoir un identifiant qui se lie à un utilisateur et qui persiste après le nettoyage ou même le remplacement du périphérique. I prévoyez d’utiliser cela dans les analyses à venir (en d’autres termes, je n’ai pas encore fait ce travail :).
Vous pouvez également considérer l'adresse MAC de l'adaptateur Wi-Fi. Récupéré ainsi:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Nécessite l'autorisation Android.permission.ACCESS_WIFI_STATE
dans le manifeste.
Signalé comme étant disponible même lorsque le Wi-Fi n'est pas connecté. Si Joe de la réponse ci-dessus donne à celui-ci un essai sur ses nombreux appareils, ce serait bien.
Sur certains appareils, il n'est pas disponible lorsque le Wi-Fi est désactivé.
NOTE: À partir d'Android 6.x, il renvoie une fausse adresse mac cohérente: 02:00:00:00:00:00
Il y a des informations plutôt utiles ici.
Il couvre cinq types d'identification différents:
Android.permission.READ_PHONE_STATE
)Android.permission.ACCESS_WIFI_STATE
)Android.permission.BLUETOOTH
)Le blog officiel des développeurs Android contient désormais un article complet sur ce sujet, Identification des installations d'applications.
Sur Google I/O Reto Meier a publié une réponse précise sur la façon de procéder, qui devrait répondre au besoin de la plupart des développeurs de suivre les utilisateurs sur les installations. Anthony Nolan indique la direction dans sa réponse, mais je pensais écrire l'approche complète afin que les autres puissent facilement voir comment le faire (cela m'a pris un certain temps pour comprendre les détails).
Cette approche vous donnera un ID utilisateur anonyme et sécurisé qui sera persistant pour l'utilisateur sur différents appareils (en fonction du compte Google principal) et pour toutes les installations. L'approche de base consiste à générer un ID utilisateur aléatoire et à le stocker dans les préférences partagées des applications. Vous utilisez ensuite l'agent de sauvegarde de Google pour stocker les préférences partagées liées au compte Google dans le cloud.
Passons en revue l'approche complète. Tout d'abord, nous devons créer une sauvegarde pour nos références partagées à l'aide du service de sauvegarde Android. Commencez par enregistrer votre application via http://developer.Android.com/google/backup/signup.html
.
Google vous fournira une clé de service de sauvegarde que vous devrez ajouter au manifeste. Vous devez également indiquer à l'application d'utiliser BackupAgent comme suit:
<application Android:label="MyApplication"
Android:backupAgent="MyBackupAgent">
...
<meta-data Android:name="com.google.Android.backup.api_key"
Android:value="your_backup_service_key" />
</application>
Ensuite, vous devez créer l'agent de sauvegarde et lui dire d'utiliser l'agent auxiliaire pour les préférences partagées:
public class MyBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "user_preferences";
// A key to uniquely identify the set of backup data
static final String PREFS_BACKUP_KEY = "prefs";
// Allocate a helper and add it to the backup agent
@Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
Pour terminer la sauvegarde, vous devez créer une instance de BackupManager dans votre activité principale:
BackupManager backupManager = new BackupManager(context);
Enfin, créez un ID utilisateur, s'il n'existe pas déjà, et stockez-le dans les SharedPreferences:
public static String getUserID(Context context) {
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
MyBackupAgent.PREFS, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
//backup the changes
BackupManager mBackupManager = new BackupManager(context);
mBackupManager.dataChanged();
}
}
return uniqueID;
}
Cet ID utilisateur sera désormais persistant dans toutes les installations, même si l'utilisateur déplace le périphérique.
Pour plus d'informations sur cette approche, voir le discours de Reto .
Et pour plus de détails sur la mise en œuvre de l'agent de sauvegarde, voir Sauvegarde des données. Je recommande particulièrement la section du bas sur les tests, car la sauvegarde ne se produit pas instantanément. Par conséquent, pour tester, vous devez forcer la sauvegarde.
Je pense que c’est là un moyen sûr de construire un squelette pour une identité unique ... jetez-y un œil.
Pseudo-unique ID fonctionnant sur tous les appareils Android Certains appareils ne possèdent pas de téléphone (par exemple, les tablettes) ou, pour une raison quelconque, vous ne souhaitez pas inclure l'autorisation READ_PHONE_STATE. Vous pouvez toujours lire des détails tels que la version ROM, le nom du fabricant, le type de CPU et d’autres détails matériels, qui vous seront utiles si vous souhaitez utiliser l’ID pour une vérification de clé de série ou à d’autres fins générales. L'ID calculé de cette manière ne sera pas unique: il est possible de trouver deux périphériques avec le même ID (basés sur le même matériel et la même image ROM), mais les modifications dans les applications réelles sont négligeables. Pour cela, vous pouvez utiliser la classe Build:
String m_szDevIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.Host.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
La plupart des membres de Build sont des chaînes, ce que nous faisons ici est de prendre leur longueur et de la transformer via modulo en un chiffre. Nous avons 13 chiffres de ce type et nous ajoutons deux autres devant (35) pour avoir le même identifiant de taille que l’IMEI (15 chiffres). Il y a d'autres possibilités ici, jetez simplement un coup d'œil à ces chaînes . Renvoie quelque chose comme 355715565309247
. Aucune autorisation spéciale n'est requise, ce qui rend cette approche très pratique.
(Extra info: La technique donnée ci-dessus a été copiée d'un article sur Pocket Magic .)
Le code suivant renvoie le numéro de série du périphérique à l'aide d'une API Android masquée. Mais, ce code ne fonctionne pas sur Samsung Galaxy Tab car "ro.serialno" n'est pas défini sur cet appareil.
String serial = null;
try {
Class<?> c = Class.forName("Android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
}
catch (Exception ignored) {
}
En utilisant le code ci-dessous, vous pouvez obtenir l'ID de périphérique unique d'un périphérique Android OS sous forme de chaîne.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID);
Un champ Série a été ajouté à la classe Build
dans le niveau 9 de l'API (Android 2.3 - Pain d'épice). La documentation indique qu'il représente le numéro de série du matériel. Ainsi, il devrait être unique, s'il existe sur le périphérique.
Je ne sais pas s'il est réellement pris en charge (= pas null) par tous les périphériques avec un niveau d'API> = 9 bien.
J'ajouterai une chose: j'ai l'une de ces situations uniques.
En utilisant:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.Android_ID);
Il s'avère que même si ma tablette G Viewsonic signale un DeviceID différent de Null, chaque tablette G indique le même nombre.
Cela rend intéressant de jouer à "Pocket Empires" qui vous donne un accès instantané au compte de quelqu'un basé sur le "unique" DeviceID.
Mon appareil n'a pas de radio cellulaire.
Pour obtenir des instructions détaillées sur l'obtention d'un identifiant unique pour chaque périphérique Android à partir duquel l'application est installée, voir la publication officielle du blog des développeurs Android Identification des installations d'application.
Il semble que le meilleur moyen consiste à en créer un vous-même lors de l'installation et à le lire ensuite au redémarrage de l'application.
Personnellement, je trouve cela acceptable mais pas idéal. Aucun identifiant fourni par Android ne fonctionne dans tous les cas, car la plupart dépendent des états de la radio du téléphone (Wi-Fi activé/désactivé, cellulaire activé/désactivé, Bluetooth activé/désactivé). Les autres, comme Settings.Secure.Android_ID
, doivent être implémentés par le fabricant et ne sont pas garantis comme étant uniques.
Voici un exemple d'écriture de données dans un fichier installation qui serait stocké avec toutes les autres données que l'application enregistre localement.
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}
Ajoutez le code ci-dessous dans le fichier de classe:
final TelephonyManager tm = (TelephonyManager) getBaseContext()
.getSystemService(SplashActivity.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
Log.v("DeviceIMEI", "" + tmDevice);
tmSerial = "" + tm.getSimSerialNumber();
Log.v("GSM devices Serial Number[simcard] ", "" + tmSerial);
androidId = "" + Android.provider.Settings.Secure.getString(getContentResolver(),
Android.provider.Settings.Secure.Android_ID);
Log.v("androidId CDMA devices", "" + androidId);
UUID deviceUuid = new UUID(androidId.hashCode(),
((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
Log.v("deviceIdUUID universally unique identifier", "" + deviceId);
String deviceModelName = Android.os.Build.MODEL;
Log.v("Model Name", "" + deviceModelName);
String deviceUSER = Android.os.Build.USER;
Log.v("Name USER", "" + deviceUSER);
String devicePRODUCT = Android.os.Build.PRODUCT;
Log.v("PRODUCT", "" + devicePRODUCT);
String deviceHARDWARE = Android.os.Build.HARDWARE;
Log.v("HARDWARE", "" + deviceHARDWARE);
String deviceBRAND = Android.os.Build.BRAND;
Log.v("BRAND", "" + deviceBRAND);
String myVersion = Android.os.Build.VERSION.RELEASE;
Log.v("VERSION.RELEASE", "" + myVersion);
int sdkVersion = Android.os.Build.VERSION.SDK_INT;
Log.v("VERSION.SDK_INT", "" + sdkVersion);
Ajouter dans AndroidManifest.xml:
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
TelephonyManager
et Android_ID
, est obtenu par:String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null) {
deviceId = mTelephony.getDeviceId();
}
else {
deviceId = Secure.getString(
getApplicationContext().getContentResolver(),
Secure.Android_ID);
}
Mais je recommande fortement une méthode suggérée par Google, voir Identification des installations d'application.
Il existe de nombreuses approches différentes pour contourner ces problèmes de Android_ID
(il peut parfois être null
ou les périphériques d’un modèle spécifique renvoient toujours le même ID) avec les avantages et les inconvénients:
Je préfère moi-même utiliser une implémentation OpenUDID existante (voir https://github.com/ylechelle/OpenUDID ) pour Android (voir https://github.com/vieux/OpenUDID ). Il est facile à intégrer et utilise le Android_ID
avec des solutions de secours pour les problèmes mentionnés ci-dessus.
Mes deux cents - NB ceci est pour un ID unique de périphérique (err) - et non pour l'installation comme indiqué dans le Blog des développeurs Android .
Il est à noter que la solution fournie par @emmby retombe dans un ID par application, car les références SharedPreferences ne sont pas synchronisées entre les processus (voir ici et ici ). J'ai donc évité tout cela.
Au lieu de cela, j’ai encapsulé les différentes stratégies pour obtenir un identifiant (de périphérique) dans une énumération - le fait de modifier l’ordre des constantes d’énum affecte la priorité des différentes manières d’obtenir l’ID. Le premier identifiant non nul est renvoyé ou une exception est levée (conformément aux bonnes pratiques de Java consistant à ne pas donner de sens à null). Ainsi, par exemple, j'ai d'abord le téléphone TELEPHONY - mais un bon choix par défaut serait le Android_ID beta:
import Android.Manifest.permission;
import Android.bluetooth.BluetoothAdapter;
import Android.content.Context;
import Android.content.pm.PackageManager;
import Android.net.wifi.WifiManager;
import Android.provider.Settings.Secure;
import Android.telephony.TelephonyManager;
import Android.util.Log;
// TODO : hash
public final class DeviceIdentifier {
private DeviceIdentifier() {}
/** @see http://code.google.com/p/Android/issues/detail?id=10603 */
private static final String Android_ID_BUG_MSG = "The device suffers from "
+ "the Android ID bug - its ID is the emulator ID : "
+ IDs.BUGGY_Android_ID;
private static volatile String uuid; // volatile needed - see EJ item 71
// need lazy initialization to get a context
/**
* Returns a unique identifier for this device. The first (in the order the
* enums constants as defined in the IDs enum) non null identifier is
* returned or a DeviceIDException is thrown. A DeviceIDException is also
* thrown if ignoreBuggyAndroidID is false and the device has the Android ID
* bug
*
* @param ctx
* an Android constant (to retrieve system services)
* @param ignoreBuggyAndroidID
* if false, on a device with the Android ID bug, the buggy
* Android ID is not returned instead a DeviceIDException is
* thrown
* @return a *device* ID - null is never returned, instead a
* DeviceIDException is thrown
* @throws DeviceIDException
* if none of the enum methods manages to return a device ID
*/
public static String getDeviceIdentifier(Context ctx,
boolean ignoreBuggyAndroidID) throws DeviceIDException {
String result = uuid;
if (result == null) {
synchronized (DeviceIdentifier.class) {
result = uuid;
if (result == null) {
for (IDs id : IDs.values()) {
try {
result = uuid = id.getId(ctx);
} catch (DeviceIDNotUniqueException e) {
if (!ignoreBuggyAndroidID)
throw new DeviceIDException(e);
}
if (result != null) return result;
}
throw new DeviceIDException();
}
}
}
return result;
}
private static enum IDs {
TELEPHONY_ID {
@Override
String getId(Context ctx) {
// TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
final TelephonyManager tm = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
w("Telephony Manager not available");
return null;
}
assertPermission(ctx, permission.READ_PHONE_STATE);
return tm.getDeviceId();
}
},
Android_ID {
@Override
String getId(Context ctx) throws DeviceIDException {
// no permission needed !
final String andoidId = Secure.getString(
ctx.getContentResolver(),
Android.provider.Settings.Secure.Android_ID);
if (BUGGY_Android_ID.equals(andoidId)) {
e(Android_ID_BUG_MSG);
throw new DeviceIDNotUniqueException();
}
return andoidId;
}
},
WIFI_MAC {
@Override
String getId(Context ctx) {
WifiManager wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (wm == null) {
w("Wifi Manager not available");
return null;
}
assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
// getMacAddress() has no Java doc !!!
return wm.getConnectionInfo().getMacAddress();
}
},
BLUETOOTH_MAC {
@Override
String getId(Context ctx) {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
w("Bluetooth Adapter not available");
return null;
}
assertPermission(ctx, permission.BLUETOOTH);
return ba.getAddress();
}
}
// TODO PSEUDO_ID
// http://www.pocketmagic.net/2011/02/Android-unique-device-id/
;
static final String BUGGY_Android_ID = "9774d56d682e549c";
private final static String TAG = IDs.class.getSimpleName();
abstract String getId(Context ctx) throws DeviceIDException;
private static void w(String msg) {
Log.w(TAG, msg);
}
private static void e(String msg) {
Log.e(TAG, msg);
}
}
private static void assertPermission(Context ctx, String perm) {
final int checkPermission = ctx.getPackageManager().checkPermission(
perm, ctx.getPackageName());
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Permission " + perm + " is required");
}
}
// =========================================================================
// Exceptions
// =========================================================================
public static class DeviceIDException extends Exception {
private static final long serialVersionUID = -8083699995384519417L;
private static final String NO_Android_ID = "Could not retrieve a "
+ "device ID";
public DeviceIDException(Throwable throwable) {
super(NO_Android_ID, throwable);
}
public DeviceIDException(String detailMessage) {
super(detailMessage);
}
public DeviceIDException() {
super(NO_Android_ID);
}
}
public static final class DeviceIDNotUniqueException extends
DeviceIDException {
private static final long serialVersionUID = -8940090896069484955L;
public DeviceIDNotUniqueException() {
super(Android_ID_BUG_MSG);
}
}
}
Que diriez-vous du IMEI . C'est unique pour Android ou d'autres appareils mobiles.
Voici comment je génère l'identifiant unique:
public static String getDeviceId(Context ctx)
{
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice = tm.getDeviceId();
String androidId = Secure.getString(ctx.getContentResolver(), Secure.Android_ID);
String serial = null;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL;
if(tmDevice != null) return "01" + tmDevice;
if(androidId != null) return "02" + androidId;
if(serial != null) return "03" + serial;
// other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)
return null;
}
Une autre méthode consiste à utiliser /sys/class/Android_usb/Android0/iSerial
dans une application sans aucune autorisation.
user@creep:~$ adb Shell ls -l /sys/class/Android_usb/Android0/iSerial
-rw-r--r-- root root 4096 2013-01-10 21:08 iSerial
user@creep:~$ adb Shell cat /sys/class/Android_usb/Android0/iSerial
0A3CXXXXXXXXXX5
Pour faire cela en Java, il suffit d'utiliser un FileInputStream pour ouvrir le fichier iSerial et lire les caractères. Assurez-vous simplement de l'envelopper dans un gestionnaire d'exceptions, car tous les périphériques ne possèdent pas ce fichier.
Au moins les périphériques suivants sont connus pour avoir ce fichier lisible par tout le monde:
Vous pouvez également voir mon article de blog Fuite du numéro de série du matériel Android vers des applications non privilégiées où je discute des autres fichiers disponibles pour information.
Plus spécifiquement, Settings.Secure.Android_ID
. Il s’agit d’une quantité de 64 bits générée et stockée lors du premier démarrage du périphérique. Il est réinitialisé lorsque le périphérique est effacé.
Android_ID
semble être un bon choix pour un identifiant de périphérique unique. Il y a des inconvénients: Premièrement, il n'est pas fiable à 100% sur les versions d'Android antérieures à la version 2.2. (“Froyo”).
De plus, il y a eu au moins un bogue largement observé dans un combiné populaire d'un grand fabricant, où chaque instance a le même Android_ID.
J'utilise le code suivant pour obtenir la IMEI
ou utilise Secure .Android_ID
comme alternative, lorsque le périphérique ne dispose pas des capacités du téléphone:
String identifier = null;
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if (tm != null)
identifier = tm.getDeviceId();
if (identifier == null || identifier .length() == 0)
identifier = Secure.getString(activity.getContentResolver(),Secure.Android_ID);
Il y a plus de 30 réponses ici et certaines sont identiques et d'autres uniques. Cette réponse est basée sur peu de ces réponses. L'un d'eux est la réponse de @Lenn Dolling.
Il combine 3 ID et crée une chaîne hexadécimale de 32 chiffres. Cela a très bien fonctionné pour moi.
3 identifiants sont:
Pseudo-ID - Il est généré en fonction des spécifications du périphérique physique.
Android_ID - Settings.Secure.Android_ID
Adresse Bluetooth - Adresse de l'adaptateur Bluetooth
Il retournera quelque chose comme ceci: 551F27C060712A72730B0A0F734064B1
Remarque: Vous pouvez toujours ajouter d'autres identifiants à la chaîne longId
. Par exemple, numéro de série. adresse de l'adaptateur wifi. IMEI. De cette façon, vous le rendez plus unique par appareil.
@SuppressWarnings("deprecation")
@SuppressLint("HardwareIds")
public static String generateDeviceIdentifier(Context context) {
String pseudoId = "35" +
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.Host.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10;
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.Android_ID);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String btId = "";
if (bluetoothAdapter != null) {
btId = bluetoothAdapter.getAddress();
}
String longId = pseudoId + androidId + btId;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(longId.getBytes(), 0, longId.length());
// get md5 bytes
byte md5Bytes[] = messageDigest.digest();
// creating a hex string
String identifier = "";
for (byte md5Byte : md5Bytes) {
int b = (0xFF & md5Byte);
// if it is a single digit, make sure it have 0 in front (proper padding)
if (b <= 0xF) {
identifier += "0";
}
// add number to string
identifier += Integer.toHexString(b);
}
// hex string to uppercase
identifier = identifier.toUpperCase();
return identifier;
} catch (Exception e) {
Log.e("TAG", e.toString());
}
return "";
}
Pour la reconnaissance matérielle d'un périphérique Android spécifique, vous pouvez vérifier les adresses MAC.
vous pouvez le faire de cette façon:
dans AndroidManifest.xml
<uses-permission Android:name="Android.permission.INTERNET" />
maintenant dans votre code:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
Dans tous les appareils Android, leur interface est au moins "wlan0" et constitue la puce WI-FI . Ce code fonctionne même lorsque WI-FI n'est pas activé.
P.S . Il y a un tas d'autres interfaces que vous obtiendrez de la liste contenant MACS Mais cela peut changer entre les téléphones.
ID d'instance Google
Publié à I/O 2015; sur Android nécessite des services de jeu 7.5.
https://developers.google.com/instance-id/
https://developers.google.com/instance-id/guides/Android-implementation
InstanceID iid = InstanceID.getInstance( context ); // Google docs are wrong - this requires context
String id = iid.getId(); // blocking call
Il semble que Google ait l'intention d'utiliser cet identifiant pour identifier les installations sous Android, Chrome et iOS.
Il identifie une installation plutôt qu'un périphérique, mais encore une fois, Android_ID (qui est la réponse acceptée) n'identifie plus non plus les périphériques. Avec l'exécution ARC, un nouvel Android_ID est généré pour chaque installation ( détails ici ), tout comme ce nouvel ID d'instance. De plus, je pense que l’identification des installations (et non des périphériques) est ce que la plupart d’entre nous recherchent réellement.
Les avantages de l'instance ID
Il me semble que Google a l'intention de l'utiliser à cette fin (identifiant vos installations), il est multi-plateforme et peut être utilisé à plusieurs autres fins (voir les liens ci-dessus).
Si vous utilisez GCM, vous devrez éventuellement utiliser cet ID d'instance, car vous en avez besoin pour obtenir le jeton GCM (qui remplace l'ancien ID d'enregistrement GCM).
Les inconvénients/problèmes
Dans l'implémentation actuelle (GPS 7.5), l'ID d'instance est extrait d'un serveur lorsque votre application le demande. Cela signifie que l'appel ci-dessus est un appel bloquant - lors de mes tests non scientifiques, cela prend 1 à 3 secondes si le périphérique est en ligne, et 0,5 à 1,0 seconde s'il est hors ligne (vraisemblablement le délai d'attente avant l'abandon et la identification aléatoire). Cela a été testé en Amérique du Nord sur Nexus 5 avec Android 5.1.1 et GPS 7.5.
Si vous utilisez l'ID aux fins auxquelles ils sont destinés - par exemple. authentification de l'application, identification de l'application, GCM - Je pense que ces 1 à 3 secondes pourraient être gênantes (selon votre application, bien sûr).
Le Mac ID du périphérique Android est également un identifiant unique, cela ne changera pas si nous formatons le périphérique lui-même, utilisez donc le code suivant pour obtenir le Mac ID
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();
N'oubliez pas non plus d'ajouter les autorisations appropriées dans votre fichier AndroidManifest.xml
<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE"/>
TelephonyManger.getDeviceId () Renvoie l'ID de périphérique unique, par exemple l'IMEI pour GSM et le MEID ou ESN pour les téléphones CDMA.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
Mais je recommande d'utiliser:
Settings.Secure.Android_ID qui renvoie l'identifiant Android sous forme de chaîne hexagonale unique de 64 bits.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID);
Parfois, TelephonyManger.getDeviceId () renvoie la valeur null. Par conséquent, pour assurer un identifiant unique, vous utiliserez cette méthode:
public String getUniqueID(){
String myAndroidDeviceId = "";
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
}else{
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.Android_ID);
}
return myAndroidDeviceId;
}
Google a maintenant un identifiant publicitaire .
Ceci peut également être utilisé, mais notez que:
L'ID de publicité est un ID unique, réinitialisable, spécifique à l'utilisateur.
et
permet aux utilisateurs de réinitialiser leur identifiant ou de désactiver les annonces basées sur les centres d'intérêt dans les applications Google Play.
Donc, bien que cet identifiant puisse changer, il semble que bientôt nous n’avons peut-être pas le choix , dépend du but de cet identifiant.
Plus d'infos @ develper.Android
HTH
1.Vous pouvez accéder à l'identifiant de l'appareil Android par le service gms. voir l'exemple donné ci-dessous,
private DeviceInfoProvider mDeviceInfo = new DeviceInfoProvider(Context)
String mDeviceId = DeviceInfoProvider.getDeviceId(Context);
Log.d("DEVICE_ID" , mDeviceId);
2.Utilisez le gestionnaire de téléphonie, qui fournit un identifiant unique (IMEI). Voir l'exemple
import Android.telephony.TelephonyManager;
import Android.content.Context;
// ...
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) getSystemService(Context.
TELEPHONY_SERVICE);
/*
* getDeviceId() returns the unique device ID.
* For example,the IMEI for GSM and the MEID or ESN for CDMA phones.
*/
String deviceId = telephonyManager.getDeviceId();
/*
* getSubscriberId() returns the unique subscriber ID,
*/
String subscriberId = telephonyManager.getSubscriberId();
Cela nécessite Android.permission.READ_PHONE_STATE à votre utilisateur, ce qui peut être difficile à justifier en suivant le type d'application que vous avez faite.
Les appareils sans services de téléphonie, tels que les tablettes, doivent signaler un identifiant d'appareil unique disponible via Android.os.Build.SERIAL depuis Android 2.3 Gingerbread. Certains téléphones disposant de services téléphoniques peuvent également définir un numéro de série. Comme tous les appareils Android n’ont pas de numéro de série, cette solution n’est pas fiable.
Sur un premier démarrage de périphérique, une valeur aléatoire est générée et stockée. Cette valeur est disponible via Settings.Secure.Android_ID. C’est un nombre 64 bits qui devrait rester constant pendant toute la durée de vie d’un périphérique. Android_ID semble un bon choix pour un identifiant unique, car il est disponible pour les smartphones et les tablettes. Pour récupérer la valeur, vous pouvez utiliser le code suivant,
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 le périphérique. Il existe également un bug connu avec un téléphone populaire d'un fabricant où chaque instance a le même Android_ID. Clairement, la solution n'est pas fiable à 100%.
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
Non recommandé car deviceId peut être utilisé comme suivi entre des mains tierces, mais c'est une autre façon.
@SuppressLint("HardwareIds")
private String getDeviceID() {
deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(),
Settings.Secure.Android_ID);
return deviceId;
}
Je suis tombé sur cette question il y a plusieurs années et j'ai appris à mettre en œuvre une solution généralisée basée sur diverses réponses.
J'ai utilisé la solution généralisée pendant plusieurs années, dans un produit du monde réel. Cela me sert assez bien jusqu'à présent. Voici l'extrait de code, basé sur diverses réponses fournies.
Notez que getEmail
retournera null la plupart du temps, car nous n’avons pas demandé la permission explicitement.
private static UniqueId getUniqueId() {
MyApplication app = MyApplication.instance();
// Our prefered method of obtaining unique id in the following order.
// (1) Advertising id
// (2) Email
// (2) Android_ID
// (3) Instance ID - new id value, when reinstall the app.
////////////////////////////////////////////////////////////////////////////////////////////
// ADVERTISING ID
////////////////////////////////////////////////////////////////////////////////////////////
AdvertisingIdClient.Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(app);
} catch (IOException e) {
Log.e(TAG, "", e);
} catch (GooglePlayServicesNotAvailableException e) {
Log.e(TAG, "", e);
} catch (GooglePlayServicesRepairableException e) {
Log.e(TAG, "", e);
}
if (adInfo != null) {
String aid = adInfo.getId();
if (!Utils.isNullOrEmpty(aid)) {
return UniqueId.newInstance(aid, UniqueId.Type.aid);
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// EMAIL
////////////////////////////////////////////////////////////////////////////////////////////
final String email = Utils.getEmail();
if (!Utils.isNullOrEmpty(email)) {
return UniqueId.newInstance(email, UniqueId.Type.eid);
}
////////////////////////////////////////////////////////////////////////////////////////////
// Android ID
////////////////////////////////////////////////////////////////////////////////////////////
final String sid = Settings.Secure.getString(app.getContentResolver(), Settings.Secure.Android_ID);
if (!Utils.isNullOrEmpty(sid)) {
return UniqueId.newInstance(sid, UniqueId.Type.sid);
}
////////////////////////////////////////////////////////////////////////////////////////////
// INSTANCE ID
////////////////////////////////////////////////////////////////////////////////////////////
final String iid = com.google.Android.gms.iid.InstanceID.getInstance(MyApplication.instance()).getId();
if (!Utils.isNullOrEmpty(iid)) {
return UniqueId.newInstance(iid, UniqueId.Type.iid);
}
return null;
}
public final class UniqueId implements Parcelable {
public enum Type implements Parcelable {
aid,
sid,
iid,
eid;
////////////////////////////////////////////////////////////////////////////
// Handling Parcelable nicely.
public static final Parcelable.Creator<Type> CREATOR = new Parcelable.Creator<Type>() {
public Type createFromParcel(Parcel in) {
return Type.valueOf(in.readString());
}
public Type[] newArray(int size) {
return new Type[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(this.name());
}
// Handling Parcelable nicely.
////////////////////////////////////////////////////////////////////////////
}
public static boolean isValid(UniqueId uniqueId) {
if (uniqueId == null) {
return false;
}
return uniqueId.isValid();
}
private boolean isValid() {
return !org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) && type != null;
}
private UniqueId(String id, Type type) {
if (org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) || type == null) {
throw new Java.lang.IllegalArgumentException();
}
this.id = id;
this.type = type;
}
public static UniqueId newInstance(String id, Type type) {
return new UniqueId(id, type);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + id.hashCode();
result = 31 * result + type.hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof UniqueId)) {
return false;
}
UniqueId uniqueId = (UniqueId)o;
return this.id.equals(uniqueId.id) && this.type == uniqueId.type;
}
@Override
public String toString() {
return type + ":" + id;
}
////////////////////////////////////////////////////////////////////////////
// Handling Parcelable nicely.
public static final Parcelable.Creator<UniqueId> CREATOR = new Parcelable.Creator<UniqueId>() {
public UniqueId createFromParcel(Parcel in) {
return new UniqueId(in);
}
public UniqueId[] newArray(int size) {
return new UniqueId[size];
}
};
private UniqueId(Parcel in) {
this.id = in.readString();
this.type = in.readParcelable(Type.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(this.id);
parcel.writeParcelable(this.type, 0);
}
// Handling Parcelable nicely.
////////////////////////////////////////////////////////////////////////////
public final String id;
public final Type type;
}
public static String getEmail() {
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
AccountManager accountManager = AccountManager.get(MyApplication.instance());
Account[] accounts = accountManager.getAccountsByType("com.google");
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
String possibleEmail = account.name;
return possibleEmail;
}
}
accounts = accountManager.getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
String possibleEmail = account.name;
return possibleEmail;
}
}
return null;
}
Voici une réponse simple pour obtenir AAID, testé et testé correctement en juin 2019
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
String token = null;
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (IOException e) {
// ...
} catch ( GooglePlayServicesRepairableException e) {
// ...
} catch (GooglePlayServicesNotAvailableException e) {
// ...
}
String Android_id = adInfo.getId();
Log.d("DEVICE_ID",Android_id);
return Android_id;
}
@Override
protected void onPostExecute(String token) {
Log.i(TAG, "DEVICE_ID Access token retrieved:" + token);
}
};
task.execute();
lire la réponse complète en détail ici :
Comprendre les identifiants uniques disponibles sur les appareils Android. Utilisez ce guide officiel.
Meilleures pratiques pour les identificateurs uniques:
IMEI, adresses Mac, ID d'instance, GUID, SSAID, ID de publicité, API Safety Net pour vérifier les périphériques.
https://developer.Android.com/training/articles/user-data-ids
Juste un avertissement pour tous ceux qui liront à la recherche d’informations plus récentes. Avec Android O, la manière dont le système gère ces identifiants a été modifiée.
https://Android-developers.googleblog.com/2017/04/changes-to-device-identifiers-in.html
tl; dr Serial nécessitera l’autorisation PHONE et l’identité Android changera pour différentes applications, en fonction du nom de leur package et de sa signature.
Google a également rédigé un document de Nice contenant des suggestions sur l'utilisation des identifiants matériel et logiciel.
https://developer.Android.com/training/articles/user-data-ids.html
Normalement, j'utilise un identifiant unique de périphérique pour mes applications. Mais parfois, j'utilise IMEI. Les deux sont des numéros uniques.
obtenirIMEI(identifiant international d'équipement mobile)
public String getIMEI(Activity activity) {
TelephonyManager telephonyManager = (TelephonyManager) activity
.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
pour obtenir identifiant unique de l'appareil
public String getDeviceUniqueID(Activity activity){
String device_unique_id = Secure.getString(activity.getContentResolver(),
Secure.Android_ID);
return device_unique_id;
}
Numéro de série est un identifiant unique disponible sur Android.os.Build.SERIAL.
public static String getSerial() {
String serial = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
serial = Build.getSerial();
}else{
serial = Build.SERIAL;
}
return serial;
}
Assurez-vous que vous disposez de READ_PHONE_STATE permission avant d'appeler getSerial ().
NOTE: - Il est Non disponible avec les appareils sans téléphonie (comme les tablettes wifi uniquement).
Pour obtenir un identifiant d'utilisateur, vous pouvez utiliser la bibliothèque de licences de Google Play.
Pour télécharger cette bibliothèque, ouvrez SDK Manager => SDK Tools. Le chemin d'accès aux fichiers de bibliothèque téléchargés est:
path_to_Android_sdk_on_votre_pc/extras/google/market_licensing/bibliothèque
Incluez la bibliothèque dans votre projet (vous pouvez simplement copier ses fichiers).
Ensuite, vous avez besoin de quelques implémentations de l'interface Policy
(vous pouvez simplement utiliser l'un des deux fichiers de la bibliothèque: ServerManagedPolicy
ou StrictPolicy
).
L'identifiant de l'utilisateur vous sera fourni dans la fonction processServerResponse()
:
public void processServerResponse(int response, ResponseData rawData) {
if(rawData != null) {
String userId = rawData.userId
// use/save the value
}
// ...
}
Ensuite, vous devez construire la LicenseChecker
avec une règle et appeler la fonction checkAccess()
. Utilisez MainActivity.Java
comme exemple de procédure. MainActivity.Java
se trouve dans ce dossier:
path_to_Android_sdk_on_votre_pc/extras/google/marché_licensing/échantillon/src/com/exemple/Android/marché/licence
N'oubliez pas d'ajouter l'autorisation CHECK_LICENSE à votre AndroidManifest.xml.
En savoir plus sur la bibliothèque de licences: https://developer.Android.com/google/play/licensing
String SERIAL_NUMER = Build.SERIAL;
Renvoie NUMÉRO DE SÉRIE sous la forme d'une chaîne unique dans chaque appareil.
Afin d'inclure Android 9 je n'ai qu'une idée qui puisse encore fonctionner, qui (probablement) n'enfreint aucun terme, nécessite des autorisations et fonctionne sur plusieurs installations et applications.
Les empreintes digitales impliquant un serveur doivent être capables d'identifier un périphérique de manière unique . La combinaison d'informations sur le matériel + les applications installées et les temps d'installation devraient faire l'affaire. Les premières heures d’installation ne changent pas sauf si une application est désinstallée puis réinstallée. Mais cela devrait être fait pour toutes les applications sur l'appareil afin de ne pas pouvoir identifier l'appareil (c'est-à-dire après une réinitialisation d'usine).
Voici comment je m'y prendrais:
Voici comment extraire toutes les applications d’Android (aucune autorisation requise):
final PackageManager pm = application.getPackageManager();
List<ApplicationInfo> packages =
pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
try {
Log.d(TAG, "Installed package :" + packageInfo.packageName);
Log.d(TAG, "Installed :" + pm.getPackageInfo(packageInfo.packageName, 0).firstInstallTime);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
NB: Ceci est une méthode non testée et non prouvée! Je suis convaincu que cela fonctionnera, mais je suis également à peu près sûr que si cela réussit, ils le fermeront d'une manière ou d'une autre.
Obtenez l'ID de périphérique une seule fois, puis stockez-le dans une base de données ou un fichier. Dans ce cas, s'il s'agit du premier démarrage de l'application, elle génère un ID et le stocke. La prochaine fois, il ne faudra que l'identifiant stocké dans le fichier.
Si vous ajoutez:
Settings.Secure.getString(context.contentResolver,
Settings.Secure.Android_ID)
Android Lint vous donnera l'avertissement suivant:
L'utilisation de getString pour obtenir les identificateurs de périphérique n'est pas recommandée. Informations de contrôle: L'utilisation de ces identificateurs de périphérique n'est pas recommandée, sauf pour la prévention des fraudes de grande valeur et les cas d'utilisation de la téléphonie avancée. Pour les cas d'utilisation de publicité, utilisez AdvertisingIdClient $ Info # getId et pour l'analyse, utilisez InstanceId # getId.
Donc, vous devriez éviter d'utiliser ceci.
Comme mentionné dans documentation pour les développeurs Android :
1: Évitez d’utiliser des identifiants matériels.
Dans la plupart des cas d'utilisation, vous pouvez éviter d'utiliser des identificateurs matériels, tels que SSAID (Android ID) et IMEI, sans limiter les fonctionnalités requises.
2: utilisez uniquement un identifiant de publicité pour les cas d'utilisation de profilage d'utilisateur ou d'annonce.
Lorsque vous utilisez un identifiant publicitaire, respectez toujours les choix des utilisateurs en matière de suivi des annonces. Assurez-vous également que l'identifiant ne peut pas être connecté à des informations d'identification personnelle (PII) et évitez de mettre en parallèle les réinitialisations d'ID de publicité.
3: Utilisez un ID d'instance ou un GUID enregistré de manière privée pour tous les autres cas d'utilisation, à l'exception de la prévention des fraudes de paiement et de la téléphonie.
Pour la grande majorité des cas d'utilisation non publicitaires, un ID d'instance ou GUID devrait suffire.
4: Utilisez des API adaptées à votre cas d'utilisation afin de minimiser les risques pour la confidentialité.
Utilisez l'API DRM pour la protection de contenu de grande valeur et les API SafetyNet pour la protection contre les abus. Les API SafetyNet constituent le moyen le plus simple de déterminer si un périphérique est authentique sans encourir de risque pour la confidentialité.
Pour être complet, voici comment vous pouvez obtenir la Id
dans Xamarin.Android
et C #:
var id = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);
Ou si vous n'êtes pas dans une Activity
:
var id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId);
Où context
est le passé dans le contexte.