2844 votes

Est-il un Android unique ID de l'appareil?

Ne les appareils Android ont un unique id, et si oui, qu'est ce qu'un simple moyen d'y accéder via Java?

2089voto

Anthony Forloney Points 30083

Settings.Secure#ANDROID_ID renvoie le Android ID unique de 64 bits hex chaîne.

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID); 

1157voto

Joe Points 20463

Il y a plusieurs réponses à cette question, dont la plupart ne travaillent "un peu" de temps, et malheureusement, ce n'est pas assez bon.

Basé sur mes tests d'appareils (tous les téléphones, au moins un qui n'est pas activé):

  1. Tous les appareils testés, a retourné une valeur de TelephonyManager.getDeviceId()
  2. Tous les appareils GSM (tous testés avec une carte SIM), a retourné une valeur de TelephonyManager.getSimSerialNumber()
  3. Tous les appareils CDMA retourné null pour getSimSerialNumber() (comme prévu)
  4. Tous les appareils avec un compte Google a été ajouté, a retourné une valeur de ANDROID_ID
  5. Tous les appareils CDMA retourné la même valeur (ou la dérivation de la même valeur) pour les deux ANDROID_ID et TelephonyManager.getDeviceId() -- aussi longtemps que un compte Google a été ajouté lors de l'installation.
  6. Je n'ai pas encore la chance de pouvoir tester des appareils GSM, sans carte SIM, un appareil GSM avec pas de compte Google ajoutée, ou de l'un de ces appareils en mode avion.

Donc, si vous voulez quelque chose d'unique à l'appareil lui-même, TM.getDeviceId() devrait être suffisant. Évidemment, certains utilisateurs sont plus paranoïaque que d'autres, alors il pourrait être utile de hachage 1 ou plusieurs de ces identifiants, de sorte que la chaîne est encore pratiquement unique de l'appareil, mais ne prévoit pas explicitement l'identification de l'utilisateur du périphérique. Par exemple, à l'aide de String.hashCode(), combiné avec 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 en résulter quelque chose comme: 00000000-54b3-e7c7-0000-000046bffd97

Il fonctionne assez bien pour moi.

Comme Richard mentionne ci-dessous, n'oubliez pas que vous avez besoin de l'autorisation de lire l' TelephonyManager propriétés, de façon à ajouter à votre manifeste:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

444voto

Jared Burrows Points 3932

Dernière Mise À Jour: 7/27/14

Après la lecture de chaque Débordement de Pile post sur la création d'un IDENTIFIANT unique, Google blog des développeurs Android et de la documentation, je me sens comme si la "Pseudo ID" est la meilleure option possible.

Répartition globale

- Garantir l'unicité (à l'exception enracinée périphériques) pour l'API => 9 (98,4% des appareils Android)

- Pas de droits supplémentaires

Pseudo code:

if API => 9: (98.4% of devices)

return unique ID containing serial id (rooted phones may be different)

else

return unique ID of build information (may overlap data - API < 9)

Grâce à @stansult pour l'affichage de toutes nos options (dans ce Débordement de Pile question).

