Android основа: как определить уникальный идентификатор устройства Android

Это статья Повторно, оригинальная ссылка ниже. Если нарушение, удалить контакт.
ссылка

Here Вставка рисунка Описание
Уникальный идентификационный должны соответствовать две характеристики , уникальные для идеального позиционирования оборудования , чтобы решить эту проблему, но решение этой проблемы предназначен только ограничение близко к совершенству:
(1) Уникальность: идентификатор должен быть уникальным для всех устройств использовать приложение
(2 ) инвариантность: идентичность должна поддерживаться на том же устройстве

Направление: Используйте идентификации аппаратных средств

На самом деле будет требоваться идентификация аппаратных средств аппаратных средств производства для удовлетворения этих двух характеристик (до сих пор неопределенность искусственно), но которые были определены в приобретенной устойчивости, как правило, трудно, например, как использование идентификационного кода аппаратных средств, уникально идентифицирующий программу, которая может быть использована более узкий диапазон, не может быть использован в качестве глобальной программы.

1. DEVICE_ID

TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();

2. Использование ANDROID_ID

String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

3. MAC ADDRESS

Приобретая Mac-адрес в качестве Bluetooth или Wi-Fi уникальных идентификационного номера

wifiManager = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE));
String macAddress = wifiManager.getConnectionInfo().getMacAddress();

4. Используйте СЕРИЙНЫЙ НОМЕР

Для того, чтобы пройти через android.os.Build.SERIAL

5. Преимущества и недостатки идентификации аппаратных средств

Преимущества: почти идеальные для удовлетворения уникальности и неизменности

Недостатки:
Here Вставка рисунка Описание

II. UUID, используя два направления

Это официальный способ рекомендуется для создания уникального кода идентификации поколения, немного по-другому, официальная схема (где) есть приложение UUID генерируется из внутренней памяти, APP изменения тяжелой техники разгрузок вызывают происходить, мы на самом деле использовать их он может храниться на внешнем хранилище, если искусственно не будут удалены, повреждены, так что она также гарантируется неизменность, а его уникальность гарантируется UUID.

Принцип анализа UUID:
вики Пояснение: Универсально уникальный идентификатор (английский: Универсально уникальный идентификатор, аббревиатура: UUID) представляет собой информацию идентификации компьютерной системы ряда 128-битный идентификатор, а также связанные с ним термины: глобально уникальное идентификатор (GUID) , . Сформировано в соответствии со стандартными методами, а не полагаться на дозирования центрального механизма регистрации, то UUID является уникальным, в отличии от большинства других схем нумерации. Повторите UUID вероятность коды близка к нулю, ничтожны

组成: 8-4-4-4-12 xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx M表示 UUID 版本,数字 N的一至三个最高有效位表示 UUID 变体

UUID根据版本不同,依赖的组成有不同的变种,基于时间的UUID版本是通过计算当前时间戳、随机数和机器MAC地址得到 。UUID的核心算法保证了即使在多处理器同时生成的UUID重复性为0,因为他们所在的时间、空间(节点:通常是MAC地址)必然不一致。

由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。

String uniqueID = UUID.randomUUID().toString();

三. 趋于完美的方案

尽可能的获取硬件标识来满足两个特性,在有限制或其他因素的条件下,尽可能满足不变性,将UUID存储在外部环境来进行读写。

(1)方案思路
尽可能的获取硬件标识
硬件标识为空,进行UUID的生成、存储

(2)方案说明:
需要在使用之前拿到设备信息权限(没有会导致DeviceID不可取,但仍然可用),外部存储读写权限(必须,否则不可用)
最好在Application中使用,唯一标识在app与服务器直接交互很常用,放在全局统一的地方方便管理使用

还有一种方案是拿到设备的某些唯一信息,生成特定的UUID,这样保持不变就可以跳过存储,但是既然拿到了唯一信息,那为啥还要生成UUID呢?

public class UniqueIDUtils {

    private static final String TAG = "UniqueIDUtils";
    private static String uniqueID;
    private static String uniqueKey = "unique_id";
    private static String uniqueIDDirPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
    private static String uniqueIDFile = "unique.txt";


