Apakah perangkat Android memiliki ID unik, dan jika demikian, apa cara sederhana untuk mengaksesnya menggunakan Java?
Apakah perangkat Android memiliki ID unik, dan jika demikian, apa cara sederhana untuk mengaksesnya menggunakan Java?
Jawaban:
Settings.Secure#ANDROID_ID
mengembalikan ID Android sebagai unik untuk setiap string hex 64-bit pengguna .
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
UPDATE : Pada versi Android terbaru, banyak masalah dengan ANDROID_ID
telah diselesaikan, dan saya percaya pendekatan ini tidak lagi diperlukan. Silakan lihat jawaban Anthony .
Pengungkapan penuh: aplikasi saya menggunakan pendekatan di bawah ini awalnya tetapi tidak lagi menggunakan pendekatan ini, dan kami sekarang menggunakan pendekatan yang diuraikan dalam entri Blog Pengembang Android yang terhubung dengan tautan emmby (yaitu, menghasilkan dan menyimpan a UUID#randomUUID()
).
Ada banyak jawaban untuk pertanyaan ini, sebagian besar hanya akan berfungsi "sebagian" pada saat itu, dan sayangnya itu tidak cukup baik.
Berdasarkan pengujian perangkat saya (semua ponsel, setidaknya satu di antaranya tidak diaktifkan):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
(seperti yang diharapkan)ANDROID_ID
ANDROID_ID
dan TelephonyManager.getDeviceId()
- selama akun Google telah ditambahkan selama pengaturan.Jadi jika Anda menginginkan sesuatu yang unik untuk perangkat itu sendiri, TM.getDeviceId()
harus cukup. Jelas beberapa pengguna lebih paranoid daripada yang lain, jadi mungkin berguna untuk hash 1 atau lebih dari pengidentifikasi ini, sehingga string masih hampir unik untuk perangkat, tetapi tidak secara eksplisit mengidentifikasi perangkat sebenarnya pengguna. Misalnya, menggunakan String.hashCode()
, dikombinasikan dengan 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();
mungkin menghasilkan sesuatu seperti: 00000000-54b3-e7c7-0000-000046bffd97
Ini cukup berhasil bagi saya.
Seperti yang disebutkan Richard di bawah ini, jangan lupa bahwa Anda perlu izin untuk membaca TelephonyManager
properti, jadi tambahkan ini ke manifes Anda:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
impor libs
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
file manifes. Jika menyimpan dalam database, string yang dikembalikan adalah 36 karakter.
Setelah membaca setiap posting Stack Overflow tentang membuat ID unik, blog pengembang Google dan dokumentasi Android, saya merasa seolah-olah 'Pseudo ID' adalah pilihan terbaik.
Kode 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)
Terima kasih kepada @stansult untuk memposting semua opsi kami (dalam pertanyaan Stack Overflow).
Email Pengguna - Perangkat Lunak
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
atau<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
( Cara mendapatkan alamat email utama perangkat Android )Nomor Telepon Pengguna - Perangkat Lunak
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
IMEI - Hardware (hanya telepon, kebutuhan android.permission.READ_PHONE_STATE
)
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Android ID - Hardware (bisa nol, bisa berubah setelah reset pabrik, bisa diubah pada perangkat yang di-rooting)
Alamat MAC WLAN - Perangkat Keras (kebutuhan android.permission.ACCESS_WIFI_STATE
)
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
Bluetooth MAC Address - Hardware (perangkat dengan Bluetooth, kebutuhan android.permission.BLUETOOTH
)
<uses-permission android:name="android.permission.BLUETOOTH "/>
Pseudo-Unique ID - Software (untuk semua perangkat Android)
Saya tahu tidak ada cara 'sempurna' untuk mendapatkan ID unik tanpa menggunakan izin; namun, terkadang kita hanya perlu melacak pemasangan perangkat. Ketika membuat ID unik, kita dapat membuat 'id unik semu' hanya berdasarkan informasi yang diberikan oleh API Android tanpa menggunakan izin tambahan. Dengan cara ini, kami dapat menunjukkan rasa hormat pengguna dan mencoba menawarkan pengalaman pengguna yang baik juga.
Dengan id pseudo-unik, Anda benar-benar hanya menemukan fakta bahwa mungkin ada duplikat berdasarkan fakta bahwa ada perangkat serupa. Anda dapat mengubah metode gabungan untuk membuatnya lebih unik; namun, beberapa pengembang perlu melacak pemasangan perangkat dan ini akan melakukan trik atau kinerja berdasarkan perangkat yang serupa.
Jika perangkat Android mereka adalah API 9 atau lebih, ini dijamin unik karena bidang 'Build.SERIAL'.
INGAT , Anda secara teknis hanya kehilangan sekitar 0,5% pengguna yang memiliki API <9 . Jadi Anda bisa fokus pada sisanya: Ini adalah 99,5% pengguna!
Jika perangkat Android pengguna lebih rendah dari API 9; semoga, mereka belum melakukan reset pabrik dan 'Secure.ANDROID_ID' mereka akan dipertahankan atau tidak 'null'. (lihat http://developer.android.com/about/dashboards/index.html )
Jika semuanya gagal, jika pengguna memang memiliki lebih rendah dari API 9 (lebih rendah dari Gingerbread), telah mengatur ulang perangkat mereka atau 'Secure.ANDROID_ID' mengembalikan 'nol', maka ID yang dikembalikan hanya akan didasarkan pada informasi perangkat Android mereka. Di sinilah tabrakan dapat terjadi.
Perubahan:
Silakan lihat metode di bawah ini:
/**
* 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();
}
Dari konsol Pengembang Google Play:
Mulai 1 Agustus 2014, Kebijakan Program Pengembang Google Play mengharuskan semua unggahan dan pembaruan aplikasi baru untuk menggunakan ID iklan sebagai pengganti pengenal persisten lainnya untuk tujuan iklan apa pun. Belajarlah lagi
Implementasi :
Izin:
<uses-permission android:name="android.permission.INTERNET" />
Kode:
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();
}
Sumber / Dokumen:
http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html
Ini dimaksudkan bahwa ID iklan sepenuhnya menggantikan penggunaan pengenal lain yang ada untuk tujuan iklan (seperti penggunaan ANDROID_ID di Pengaturan. Aman) ketika Layanan Google Play tersedia. Kasus di mana Layanan Google Play tidak tersedia ditunjukkan oleh GooglePlayServicesNotAvailableException dilemparkan oleh getAdvertisingIdInfo ().
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
Saya telah mencoba merujuk setiap tautan yang saya ambil informasinya. Jika Anda hilang dan perlu dimasukkan, beri komentar!
Build
kelas akan berubah setelah pembaruan OS? Terutama jika API diperbarui? Jika demikian, bagaimana Anda menjamin ini unik? (Berbicara tentang metode yang Anda tulis)
Seperti yang disebutkan Dave Webb, Blog Pengembang Android memiliki artikel yang membahas hal ini. Solusi pilihan mereka adalah melacak pemasangan aplikasi daripada perangkat, dan itu akan bekerja dengan baik untuk sebagian besar kasus penggunaan. Posting blog akan menunjukkan kepada Anda kode yang diperlukan untuk membuatnya bekerja, dan saya sarankan Anda memeriksanya.
Namun, posting blog berlanjut untuk membahas solusi jika Anda memerlukan pengenal perangkat daripada pengenal instalasi aplikasi. Saya berbicara dengan seseorang di Google untuk mendapatkan klarifikasi tambahan tentang beberapa item jika Anda perlu melakukannya. Inilah yang saya temukan tentang pengidentifikasi perangkat yang TIDAK disebutkan dalam posting blog tersebut:
Berdasarkan rekomendasi Google, saya menerapkan kelas yang akan menghasilkan UUID unik untuk setiap perangkat, menggunakan ANDROID_ID sebagai unggulan jika diperlukan, kembali ke TelephonyManager.getDeviceId () sebagaimana diperlukan, dan jika gagal, beralih ke UUID unik yang dibuat secara acak yang bertahan di seluruh aplikasi restart (tetapi tidak menginstal ulang aplikasi).
Perhatikan bahwa untuk perangkat yang harus mundur pada ID perangkat, ID unik AKAN bertahan di seluruh pabrik. Ini adalah sesuatu yang harus diperhatikan. Jika Anda perlu memastikan bahwa pengaturan ulang pabrik akan mengatur ulang ID unik Anda, Anda mungkin ingin mempertimbangkan untuk langsung kembali ke UUID acak daripada ID perangkat.
Sekali lagi, kode ini untuk ID perangkat, bukan ID instalasi aplikasi. Untuk sebagian besar situasi, ID penginstalan aplikasi mungkin adalah yang Anda cari. Tetapi jika Anda benar-benar membutuhkan ID perangkat, maka kode berikut mungkin akan bekerja untuk Anda.
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;
}
}
Berikut adalah kode yang digunakan Reto Meier dalam presentasi Google I / O tahun ini untuk mendapatkan id unik bagi pengguna:
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;
}
Jika Anda menyandingkan ini dengan strategi cadangan untuk mengirim preferensi ke cloud (juga dijelaskan dalam ceramah Reto , Anda harus memiliki id yang terkait dengan pengguna dan bertahan setelah perangkat dihapus, atau bahkan diganti. Saya berencana untuk menggunakan ini dalam analitik maju (dengan kata lain, saya belum melakukan itu sedikit :).
Anda juga dapat mempertimbangkan alamat MAC adaptor Wi-Fi. Diperoleh seperti ini:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Membutuhkan izin android.permission.ACCESS_WIFI_STATE
dalam manifes.
Dilaporkan akan tersedia bahkan ketika Wi-Fi tidak terhubung. Jika Joe dari jawaban di atas mencoba ini di banyak perangkatnya, itu akan menyenangkan.
Pada beberapa perangkat, itu tidak tersedia ketika Wi-Fi dimatikan.
CATATAN: Dari Android 6.x, ia mengembalikan alamat mac palsu yang konsisten:02:00:00:00:00:00
android.permission.ACCESS_WIFI_STATE
02:00:00:00:00:00
Ada info yang agak berguna di sini .
Ini mencakup lima jenis ID yang berbeda:
android.permission.READ_PHONE_STATE
)android.permission.ACCESS_WIFI_STATE
)android.permission.BLUETOOTH
)Blog Pengembang Android resmi sekarang memiliki artikel lengkap tentang subjek ini, Mengidentifikasi Instalasi Aplikasi .
Di Google I / O Reto Meier merilis jawaban yang kuat tentang cara melakukan pendekatan yang harus memenuhi sebagian besar pengembang untuk melacak pengguna di seluruh instalasi. Anthony Nolan menunjukkan arah dalam jawabannya, tetapi saya pikir saya akan menulis pendekatan lengkap sehingga orang lain dapat dengan mudah melihat bagaimana melakukannya (butuh beberapa saat untuk mengetahui detailnya).
Pendekatan ini akan memberi Anda ID pengguna anonim, aman yang akan bertahan untuk pengguna di berbagai perangkat (berdasarkan akun Google utama) dan di seluruh pemasangan. Pendekatan dasarnya adalah membuat ID pengguna acak dan menyimpannya di preferensi bersama aplikasi. Anda kemudian menggunakan agen cadangan Google untuk menyimpan preferensi bersama yang ditautkan ke akun Google di cloud.
Mari kita pergi melalui pendekatan penuh. Pertama, kita perlu membuat cadangan untuk SharedPreferences kita menggunakan Layanan Cadangan Android. Mulailah dengan mendaftarkan aplikasi Anda melalui http://developer.android.com/google/backup/signup.html
.
Google akan memberi Anda kunci layanan cadangan yang perlu Anda tambahkan ke manifes. Anda juga perlu memberi tahu aplikasi untuk menggunakan BackupAgent sebagai berikut:
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="your_backup_service_key" />
</application>
Maka Anda perlu membuat agen cadangan dan mengatakannya untuk menggunakan agen pembantu untuk preferensi bersama:
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);
}
}
Untuk menyelesaikan pencadangan, Anda perlu membuat instance dari BackupManager di Aktivitas utama Anda:
BackupManager backupManager = new BackupManager(context);
Terakhir buat ID pengguna, jika belum ada, dan simpan di SharedPreferences:
public static String getUserID(Context context) {
private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
if (uniqueID == null) {
SharedPreferences sharedPrefs = context.getSharedPreferences(
MyBackupAgent.PREFS, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
//backup the changes
BackupManager mBackupManager = new BackupManager(context);
mBackupManager.dataChanged();
}
}
return uniqueID;
}
User_ID ini sekarang akan tetap ada di seluruh instalasi, bahkan jika pengguna memindahkan perangkat.
Untuk informasi lebih lanjut tentang pendekatan ini lihat bicara Reto .
Dan untuk detail lengkap tentang cara menerapkan agen cadangan, lihat Cadangan Data . Saya terutama merekomendasikan bagian di bagian bawah pada pengujian karena cadangan tidak terjadi secara instan dan untuk menguji Anda harus memaksa cadangan.
Saya pikir ini pasti cara api membangun kerangka untuk ID unik ... coba lihat.
Pseudo-Unique ID, yang berfungsi di semua perangkat Android Beberapa perangkat tidak memiliki ponsel (mis. Tablet) atau karena alasan tertentu, Anda tidak ingin menyertakan izin READ_PHONE_STATE. Anda masih dapat membaca detail seperti Versi ROM, nama Pabrikan, tipe CPU, dan detail perangkat keras lainnya, yang cocok jika Anda ingin menggunakan ID untuk pemeriksaan kunci seri, atau tujuan umum lainnya. ID yang dihitung dengan cara ini tidak akan unik: adalah mungkin untuk menemukan dua perangkat dengan ID yang sama (berdasarkan pada perangkat keras dan gambar ROM yang sama) tetapi perubahan dalam aplikasi dunia nyata dapat diabaikan. Untuk tujuan ini, Anda dapat menggunakan kelas Build:
String m_szDevIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
Sebagian besar anggota Build adalah string, yang kami lakukan di sini adalah mengambil langkah panjang dan mengubahnya melalui modulo dalam digit. Kami memiliki 13 digit seperti itu dan kami menambahkan dua lagi di depan (35) untuk memiliki ID ukuran yang sama dengan IMEI (15 digit). Ada kemungkinan lain di sini baik-baik saja, lihat saja string ini. Mengembalikan sesuatu seperti 355715565309247
. Tidak diperlukan izin khusus, membuat pendekatan ini sangat nyaman.
(Info tambahan: Teknik yang diberikan di atas disalin dari artikel di Pocket Magic .)
Kode berikut mengembalikan nomor seri perangkat menggunakan API Android tersembunyi. Tetapi, kode ini tidak berfungsi pada Samsung Galaxy Tab karena "ro.serialno" tidak diset pada perangkat ini.
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) {
}
ro.serialno
digunakan untuk menghasilkan Settings.Secure.ANDROID_ID
. Jadi mereka pada dasarnya adalah representasi berbeda dari nilai yang sama.
ANDROID_ID
yang diturunkan darinya.
android.os.Build.SERIAL
android.os.Build.SERIAL
akan ditinggalkan di Android O, lihat android-developers.googleblog.com/2017/04/…
Ini pertanyaan sederhana, tanpa jawaban sederhana.
Terlebih lagi, semua jawaban yang ada di sini adalah ketinggalan zaman atau tidak dapat diandalkan.
Jadi, jika Anda mencari solusi pada tahun 2020 .
Berikut adalah beberapa hal yang perlu diingat:
Semua pengidentifikasi berbasis perangkat keras (SSAID, IMEI, MAC, dll) tidak dapat diandalkan untuk perangkat non-google (Semuanya kecuali Pixel dan Nexus), yang merupakan lebih dari 50% perangkat aktif di seluruh dunia. Oleh karena itu praktik terbaik pengidentifikasi Android resmi dengan jelas menyatakan:
Hindari menggunakan pengidentifikasi perangkat keras , seperti SSAID (Android ID), IMEI, alamat MAC, dll ...
Itu membuat sebagian besar jawaban di atas tidak valid. Juga karena pembaruan keamanan android yang berbeda, beberapa dari mereka memerlukan izin runtime yang lebih baru dan lebih ketat, yang dapat dengan mudah ditolak oleh pengguna.
Sebagai contoh CVE-2018-9489
yang mempengaruhi semua teknik berbasis WIFI yang disebutkan di atas.
Itu membuat pengidentifikasi tersebut tidak hanya tidak dapat diandalkan, tetapi juga tidak dapat diakses dalam banyak kasus.
Jadi dengan kata sederhana: jangan gunakan teknik itu .
Banyak jawaban lain di sini menyarankan untuk menggunakan AdvertisingIdClient
, yang juga tidak kompatibel, karena desainnya harus digunakan hanya untuk pembuatan profil iklan. Itu juga dinyatakan dalam referensi resmi
Hanya gunakan ID Iklan untuk pembuatan profil pengguna atau kasus penggunaan iklan
Ini tidak hanya tidak dapat diandalkan untuk identifikasi perangkat, tetapi Anda juga harus mengikuti privasi pengguna mengenai kebijakan pelacakan iklan , yang menyatakan dengan jelas bahwa pengguna dapat mengatur ulang atau memblokirnya kapan saja.
Jadi jangan gunakan itu juga .
Karena Anda tidak dapat memiliki pengidentifikasi perangkat statis yang diinginkan secara global unik dan andal. Referensi resmi Android menyarankan:
Gunakan FirebaseInstanceId atau GUID yang disimpan secara pribadi jika memungkinkan untuk semua kasus penggunaan lainnya, kecuali untuk pencegahan penipuan pembayaran dan telepon.
Ini unik untuk instalasi aplikasi pada perangkat, jadi ketika pengguna menghapus aplikasi - itu terhapus, sehingga tidak 100% dapat diandalkan, tetapi itu adalah hal terbaik berikutnya.
Untuk menggunakan FirebaseInstanceId
tambahkan dependensi firebase-messaging terbaru ke dalam gradle Anda
implementation 'com.google.firebase:firebase-messaging:20.2.0'
Dan gunakan kode di bawah ini di utas latar:
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
Jika Anda perlu menyimpan identifikasi perangkat di server jauh Anda, maka jangan menyimpannya seperti (teks biasa), tetapi hash dengan garam .
Hari ini bukan hanya praktik terbaik, Anda benar-benar harus melakukannya oleh hukum sesuai dengan GDPR - pengidentifikasi dan peraturan serupa.
Menggunakan kode di bawah ini, Anda bisa mendapatkan ID perangkat unik dari perangkat OS Android sebagai string.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Sebuah Serial lapangan telah ditambahkan ke Build
kelas dalam API level 9 (Android 2.3 - Gingerbread). Dokumentasi mengatakan itu mewakili nomor seri perangkat keras. Jadi itu harus unik, jika ada di perangkat.
Saya tidak tahu apakah itu benar-benar didukung (= bukan nol) oleh semua perangkat dengan level API> = 9.
Satu hal yang akan saya tambahkan - Saya punya satu dari situasi unik itu.
Menggunakan:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
Ternyata meskipun Tablet Viewsonic G saya melaporkan DeviceID yang bukan Null, setiap Tablet G melaporkan nomor yang sama.
Jadikan itu menarik dengan bermain "Pocket Empires" yang memberi Anda akses instan ke akun seseorang berdasarkan pada DeviceID "unik".
Perangkat saya tidak memiliki radio seluler.
9774d56d682e549c
?
Untuk instruksi terperinci tentang cara mendapatkan pengenal unik untuk setiap perangkat Android tempat aplikasi Anda terinstal, lihat posting Blog Pengembang Android resmi Mengidentifikasi Instalasi Aplikasi .
Tampaknya cara terbaik bagi Anda untuk membuat sendiri setelah instalasi dan kemudian membacanya ketika aplikasi diluncurkan kembali.
Saya pribadi menemukan ini dapat diterima tetapi tidak ideal. Tidak ada satu pun pengidentifikasi yang disediakan oleh Android yang berfungsi dalam semua keadaan karena sebagian besar tergantung pada kondisi radio ponsel (Wi-Fi on / off, seluler on / off, Bluetooth on / off). Yang lain, suka Settings.Secure.ANDROID_ID
harus diterapkan oleh pabrikan dan tidak dijamin unik.
Berikut ini adalah contoh penulisan data ke file instalasi yang akan disimpan bersama dengan data lain yang disimpan aplikasi secara lokal.
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();
}
}
Tambahkan kode di bawah ini dalam file kelas:
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);
Tambahkan di AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
TelephonyManager
dan ANDROID_ID
, diperoleh oleh: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);
}
Tetapi saya sangat merekomendasikan metode yang disarankan oleh Google, lihat Mengidentifikasi Instalasi Aplikasi .
Ada banyak pendekatan berbeda untuk mengatasi ANDROID_ID
masalah - masalah tersebut (mungkin null
kadang - kadang atau perangkat model tertentu selalu mengembalikan ID yang sama) dengan pro dan kontra:
Saya sendiri lebih suka menggunakan implementasi OpenUDID yang ada (lihat https://github.com/ylechelle/OpenUDID ) untuk Android (lihat https://github.com/vieux/OpenUDID ). Sangat mudah untuk diintegrasikan dan memanfaatkanANDROID_ID
fallback untuk masalah yang disebutkan di atas.
Bagaimana dengan IMEI . Itu unik untuk Android atau perangkat seluler lainnya.
Inilah cara saya menghasilkan id unik:
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;
}
Dua sen saya - NB ini untuk perangkat (err) ID unik - bukan instalasi seperti yang dibahas di blog pengembang Android .
Perlu dicatat bahwa solusi yang disediakan oleh @emmby jatuh kembali dalam per aplikasi ID sebagai SharedPreferences tidak disinkronkan di seluruh proses (lihat di sini dan di sini ). Jadi saya menghindari ini sama sekali.
Sebaliknya, saya merangkum berbagai strategi untuk mendapatkan ID (perangkat) dalam enum - mengubah urutan konstanta enum memengaruhi prioritas berbagai cara untuk mendapatkan ID. ID non-null pertama dikembalikan atau pengecualian dilemparkan (sesuai praktik Java yang baik untuk tidak memberikan arti nol). Jadi misalnya saya punya TELEPHONY yang pertama - tetapi pilihan default yang bagus adalah beta 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);
}
}
}
Ada 30+ jawaban di sini dan ada yang sama dan ada yang unik. Jawaban ini didasarkan pada beberapa jawaban itu. Salah satunya adalah jawaban @Lenn Dolling.
Ini menggabungkan 3 ID dan menciptakan string hex 32-digit. Ini bekerja sangat baik untuk saya.
3 ID adalah:
Pseudo-ID - Ini dibuat berdasarkan spesifikasi perangkat fisik
ANDROID_ID - Settings.Secure.ANDROID_ID
Alamat Bluetooth - Alamat adaptor Bluetooth
Ini akan mengembalikan sesuatu seperti ini: 551F27C060712A72730B0A0F734064B1
Catatan: Anda selalu dapat menambahkan lebih banyak ID ke longId
string. Misalnya, Serial #. alamat adaptor wifi. IMEI. Dengan cara ini Anda membuatnya lebih unik per perangkat.
@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 "";
}
longId
dan menyimpannya dalam file, akan membuatnya menjadi pengidentifikasi yang paling unik:String uuid = UUID.randomUUID().toString();
longId
. Ubah satu baris seperti ini: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString();
Ini menjamin bahwa ID yang dihasilkan akan unik.
Cara lain adalah menggunakan /sys/class/android_usb/android0/iSerial
aplikasi tanpa izin apa pun.
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
Untuk melakukan ini di Java, cukup gunakan FileInputStream untuk membuka file iSerial dan membacakan karakter. Pastikan Anda membungkusnya dengan penangan pengecualian, karena tidak semua perangkat memiliki file ini.
Setidaknya perangkat berikut diketahui memiliki file ini dapat dibaca dunia:
Anda juga dapat melihat posting blog saya Membocorkan nomor seri perangkat keras Android ke aplikasi yang tidak terjangkau di mana saya membahas file apa yang tersedia untuk informasi.
TelephonyManger.getDeviceId () Mengembalikan ID perangkat unik, misalnya, IMEI untuk GSM dan MEID atau ESN untuk telepon CDMA.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
Tetapi saya merekomendasikan untuk menggunakan:
Pengaturan. Aman.ANDROID_ID yang mengembalikan ID Android sebagai string hex 64-bit yang unik.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Terkadang TelephonyManger.getDeviceId () akan mengembalikan nol, jadi untuk memastikan id unik Anda akan menggunakan metode ini:
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;
}
Untuk pengenalan perangkat keras dari perangkat Android tertentu, Anda dapat memeriksa Alamat MAC.
Anda bisa melakukannya dengan cara itu:
di AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
sekarang dalam kode Anda:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
Di setiap perangkat Android, setidaknya penyihir Antarmuka "wlan0" adalah chip WI-FI. Kode ini berfungsi bahkan ketika WI-FI tidak dihidupkan.
PS Mereka adalah banyak Antarmuka lain yang akan Anda dapatkan dari daftar yang berisi MACS Tetapi ini dapat berubah di antara telepon.
Saya menggunakan kode berikut untuk mendapatkan IMEI
atau menggunakan Secure. ANDROID_ID
sebagai alternatif, ketika perangkat tidak memiliki kemampuan telepon:
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);
Lebih khusus lagi Settings.Secure.ANDROID_ID
,. Ini adalah jumlah 64-bit yang dihasilkan dan disimpan saat perangkat melakukan booting pertama kali. Di-reset ketika perangkat dihapus.
ANDROID_ID
tampaknya merupakan pilihan yang baik untuk pengidentifikasi perangkat unik. Ada kelemahan: Pertama, itu tidak 100% dapat diandalkan pada rilis Android sebelum 2.2 (“Froyo”).
Juga, telah ada setidaknya satu bug yang diamati secara luas di handset populer dari produsen utama, di mana setiap instance memiliki ANDROID_ID yang sama.
Untuk memahami Id Unik yang tersedia di perangkat Android. Gunakan panduan resmi ini.
Praktik terbaik untuk pengidentifikasi unik:
IMEI, Alamat Mac, ID Instans, GUID, SSAID, Id Iklan, API Jaring Pengaman untuk memverifikasi perangkat.
https://developer.android.com/training/articles/user-data-ids
ID Google Instance
Dirilis pada I / O 2015; di Android membutuhkan layanan bermain 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
Tampaknya Google bermaksud agar ID ini digunakan untuk mengidentifikasi instalasi di Android, Chrome, dan iOS.
Ini mengidentifikasi instalasi daripada perangkat, tetapi sekali lagi, ANDROID_ID (yang merupakan jawaban yang diterima) sekarang tidak lagi mengidentifikasi perangkat. Dengan runtime ARC, ANDROID_ID baru dihasilkan untuk setiap instalasi ( detail di sini ), sama seperti ID instance baru ini. Juga, saya pikir mengidentifikasi instalasi (bukan perangkat) adalah apa yang sebenarnya dicari oleh kebanyakan dari kita.
Keuntungan dari instance ID
Tampaknya bagi saya bahwa Google bermaksud untuk menggunakannya untuk tujuan ini (mengidentifikasi instalasi Anda), ini adalah lintas platform, dan dapat digunakan untuk sejumlah tujuan lain (lihat tautan di atas).
Jika Anda menggunakan GCM, pada akhirnya Anda harus menggunakan ID instance ini karena Anda memerlukannya untuk mendapatkan token GCM (yang menggantikan ID registrasi GCM lama).
Kerugian / masalah
Dalam implementasi saat ini (GPS 7.5) ID instance diambil dari server ketika aplikasi Anda memintanya. Ini berarti bahwa panggilan di atas adalah panggilan pemblokiran - dalam pengujian tidak ilmiah saya perlu 1-3 detik jika perangkat online, dan 0,5 - 1,0 detik jika offline (mungkin ini adalah berapa lama menunggu sebelum menyerah dan menghasilkan ID acak). Ini diuji di Amerika Utara pada Nexus 5 dengan Android 5.1.1 dan GPS 7.5.
Jika Anda menggunakan ID untuk tujuan yang mereka maksud - misalnya. otentikasi aplikasi, identifikasi aplikasi, GCM - Saya pikir ini 1-3 detik bisa menjadi gangguan (tergantung pada aplikasi Anda, tentu saja).
ANDROID_ID
pastikan untuk membaca jawaban ini dan bug ini .