Pertanyaan Apakah ada ID perangkat Android unik?


Apakah perangkat Android memiliki ID unik, dan jika ya, apa cara mudah untuk mengaksesnya menggunakan Java?


2309
2018-05-07 00:47


asal


Jawaban:


Settings.Secure#ANDROID_ID mengembalikan ID Android sebagai unik untuk setiap pengguna String hex 64-bit.

import android.provider.Settings.Secure;

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

1697
2018-05-07 00:49



MEMPERBARUI: Seperti Android versi terbaru, banyak masalah dengan ANDROID_ID telah diselesaikan, dan saya yakin pendekatan ini tidak lagi diperlukan. Silakan dilihat 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 Blog Pengembang Android masukkan itu Jawaban emmby tautan ke (yaitu, menghasilkan dan menyimpan UUID#randomUUID()).


Ada banyak jawaban untuk pertanyaan ini, yang sebagian besar hanya akan berfungsi "beberapa" waktu, dan sayangnya itu tidak cukup baik.

Berdasarkan pengujian perangkat saya (semua ponsel, setidaknya salah satunya tidak diaktifkan):

  1. Semua perangkat yang diuji mengembalikan nilai untuk TelephonyManager.getDeviceId()
  2. Semua perangkat GSM (semua diuji dengan SIM) mengembalikan nilai untuk TelephonyManager.getSimSerialNumber()
  3. Semua perangkat CDMA mengembalikan null untuk getSimSerialNumber() (seperti yang diharapkan)
  4. Semua perangkat dengan akun Google menambahkan mengembalikan nilai untuk ANDROID_ID
  5. Semua perangkat CDMA mengembalikan nilai yang sama (atau derivasi dari nilai yang sama) untuk keduanya ANDROID_ID dan TelephonyManager.getDeviceId() - selama akun Google telah ditambahkan selama pengaturan.
  6. Saya belum memiliki kesempatan untuk menguji perangkat GSM tanpa SIM, perangkat GSM tanpa akun Google yang ditambahkan, atau salah satu perangkat dalam mode pesawat.

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 tersebut masih benar-benar unik untuk perangkat, tetapi tidak secara eksplisit mengidentifikasi perangkat aktual 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 bekerja dengan cukup baik untuk saya.

Seperti yang Richard sebutkan 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" />

mengimpor libs

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

1056
2018-05-17 22:12



Terakhir Diperbarui: 6/2/15


Setelah membaca setiap posting Stack Overflow tentang membuat ID unik, blog pengembang Google dan dokumentasi Android, saya merasa seolah-olah 'Pseudo ID' adalah opsi terbaik yang memungkinkan.

Masalah Utama: Perangkat Lunak vs Perangkat Lunak

Perangkat keras

  • Pengguna dapat mengubah perangkat keras, tablet atau ponsel Android mereka, jadi ID unik berdasarkan perangkat keras bukanlah ide yang baik PENGGUNA TRACKING
  • Untuk TRACKING HARDWAREIni ide yang bagus

Perangkat lunak

  • Pengguna dapat menghapus / mengubah ROM mereka jika mereka di-root
  • Anda dapat melacak pengguna di seluruh platform (iOS, Android, Windows, dan Web)
  • Keinginan terbaik untuk TRACK PENGGUNA INDIVIDU dengan milik mereka persetujuan adalah meminta mereka untuk masuk (menjadikannya mulus menggunakan OAuth)

Kerusakan keseluruhan dengan Android

- Garansi keunikan (termasuk perangkat yang di-rooting) untuk API> = 9/10 (99,5% perangkat Android)

- Tidak ada izin ekstra

Kode psuedo:

if API >= 9/10: (99.5% of devices)

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

else

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

Terima kasih kepada @stansult untuk posting semua pilihan kami (dalam pertanyaan Stack Overflow ini).

Daftar opsi - alasan mengapa / mengapa tidak menggunakannya:

  • Email Pengguna - Perangkat Lunak

    • Pengguna dapat mengubah email - SANGAT tidak mungkin
    • API 5+ <uses-permission android:name="android.permission.GET_ACCOUNTS" /> atau
    • API 14+ <uses-permission android:name="android.permission.READ_PROFILE" />  <uses-permission android:name="android.permission.READ_CONTACTS" /> (Cara mendapatkan alamat e-mail utama perangkat Android)
  • Nomor Telepon Pengguna - Perangkat Lunak

    • Pengguna dapat mengubah nomor telepon - SANGAT tidak mungkin
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • IMEI - Hardware (hanya telepon, kebutuhan android.permission.READ_PHONE_STATE)

    • Sebagian besar pengguna membenci fakta bahwa ia mengatakan "Panggilan Telepon" dalam izin. Beberapa pengguna memberikan peringkat buruk, karena mereka yakin Anda hanya mencuri informasi pribadi mereka, padahal yang benar-benar Anda inginkan adalah melacak pemasangan perangkat. Jelas bahwa Anda mengumpulkan data.
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • ID Android - Perangkat Keras (bisa nihil, bisa berubah saat reset pabrik, bisa diubah pada perangkat yang di-root)

    • Karena dapat 'null', kita dapat memeriksa 'null' dan mengubah nilainya, tetapi ini berarti tidak akan menjadi unik lagi.
    • Jika Anda memiliki pengguna dengan perangkat penyetelan ulang pabrik, nilainya mungkin telah berubah atau diubah pada perangkat yang di-rooting sehingga mungkin ada entri duplikat jika Anda melacak pemasangan pengguna.
  • Alamat MAC WLAN - Hardware (kebutuhan android.permission.ACCESS_WIFI_STATE)

    • Ini bisa menjadi opsi terbaik kedua, tetapi Anda masih mengumpulkan dan menyimpan pengenal unik yang berasal langsung dari pengguna. Ini jelas bahwa Anda mengumpulkan data.
    • <uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
  • Bluetooth MAC Address - Hardware (perangkat dengan Bluetooth, kebutuhan android.permission.BLUETOOTH)

    • Sebagian besar aplikasi di pasar tidak menggunakan Bluetooth, dan jadi jika aplikasi Anda tidak menggunakan Bluetooth dan Anda termasuk ini, pengguna bisa menjadi curiga.
    • <uses-permission android:name="android.permission.BLUETOOTH "/>
  • ID Pseudo-Unik - Perangkat Lunak (untuk semua perangkat Android)

    • Sangat mungkin, mungkin berisi tabrakan - Lihat metode saya diposting di bawah ini!
    • Ini memungkinkan Anda memiliki ID 'hampir unik' dari pengguna tanpa mengambil apa pun yang bersifat pribadi. Anda dapat membuat Anda memiliki ID anonim dari informasi perangkat.

Saya tahu tidak ada cara 'sempurna' untuk mendapatkan ID unik tanpa menggunakan izin; Namun, terkadang kami hanya benar-benar perlu melacak instalasi perangkat. Ketika datang untuk membuat ID unik, kita dapat membuat 'pseudo unique id' hanya berdasarkan informasi yang diberikan API Android kepada kami tanpa menggunakan izin tambahan. Dengan cara ini, kita dapat menunjukkan rasa hormat kepada pengguna dan mencoba untuk menawarkan pengalaman pengguna yang baik juga.

Dengan pseudo-unique id, Anda benar-benar hanya menemukan fakta bahwa mungkin ada duplikat berdasarkan fakta bahwa ada perangkat serupa. Anda dapat menyesuaikan metode gabungan untuk membuatnya lebih unik; namun, beberapa pengembang perlu melacak pemasangan perangkat dan ini akan melakukan trik atau kinerja berdasarkan perangkat yang serupa.

API> = 9:

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 dapat fokus pada yang lain: Ini adalah 99,5% dari pengguna!

API <9:

Jika perangkat Android pengguna lebih rendah dari API 9; mudah-mudahan, 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 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 'null', maka hanya ID yang dikembalikan akan sepenuhnya berdasarkan informasi perangkat Android mereka. Di sinilah tabrakan bisa terjadi.

Perubahan:

  • Menghapus 'Android.SECURE_ID' karena pengaturan ulang pabrik dapat menyebabkan nilai berubah
  • Diedit kode untuk mengubah pada API
  • Mengubah Pseudo

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

Baru (untuk aplikasi dengan iklan DAN Layanan Google Play):

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   pengganti pengenal tetap lainnya untuk tujuan periklanan apa pun.   Belajarlah lagi

Pelaksanaan:

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

Penting:

Ini dimaksudkan agar ID iklan sepenuhnya menggantikan yang ada   penggunaan pengenal lain untuk tujuan iklan (seperti penggunaan ANDROID_ID   di Settings.Secure) ketika Layanan Google Play tersedia. Kasus   di mana Layanan Google Play tidak tersedia ditunjukkan oleh   GooglePlayServicesNotAvailableException dilemparkan oleh   getAdvertisingIdInfo ().

Peringatan, pengguna dapat mengatur ulang:

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

Saya telah mencoba mereferensikan setiap tautan yang saya ambil informasinya. Jika Anda hilang dan perlu dimasukkan, silakan komentar!

Google Player Services InstanceID

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


364
2017-07-12 23:58



Seperti disebutkan Dave Webb, the Blog Pengembang Android memiliki artikel yang menutupi ini. Solusi yang mereka sukai 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 membuat pekerjaan itu, dan saya sarankan Anda memeriksanya.

Namun, pos blog melanjutkan untuk membahas solusi jika Anda memerlukan pengenal perangkat daripada pengenal pemasangan aplikasi. Saya berbicara dengan seseorang di Google untuk mendapatkan klarifikasi tambahan tentang beberapa item jika Anda perlu melakukannya. Inilah yang saya temukan tentang pengenal perangkat yang TIDAK disebutkan dalam posting blog yang disebutkan di atas:

  • ANDROID_ID adalah pengenal perangkat yang disukai. ANDROID_ID sangat andal pada versi Android <= 2.1 atau> = 2.3. Hanya 2,2 memiliki masalah yang disebutkan dalam posting.
  • Beberapa perangkat oleh beberapa produsen dipengaruhi oleh bug ANDROID_ID di 2.2.
  • Sejauh yang saya bisa tentukan, semua perangkat yang terpengaruh ANDROID_ID yang sama, yang mana 9774d56d682e549c. Yang juga merupakan id perangkat yang sama yang dilaporkan oleh emulator, btw.
  • Google percaya bahwa OEM telah memperbaiki masalah untuk sebagian besar atau sebagian besar perangkat mereka, tetapi saya dapat memverifikasi bahwa mulai awal April 2011, setidaknya, masih cukup mudah untuk menemukan perangkat yang rusak ANDROID_ID.

Berdasarkan rekomendasi Google, saya menerapkan kelas yang akan menghasilkan UUID unik untuk masing-masing perangkat, menggunakan ANDROID_ID sebagai benih yang sesuai, jatuh kembali pada TelephonyManager.getDeviceId () seperlunya, dan jika itu gagal, beralih ke UUID unik yang dihasilkan secara acak yang tetap ada di aplikasi dimulai ulang (tetapi tidak menginstal ulang aplikasi).

Perhatikan bahwa untuk perangkat yang harus mundur pada ID perangkat, ID unik AKAN bertahan di seluruh pengaturan ulang 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 mundur kembali secara langsung ke UUID acak alih-alih ID perangkat.

Sekali lagi, kode ini adalah untuk ID perangkat, bukan ID pemasangan aplikasi. Untuk sebagian besar situasi, ID pemasangan aplikasi mungkin yang Anda cari. Tetapi jika Anda memang 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;
    }
}

