Comment trouver le numéro de série de l'appareil Android?
16 réponses
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();
getSystemService est une méthode de la classe D'activité. getDeviceID () retournera le MDN ou le MEID De l'appareil en fonction de la radio utilisée (GSM ou CDMA).
chaque appareil doit retourner une valeur unique ici (en supposant que c'est un téléphone). Cela devrait fonctionner pour N'importe quel appareil Android avec un slot sim ou une radio CDMA. Vous êtes sur votre propre avec Android four à micro-ondes ;-)
comme Dave Webb le mentionne, le Android Developer Blog a un article qui couvre ceci.
j'ai parlé à Quelqu'un chez Google pour obtenir des éclaircissements supplémentaires sur quelques éléments. Voici ce que j'ai découvert qui N'est pas mentionné dans le billet de blog susmentionné:
- ANDROID_ID est la solution préférée. ANDROID_ID est parfaitement fiable sur les versions D'Android <=2.1 ou >=2.3. Seulement 2,2 a les problèmes mentionné dans le post.
- plusieurs appareils de plusieurs fabricants sont affectés par le bug ANDROID_ID en 2.2.
- d'après ce que j'ai pu déterminer, tous les appareils affectés ont le même ANDROID_ID , qui est 9774d56d682e549c . Qui est aussi le même ID de périphérique rapporté par l'émulateur, btw.
- Google estime que les OEM ont corrigé la question pour beaucoup ou la plupart de leurs dispositifs, mais j'ai pu vérifier qu'au début du mois d'avril 2011, au moins, il est encore assez facile de trouver des dispositifs qui ont l'ANDROID_ID cassé.
sur la base des recommandations de Google, j'ai mis en œuvre une classe qui va générer un UUID unique pour chaque périphérique, en utilisant ANDROID_ID comme la graine le cas échéant, en retombant sur TelephonyManager.getDeviceId () si nécessaire, et si cela échoue, en recourant à un UUID unique généré au hasard qui persiste l'ensemble des redémarrages d'applications (mais pas les ré-installations d'applications).
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 static volatile 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;
}
}
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) {
}
ce code renvoie le numéro de série du périphérique à l'aide d'une API Android cachée.
String deviceId = Settings.System.getString(getContentResolver(),
Settings.System.ANDROID_ID);
bien que, il n'est pas garanti que L'ID Android sera un identifiant unique.
Il y a un excellent post sur l'Android Developer Blog de discuter de cette .
il recommande de ne pas utiliser TelephonyManager.getDeviceId()
car il ne fonctionne pas sur les appareils Android qui ne sont pas des téléphones tels que les tablettes, il nécessite la permission READ_PHONE_STATE
et il ne fonctionne pas de manière fiable sur tous les téléphones.
à la place, vous pouvez utiliser l'un des suivants:
- Adresse Mac
- Numéro De Série
- ANDROID_ID
La poste examine les avantages et les inconvénients de chacun et il est intéressant de lire, de sorte que vous pouvez travailler sur ce qui serait le meilleur pour votre utilisation.
pour un nombre simple qui est unique à l'appareil et constant pour sa durée de vie (sauf réarmement ou piratage d'usine), utilisez les paramètres .Sécuriser.ANDROID_ID .
String id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
pour utiliser le numéro de série de l'appareil (celui indiqué dans "Paramètres du système / à propos / état") si disponible et de retomber à Android ID:
String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);
L'IMEI est bon, mais ne fonctionne que sur les appareils Android avec le téléphone. Vous devriez envisager de soutien pour les Tablettes ou d'autres appareils Android, qui n'ont pas de téléphone.
vous avez quelques alternatives comme: construire des membres de classe, BT MAC, WLAN MAC, ou encore mieux - une combinaison de tous ces.
j'ai expliqué Ces détails dans un article sur mon blog, voir: http://www.pocketmagic.net/?p=1662
depuis aucune réponse ici ne mentionne un ID parfait, infaillible qui est à la fois persistante à travers les mises à jour du système et existe dans tous les appareils (principalement en raison du fait qu'il n'y a pas une solution individuelle de Google), j'ai décidé de poster une méthode qui est la prochaine meilleure chose en combinant deux des identificateurs disponibles, et une vérification à choisir entre eux à l'exécution.
avant code, 3 faits:
-
TelephonyManager.getDeviceId()
(A. K. A. IMEI) ne fonctionnera pas bien ou pas du tout pour les non-GSM, 3G, LTE, etc. les appareils, mais retourneront toujours un ID unique quand le matériel correspondant est présent , même quand aucun SIM n'est inséré ou même quand aucun slot SIM n'existe (certains OEM l'ont fait). -
depuis Gingerbread (Android 2.3)
android.os.Build.SERIAL
doit exister sur tout appareil qui ne fournit pas IMEI , c'est-à-dire, n'a pas le susmentionné matériel présent, conformément à la Politique Android. -
en Raison du fait, paragraphe 2.), au moins un de ces deux identificateurs uniques sera toujours présent , et le numéro de série can sera toujours présent en même temps que L'IMEI.
Note: (1. et 2.) sont basé sur les déclarations de Google
SOLUTION
avec les faits ci-dessus, on peut toujours avoir un identifiant unique en vérifiant s'il y a du matériel lié à IMEI, et revenir à la série quand ce n'est pas le cas, car on ne peut pas vérifier si la série existante est valide. La classe statique suivante présente 2 méthodes pour vérifier cette présence et en utilisant soit IMEI soit SERIAL:
import java.lang.reflect.Method;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
public class IDManagement {
public static String getCleartextID_SIMCHECK (Context mContext){
String ret = "";
TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if(isSIMAvailable(mContext,telMgr)){
Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId());
return telMgr.getDeviceId();
}
else{
Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
// return Settings.Secure.ANDROID_ID;
return android.os.Build.SERIAL;
}
}
public static String getCleartextID_HARDCHECK (Context mContext){
String ret = "";
TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if(telMgr != null && hasTelephony(mContext)){
Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId() + "");
return telMgr.getDeviceId();
}
else{
Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
// return Settings.Secure.ANDROID_ID;
return android.os.Build.SERIAL;
}
}
public static boolean isSIMAvailable(Context mContext,
TelephonyManager telMgr){
int simState = telMgr.getSimState();
switch (simState) {
case TelephonyManager.SIM_STATE_ABSENT:
return false;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
return false;
case TelephonyManager.SIM_STATE_PIN_REQUIRED:
return false;
case TelephonyManager.SIM_STATE_PUK_REQUIRED:
return false;
case TelephonyManager.SIM_STATE_READY:
return true;
case TelephonyManager.SIM_STATE_UNKNOWN:
return false;
default:
return false;
}
}
static public boolean hasTelephony(Context mContext)
{
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null)
return false;
//devices below are phones only
if (Build.VERSION.SDK_INT < 5)
return true;
PackageManager pm = mContext.getPackageManager();
if (pm == null)
return false;
boolean retval = false;
try
{
Class<?> [] parameters = new Class[1];
parameters[0] = String.class;
Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
Object [] parm = new Object[1];
parm[0] = "android.hardware.telephony";
Object retValue = method.invoke(pm, parm);
if (retValue instanceof Boolean)
retval = ((Boolean) retValue).booleanValue();
else
retval = false;
}
catch (Exception e)
{
retval = false;
}
return retval;
}
}
je conseillerais d'utiliser getCleartextID_HARDCHECK
. Si la réflexion ne colle pas dans votre environnement, utilisez la méthode getCleartextID_SIMCHECK
au lieu de cela, mais prenez en considération qu'il devrait être adapté à vos besoins spécifiques SIM-présence.
P.S. : veuillez noter que les OEM ont géré de bug sur Série contre Google politique (plusieurs appareils avec la même série), et Google comme indiqué Il ya au moins un cas connu dans un grand OEM (pas divulgué et je ne sais pas quelle marque il est soit, je suppose Samsung).
clause de non-responsabilité : cela répond à la question originale d'obtenir un identifiant unique de périphérique, mais L'OP a introduit l'ambiguïté en affirmant qu'il a besoin d'un identifiant unique pour une application. Même si pour de tels scénarios Android_ID serait mieux, il ne fonctionnera pas après, par exemple, une sauvegarde Titanium d'une application à travers 2 ROM différentes installe (peut même être la même ROM). Ma solution maintient la persistance qui est indépendante d'un flash ou d'une réinitialisation d'usine, et ne peut échouer que si IMEI ou une falsification en série se produit par le biais de hacks/hardware mods.
il y a des problèmes avec toutes les approches ci-dessus. Chez Google i/o Reto Meier publié une réponse robuste à la façon d'aborder ce qui devrait répondre à la plupart des besoins des développeurs de suivre les utilisateurs à travers les installations.
cette approche vous donnera un identifiant d'utilisateur anonyme et sécurisé qui sera persistant pour l'utilisateur à travers différents appareils (y compris les tablettes, basé sur le compte Google primaire) et à travers les installations sur le même appareil. L'approche de base consiste à générer un nom d'utilisateur aléatoire et de 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.
permet de passer par l'approche complète. Tout d'abord, nous avons besoin de créer une sauvegarde pour nos références partagées en utilisant le service de sauvegarde Android. Commencez par enregistrer votre application via ce lien: http://developer.android.com/google/backup/signup.html
Google will vous donner une clé de service de sauvegarde que vous devez ajouter au manifeste. Vous devez également dire à l'application d'utiliser le 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 helper pour sharedpreferences:
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 compléter la sauvegarde dont vous avez besoin pour créer une instance de BackupManager dans votre activité principale:
BackupManager backupManager = new BackupManager(context);
enfin créer un ID utilisateur, si il n'existe pas encore, et le stocker dans les références partagées:
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 User_ID sera maintenant persistant dans toutes les installations, même si l'utilisateur change de périphérique.
pour plus d'informations sur cette approche, voir reto's talk ici http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html
et pour plus de détails sur la façon de mettre en œuvre l'agent de sauvegarde voir le site du développeur ici: http://developer.android.com/guide/topics/data/backup.html Je recommande particulièrement la section en bas sur testing car la sauvegarde ne se produit pas instantanément et donc pour tester vous devez forcer la sauvegarde.
une autre façon est d'utiliser /sys/class/android_usb/android0/iSerial dans une application sans aucune permission.
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. Juste être sûr que vous l'enveloppez dans un gestionnaire d'exception parce que tous les appareils n'ont pas ce fichier.
au moins les dispositifs suivants sont connus pour avoir ce fichier lisible dans le monde:
- Galaxy Nexus
- Nexus S
- Motorola Xoom 3g
- Toshiba AT300
- HTC One V
- Mini MK802
- Samsung Galaxy S II
vous pouvez aussi voir mon billet de blog ici: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html où je discute des autres fichiers disponibles pour info.
IDENTIFIANT Unique de l'appareil du système d'exploitation Android de l'Appareil en tant que Chaîne de caractères.
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 vivement cette méthode proposée par Google::
comme dit @haserman:
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();
mais il est nécessaire d'inclure la permission dans le fichier manifeste:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
je sais que cette question Est ancienne mais elle peut être faite dans une ligne de code
String deviceID = Build.SERIAL;
Build.SERIAL
est la façon la plus simple d'aller, mais pas entièrement fiable car il peut être vide ou parfois retourner une valeur différente ( preuve 1 , preuve 2 ) que ce que vous pouvez voir dans les paramètres de votre appareil.
il y a plusieurs façons d'obtenir ce nombre en fonction du fabricant de l'appareil et de la version Android, donc j'ai décidé de compiler toutes les solutions possibles que je pourrais trouver dans un seul gist . En voici une version simplifiée:
public static String getSerialNumber() {
String serialNumber;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serialNumber = (String) get.invoke(c, "gsm.sn1");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ril.serialnumber");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "ro.serialno");
if (serialNumber.equals(""))
serialNumber = (String) get.invoke(c, "sys.serialnumber");
if (serialNumber.equals(""))
serialNumber = Build.SERIAL;
// If none of the methods above worked
if (serialNumber.equals(""))
serialNumber = null;
} catch (Exception e) {
e.printStackTrace();
serialNumber = null;
}
return serialNumber;
}
j'ai trouvé la classe exemple posté par @emmby ci-dessus pour être un bon point de départ. Mais il a quelques défauts, comme mentionné par d'autres affiches. La principale est qu'il persiste l'UUID à un fichier XML inutilement et par la suite toujours le récupère à partir de ce fichier. Cela rend la classe ouverte à un piratage facile: n'importe qui avec un téléphone enraciné peut éditer le fichier XML pour se donner un nouvel UUID.
j'ai mis à jour le code de sorte qu'il ne persiste à XML si absolument nécessaire (c. - à-d. lors de l'utilisation d'un UUID généré au hasard) et recalculé la logique selon la réponse de @Brill Pappin:
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 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) || (androidId == null) ) {
final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();
if (deviceId != null)
{
uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
}
else
{
uuid = UUID.randomUUID();
// Write the value out to the prefs file so it persists
prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
}
}
else
{
uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
/**
* 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;
}
Oui. Il s'agit d'un numéro de série matériel de périphérique et il est unique. Ainsi, au niveau de l'api 2.3 et au-dessus, vous pouvez utiliser android.OS.Construire.ANDROID_ID pour l'obtenir. Pour un niveau D'API inférieur à 2.3, utilisez TelephonyManager.getDeviceID () .
vous pouvez lire ce http://android-developers.blogspot.in/2011/03/identifying-app-installations.html