क्या एक अद्वितीय एंड्रॉइड डिवाइस आईडी है?


2751

क्या एंड्रॉइड डिवाइस में एक अद्वितीय आईडी है, और यदि हां, तो जावा का उपयोग करके इसे एक्सेस करने का एक सरल तरीका क्या है?


38
यदि आप इस उत्तर और इस बगANDROID_ID को पढ़ना सुनिश्चित कर रहे हैं ।
धीरज वेपकोमा १६'१३ को V:

यदि आपको 2020 में समाधान की आवश्यकता है, तो आपको 2020 में Android पहचानकर्ताओं
निकिता कर्टिन

जवाबों:


2024

Settings.Secure#ANDROID_IDप्रत्येक उपयोगकर्ता 64-बिट हेक्स स्ट्रिंग के लिए एक अद्वितीय के रूप में एंड्रॉइड आईडी देता है ।

import android.provider.Settings.Secure;

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

476
यह कभी-कभी अशक्त होने के लिए जाना जाता है, इसे "फ़ैक्टरी रीसेट पर बदल सकता है" के रूप में प्रलेखित किया गया है। अपने जोखिम पर उपयोग करें, और इसे आसानी से जड़ वाले फोन पर बदला जा सकता है।
सेवा अलेक्सेयेव


18
मुझे लगता है कि हमें पहले उत्तर में ANDROID_ID का उपयोग करने के बारे में सावधान रहने की आवश्यकता है क्योंकि इसके बारे में यह निर्धारित नहीं किया जा सकता है कि ऐप को पहली बार चलाने पर इसे बाद में सेट किया जा सकता है, या सिद्धांत में भी बदल सकता है, इसलिए अद्वितीय आईडी बदल सकती है

46
ज्ञात हो कि इस समाधान के साथ बहुत बड़ी सीमाएँ हैं: android-developers.blogspot.com/2011/03/…
emmby

35
ANDROID_ID अब विशिष्ट रूप से एक डिवाइस (4.2 के रूप में) की पहचान नहीं करता है: stackoverflow.com/a/13465373/150016
टॉम

1144

अद्यतन : Android के हाल के संस्करणों के रूप में, के साथ कई मुद्दों ANDROID_IDको हल कर दिया गया है, और मेरा मानना ​​है कि यह दृष्टिकोण अब आवश्यक नहीं है। कृपया एंथनी के जवाब पर एक नज़र डालें ।

पूर्ण प्रकटीकरण: मेरे ऐप ने मूल रूप से नीचे दिए गए दृष्टिकोण का उपयोग किया था लेकिन अब इस दृष्टिकोण का उपयोग नहीं करता है, और हम अब एंड्रॉइड डेवलपर ब्लॉग प्रविष्टि में उल्लिखित दृष्टिकोण का उपयोग करते हैं जो एमएमबी के उत्तर लिंक (अर्थात्, उत्पन्न और बचत UUID#randomUUID()) के लिए लिंक का उपयोग करता है ।


इस सवाल के कई जवाब हैं, जिनमें से अधिकांश केवल समय के "कुछ" काम करेंगे, और दुर्भाग्य से यह काफी अच्छा नहीं है।

उपकरणों के मेरे परीक्षणों के आधार पर (सभी फोन, जिनमें से कम से कम एक सक्रिय नहीं है):

  1. परीक्षण किए गए सभी उपकरणों ने एक मान लौटाया TelephonyManager.getDeviceId()
  2. सभी जीएसएम डिवाइस (सभी एक सिम के साथ परीक्षण किए गए) के लिए एक मान लौटाया TelephonyManager.getSimSerialNumber()
  3. सभी सीडीएमए उपकरणों के लिए अशक्त लौट आए getSimSerialNumber()(उम्मीद के मुताबिक)
  4. Google खाते के साथ सभी उपकरणों के लिए एक मान लौटाया गया ANDROID_ID
  5. सभी सीडीएमए उपकरणों ने दोनों के लिए समान मूल्य (या समान मूल्य का व्युत्पन्न) लौटाया ANDROID_IDऔर TelephonyManager.getDeviceId()- जब तक कि सेटअप के दौरान Google खाता जोड़ा गया हो।
  6. मेरे पास अभी तक बिना सिम वाले जीएसएम उपकरणों का परीक्षण करने का मौका नहीं है, एक जीएसएम डिवाइस जिसमें कोई Google खाता नहीं है, या हवाई जहाज मोड में कोई भी उपकरण है।

इसलिए यदि आप डिवाइस के लिए कुछ अनूठा चाहते हैं, तो TM.getDeviceId() करना चाहिए तो पर्याप्त चाहिए। स्पष्ट रूप से कुछ उपयोगकर्ता दूसरों की तुलना में अधिक पागल हैं, इसलिए हो सकता है कि यह 1 या उससे अधिक पहचानकर्ताओं के लिए उपयोगी हो, ताकि स्ट्रिंग अभी भी डिवाइस के लिए लगभग अद्वितीय है, लेकिन उपयोगकर्ता के वास्तविक डिवाइस की स्पष्ट रूप से पहचान नहीं करता है। उदाहरण के लिए, String.hashCode()यूयूआईडी के साथ संयुक्त , उपयोग करना :

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();

परिणाम कुछ इस तरह हो सकता है: 00000000-54b3-e7c7-0000-000046bffd97

यह मेरे लिए काफी अच्छा काम करता है।

जैसा कि नीचे रिचर्ड का उल्लेख है, यह मत भूलो कि आपको TelephonyManagerसंपत्तियों को पढ़ने की अनुमति की आवश्यकता है , इसलिए इसे अपने प्रकट में जोड़ें:

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

आयात लिबास

import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;

151
टेलीफोनी-आधारित आईडी टैबलेट डिवाइस, नेह पर नहीं होगी?
सेवा अलेक्सेयेव

22
इसलिए मैंने कहा कि अधिकांश समय काम नहीं करेगा :) मैंने अभी तक इस सवाल का कोई जवाब नहीं देखा है जो सभी उपकरणों, सभी डिवाइस प्रकारों और सभी हार्डवेयर कॉन्फ़िगरेशन के लिए विश्वसनीय है। इसीलिए यह प्रश्न यहाँ से शुरू होता है। यह स्पष्ट है कि इसका कोई अंतिम-समाधान नहीं है। व्यक्तिगत डिवाइस निर्माताओं के पास डिवाइस सीरियल नंबर हो सकते हैं, लेकिन वे हमारे लिए उपयोग करने के लिए उजागर नहीं हैं, और यह एक आवश्यकता नहीं है। इस प्रकार हमारे पास जो उपलब्ध है उससे हम बचे हैं।
जो

31
कोड सैंपल बढ़िया काम करता है। <uses-permission android:name="android.permission.READ_PHONE_STATE" />मैनिफ़ेस्ट फ़ाइल में जोड़ना याद रखें । यदि डेटाबेस में स्टोर किया जाता है, तो लौटा हुआ स्ट्रिंग 36 वर्ण लंबा होता है।
रिचर्ड

10
ज्ञात हो कि इस समाधान के साथ बहुत बड़ी सीमाएँ हैं: android-developers.blogspot.com/2011/03/…
emmby

18
@ सोफ्टरन: मेरा मानना ​​है कि आप जिस एंड्रॉइड डेवलपर ब्लॉग का जिक्र कर रहे हैं, वह पहले से ही जुड़ा हुआ है, जो बताता है कि आप क्या कहना चाह रहे हैं, इसलिए शायद आपको उसकी जगह सिर्फ टिप्पणी करनी चाहिए थी। किसी भी तरह से, जैसा कि उनके उत्तर में एम्बी का उल्लेख है, ब्लॉग जानकारी के साथ अभी भी समस्याएं हैं। प्रश्न एक अद्वितीय DEVICE पहचानकर्ता (स्थापना पहचानकर्ता नहीं) के लिए पूछता है , इसलिए मैं आपके कथन से असहमत हूं। ब्लॉग एक धारणा बना रहा है कि आप जो चाहते हैं वह डिवाइस को ट्रैक करने के लिए जरूरी नहीं है , जबकि सवाल बस यही पूछता है। मैं अन्यथा ब्लॉग से सहमत हूं।
जो

438

अंतिम अपडेट: 6/2/15


यूनिक आईडी बनाने के बारे में हर स्टैक ओवरफ्लो पोस्ट को पढ़ने के बाद, Google डेवलपर ब्लॉग और एंड्रॉइड डॉक्यूमेंटेशन, मुझे लगता है कि 'स्यूडो आईडी' सबसे अच्छा संभव विकल्प है।

मुख्य मुद्दा: हार्डवेयर बनाम सॉफ्टवेयर

हार्डवेयर

  • उपयोगकर्ता अपने हार्डवेयर, एंड्रॉइड टैबलेट या फोन को बदल सकते हैं, इसलिए हार्डवेयर पर आधारित अद्वितीय आईडी अच्छे विचार नहीं हैं ट्रैकिंग उपयोगकर्ताओं के
  • के लिए ट्रैकिंग हार्डवेयर , यह एक बहुत अच्छा विचार है