Liste des options - les raisons de ne pas les utiliser:

  • IMEI (uniquement pour les appareils Android grâce à l'utilisation du téléphone, les besoins en android.permission.READ_PHONE_STATE)
    • La plupart des utilisateurs déteste le fait qu'il dit "Appels Téléphoniques" dans l'autorisation. Certains utilisateurs donnent le mauvais cote, car ils croient que vous êtes tout simplement voler leurs informations personnelles, quand tout ce que vous voulez vraiment faire est de suivre l'installation des périphériques. Il est évident que vous êtes à la collecte de données.
    • Une autorisation supplémentaire
  • Android ID (peut être null, peut changer lors de la réinitialisation d'usine, peut être modifié sur un téléphone enracinée)
    • Car il peut être 'null', nous pouvons vérifier pour 'null', et changer sa valeur, mais cela signifie qu'il n'est plus unique.
    • Si vous avez un utilisateur avec une usine réinitialiser le téléphone, la valeur peut avoir changé ou modifié sur le téléphone enracinée donc il y a peut-être des doublons entrées si vous êtes le suivi de l'utilisateur installe.
  • Adresse MAC WLAN chaîne (besoins android.la permission.ACCESS_WIFI_STATE)
    • Cela pourrait être la deuxième meilleure option, mais vous êtes toujours à la collecte et le stockage d'un identifiant unique qui vient directement de l'utilisateur. C'est évident que vous êtes à la collecte de données.
    • Encore une fois, c'est une autre autorisation
  • Bluetooth Adresse MAC de la chaîne (les appareils avec Bluetooth, les besoins de android.la permission.BLUETOOTH)
    • La plupart des applications sur le marché n'utilisez pas la connectivité Bluetooth, et donc, si votre application n'utilise pas le Bluetooth et que vous êtes y compris la présente, l'utilisateur pourrait devenir suspect.
    • Encore une fois, c'est une autre autorisation
  • Pseudo-ID Unique (pour tous les appareils Android)
    • Très possible, peut contenir des collisions - Voir ma méthode affichés ci-dessous!
    • Cela vous permet d'avoir un " presque unique d'identification de l'utilisateur, sans prendre tout ce qui est privé. Vous pouvez créer votre propre unanime ID de périphérique de l'information.

Je sais qu'il n'est pas "parfait" d'obtenir un ID unique sans l'aide d'autorisations; cependant, parfois nous n'avons vraiment besoin de faire est de suivre l'installation de l'appareil. Quand il s'agit de la création d'un IDENTIFIANT unique, nous pouvons créer un pseudo unique id " basée uniquement au large de l'information que l'API Android nous donne sans l'aide des autorisations supplémentaires. De cette façon, nous pouvons montrer à l'utilisateur de respect et d'essayer d'offrir une bonne expérience utilisateur.

Avec un pseudo-id unique, vous vraiment exécuter uniquement dans le fait qu'il peut y avoir des doublons sur la base du fait qu'il existe des dispositifs similaires. Vous pouvez modifier la méthode combinée pour le rendre plus unique; toutefois, certains développeurs ont besoin pour suivre l'installation des périphériques et cela fera l'affaire ou de la performance, basée sur des dispositifs similaires.

API => 9:

Si leur appareil Android API 9 ou plus, c'est la garantie d'être unique en raison de la 'Construire.SÉRIE".

RAPPELEZ-vous, vous êtes techniquement seulement absent dehors sur environ 1,6% des utilisateurs qui ont API < 9. Vous pouvez donc vous concentrer sur le reste: C'est de 98,4% des utilisateurs!

API < 9:

Si l'utilisateur de l'appareil Android est inférieure à celle de l'API 9; avec de la chance, ils n'ont pas fait un factory reset et de leur Sécurité.ANDROID_ID " sera conservé ou non, 'null'. (voir http://developer.android.com/about/dashboards/index.html)

Si tout le reste échoue:

Si tout le reste échoue, si l'utilisateur est inférieur API 9 (moins de pain d'épice), a remis son téléphone ou 'Secure.ANDROID_ID' retourne 'null', puis tout simplement l'ID retourné sera uniquement basé sur leur appareil Android de l'information. C'est l'endroit où les collisions peuvent se produire.

Changements:

  • Suppression De 'Android.SECURE_ID " parce que de l'usine réinitialise pourrait causer la valeur à modifier
  • Modifié le code pour changer sur les API
  • Changé le Pseudo

Veuillez 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 phone 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!
    // http://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 phone, 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 e)
    {
        // String needs to be initialized
        serial = "serial"; // some value
    }

    // Thanks @Joe!
    // http://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();
}

Nouvelle(pour les applications avec des annonces ET Google Play Services):

Depuis le Google Play Developer console:

Début le 1er août 2014, le Google Play pour les Développeurs de Programme et de Politique exige que toutes les nouvelles appli les téléchargements et les mises à jour pour utiliser l'ID dans la publicité la place de tout autre identificateurs persistants pour toutes les fins de publicité. En savoir plus