    public static String getUniqueID(Context context) {
        //三步读取:内存中,存储的SP表中,外部存储文件中
        if (!TextUtils.isEmpty(uniqueID)) {
            Log.e(TAG, "getUniqueID: 内存中获取" + uniqueID);
            return uniqueID;
        }
        uniqueID = PreferenceManager.getDefaultSharedPreferences(context).getString(uniqueKey, "");
        if (!TextUtils.isEmpty(uniqueID)) {
            Log.e(TAG, "getUniqueID: SP中获取" + uniqueID);
            return uniqueID;
        }
        readUniqueFile(context);
        if (!TextUtils.isEmpty(uniqueID)) {
            Log.e(TAG, "getUniqueID: 外部存储中获取" + uniqueID);
            return uniqueID;
        }
        //两步创建:硬件获取;自行生成与存储
        getDeviceID(context);
        getAndroidID(context);
        getSNID();
        createUniqueID(context);
        PreferenceManager.getDefaultSharedPreferences(context).edit().putString(uniqueKey, uniqueID);
        return uniqueID;
    }

    @SuppressLint("MissingPermission")
    private static void getDeviceID(Context context) {
        if (!TextUtils.isEmpty(uniqueID)) {
            return;
        }
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
            return;
        }
        String deviceId = null;
        try {
            deviceId = ((TelephonyManager) context.getSystemService(TELEPHONY_SERVICE)).getDeviceId();
            if (TextUtils.isEmpty(deviceId)) {
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        uniqueID = deviceId;
        Log.e(TAG, "getUniqueID: DeviceId获取成功" + uniqueID);
    }

    private static void getAndroidID(Context context) {
        if (!TextUtils.isEmpty(uniqueID)) {
            return;
        }
        String androidID = null;
        try {
            androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            if (TextUtils.isEmpty(androidID) || "9774d56d682e549c".equals(androidID)) {
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        uniqueID = androidID;
        Log.e(TAG, "getUniqueID: AndroidID获取成功" + uniqueID);
    }

    private static void getSNID() {
        if (!TextUtils.isEmpty(uniqueID)) {
            return;
        }
        String snID = Build.SERIAL;
        if (TextUtils.isEmpty(snID)) {
            return;
        }
        uniqueID = snID;
        Log.e(TAG, "getUniqueID: SNID获取成功" + uniqueID);
    }


    private static void createUniqueID(Context context) {
        if (!TextUtils.isEmpty(uniqueID)) {
            return;
        }
        uniqueID = UUID.randomUUID().toString();
        Log.e(TAG, "getUniqueID: UUID生成成功" + uniqueID);
        File filesDir = new File(uniqueIDDirPath + File.separator + context.getApplicationContext().getPackageName());
        if (!filesDir.exists()) {
            filesDir.mkdir();
        }
        File file = new File(filesDir, uniqueIDFile);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            outputStream.write(uniqueID.getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void readUniqueFile(Context context) {
        File filesDir = new File(uniqueIDDirPath + File.separator + context.getApplicationContext().getPackageName());
        File file = new File(filesDir, uniqueIDFile);
        if (file.exists()) {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(file);
                byte[] bytes = new byte[(int) file.length()];
                inputStream.read(bytes);
                uniqueID = new String(bytes);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void clearUniqueFile(Context context) {
        File filesDir = new File(uniqueIDDirPath + File.separator + context.getApplicationContext().getPackageName());
        deleteFile(filesDir);
    }

    private static void deleteFile(File file) {
        if (file.isDirectory()) {
            for (File listFile : file.listFiles()) {
                deleteFile(listFile);
            }
        } else {
            file.delete();
        }
    }
}

四.希望但又矛盾的完美方案

硬件标识既然对获取方关闭,那提供基于硬件标识生成的标识(类似UUID)暴露给获取方,但Android10上对于设备隐私的控制又明确了Google是不想app能够长久定位同一台设备的。不过如果基于硬件标识及app包名来生成的呢?

名词解释
Here Вставка рисунка Описание

Опубликовано 81 оригинальные статьи · вона похвала 37 · просмотров 50000 +

рекомендация

отblog.csdn.net/gaolh89/article/details/103987866