सॉफ्टवेयर

  • यदि वे रूट किए गए हैं, तो उपयोगकर्ता अपने ROM को मिटा / बदल सकते हैं
  • आप प्लेटफ़ॉर्म (iOS, Android, Windows और वेब) पर उपयोगकर्ताओं को ट्रैक कर सकते हैं
  • अपनी सहमति के साथ सबसे अच्छा USER को ट्रैक करना चाहते हैं, बस उन्हें लॉगिन करना है (इस सहज का उपयोग करके आराम करें)

एंड्रॉइड के साथ कुल मिलाकर ब्रेकडाउन

- API> = 9/10 (99.5% Android डिवाइस) के लिए गारंटी विशिष्टता (रूट किए गए डिवाइस शामिल करें)

- कोई अतिरिक्त अनुमति नहीं

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)

हमारे सभी विकल्पों को पोस्ट करने के लिए @stansult का धन्यवाद (इस स्टैक ओवरफ्लो प्रश्न में) ।

विकल्पों की सूची - कारणों का उपयोग क्यों / क्यों नहीं करना है:

  • उपयोगकर्ता ईमेल - सॉफ्टवेयर

  • उपयोगकर्ता फोन नंबर - सॉफ्टवेयर

    • उपयोगकर्ता फ़ोन नंबर बदल सकते हैं - अत्यधिक संभावना नहीं है
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • IMEI - हार्डवेयर (केवल फोन, आवश्यकताएं android.permission.READ_PHONE_STATE)

    • अधिकांश उपयोगकर्ता इस तथ्य से नफरत करते हैं कि यह अनुमति में "फोन कॉल" कहता है। कुछ उपयोगकर्ता खराब रेटिंग देते हैं, क्योंकि उनका मानना ​​है कि आप बस उनकी व्यक्तिगत जानकारी चुरा रहे हैं जब आप वास्तव में करना चाहते हैं तो डिवाइस इंस्टॉल को ट्रैक करना है। यह स्पष्ट है कि आप डेटा एकत्र कर रहे हैं।
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • एंड्रॉइड आईडी - हार्डवेयर (शून्य हो सकता है, फ़ैक्टरी रीसेट पर बदल सकता है, रूट किए गए डिवाइस पर बदला जा सकता है)

    • चूंकि यह 'अशक्त' हो सकता है, हम 'अशक्त' के लिए जाँच कर सकते हैं और इसका मान बदल सकते हैं, लेकिन इसका अर्थ यह नहीं होगा कि यह अद्वितीय होगा।
    • यदि आपके पास फ़ैक्टरी रीसेट डिवाइस वाला कोई उपयोगकर्ता है, तो मान रूट किए गए डिवाइस पर परिवर्तित या परिवर्तित हो सकता है इसलिए यदि आप उपयोगकर्ता इंस्टॉल को ट्रैक कर रहे हैं तो डुप्लिकेट प्रविष्टियां हो सकती हैं।
  • WLAN MAC पता - हार्डवेयर (ज़रूरतें android.permission.ACCESS_WIFI_STATE)

    • यह दूसरा सबसे अच्छा विकल्प हो सकता है, लेकिन आप अभी भी एक अद्वितीय पहचानकर्ता को इकट्ठा और संग्रहीत कर रहे हैं जो सीधे उपयोगकर्ता से आता है। यह स्पष्ट है कि आप डेटा एकत्र कर रहे हैं।
    • <uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
  • ब्लूटूथ मैक पता - हार्डवेयर (ब्लूटूथ, आवश्यकता वाले उपकरण android.permission.BLUETOOTH)

    • बाजार के अधिकांश एप्लिकेशन ब्लूटूथ का उपयोग नहीं करते हैं, और इसलिए यदि आपका एप्लिकेशन ब्लूटूथ का उपयोग नहीं करता है और आप इसमें शामिल हैं, तो उपयोगकर्ता संदिग्ध हो सकता है।
    • <uses-permission android:name="android.permission.BLUETOOTH "/>
  • स्यूडो-यूनिक आईडी - सॉफ्टवेयर (सभी Android उपकरणों के लिए)

    • बहुत संभव है, इसमें टक्कर हो सकती है - नीचे पोस्ट की गई मेरी विधि देखें!
    • यह आपको उपयोगकर्ता से 'लगभग अद्वितीय' आईडी प्राप्त करने की अनुमति देता है, जो कुछ भी निजी नहीं है। आप डिवाइस की जानकारी से अपनी खुद की अनाम आईडी बना सकते हैं।

मुझे पता है कि अनुमतियों का उपयोग किए बिना एक अद्वितीय आईडी प्राप्त करने का कोई 'सही' तरीका नहीं है; हालाँकि, कभी-कभी हमें केवल डिवाइस इंस्टॉलेशन को ट्रैक करने की आवश्यकता होती है। जब एक अद्वितीय आईडी बनाने की बात आती है, तो हम पूरी तरह से सूचना के आधार पर 'छद्म अद्वितीय आईडी' बना सकते हैं जो Android API हमें बिना अतिरिक्त अनुमतियों के उपयोग के देता है। इस तरह, हम उपयोगकर्ता को सम्मान दिखा सकते हैं और साथ ही एक अच्छा उपयोगकर्ता अनुभव प्रदान करने का प्रयास कर सकते हैं।

एक छद्म-अद्वितीय आईडी के साथ, आप वास्तव में केवल इस तथ्य पर चलते हैं कि इस तथ्य के आधार पर डुप्लिकेट हो सकते हैं कि समान डिवाइस हैं। आप इसे और अधिक अद्वितीय बनाने के लिए संयुक्त विधि को घुमा सकते हैं; हालांकि, कुछ डेवलपर्स को डिवाइस इंस्टॉल को ट्रैक करने की आवश्यकता होती है और यह इसी तरह के उपकरणों के आधार पर चाल या प्रदर्शन करेगा।

API> = 9:

यदि उनका Android उपकरण API 9 या अधिक है, तो यह 'Build.SERIAL' क्षेत्र के कारण अद्वितीय होने की गारंटी है।

याद रखें , आप तकनीकी रूप से केवल उन लगभग 0.5% उपयोगकर्ताओं को याद कर रहे हैं जिनके पास API <9 है । तो आप बाकी पर ध्यान केंद्रित कर सकते हैं: यह 99.5% उपयोगकर्ता हैं!

एपीआई <9:

यदि उपयोगकर्ता का एंड्रॉइड डिवाइस एपीआई 9 से कम है; उम्मीद है, उन्होंने फ़ैक्टरी रीसेट नहीं किया है और उनका 'Secure.ANDROID_ID' संरक्षित रहेगा या 'शून्य' नहीं होगा। (देखें http://developer.android.com/about/dashboards/index.html )

यदि सभी अन्य विफल होते हैं:

यदि अन्य सभी विफल हो जाते हैं, यदि उपयोगकर्ता के पास एपीआई 9 (जिंजरब्रेड से कम) है, तो अपने डिवाइस को रीसेट कर दिया है या 'Secure.ANDROID_ID' रिटर्न 'शून्य' कर दिया है, तो बस लौटी आईडी पूरी तरह से उनके एंड्रॉइड फोन की जानकारी से दूर होगी। यह वह जगह है जहां टकराव हो सकता है।

परिवर्तन:

  • फैक्ट्री रीसेट के कारण 'Android.SECURE_ID' को हटा देने से मान बदल सकता है
  • एपीआई पर बदलने के लिए कोड का संपादन किया
  • छद्म को बदल दिया

कृपया नीचे दी गई विधि पर एक नज़र डालें:

/**
 * 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();
}

नए (विज्ञापनों और Google Play सेवाओं वाले ऐप्स के लिए):

Google Play डेवलपर के कंसोल से:

1 अगस्त 2014 से, Google Play डेवलपर प्रोग्राम नीति को किसी भी अन्य विज्ञापनदाताओं को किसी भी विज्ञापन उद्देश्यों के लिए किसी अन्य स्थायी पहचानकर्ता के बदले विज्ञापन आईडी का उपयोग करने के लिए सभी नए एप्लिकेशन अपलोड और अपडेट की आवश्यकता होती है। और अधिक जानें

कार्यान्वयन :

अनुमति:

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

कोड:

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();
}

स्रोत / डॉक्स:

http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdolarsIdClient.html

जरूरी:

यह इरादा है कि विज्ञापन आईडी Google उद्देश्यों के लिए विज्ञापन पहचान के अन्य उपयोगों (जैसे कि सेटिंग में ANDROID_ID के उपयोग के रूप में) को पूरी तरह से बदल देती है। ऐसे मामले जहां Google Play सेवाएं उपलब्ध नहीं हैं, GooglePlayServicesNotAvailableException getAdpretIdInfo () द्वारा फेंके जाने के संकेत हैं।

चेतावनी, उपयोगकर्ता रीसेट कर सकते हैं:

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

मैंने हर उस लिंक को संदर्भित करने की कोशिश की है जिससे मैंने जानकारी ली थी। यदि आप गायब हैं और शामिल करने की आवश्यकता है, तो कृपया टिप्पणी करें!

Google प्लेयर सेवा इंस्टेंस

https://developers.google.com/instance-id/


लेकिन क्या BuildOS अपडेट पर वर्ग परिवर्तन नहीं होगा ? खासकर अगर एपीआई अपडेट हो गया? यदि हां, तो आप कैसे गारंटी देते हैं कि यह अद्वितीय है? (आपके लिखे तरीके के बारे में बात करते हुए)
लकी मैम

2
मैंने टिप्पणी भेजने के लिए अपने ऐप में आपके तरीके का उपयोग किया। मेरे पास बुरी खबर है। दुर्भाग्य से PsuedoID पूरी तरह से अद्वितीय नहीं है। मेरे सर्वर ने 5 आईडी के लिए 100 से अधिक और लगभग 30 आईडी के लिए 30 से अधिक रिकॉर्ड किया। सबसे दोहराया आईडी 'ffffffff-fc8f-6093-ffff-ffffd8' (159 रिकॉर्ड) और 'ffffffff-fe99-b334-ffff-ffffef' (154 समय) हैं। समय और टिप्पणियों के आधार पर यह स्पष्ट है कि विभिन्न लोग हैं। अब तक के कुल रिकॉर्ड 10,000 हैं। कृपया मुझे बताएं कि ऐसा क्यों हुआ। टैंक।
हज्जत रेहाने

1
मैंने यह 1.5+ साल पहले लिखा था। मुझे यकीन नहीं है कि यह आपके लिए अद्वितीय क्यों नहीं है। आप विज्ञापन आईडी की कोशिश कर सकते हैं। यदि नहीं, तो आप अपने स्वयं के समाधान के साथ आ सकते हैं।
जारेड बुरो

2
Sorta..मैं वास्तव में सराहना करेंगे यदि आप सवाल के माध्यम से जाते हैं और इस पर अपने विचार देते हैं
दुरई अमुथन।

1
@ user1587329 धन्यवाद। मैं इसे सभी के लिए अद्यतित रखने की कोशिश कर रहा हूं। जब यह हार्डवेयर बनाम सॉफ्टवेयर और क्रॉस प्लेटफॉर्म पर आता है तो यह प्रश्न मुश्किल है।
जेरेड मेव्स

340

जैसा कि डेव वेब का उल्लेख है, एंड्रॉइड डेवलपर ब्लॉग में एक लेख है जो इसे कवर करता है। उनका पसंदीदा समाधान उपकरणों के बजाय ऐप इंस्टॉल को ट्रैक करना है, और यह अधिकांश उपयोग के मामलों के लिए अच्छी तरह से काम करेगा। ब्लॉग पोस्ट आपको वह काम करने के लिए आवश्यक कोड दिखाएगा, और मैं आपको इसकी जांच करने की सलाह देता हूं।

हालाँकि, यदि आप ऐप इंस्टॉलेशन आइडेंटिफायर के बजाय डिवाइस आइडेंटिफायर की जरूरत है तो ब्लॉग पोस्ट समाधानों पर चर्चा करता है। मैंने Google पर किसी व्यक्ति के साथ उस घटना में कुछ वस्तुओं पर कुछ अतिरिक्त स्पष्टीकरण प्राप्त करने के लिए बात की थी जो आपको करने की आवश्यकता है। यहाँ मैंने उन डिवाइस पहचानकर्ताओं के बारे में पता लगाया है जिनका उल्लेख उपरोक्त ब्लॉग पोस्ट में नहीं किया गया है:

  • ANDROID_ID पसंदीदा डिवाइस पहचानकर्ता है। ANDROID_ID Android के संस्करणों पर पूरी तरह से विश्वसनीय है <= 2.1 या> = 2.3। केवल 2.2 में पोस्ट में उल्लिखित समस्याएं हैं।
  • 2.2 में ANDROID_ID बग से कई निर्माताओं के कई उपकरण प्रभावित होते हैं।
  • जहां तक ​​मैं निर्धारित करने में सक्षम रहा हूं, सभी प्रभावित उपकरणों में एक ही ANDROID_ID है , जो 9774d56d682e549c है । एमुलेटर, btw द्वारा रिपोर्ट की गई वही डिवाइस आईडी भी है।
  • Google का मानना ​​है कि ओईएम ने कई या अधिकांश डिवाइसों के लिए समस्या को पैच किया है, लेकिन मैं यह सत्यापित करने में सक्षम था कि अप्रैल 2011 की शुरुआत में, कम से कम, अभी भी उन डिवाइसों को ढूंढना काफी आसान है जिनके पास ANDROID_ID टूटे हुए हैं।

Google की सिफारिशों के आधार पर, मैंने एक वर्ग लागू किया है जो ANDROID_ID को बीज के रूप में उपयोग करते हुए प्रत्येक डिवाइस के लिए एक अद्वितीय UUID उत्पन्न करेगा, जहां उपयुक्त हो, आवश्यक रूप से TelephonyManager.getDeviceId () पर वापस गिर रहा है, और यदि वह विफल रहता है, तो एक यादृच्छिक रूप से उत्पन्न अद्वितीय UUID का सहारा लेना यह एप रीस्टार्ट (लेकिन एप री-इंस्टॉलेशन नहीं) है।

ध्यान दें कि जिन डिवाइसों में डिवाइस आईडी पर कमबैक करना है, उनके लिए यूनीक आईडी WILL फैक्ट्री रिसेट्स में बनी रहती है। इसके लिए जागरूक होना कुछ है। यदि आपको यह सुनिश्चित करने की आवश्यकता है कि फ़ैक्टरी रीसेट आपकी अद्वितीय आईडी को रीसेट कर देगा, तो आप डिवाइस आईडी के बजाय सीधे यादृच्छिक यूयूआईडी पर वापस गिरने पर विचार कर सकते हैं।

फिर, यह कोड डिवाइस आईडी के लिए है, न कि ऐप इंस्टॉलेशन आईडी के लिए। ज्यादातर स्थितियों के लिए, एक ऐप इंस्टॉलेशन आईडी संभवतः वह है जो आप खोज रहे हैं। लेकिन अगर आपको डिवाइस आईडी की आवश्यकता है, तो निम्नलिखित कोड शायद आपके लिए काम करेगा।

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;
    }
}

6
क्या आपको विभिन्न आईडी पर हैशिंग नहीं होना चाहिए ताकि वे सभी समान आकार के हों? इसके अतिरिक्त, आपको निजी जानकारी को गलत तरीके से उजागर नहीं करने के लिए डिवाइस आईडी पर हैशिंग होना चाहिए।
स्टीव पोमोरॉय

2
अच्छे अंक, स्टीव। मैंने हमेशा UUID वापस करने के लिए कोड अपडेट किया। यह सुनिश्चित करता है कि ए) उत्पन्न आईडी हमेशा एक ही आकार की होती है, और बी) Android और डिवाइस आईडी व्यक्तिगत जानकारी को उजागर करने से बचने के लिए लौटने से पहले एंड्रॉइड और डिवाइस आईडी को हैशेड किया जाता है। मैंने यह नोट करने के लिए विवरण भी अपडेट किया कि डिवाइस आईडी फैक्ट्री रीसेट पर बनी रहेगी और यह कुछ उपयोगकर्ताओं के लिए वांछनीय नहीं हो सकता है।
21

1
मेरा मानना ​​है कि आप गलत हैं; पसंदीदा समाधान प्रतिष्ठानों को ट्रैक करना है, न कि डिवाइस पहचानकर्ताओं को। आपका पोस्ट ब्लॉग पोस्ट की तुलना में काफी लंबा और अधिक जटिल है और यह मेरे लिए स्पष्ट नहीं है कि यह किसी भी मूल्य को जोड़ता है।
टिम ब्रे

7
अच्छी बात है, मैंने उपयोगकर्ताओं को डिवाइस आईडी के बजाय ऐप इंस्टॉलेशन आईडी का उपयोग करने का जोरदार सुझाव देने के लिए कमेंट्री को अपडेट किया। हालांकि, मुझे लगता है कि यह समाधान अभी भी उन लोगों के लिए मूल्यवान है, जिन्हें इंस्टॉलेशन आईडी के बजाय डिवाइस की आवश्यकता है।
एम्मबी

8
ANDROID_ID फ़ैक्टरी रीसेट पर बदल सकता है, इसलिए यह उपकरणों की पहचान नहीं कर सकता है
सैमुअल

180

यहाँ कोड है कि रेटो मीयर ने इस वर्ष Google I / O प्रस्तुति में उपयोग किया था ताकि उपयोगकर्ता को एक अद्वितीय आईडी मिल सके:

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;
}

यदि आप इसे क्लाउड पर प्राथमिकताएं भेजने के लिए एक बैकअप रणनीति के साथ जोड़ते हैं (रेटो की बात में भी वर्णित है , तो आपके पास एक आईडी होनी चाहिए जो डिवाइस को मिटा दिए जाने के बाद किसी उपयोगकर्ता से चिपक जाती है या प्रतिस्थापित हो जाती है। मैं इसे उपयोग करने की योजना बना रहा हूं। विश्लेषण में आगे जा रहा है (दूसरे शब्दों में, मैंने अभी तक ऐसा नहीं किया है :)।


मैं @ आईडी का उपयोग कर रहा था, वर्तमान समय के साथ अद्वितीय आईडी के लिए गुड़िया बनाने की विधि। लेकिन यह अधिक सरल और विश्वसनीय तरीका लगता है। धन्यवाद रीटो मीयर और एंटनी नोलन
गोखान बैरिस एकर

यह महान है लेकिन जड़ वाले उपकरणों के बारे में क्या? वे इसे एक्सेस कर सकते हैं और यूआईडी को एक अलग से आसानी से बदल सकते हैं।
तस्मानी

3
बढ़िया विकल्प अगर आपको अनइंस्टॉल और रीइंस्टॉल होने के बाद यूनिक आईडी की जरूरत नहीं है (उदाहरण के लिए प्रचार कार्यक्रम / खेल जहाँ आपको जीतने के तीन मौके मिलते हैं, अवधि)।
काइल क्लेग ने

2
Meier प्रस्तुति एंड्रॉइड बैकअप मैनेजर का उपयोग करने पर निर्भर करता है, जो बदले में उस सुविधा को चालू करने के लिए चुनने वाले उपयोगकर्ता पर निर्भर करता है। यह ऐप उपयोगकर्ता की प्राथमिकताओं (मीयर के उपयोग) के लिए ठीक है, क्योंकि यदि उपयोगकर्ता ने उस विकल्प का चयन नहीं किया है, तो वह केवल उन बैकअप प्राप्त नहीं करेगा। हालाँकि, मूल प्रश्न डिवाइस के लिए एक विशिष्ट आईडी जनरेट करने के बारे में है , और यह आईडी प्रति ऐप जनरेट किया गया है, और प्रति इंस्टॉलेशन भी नहीं है, प्रति डिवाइस अकेले जाने दें, और चूंकि यह बैकअप विकल्प का चयन करने वाले उपयोगकर्ता पर निर्भर करता है, इसलिए इसका उपयोग उपयोगकर्ता से परे है वरीयताएँ (उदाहरण के लिए, एक समय सीमित परीक्षण के लिए) सीमित हैं।
कार्ल

12
यह डेटा की स्थापना रद्द या साफ़ करने पर काम नहीं करेगा।
जॉन शेली

106

इसके अलावा, आप वाई-फाई एडेप्टर के मैक पते पर विचार कर सकते हैं। इस प्रकार लिया गया:

WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();

अनुमति की आवश्यकता है android.permission.ACCESS_WIFI_STATEमेनिफेस्ट में ।

वाई-फाई कनेक्ट नहीं होने पर भी उपलब्ध होने की सूचना दी। यदि ऊपर दिए गए उत्तर में से जो यह अपने कई उपकरणों पर कोशिश करता है, तो यह अच्छा होगा।

कुछ उपकरणों पर, वाई-फाई बंद होने पर यह उपलब्ध नहीं होता है।

नोट: Android 6.x से, यह लगातार नकली मैक पते देता है:02:00:00:00:00:00


8
यह आवश्यक हैandroid.permission.ACCESS_WIFI_STATE
ओहोरोब

5
मुझे लगता है कि वाईफाई के बंद होने पर, सभी एंड्रॉइड डिवाइसों पर बहुत अधिक उपलब्ध होने पर आप पाएंगे कि यह अनुपलब्ध है। वाईफाई को बंद करने से डिवाइस को कर्नेल स्तर पर हटा दिया जाता है।
क्रिसडाउन

12
@ सांड्रिया - चलो इसका सामना करते हैं, एक रूट किए गए डिवाइस पर सब कुछ खराब हो सकता है।
ओसोडो

5
एंड्रॉइड M पर वाईफाई मैक एड्रेस को एक्सेस करना बंद कर दिया गया है: stackoverflow.com/questions/31329733/…
breez

6
Android 6.x से यह लगातार नकली मैक एड्रेस देता है:02:00:00:00:00:00
Behrouz.M

87

यहाँ बल्कि उपयोगी जानकारी है

इसमें पांच अलग-अलग आईडी प्रकार शामिल हैं:

  1. IMEI (केवल Android उपकरणों के लिए फोन के उपयोग के साथ; जरूरतों;android.permission.READ_PHONE_STATE )
  2. छद्म-यूनिक आईडी (सभी Android उपकरणों के लिए)
  3. Android ID (शून्य हो सकता है, फ़ैक्टरी रीसेट पर बदल सकता है, रूट किए गए फोन पर बदल सकता है)
  4. WLAN मैक एड्रेस स्ट्रिंग (आवश्यकताएं)android.permission.ACCESS_WIFI_STATE )
  5. बीटी मैक एड्रेस स्ट्रिंग (ब्लूटूथ, जरूरतों वाले उपकरण android.permission.BLUETOOTH)

2
महत्वपूर्ण बिंदु छोड़ दिया (यहाँ और लेख में): आप WLAN या BT MAC प्राप्त नहीं कर सकते हैं जब तक कि वे चालू न हों! अन्यथा मुझे लगता है कि WLAN MAC सही पहचानकर्ता होगा। आपको इस बात की कोई गारंटी नहीं है कि उपयोगकर्ता कभी भी अपने वाई-फाई को चालू करेगा, और मुझे नहीं लगता कि इसे अपने आप चालू करना 'उचित' है।
टॉम

1
@ आप गलत हैं। जब आप बंद कर देते हैं तब भी आप WLAN या BT MAC पढ़ सकते हैं। हालाँकि, इस बात की कोई गारंटी नहीं है कि डिवाइस में WLAN या BT मॉड्यूल उपलब्ध हैं।
Marqs

2
सबसे विशेष रूप से, स्थानीय वाईफाई और ब्लूटूथ मैक पते अब उपलब्ध नहीं हैं। getMacAddress () aWifiInfo ऑब्जेक्ट और BluetoothAdapter.getDefaultAdapter () की विधि। getAddress () विधि दोनों अब वापस आ जाएगी ।2: 00: 00: 00: 00 अब से।
सारिका केट

4
@sarikakate यह केवल 6.0 मार्शमैलो और इसके बाद के संस्करण में सच है ... यह अभी भी 6.0 मार्शमैलो के नीचे की उम्मीद के अनुसार काम कर रहा है।
स्मेटी

@Smeet हाँ आप सही हैं। मैं यह उल्लेख करना भूल गया कि इसका काम 6.0 से नीचे है
सारिका केट

51

आधिकारिक एंड्रॉइड डेवलपर्स ब्लॉग में अब इस विषय के बारे में एक पूर्ण लेख है, आइडेंटिफिकेशन ऐप प्रतिष्ठान


4
और उस तर्क का मुख्य बिंदु यह है कि यदि आप हार्डवेयर से एक अद्वितीय आईडी प्राप्त करने का प्रयास कर रहे हैं, तो आप शायद गलती कर रहे हैं।
टिम ब्रे

3
और अगर आप अपने डिवाइस-लॉक को फ़ैक्टरी रीसेट द्वारा रीसेट करने की अनुमति दे रहे हैं, तो आपका ट्रायलवेयर मॉडल मृत के रूप में अच्छा है।
सेवा अलेक्सेयेव

43

पर गूगल आई / ओ रीटो मायर इस जो प्रतिष्ठानों भर में उपयोगकर्ताओं को ट्रैक करने के लिए सबसे डेवलपर्स की जरूरतों को पूरा करना चाहिए कि दृष्टिकोण करने के लिए एक मजबूत जवाब का विमोचन किया। एंथनी नोलन अपने जवाब में दिशा दिखाते हैं, लेकिन मुझे लगा कि मैं पूरा तरीका लिखूंगा ताकि दूसरे आसानी से देख सकें कि यह कैसे करना है (विवरण निकालने में मुझे थोड़ा समय लगा)।

यह दृष्टिकोण आपको एक अनाम, सुरक्षित उपयोगकर्ता आईडी देगा जो विभिन्न उपकरणों (प्राथमिक Google खाते के आधार पर) और इंस्टॉल के दौरान उपयोगकर्ता के लिए निरंतर रहेगा। मूल दृष्टिकोण एक यादृच्छिक उपयोगकर्ता आईडी उत्पन्न करना है और इसे ऐप्स की साझा प्राथमिकताओं में संग्रहीत करना है। फिर आप क्लाउड में Google खाते से जुड़ी साझा प्राथमिकताओं को संग्रहीत करने के लिए Google के बैकअप एजेंट का उपयोग करते हैं।

चलो पूर्ण दृष्टिकोण से गुजरते हैं। सबसे पहले, हमें एंड्रॉइड बैकअप सेवा का उपयोग करके अपने SharedPreferences के लिए एक बैकअप बनाने की आवश्यकता है। के माध्यम से अपने एप्लिकेशन को पंजीकृत करके शुरू करेंhttp://developer.android.com/google/backup/signup.html

Google आपको एक बैकअप सेवा कुंजी देगा जिसे आपको मैनिफ़ेस्ट में जोड़ना होगा। आपको निम्नानुसार BackupAgent का उपयोग करने के लिए एप्लिकेशन को भी बताने की आवश्यकता है:

<application android:label="MyApplication"
         android:backupAgent="MyBackupAgent">
    ...
    <meta-data android:name="com.google.android.backup.api_key"
        android:value="your_backup_service_key" />
</application>

फिर आपको बैकअप एजेंट बनाने और इसे साझा करने वाले के लिए सहायक एजेंट का उपयोग करने की आवश्यकता है:

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);
    }
}

बैकअप को पूरा करने के लिए आपको अपनी मुख्य गतिविधि में BackupManager का एक उदाहरण बनाना होगा:

BackupManager backupManager = new BackupManager(context);

अंत में एक उपयोगकर्ता आईडी बनाएं, यदि यह पहले से मौजूद नहीं है, और इसे साझा किए गए संदर्भों में संग्रहीत करें:

  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;
}

यह User_ID अब पूरे इंस्टॉलेशन में लगातार रहेगा, भले ही उपयोगकर्ता डिवाइस को चलाए।

इस दृष्टिकोण की अधिक जानकारी के लिए रेटो की बात देखें ।

और बैकअप एजेंट को कैसे लागू किया जाए इसकी पूरी जानकारी के लिए डेटा बैकअप देखें । मैं विशेष रूप से परीक्षण पर नीचे के खंड की सलाह देता हूं क्योंकि बैकअप तुरंत नहीं होता है और इसलिए परीक्षण के लिए आपको बैकअप को मजबूर करना पड़ता है।


5
क्या एक उपयोगकर्ता के पास एक से अधिक डिवाइस होने पर एक ही आईडी के साथ कई डिवाइस पर नहीं जाता है? एक टैबलेट और उदाहरण के लिए एक फोन।
तोशा

इसके लिए न्यूनतम लक्ष्य 8 आवश्यक है।
१०:२४ बजे

क्या यह इन-ऐप खरीदारी करते समय सत्यापन पेलोड बनाने का पसंदीदा तरीका होगा? इन-ऐप बिलिंग उदाहरण कोड टिप्पणी से: "तो एक अच्छा डेवलपर पेलोड में ये विशेषताएं हैं: 1. यदि दो अलग-अलग उपयोगकर्ता एक आइटम खरीदते हैं, तो उनके बीच पेलोड अलग-अलग होता है, ताकि एक उपयोगकर्ता की खरीद दूसरे उपयोगकर्ता को दोबारा न मिले। 2. पेलोड ऐसा होना चाहिए कि आप इसे तब भी सत्यापित कर सकें, जब ऐप वह नहीं था जिसने खरीद प्रवाह शुरू किया था (ताकि उपयोगकर्ता द्वारा खरीदी गई वस्तुएं उपयोगकर्ता के स्वामित्व वाले अन्य उपकरणों पर काम करें)। "
टचबार्डर

@ तोशा मेरा बस एक ही सवाल था। लेकिन क्या हम वर्चुअल डिवाइस आईडी बनाने के लिए फिर से उसी तकनीक का उपयोग नहीं कर सकते हैं और उसी तरह वापस नहीं कर सकते हैं? डिवाइस आईडी एक वाइप या पुनर्स्थापना के अतीत को बनाए नहीं रखेगा लेकिन अगर हमारे पास लगातार यूजर आईडी है तो हमें डिवाइस आईडी से उतनी आवश्यकता नहीं हो सकती है।
jwehrle

39

मुझे लगता है कि यह एक अद्वितीय आईडी के लिए कंकाल बनाने का निश्चित रूप से आग का तरीका है ... इसे देखें।

स्यूडो-यूनिक आईडी, जो सभी एंड्रॉइड डिवाइसों पर काम करता है। कुछ डिवाइसों में फोन (जैसे टैबलेट) नहीं है या किसी कारण से, आप READ_PHONE_STATE अनुमति शामिल नहीं करना चाहते हैं। आप अभी भी रॉम संस्करण, निर्माता का नाम, सीपीयू प्रकार, और अन्य हार्डवेयर विवरण जैसे विवरण पढ़ सकते हैं, यदि आप सीरियल कुंजी की जांच, या अन्य सामान्य प्रयोजनों के लिए आईडी का उपयोग करना चाहते हैं तो यह अच्छी तरह से अनुकूल होगा। इस तरह से गणना की गई आईडी अद्वितीय नहीं होगी: एक ही आईडी (एक ही हार्डवेयर और रोम छवि के आधार पर) के साथ दो डिवाइस ढूंढना संभव है, लेकिन वास्तविक दुनिया के अनुप्रयोगों में परिवर्तन नगण्य हैं। इस उद्देश्य के लिए आप बिल्ड क्लास का उपयोग कर सकते हैं:

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

बिल्ड के अधिकांश सदस्य स्ट्रिंग्स हैं, जो हम यहां कर रहे हैं वह उनकी लंबाई लेने के लिए है और इसे एक अंक में मोडुलो के माध्यम से बदलना है। हमारे पास 13 ऐसे अंक हैं और हम दो और सामने जोड़ रहे हैं (35) IMEI के समान आकार की आईडी (15 अंक)। यहां अन्य संभावनाएं भी अच्छी हैं, बस इन तारों पर एक नजर है। कुछ इस तरह लौटता है 355715565309247। कोई विशेष अनुमति की आवश्यकता नहीं है, जिससे यह दृष्टिकोण बहुत सुविधाजनक हो।


(अतिरिक्त जानकारी: ऊपर दी गई तकनीक को पॉकेट मैजिक के एक लेख से कॉपी किया गया था ।)


7
दिलचस्प समाधान। ऐसा लगता है कि यह एक ऐसी स्थिति है, जहां आपको वास्तव में अपने स्वयं के "हैश" फ़ंक्शन के साथ आने की कोशिश करने के बजाय सभी डेटा को समेटना चाहिए। ऐसे कई उदाहरण हैं जहां आपको पर्याप्त डेटा होने पर भी टक्कर मिलेगी, जो प्रत्येक मान के लिए अलग है। मेरी सिफारिश: एक हैश फ़ंक्शन का उपयोग करें और फिर द्विआधारी परिणामों को दशमलव में बदल दें और इसे आवश्यकतानुसार काट दें। इसे सही करने के लिए, हालांकि आपको वास्तव में एक यूयूआईडी या पूर्ण हैश स्ट्रिंग का उपयोग करना चाहिए।
स्टीव पोमेरॉय

21
आपको अपने स्रोतों को श्रेय देना चाहिए ... यह सीधे निम्नलिखित लेख से बाहर निकाल दिया गया है: pocketmagic.net/?p=1662
स्टीव हेली

8
यह आईडी उन टकरावों के लिए खुली है जैसे आप नहीं जानते कि क्या। यह व्यावहारिक रूप से एक ही वाहक से समान उपकरणों पर समान होने की गारंटी है।
सेवा अलेक्सेयेव

7
डिवाइस के अपग्रेड होने पर यह भी बदल सकता है।
डेविड

8
बहुत, बहुत बुरा समाधान। दो Nexus 5 पर परीक्षण किया गया ... समान संख्याएँ लौटाएँ।
सिनान डिज़ादेर्विएव

38

निम्न कोड एक छिपे हुए एंड्रॉइड एपीआई का उपयोग करके डिवाइस सीरियल नंबर देता है। लेकिन, यह कोड सैमसंग गैलेक्सी टैब पर काम नहीं करता है क्योंकि इस डिवाइस पर "ro.serialno" सेट नहीं है।

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) {

}

मैं सिर्फ xda डेवलपर पर पढ़ता हूं ro.serialnoजिसका उपयोग उत्पन्न करने के लिए किया जाता है Settings.Secure.ANDROID_ID। इसलिए वे मूल रूप से एक ही मूल्य के विभिन्न प्रतिनिधित्व हैं।
मार्टिन

@Martin: लेकिन शायद सीरियल नंबर डिवाइस को रीसेट करने पर नहीं बदलता है। है ना? बस इसके लिए एक नया मूल्य ANDROID_IDप्राप्त होता है।
रॉनी

वास्तव में सभी उपकरणों पर मैंने उनका परीक्षण किया है जहां समान समान है। या कम से कम हैश मूल्य जहां एक ही है (गोपनीयता कारणों से मैं लॉग फाइल के लिए सही मान नहीं लिखता हूं)।
मार्टिन

यह मान वैसा ही हैandroid.os.Build.SERIAL
यूजेनिक

android.os.Build.SERIALएंड्रॉयड हे में हटा दिया जाएगा, देख android-developers.googleblog.com/2017/04/...
EpicPandaForce

32

यह एक सरल प्रश्न है, कोई सरल उत्तर नहीं है।

इससे अधिक, यहां सभी मौजूदा उत्तर हैं कि क्या यह पुराना है या अविश्वसनीय है।

तो अगर आप 2020 में एक समाधान के लिए खोज रहे हैं

यहां कुछ बातों को ध्यान में रखा गया है:

सभी हार्डवेयर आधारित पहचानकर्ता (SSAID, IMEI, MAC, इत्यादि) गैर-Google के उपकरणों (पिक्सेल और नेक्सस को छोड़कर सब कुछ) के लिए अविश्वसनीय हैं, जो दुनिया भर में सक्रिय उपकरणों के 50% से अधिक हैं। इसलिए आधिकारिक एंड्रॉइड पहचानकर्ता सर्वोत्तम प्रथाओं को स्पष्ट रूप से बताता है:

SSAID (Android ID), IMEI, MAC एड्रेस आदि जैसे हार्डवेयर पहचानकर्ताओं का उपयोग करने से बचें ...

यह अधिकांश उत्तरों को अमान्य बना देता है। अलग-अलग एंड्रॉइड सुरक्षा अपडेट्स के कारण, उनमें से कुछ को नए और सख्त रनटाइम अनुमतियों की आवश्यकता होती है, जिन्हें उपयोगकर्ता द्वारा केवल नकार दिया जा सकता है।

उदाहरण के रूप में CVE-2018-9489 जो उपरोक्त सभी वाईफ़ाई आधारित तकनीकों को प्रभावित करता है।

यह उन पहचानकर्ताओं को न केवल अविश्वसनीय बनाता है, बल्कि कई मामलों में अस्वीकार्य भी बनाता है।

तो सरल शब्दों में: उन तकनीकों का उपयोग न करें

यहाँ कई अन्य उत्तर AdvertisingIdClientभी उपयोग करने का सुझाव दे रहे हैं , जो कि असंगत भी है, क्योंकि इसके डिज़ाइन द्वारा इसका उपयोग केवल विज्ञापनों की रूपरेखा के लिए किया जाना चाहिए। यह आधिकारिक संदर्भ में भी कहा गया है

उपयोगकर्ता प्रोफाइलिंग या विज्ञापनों के मामलों के लिए केवल एक विज्ञापन आईडी का उपयोग करें

यह न केवल डिवाइस पहचान के लिए अविश्वसनीय है, बल्कि आपको विज्ञापन ट्रैकिंग के बारे में उपयोगकर्ता की गोपनीयता का भी पालन करना चाहिए नीति के , जो स्पष्ट रूप से बताता है कि उपयोगकर्ता किसी भी समय इसे रीसेट या ब्लॉक कर सकता है।

तो यह भी उपयोग न करें

चूँकि आपके पास वांछित स्थिर विश्वव्यापी अद्वितीय और विश्वसनीय उपकरण पहचानकर्ता नहीं हो सकता है। Android का आधिकारिक संदर्भ सुझाव:

भुगतान धोखाधड़ी की रोकथाम और टेलीफोनी को छोड़कर, अन्य सभी उपयोग के मामलों के लिए जब भी संभव हो एक FirebaseInstanceId या एक निजी रूप से संग्रहीत GUID का उपयोग करें।

यह डिवाइस पर एप्लिकेशन इंस्टॉलेशन के लिए अद्वितीय है, इसलिए जब उपयोगकर्ता एप्लिकेशन को अनइंस्टॉल करता है - यह मिटा दिया जाता है, तो यह 100% विश्वसनीय नहीं है, लेकिन यह अगली सबसे अच्छी बात है।

अपने ग्रेड में नवीनतम फायरबेस-मैसेजिंग निर्भरताFirebaseInstanceId जोड़ने के लिए उपयोग करें

implementation 'com.google.firebase:firebase-messaging:20.2.0'

और एक पृष्ठभूमि थ्रेड में नीचे दिए गए कोड का उपयोग करें:

String reliableIdentifier = FirebaseInstanceId.getInstance().getId();

यदि आपको अपने दूरस्थ सर्वर पर डिवाइस पहचान को संग्रहीत करने की आवश्यकता है, तो इसे (सादे पाठ) के रूप में संग्रहीत न करें, लेकिन नमक के साथ एक हैश

आज यह न केवल एक सर्वोत्तम प्रथा है, आपको वास्तव में इसे GDPR के अनुसार करना होगा - पहचानकर्ता और समान नियम।


3
अभी के लिए, यह सबसे अच्छा उत्तर है, और पहला वाक्य सबसे अच्छा सारांश है: "यह एक सरल प्रश्न है, एक सरल उत्तर के बिना - बस इसे प्यार करें।
b2mob

आपको "भुगतान धोखाधड़ी की रोकथाम और टेलीफोनी को छोड़कर" की सराहना करनी होगी, इस बात का कोई जवाब नहीं दिया जाएगा कि कैसे उस मामले का उपयोग किया जाए।
एरन बुदजनाह

@EranBoudjnah आधिकारिक संदर्भ से वह उद्धरण है, जो उत्तर में जुड़ा हुआ है। मैं उस उपयोग मामले को संबोधित करने का प्रयास कर सकता हूं, लेकिन चूंकि यह ओपी प्रश्न के लिए विशिष्ट नहीं है, स्टैकओवरफ्लो की नीति के अनुसार - यह एक अलग समर्पित प्रश्न में किया जाना चाहिए।
निकिता कुर्तिन

मैं सिर्फ इतना कह रहा हूं कि जवाब अधूरा है। लेकिन मुझे पता है कि यह आपकी गलती नहीं है क्योंकि यह एक उद्धरण है।
एरन बौद्जनाह

1
@ M.UsmanKhan, उत्तर इसके ठीक बाद लिखा है: " आज यह न केवल एक सर्वोत्तम अभ्यास है, आपको वास्तव में इसे GDPR - पहचानकर्ताओं और समान नियमों के अनुसार कानून द्वारा करना होगा। "
निकिता कुर्टिन

27

नीचे दिए गए कोड का उपयोग करके, आप एक स्ट्रिंग के रूप में एंड्रॉइड ओएस डिवाइस की अनूठी डिवाइस आईडी प्राप्त कर सकते हैं।

deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 

21

एक सीरियल फ़ील्ड को जोड़ा गया थाBuildएपीआई स्तर 9 (एंड्रॉइड 2.3 - जिंजरब्रेड) में कक्षा में । प्रलेखन का कहना है कि यह हार्डवेयर सीरियल नंबर का प्रतिनिधित्व करता है। इस प्रकार यह अद्वितीय होना चाहिए, अगर यह डिवाइस पर मौजूद है।

मुझे नहीं पता कि यह एपीआई स्तर> = 9 के साथ सभी उपकरणों द्वारा वास्तव में समर्थित (= शून्य नहीं) है।


2
दुर्भाग्य से, यह "अज्ञात" है।
m0skit0

18

एक चीज जो मैं जोड़ूंगा - मेरे पास उन अद्वितीय स्थितियों में से एक है।

का उपयोग करते हुए:

deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);

यह बताते हुए कि मेरी Viewsonic G Tablet एक डिवाइसआईडी की रिपोर्ट करती है, जो अशक्त नहीं है, हर एक जी टैबलेट एक ही नंबर की रिपोर्ट करता है।

यह दिलचस्प खेल बनाता है "पॉकेट एम्पायर" जो आपको "अद्वितीय" डिवाइसआईडी के आधार पर किसी के खाते में त्वरित पहुंच प्रदान करता है।

मेरे डिवाइस में सेल रेडियो नहीं है।


आईडी क्या है? क्या यह खतरनाक है 9774d56d682e549c?
Mr_and_Mrs_D

वाह, जो बहुत पहले था मैं उस टैबलेट को फेंकने के बाद से बहुत लंबा हूं। कह नहीं सका।
टोनी मारो

काम करता है। इसके अलावा, आईडी से बहुत अधिक कॉम्पैक्ट है जो मुझे यादृच्छिक यूयूआईडी से मिलता है।
ट्रेवेल्ली

1
@ ट्रेवेल्ली काम करता है? क्या आप अलग-अलग ऐप से एक ही डिवाइस आईडी प्राप्त कर सकते हैं?
अर्नोल्ड ब्राउन

@AnnoldBrown हां। इसका पूरी तरह से परीक्षण अवश्य करें। एक महान दिन है: डी
ट्रेवेल्ली

16

आपके Android एप्लिकेशन के लिए एक विशिष्ट पहचानकर्ता कैसे प्राप्त किया जाए, इस बारे में विस्तृत निर्देशों के लिए, आधिकारिक Android डेवलपर्स ब्लॉग पोस्टिंग आइडेंटीटीज़ टूल देखें

ऐसा लगता है कि आपके लिए सबसे अच्छा तरीका है कि आप खुद को इंस्टॉलेशन के लिए जनरेट करें और बाद में जब एप्लिकेशन दोबारा लॉन्च किया जाए तो इसे पढ़ें।

मुझे व्यक्तिगत रूप से यह स्वीकार्य लगता है लेकिन आदर्श नहीं। सभी उदाहरणों में एंड्रॉइड द्वारा प्रदान किया गया कोई भी पहचानकर्ता नहीं है क्योंकि अधिकांश फोन के रेडियो स्टेट्स (वाई-फाई ऑन / ऑफ, सेलुलर ऑन / ऑफ, ब्लूटूथ ऑन / ऑफ) पर निर्भर हैं। अन्य, जैसे Settings.Secure.ANDROID_IDनिर्माता द्वारा लागू किया जाना चाहिए और अद्वितीय होने की गारंटी नहीं है।

निम्नलिखित एक इंस्टॉलेशन फ़ाइल में डेटा लिखने का एक उदाहरण है जिसे किसी भी अन्य डेटा के साथ संग्रहीत किया जाएगा जो एप्लिकेशन स्थानीय रूप से बचाता है।

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();
    }
}

यदि आप ऐप इंस्टॉलेशन को ट्रैक करना चाहते हैं तो यह एकदम सही है। ट्रैकिंग डिवाइस हालांकि एक बहुत पेचीदा मामला है, और इसमें पूरी तरह से हवा-तंग समाधान दिखाई नहीं देता है।
लुका स्पिलर

निहित उपकरणों के बारे में क्या? वे इस स्थापना आईडी को आसानी से बदल सकते हैं, है ना?
tasomaniac

पूर्ण रूप से। रूट इंस्टॉलेशन आईडी को बदल सकता है। आप इस कोड ब्लॉक का उपयोग करके रूट की जांच कर सकते हैं: stackoverflow.com/questions/1101380/…
केविन पार्कर

यदि हम फ़ैक्टरी को रीसेट करते हैं, तो क्या फ़ाइल डिलीट हो जाएगी?
जामशीद

यदि आप रीसेट करते हैं और / डेटा विभाजन को हटाते हैं या प्रारूपित करते हैं तो UUID अलग है।
केविन पार्कर

12

वर्ग फ़ाइल में नीचे कोड जोड़ें:

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);

AndroidManifest.xml में जोड़ें:

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

10

स्ट्रिंग, उपयोग TelephonyManagerऔर ANDROID_ID, के रूप में एक Android OS डिवाइस की अद्वितीय डिवाइस आईडी इसके द्वारा प्राप्त की जाती है:

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);
}

लेकिन मैं Google द्वारा सुझाई गई विधि की दृढ़ता से अनुशंसा करता हूं, पहचानना ऐप प्रतिष्ठान देखें


9

उन ANDROID_IDमुद्दों के आसपास काम करने के लिए बहुत सारे अलग-अलग दृष्टिकोण हैं ( nullकभी-कभी हो सकते हैं या किसी विशिष्ट मॉडल के उपकरण हमेशा एक ही आईडी लौटा सकते हैं) पेशेवरों और के साथ:

  • कस्टम आईडी जनरेशन एल्गोरिथ्म को लागू करना (डिवाइस के गुणों के आधार पर जो स्थिर माना जाता है और नहीं बदलेगा -> कौन जानता है)
  • IMEI , सीरियल नंबर, वाई-फाई / ब्लूटूथ-मैक एड्रेस जैसी अन्य आईडी का दुरुपयोग करना (वे सभी उपकरणों पर मौजूद नहीं होंगे या अतिरिक्त अनुमतियाँ आवश्यक हैं)

मैं खुद एंड्रॉइड के लिए एक मौजूदा OpenUDID कार्यान्वयन ( https://github.com/ylechelle/OpenUDID देखें ) का उपयोग करना पसंद करता हूं ( https://github.com/vieux/OpenUDID देखें )। यह ANDROID_IDऊपर वर्णित उन मुद्दों के लिए कमियों के साथ एकीकृत करना और उपयोग करना आसान है ।


8

कैसे के बारे में आईएमईआई । यह Android या अन्य मोबाइल उपकरणों के लिए अद्वितीय है।


9
मेरे टेबलेट के लिए नहीं, जिनके पास IMEI नहीं है क्योंकि वे मेरे मोबाइल वाहक से कनेक्ट नहीं होते हैं।
ब्रिल पप्पिन

2
सीडीएमए उपकरणों का उल्लेख नहीं है जिनके पास आईएमईआई के बजाय ईएसएन है।
डेविड

@ डेविड को देखते हुए क्या Android के साथ कोई सीडीएमए है?
एलजो वलूगी

1
यह केवल यह है कि यह क्या करेंगे है एक टेलीफोन :) एक गोली नहीं हो सकता।
ब्रिल पप्पिन

3
@ElzoValugi यह "इस दिन" पहले से ही है और अभी भी सभी टैबलेट में सिम कार्ड नहीं हैं।
मैथ्यू क्विरोस

8

यहां बताया गया है कि मैं कैसे विशिष्ट आईडी बना रहा हूं:

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;
}

अगर हम 6.0 रन संस्करण में ReadPhoneState का उपयोग करते हैं, तो रनटाइम अनुमति के लिए पूछते हैं
हर्षा

8

मेरे दो सेंट - एनबी यह एक डिवाइस (इरेट) यूनिक आईडी के लिए है - इंस्टॉलेशन एक नहीं जैसा कि एंड्रॉइड डेवलपर्स के ब्लॉग में चर्चा की गई है ।

ध्यान दें कि @emmby द्वारा प्रदान किया गया समाधान प्रति एप्लिकेशन ID में वापस आता है क्योंकि SharedPreferences प्रक्रियाओं के दौरान सिंक्रनाइज़ नहीं किए जाते हैं ( यहां और यहां देखें )। इसलिए मैंने इससे पूरी तरह परहेज किया।

इसके बजाय, मैंने एक एनरम में एक डिवाइस (डिवाइस) आईडी प्राप्त करने के लिए विभिन्न रणनीतियों का एनकाउंटर किया - एनुम स्थिरांक के क्रम को बदलने से आईडी प्राप्त करने के विभिन्न तरीकों की प्राथमिकता प्रभावित होती है। पहली गैर-नल आईडी लौटा दी जाती है या एक अपवाद फेंक दिया जाता है (जैसा कि अच्छे जावा अभ्यास के अनुसार अशक्त अर्थ नहीं देता है)। इसलिए उदाहरण के लिए मेरे पास एक पहले TELEPHONY है - लेकिन एक अच्छा डिफ़ॉल्ट विकल्प ANDROID_ID बीटा होगा:

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);
        }
    }
}

8

यहां 30+ उत्तर हैं और कुछ समान हैं और कुछ अद्वितीय हैं। यह उत्तर उन कुछ जवाबों पर आधारित है। उनमें से एक है @Lenn गुड़िया का जवाब।

यह 3 आईडी को जोड़ती है और 32 अंकों की हेक्स स्ट्रिंग बनाता है। इसने मेरे लिए बहुत अच्छा काम किया है।

3 आईडी हैं:
Pseudo-ID - यह भौतिक उपकरण विशिष्टताओं
ANDROID_ID - ब्लूटूथ पते के आधार पर उत्पन्न होता हैSettings.Secure.ANDROID_ID
- ब्लूटूथ एडाप्टर पता

यह कुछ इस तरह लौटेगा: 551F27C060712A72730B0A0F734064B1

नोट: आप हमेशा longIdस्ट्रिंग में अधिक आईडी जोड़ सकते हैं । उदाहरण के लिए, सीरियल #। वाईफाई एडेप्टर पता। आईएमईआई। इस तरह आप इसे प्रति डिवाइस अधिक विशिष्ट बना रहे हैं।

@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 "";
}

1
UUID को इसमें जोड़ना longIdऔर किसी फ़ाइल में संग्रहीत करना, इसे सबसे विशिष्ट पहचानकर्ता बना देगा:String uuid = UUID.randomUUID().toString();
Mousa Alfhaily

1
यदि अन्य सभी विफल रहता है, अगर उपयोगकर्ता के पास एपीआई 9 (जिंजरब्रेड से कम) है, तो अपने फोन या 'Secure.ANDROID_ID' को रीसेट कर दिया है। यदि रिटर्न 'शून्य' है, तो बस वापस लौटी आईडी पूरी तरह से उनके एंड्रॉइड डिवाइस की जानकारी के आधार पर होगी। यह वह जगह है जहां टकराव हो सकता है। DISPLAY, HOST या ID का उपयोग न करने की कोशिश करें - ये आइटम बदल सकते हैं। यदि टकराव होते हैं, तो अतिव्यापी डेटा होगा। स्रोत: gist.github.com/pedja1/fe69e8a80ed505500caa
Mousa Alfhaily

यदि हम कोड की इस लाइन द्वारा यूनिक नंबर प्राप्त करने का प्रयास करते हैं, तो हम यह कह सकते हैं कि यह विशिष्ट ईद है और यह कभी किसी अन्य डिवाइस के साथ संघर्ष नहीं करेगा?
निंजा

1
@ निंजा चूंकि बीएलई मैक एड्रेस अद्वितीय है, हां जनरेट की गई आईडी हमेशा अनूठी होगी। हालाँकि, यदि आप वास्तव में निश्चित होना चाहते हैं, तो मैं इसमें UUID जोड़ने का सुझाव दूंगा longId। इस तरह एक पंक्ति को बदलें: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString();यह गारंटी देता है कि उत्पन्न आईडी अद्वितीय होगी।

@ help इस भारी मदद के लिए बहुत बहुत धन्यवाद। वास्तव में मेरा ऐप बहुत संवेदनशील डेटा है, इसलिए मुझे इसके बारे में सुनिश्चित करने की आवश्यकता है कि मैं सिर्फ इस चीजों की पुष्टि क्यों कर रहा हूं।
निंजा

7

दूसरा तरीका यह है कि /sys/class/android_usb/android0/iSerialकिसी भी अनुमति के बिना किसी ऐप में उपयोग किया जाए।

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

जावा में ऐसा करने के लिए iSerial फ़ाइल खोलने और वर्णों को पढ़ने के लिए एक FileInputStream का उपयोग करना होगा। बस सुनिश्चित करें कि आप इसे अपवाद हैंडलर में लपेटते हैं, क्योंकि सभी उपकरणों में यह फ़ाइल नहीं है।

कम से कम निम्नलिखित उपकरणों को इस फ़ाइल को विश्व-पठनीय माना जाता है:

  • गैलेक्सी नेक्सस
  • नेक्सस एस
  • मोटोरोला Xoom 3 जी
  • तोशिबा AT300
  • एचटीसी वन वी
  • मिनी MK802
  • सैमसंग गैलेक्सी एस II

आप मेरे ब्लॉग पोस्ट को लीक करने वाले एंड्रॉइड हार्डवेयर सीरियल नंबर को बिना पढ़े ऐप में भी देख सकते हैं, जहां मैं चर्चा करता हूं कि जानकारी के लिए अन्य फाइलें क्या उपलब्ध हैं।


मैंने अभी आपका ब्लॉग पोस्ट पढ़ा। मेरा मानना ​​है कि यह अद्वितीय नहीं है: Build.SERIAL भी किसी भी अनुमति w / o उपलब्ध है, और (सिद्धांत रूप में) एक अद्वितीय हार्डवेयर सीरियल नंबर है।
टॉम

1
आप सही हे। यह केवल एक और तरीका है कि आपके डिवाइस को ट्रैक किया जा सकता है, और जैसा कि आपने कहा कि इन दोनों तरीकों के लिए ऐप की अनुमति की आवश्यकता नहीं है।
इंसिटिटेक

7

TelephonyManger.getDeviceId () अद्वितीय डिवाइस ID लौटाता है, उदाहरण के लिए, GSM के लिए IMEI और CDMA फोन के लिए MEID या ESN।

final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            
String myAndroidDeviceId = mTelephony.getDeviceId(); 

लेकिन मैं उपयोग करने की सलाह देता हूं:

Settings.Secure.ANDROID_ID जो एक अद्वितीय 64-बिट हेक्स स्ट्रिंग के रूप में Android आईडी लौटाता है।

    String   myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 

कभी-कभी TelephonyManger.getDeviceId () अशक्त वापस आ जाएगी, इसलिए एक अनूठी आईडी को आश्वस्त करने के लिए आप इसे प्रदान करेंगे:

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;
}

मुझे हाल ही में पता चला है कि क्लाइंट का डिवाइस SM-G928F / Galaxy S6 edge + में एंड्रॉइड आईडी के लिए 16 हेक्स अंकों के बजाय केवल 15 बचाता है।
होल्गर जकॉब्स

7

एक विशिष्ट एंड्रॉइड डिवाइस की हार्डवेयर पहचान के लिए आप मैक एड्रेस की जांच कर सकते हैं।

आप इसे इस तरह से कर सकते हैं:

AndroidManifest.xml में

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

अब आपके कोड में:

List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());

for (NetworkInterface interface : interfacesList) {
   // This will give you the interface MAC ADDRESS
   interface.getHardwareAddress();
}

हर Android डिवाइस में उनका कम से कम "wlan0" इंटरफ़ेस डायन WI-FI चिप होता है। यह कोड तब भी काम करता है जब WI-FI चालू नहीं होता है।

PS उनके अन्य इंटरफेस का एक गुच्छा है जो आपको MACS वाली सूची से मिलेगा लेकिन यह फोन के बीच बदल सकता है।


7

IMEIसुरक्षित पाने या उपयोग करने के लिए मैं निम्नलिखित कोड का उपयोग करता हूं । ANDROID_IDएक विकल्प के रूप में, जब डिवाइस में फोन क्षमताएं नहीं होती हैं:

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);

7

विशेष रूप से, Settings.Secure.ANDROID_ID। यह 64-बिट की मात्रा है जो डिवाइस के पहले बूट होने पर जेनरेट और स्टोर की जाती है। जब डिवाइस मिटा दिया जाता है तो यह रीसेट हो जाता है।

ANDROID_IDएक अद्वितीय उपकरण पहचानकर्ता के लिए एक अच्छा विकल्प लगता है। डाउनसाइड्स हैं: पहला, यह 2.2 से पहले एंड्रॉइड की रिलीज़ पर 100% विश्वसनीय नहीं है। (“Froyo”).इसके अलावा, एक प्रमुख निर्माता से एक लोकप्रिय हैंडसेट में कम से कम एक व्यापक रूप से देखा गया बग है, जहां हर उदाहरण में एक ही ANDROID_ID है।


1
यह उत्तर पुराने Google ब्लॉग android-developers.googleblog.com/2011/03/… से एक कॉपीपेस्ट है । तो बग पहले से ही हल है?
सेर्गेई

7

एंड्रॉइड डिवाइसों में उपलब्ध यूनीक आईडीएस को समझने के लिए। इस आधिकारिक गाइड का उपयोग करें।

विशिष्ट पहचानकर्ताओं के लिए सर्वोत्तम अभ्यास:

IMEI, मैक एड्रेस, इंस्टेंस आईडी, GUIDs, SSAID, विज्ञापन आईडी, उपकरणों को सत्यापित करने के लिए सेफ्टी नेट एपीआई।

https://developer.android.com/training/articles/user-data-ids


6

Google इंस्टेंस आईडी

I / O 2015 में जारी; Android पर खेल सेवाओं 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

ऐसा लगता है कि Google का इरादा इस ID का उपयोग Android, Chrome और iOS में स्थापना की पहचान करने के लिए करना है।

यह एक इंस्टॉलेशन की पहचान करता है फिर एक डिवाइस, लेकिन फिर, ANDROID_ID (जो स्वीकृत उत्तर है) अब डिवाइस की पहचान नहीं करता है। ARC रनटाइम के साथ एक नया ANDROID_ID हर इंस्टॉलेशन ( यहां विवरण ) के लिए उत्पन्न होता है , ठीक इसी तरह नई इंस्टेंस आईडी। इसके अलावा, मुझे लगता है कि प्रतिष्ठानों की पहचान करना (उपकरणों का नहीं) वास्तव में हम में से अधिकांश की तलाश क्या है।

उदाहरण ID के फायदे

यह मुझे प्रतीत होता है कि Google इस उद्देश्य के लिए इसका उपयोग करने का इरादा रखता है (आपके प्रतिष्ठानों की पहचान), यह क्रॉस-प्लेटफ़ॉर्म है, और इसका उपयोग कई अन्य उद्देश्यों के लिए किया जा सकता है (ऊपर लिंक देखें)।

यदि आप GCM का उपयोग करते हैं, तो आपको अंततः इस उदाहरण ID का उपयोग करने की आवश्यकता होगी क्योंकि GCM टोकन प्राप्त करने के लिए आपको इसकी आवश्यकता है (जो पुराने GCM पंजीकरण आईडी को बदल देता है)।

नुकसान / मुद्दे

वर्तमान कार्यान्वयन (GPS 7.5) में उदाहरण ID तब सर्वर से पुनर्प्राप्त किया जाता है जब आपका ऐप इसका अनुरोध करता है। इसका मतलब है कि उपरोक्त कॉल एक अवरुद्ध कॉल है - मेरे अवैज्ञानिक परीक्षण में डिवाइस ऑनलाइन होने पर 1-3 सेकंड लगते हैं, और 0.5 - 1.0 सेकंड अगर ऑफ-लाइन (संभवतः यह है कि यह छोड़ने और उत्पन्न करने से पहले कितने समय तक इंतजार करता है यादृच्छिक आईडी)। यह एंड्रॉइड 5.1.1 और जीपीएस 7.5 के साथ नेक्सस 5 पर उत्तरी अमेरिका में परीक्षण किया गया था।

यदि आप उन उद्देश्यों के लिए आईडी का उपयोग करते हैं जो वे चाहते हैं - जैसे। ऐप प्रमाणीकरण, ऐप पहचान, जीसीएम - मुझे लगता है कि यह 1-3 सेकंड एक उपद्रव हो सकता है (आपके ऐप पर निर्भर करता है, निश्चित रूप से)।


1
InstID का एक और महत्वपूर्ण पहलू यह है कि यदि उपयोगकर्ता ऐप का डेटा क्लियर करता है तो आपके लिए एक नया इंस्टिड उत्पन्न होगा।
इडनकव

दिलचस्प है, लेकिन मुझे नहीं लगता कि यह वास्तव में संभावित उपयोग के मामलों में बदलाव करता है: उदाहरण के लिए, जैसे कि android_id, डिवाइस की पहचान करने के लिए अनुकूल नहीं है। तो आपके सर्वर को उपयोगकर्ता क्लियरिंग डेटा जैसे उपयोगकर्ता अनइंस्टॉल करना और आपके ऐप को फिर से स्थापित करना होगा - जो अनुचित नहीं है।
टॉम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.