Mise en œuvre:

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 e) {
    // Unrecoverable error connecting to Google Play services (e.g.,
    // the old version of the service doesn't support getting AdvertisingId).

  } catch (GooglePlayServicesAvailabilityException e) {
    // Encountered a recoverable error connecting to Google Play services. 

  } catch (GooglePlayServicesNotAvailableException e) {
    // 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.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html

Important:

Il est prévu que la publicité ID complètement remplacer les l'utilisation d'autres identificateurs pour les annonces fins (tels que l'utilisation de ANDROID_ID dans les Paramètres.Sécurisé) lors de la Google Play Services est disponible. Cas où Google Play Services n'est pas disponible sont indiqués par un GooglePlayServicesNotAvailableException jetés par getAdvertisingIdInfo().

Avertissement: l'Utilisateur peut réinitialiser:

http://en.kioskea.net/faq/34732-android-reset-your-advertising-id

J'ai essayé de faire référence à tous les liens que j'ai pris des informations. Si vous êtes absent et doivent être inclus, s'il vous plaît commentaire!

342voto

emmby Points 35359

Comme Dave Webb mentionne, le Développeur Android Blog a un article qui traite ce. Leur solution préférée est de suivre l'application s'installe plutôt que de dispositifs, et qui fonctionne bien pour la plupart des cas d'utilisation. Le blog sera de vous montrer le code nécessaire pour faire ce travail, et je vous recommande de vérifier it out.

Cependant, le blog va sur pour discuter des solutions si vous avez besoin d'un identifiant de l'appareil plutôt que d'une application de l'identificateur d'installation. J'ai parlé avec quelqu'un de chez Google pour obtenir des précisions complémentaires sur quelques éléments dans le cas où vous avez besoin de le faire. Voici ce que j'ai découvert sur les identificateurs de l'instrument qui n'est PAS mentionné dans le post de blog:

  • ANDROID_ID est le préféré de l'identifiant de l'appareil. ANDROID_ID est parfaitement fiable sur les versions d'Android <=2.1 ou >=2.3. Seulement 2,2 a le problème mentionné dans le post.
  • Plusieurs appareils par plusieurs fabricants, sont touchés par la ANDROID_ID bug dans 2.2.
  • Aussi loin que j'ai été en mesure de déterminer de, tous les appareils ont le même ANDROID_ID, qui est 9774d56d682e549c. Qui est aussi le même id de l'appareil rapporté par l'émulateur, btw.
  • Google estime que les constructeurs ont corrigé le problème pour beaucoup ou la plupart de leurs appareils, mais j'ai pu vérifier que, dès le début du mois d'avril 2011, au moins, il est toujours assez facile de trouver des appareils qui ont brisé ANDROID_ID.

Basé sur Google recommandations, j'ai mis en place une classe qui va générer un UUID unique pour chaque appareil à l'aide d'ANDROID_ID comme la semence, le cas échéant, pour retomber sur TelephonyManager.getDeviceId (), si nécessaire, et en cas d'échec, le recours à un unique généré de façon aléatoire UUID qui est conservé à travers application redémarre (mais pas app ré-installations).

Notez que pour les appareils qui ont de repli sur l'ID de l'appareil, l'IDENTIFIANT unique SERA persistent dans l'usine réinitialise. C'est quelque chose d'être conscient de. Si vous devez vous assurer qu'une réinitialisation aux paramètres d'usine réinitialiser votre ID unique, vous pouvez envisager de redescendre directement à l'aléatoire UUID au lieu de l'ID de l'appareil.

Encore une fois, ce code est pour l'ID de périphérique, pas une application d'identification de l'installation. Pour la plupart des situations, une application d'identification de l'installation est probablement ce que vous cherchez. Mais si vous avez besoin d'un ID de périphérique, puis le code suivant va probablement travailler 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;
    }
}

182voto

Anthony Nolan Points 1110

Voici le code que Reto Meier utilisé dans la Google I/O de la présentation de cette année pour obtenir un id 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 rajoutez à cela une stratégie de sauvegarde pour envoyer des préférences pour le cloud (également décrits dans Reto de parler, vous devez avoir une carte d'identité qui le lie à un utilisateur et autour de bâtons après que l'appareil a été effacé, ou même remplacés. J'ai l'intention de l'utiliser dans l'analytique à l'avenir (en d'autres termes, je n'ai pas fait que peu encore :).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X