314
2018-04-11 19:06



Berikut adalah kode yang digunakan Reto Meier dalam Google I / O presentasi tahun ini untuk mendapatkan id unik untuk 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 memasangkan ini dengan strategi cadangan untuk mengirim preferensi ke cloud (juga dijelaskan dalam Reto berbicara, Anda harus memiliki id yang terkait dengan pengguna dan tetap ada setelah perangkat dihapus, atau bahkan diganti. Saya berencana untuk menggunakan ini dalam analisis maju (dengan kata lain, saya belum melakukan itu sedikit :).


165
2017-10-28 13:19



Anda juga dapat mempertimbangkan alamat MAC adaptor Wi-Fi. Diperoleh dengan demikian:

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

Membutuhkan izin android.permission.ACCESS_WIFI_STATE di manifes.

Dilaporkan akan tersedia bahkan ketika Wi-Fi tidak terhubung. Jika Joe dari jawaban di atas memberi yang ini coba di banyak perangkatnya, itu bagus.

Di 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


97
2018-06-23 14:27



Ada info yang agak berguna sini.

Ini mencakup lima jenis ID yang berbeda:

  1. IMEI (hanya untuk perangkat Android dengan penggunaan Telepon; kebutuhan android.permission.READ_PHONE_STATE)
  2. ID Unik Palsu (untuk semua perangkat Android)
  3. ID Android (bisa nihil, bisa berubah saat reset pabrik, bisa diubah pada ponsel yang di-rooting)
  4. Alamat MAC WLAN string (kebutuhan android.permission.ACCESS_WIFI_STATE)
  5. Alamat MAC BT string (perangkat dengan Bluetooth, kebutuhan android.permission.BLUETOOTH)

78
2018-02-08 02:16



Blog Pengembang Android resmi kini memiliki artikel lengkap tentang subjek ini, Mengidentifikasi Instalasi Aplikasi.


43
2018-04-06 07:36