精华内容
下载资源
问答
  • 手机设备身份识别码之IMEI

    千次阅读 2018-11-14 08:25:27
    手机设备身份识别码之IMEI

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                    文章来源:http://baike.baidu.com/view/90099.htm 
    前言
      IMEI(International Mobile Equipment Identity)是国际移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的"电子 串号",它与每台手机一一对应,而且该码是全世界唯一的。每一只手机在组装完成后都将被赋予一个全球唯一的一组号码,这个号码从生产到交付使用都将被制造生产的厂商所记录。

    简介

      国际 移动设备识别码(IMEI:InternationalMobileEquipmentIdentificationNumber) 是区别移动设备的标志,储存在移动设备中,可用于监控被窃或无效的移动设备。IMEI组成如下图所示,移动终端设备通过键入“*#06#”即可查得。其总 长为15位,每位数字仅使用0~9的数字。其中TAC代表型号装配码,由欧洲型号标准中心分配;FAC代表装配厂家号码;SNR为产品序号,用于区别同一 个TAC和FAC中的每台移动设备;SP是备用编码。
      IMEI俗称“串号”存储在手机的EEPROM(俗称码片)里,熟悉并了解这个号码对我们今后 识别手机会起到非常大的作用。首先TAC码前三位在不同的时期会发生变化,过去的TAC码前三位在现在的手机上不会出现。过去的一些老型号的手机基本上都 是446/448开头,如moto v328 nokia 7110,而且即使同一部手机在不同的时期也会有不同的TAC码如大家最熟悉的8210升级8250,如果前三位是448902就不能升级,因为CPU不 同。因此过去所说的只要是同一型号的手机TAC码一定一样的说法是不够准确的,再如 爱立信的同一型号手机T39MC在不同地区的地方亦会有不同的号码:大陆行货为520406, 香港则为520407。我们知道这些区别后就可以通过TAC码来进行“设备识别”了,而不必去费心的去牢记IMEI的7.8位数字代表的产地。

    IMEI分配

      IMEI码由 GSM(全球移动通信协会)统一分配,授权BABT(英国通信认证管理委员会)审受
    手机身份识别码之IMEI - hubingforever - 民主与科学

    IMEI组成

       IMEI由15位数字组成,其组成为:
      1、前6位数(TAC)是"型号核准号码",一般代表机型。
    手机身份识别码之IMEI - hubingforever - 民主与科学

           2、接着的2位数(FAC)是"最后装配号",一般代表产地。                       
      3、之后的6位数(SNR)是"串号",一般代表生产顺序号。
      4、最后1位数(SP)通常是"0",为检验码,目前暂备用。
      IMEI码具有唯一性,贴在手机背面的标志上,并且读写于手机内存中。 它也是该手机在厂家的"档案"和"身份证号"。

    TAC

      TAC(设备型号核准号码)由 欧洲型 号认证中心分配。TAC码前三位在不同的时期会发生变化,过去的TAC码前三位在现在的手机上不会出现。过去的一些老型号的手机基本上都是446/448 开头,如moto v328 nokia 7110,而且即使同一部手机在不同的时期也会有不同的TAC码如大家最熟悉的8210升级8250,如果前三位是448902就不能升级,因为CPU不 同。因此过去所说的只要是同一型号的手机TAC码一定一样的说法是不够准确的,再如爱立信的同一型号手机T39MC在不同地区的地方亦会有不同的号码大陆 行货为520406香港则为520407。我们知道这些区别后就可以通过TAC码来进行“设备识别”了,而不必去费心的去牢记IMEI的7.8位数字代表 的产地。

    FAC

      FAC(工厂装配码)由厂家编码,通常表示生产厂家及其装配地。有时FAC也不能完全证明手机是否是行货,T68上市后热买一度造成缺货,因此爱立信代理商调集了一部分 马来西亚生产(FAC码71)紧急救援,因此这部分有入网许可证T68同样是“行货”。(前面我们我们说过了IMEI和取得入网许可证之间的联系)不过,需要指出的是这部分T68仅限于前期一部分软件版本为R1B的T68。 FAC
    手机身份识别码之IMEI - hubingforever - 民主与科学

    码 也不是一成不变的即使是同一产地的产品,如西门子3508I和MOTO C300因为其产量巨大已经从开始的37升级到40,而C300的行货FAC也有80/81/82。尤其重要的是欧洲型号认证中心今年重新分配了 IMEI,FAC被和TAC合并在一起,FAC码的数字统一从00开始,因此无论什么型号什么品牌其7,8位均是00、01、02或03这样向后编排。如 最新的C289,三星V200 、 西门子A55、 索尼爱立信T618都在手机上出现了351***00这样的IMEI。幸好我们有前面介绍过的TAC码鉴别办法,如T618的IMEI虽然过去的FAC现 在统一为00但港行和大陆行货TAC后三位上还是有差异的.港行为351253大陆T618为351254,其实这里已经说明了一个问题351253代表 的是T610(中
    手机身份识别码之IMEI - hubingforever - 民主与科学

    文繁体版)351254则为T618。而TAC码的真正含义正在于此--设备型号核准。
    SNR码
      SNR码即序号码,也由厂家分配。识别每个TAC和FAC中的某个设备的。每一
      部手机的SNR都不会一样.简单的说该号码可以说明手机出产日期的先后,通常数值越大说明该机 型出厂时间越晚,所以如果一部刚上市不久的手机的IMEI上出现了6位的数字你就得小心了,因为刚上市不久的手机其SNR最多不会超过四位,大家可以在购 机时留意一下。也许这可以作为鉴别手机是否被JS修改IMEI的好办法之一。

    SP备用码

      SP备用码,现在的SP基本上没有象过去文章所说那样“一般为0”了,其号码由厂家做设置,可忽略
      当然,有些手机在IMEI 上做了自己的定义.爱立信手机在待机时输入*#06#就会出现17位的IMEI,其最后两位的主要作用是用来识别软件版本。这里需要说明的是三星V200 也开始使用17位的IMEI了,最后两位的主要作用是用来识别软件版本,一般来说数值越低版本也越低,比如T618的R1A版本为02而R1F版本则为 03,最新的R1L版本是05。

    作用

      IMEI为TAC + FAC + SNR + SP。IMEI(International Mobile Equipment Identity)是国际
    手机身份识别码之IMEI - hubingforever - 民主与科学

    移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的"电子串号",它与每台手机一一对应,而且该码是全世界唯一的。每一只手机在组装完成后都将被赋予一个全球唯一的一组号码,这个号码从生产到交付使用都将被制造生产的厂商所记录。

    查看方法

      在手机上输入*#06# 输完这5个键符后, 手机屏幕上会出现一行阿拉伯数字,即为该手机的串号。
      以上说的使用方法为G网手机,C网手机用上述办法则无法查看。

    IMEI七八位含义

      SAMSUNG
      韩国----89,90,92
    手机身份识别码之IMEI - hubingforever - 民主与科学

    Panasonic
      北京----62
      SIEMENS D
      上海----37
      德国----51
      MOTOROLA
      天津----80,81,82,83
      德国----07,08,06(部分)
      新加坡----18
      英国----44
      香港, 东南亚改装机----47
       中国大陆改装机----48
      中国 杭州东信----92,93
      美国----67,68
      马来西亚----17
      苏格兰----40,41
      ERICSSON
      英国----19
      香港----61
      马来西亚----71
      爱沙尼亚----42
      南京----63
      瑞典----51
      NOKIA
      中国----40(北京),48,60( 东莞),62,80,81,92,93
      法国----06,07,08
      韩国----30 9
      新加坡----18
      德国----20
      芬兰----10,70
      美国----67,68
      英国----19,41,44
      ————————————————————————————————
      现在78位不是产地了,开始的1批肯定00或01的,09年上半年一般是02的,78位数根本不分哪产的,现在行货水货还是各种版本只要是最新的都03的,除了买了翻新的01或02的,现在6120CI都出04的(E63也出到04了)。
               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • Android设备唯一识别码的获取

    千次阅读 2020-02-14 13:46:34
    应用设备唯一识别码的解决方案 唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美 唯一性:标识必须在所有使用该应用的设备上保持唯一性 不变性:标识必须在同一...

    应用设备唯一识别码的解决方案
    设备唯一识别码.png
    唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美

    唯一性:标识必须在所有使用该应用的设备上保持唯一性
    不变性:标识必须在同一设备上保持不变
    方向一:使用硬件标识
    硬件标识实际上在硬件生产之时就被要求满足这两个特性(依然有人工生产的不确定性),但标识的获取趋于困难性,使得使用硬件标识作为唯一识别码的方案所能使用的范围越来越狭窄,不能作为全局方案使用。

    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
      通过获取蓝牙或wifi的Mac地址 作为唯一识别号

    wifiManager = ((WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE));
    String macAddress = wifiManager.getConnectionInfo().getMacAddress();
    4. 使用 SERIAL NUMBER
    通过 android.os.Build.SERIAL来获取

    1. 硬件标识的优势与局限性
      优势:几乎完美满足唯一性与不变性

    劣势:

    硬件标识 局限
    DEVICE_ID - 适用 Android9以下设备,但需要申请Manifest.permission.READ_PHONE_STATE权限

    • 非手机设备不能使用: 如果只带有Wifi的设备或者音乐播放器没有通话的硬件功能的话就没有这个DEVICE_ID
    • 有bug:在少数的一些手机设备上,该实现有漏洞,会返回垃圾,如:zeros或者asterisks的产品
    • Android 10 设备上即使授予权限也会报错Process: com.sj.d_1_adaptiveversion, PID: 8768 java.lang.SecurityException: getUniqueDeviceId: The user 10285 does not meet the requirements to access device identifiers.
      ANDROID_ID - 厂商定制系统的Bug: 不同的设备可能会产生相同的ANDROID_ID:9774d56d682e549c;有些设备返回的值为null;
      适配局限(基本不考虑):在Android <=2.1 or Android >=2.3的版本是可靠、稳定的,但在2.2的版本并不是100%可靠的
      设备差异(不考虑):对于CDMA设备,ANDROID_ID和TelephonyManager.getDeviceId() 返回相同的值
      MAC ADDRESS - 硬件限制:并不是所有的设备都有WiFi和蓝牙硬件
    • 获取的限制:如果WiFi没有打开过,是无法获取其Mac地址的;而蓝牙是只有在打开的时候才能获取到其Mac地址
    • Android 6.0(API 级别 23)到 Android 9(API 级别 28)中,无法通过第三方 API 使用 Wi-Fi 和蓝牙等本地设备 Mac 地址。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getDefaultAdapter().getAddress() 方法都返回 02:00:00:00:00:00。
      SERIAL NUMBER 经常会返回Unknown
      方向二 使用UUID
      这也是官方推荐的生成的唯一标识码生成方式,有一点不同的时,官方方案(在这里)将生成的UUID存在应用内部存储当中,APP的卸载重装会导致发生更改;在实际使用当中我们可以存储到外部存储,除非人为的删除、损坏,这样它的不变性也得到了保障,而它的唯一性则由UUID来保证。

    UUID的实现原理简析:
    Wiki解释:通用唯一识别码(英语:Universally Unique Identifier,缩写: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存储在外部环境来进行读写。

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

    方案说明:

    需要在使用之前拿到设备信息权限(没有会导致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包名来生成的呢?

    名词解释
    设备码缩写(全称) 定义
    IMEI(International Mobile Equipment Identity) 国际移动电话设备识别码:由15位数字组成的"电子串号",它与每台手机一一对应,而且该码是全世界唯一的
    UUID(Universally Unique Identifier) 全局唯一标识符:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得)
    MEID(Mobile Equipment IDentifier ) 是全球唯一的56bit CDMA制式移动终端标识号。标识号会被烧入终端里,并且不能被修改。可用来对CDMA制式移动式设备进行身份识别和跟踪
    IMEI是手机的身份证,MEID是CDMA制式(电信运营的)的专用身份证;IMEI是15位,MEID是14位
    DEVICE_ID Android系统为开发者提供的用于标识手机设备的串号 ; 它根据不同的手机设备返回IMEI,MEID或者ESN码 ;它返回的是设备的真实标识(因此Android10上更新的隐私保护上无法对它进行正常获取了)
    ANDROID_ID 在设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来 。 当设备被wipe后该值会被重置 (wipe:手机恢复出厂设置、刷机或其他类似操作)
    Serial Number SN码是Serial Number的缩写,有时也叫SerialNo,也就是产品序列号,产品序列是为了验证“产品的合法身份”而引入的一个概念,它是用来保障用户的正版权益,享受合法服务的;一套正版的产品只对应一组产品序列号。SN码别称:机器码、认证码、注册申请码等
    MAC ADDRESS 媒体访问控制地址,也称为局域网地址(LAN Address),以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的地址。 在OSI模型中,第三层网络层负责IP地址,第二层数据链接层则负责MAC地址。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。详细参考WIKI百科
    ESN码 (Electronic Serial Number ) 美国联邦通信委员会规定的,每一台移动设备(例如移动电话、智能手机、平板电脑等)独有的参数,其长度为32位
    ESN码一开始使用于AMPS和D-AMPS手机上,当前则于CDMA手机上最为常见;IMEI则最常使用在GSM制式的手机上

    展开全文
  • 手机IMEI真实数据修改

    2018-11-01 09:49:28
    手机IMEI 移动识别码 真实数据修改 可用于注册多个帐号
  • 本文介绍了如何确定Android设备唯一标识 方向一:使用硬件标识 方向二:使用UUID 方向三: 趋于完美的方案

    本文为转载文章,原文链接如下。如有侵权,联系后删除。
    链接

    在这里插入图片描述
    唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美:
    (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

    通过获取蓝牙或wifi的Mac地址 作为唯一识别号

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

    4. 使用 SERIAL NUMBER

    通过 android.os.Build.SERIAL来获取

    5. 硬件标识的优势与局限性

    优势:几乎完美满足唯一性与不变性

    劣势:
    在这里插入图片描述

    二. 方向二 使用UUID

    这也是官方推荐的生成的唯一标识码生成方式,有一点不同的时,官方方案(在这里)将生成的UUID存在应用内部存储当中,APP的卸载重装会导致发生更改;在实际使用当中我们可以存储到外部存储,除非人为的删除、损坏,这样它的不变性也得到了保障,而它的唯一性则由UUID来保证。

    UUID的实现原理简析:
    Wiki解释:通用唯一识别码(英语:Universally Unique Identifier,缩写: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包名来生成的呢?

    名词解释
    在这里插入图片描述

    展开全文
  • 如何确定Android设备唯一识别码

    千次阅读 2020-01-14 10:55:08
    文章目录应用设备唯一识别码的解决方案方向一:使用硬件标识1. 使用 DEVICE_ID2. 使用 ANDROID_ID3. 使用 MAC ADDRESS4. 使用 SERIAL NUMBER5. 硬件标识的优势与局限性方向二 使用UUID趋于完美的方案希望但又矛盾的...

    应用设备唯一识别码的解决方案

    在这里插入图片描述

    唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美

    • 唯一性:标识必须在所有使用该应用的设备上保持唯一性
    • 不变性:标识必须在同一设备上保持不变

    方向一:使用硬件标识

    硬件标识实际上在硬件生产之时就被要求满足这两个特性(依然有人工生产的不确定性),但标识的获取趋于困难性,使得使用硬件标识作为唯一识别码的方案所能使用的范围越来越狭窄,不能作为全局方案使用。

    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

    通过获取蓝牙或wifi的Mac地址 作为唯一识别号

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

    4. 使用 SERIAL NUMBER

    通过 android.os.Build.SERIAL来获取

    5. 硬件标识的优势与局限性

    优势:几乎完美满足唯一性与不变性

    劣势:

    硬件标识局限
    DEVICE_ID- 适用 Android9以下设备,但需要申请Manifest.permission.READ_PHONE_STATE权限
    - 非手机设备不能使用: 如果只带有Wifi的设备或者音乐播放器没有通话的硬件功能的话就没有这个DEVICE_ID
    - 有bug:在少数的一些手机设备上,该实现有漏洞,会返回垃圾,如:zeros或者asterisks的产品
    - Android 10 设备上即使授予权限也会报错Process: com.sj.d_1_adaptiveversion, PID: 8768 java.lang.SecurityException: getUniqueDeviceId: The user 10285 does not meet the requirements to access device identifiers.
    ANDROID_ID- 厂商定制系统的Bug: 不同的设备可能会产生相同的ANDROID_ID:9774d56d682e549c;有些设备返回的值为null;
    适配局限(基本不考虑):在Android <=2.1 or Android >=2.3的版本是可靠、稳定的,但在2.2的版本并不是100%可靠的
    设备差异(不考虑):对于CDMA设备,ANDROID_ID和TelephonyManager.getDeviceId() 返回相同的值
    MAC ADDRESS- 硬件限制:并不是所有的设备都有WiFi和蓝牙硬件
    - 获取的限制:如果WiFi没有打开过,是无法获取其Mac地址的;而蓝牙是只有在打开的时候才能获取到其Mac地址
    - Android 6.0(API 级别 23)到 Android 9(API 级别 28)中,无法通过第三方 API 使用 Wi-Fi 和蓝牙等本地设备 Mac 地址。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getDefaultAdapter().getAddress() 方法都返回 02:00:00:00:00:00
    SERIAL NUMBER经常会返回Unknown

    方向二 使用UUID

    这也是官方推荐的生成的唯一标识码生成方式,有一点不同的时,官方方案(在这里)将生成的UUID存在应用内部存储当中,APP的卸载重装会导致发生更改;在实际使用当中我们可以存储到外部存储,除非人为的删除、损坏,这样它的不变性也得到了保障,而它的唯一性则由UUID来保证。

    UUID的实现原理简析:
    Wiki解释:通用唯一识别码(英语:Universally Unique Identifier,缩写: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存储在外部环境来进行读写。

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

    方案说明:

    1. 需要在使用之前拿到设备信息权限(没有会导致DeviceID不可取,但仍然可用),外部存储读写权限(必须,否则不可用)
    2. 最好在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包名来生成的呢?

    名词解释

    设备码缩写(全称)定义
    IMEI(International Mobile Equipment Identity)国际移动电话设备识别码:由15位数字组成的"电子串号",它与每台手机一一对应,而且该码是全世界唯一的
    UUID(Universally Unique Identifier)全局唯一标识符:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得)
    MEID(Mobile Equipment IDentifier )是全球唯一的56bit CDMA制式移动终端标识号。标识号会被烧入终端里,并且不能被修改。可用来对CDMA制式移动式设备进行身份识别和跟踪
    IMEI是手机的身份证,MEID是CDMA制式(电信运营的)的专用身份证;IMEI是15位,MEID是14位
    DEVICE_IDAndroid系统为开发者提供的用于标识手机设备的串号 ; 它根据不同的手机设备返回IMEI,MEID或者ESN码 ;它返回的是设备的真实标识(因此Android10上更新的隐私保护上无法对它进行正常获取了)
    ANDROID_ID在设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来 。 当设备被wipe后该值会被重置 (wipe:手机恢复出厂设置、刷机或其他类似操作)
    Serial NumberSN码是Serial Number的缩写,有时也叫SerialNo,也就是产品序列号,产品序列是为了验证“产品的合法身份”而引入的一个概念,它是用来保障用户的正版权益,享受合法服务的;一套正版的产品只对应一组产品序列号。SN码别称:机器码、认证码、注册申请码等
    MAC ADDRESS媒体访问控制地址,也称为局域网地址(LAN Address),以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的地址。 在OSI模型中,第三层网络层负责IP地址,第二层数据链接层则负责MAC地址。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。详细参考WIKI百科
    ESN码 (Electronic Serial Number )美国联邦通信委员会规定的,每一台移动设备(例如移动电话、智能手机、平板电脑等)独有的参数,其长度为32位
    ESN码一开始使用于AMPS和D-AMPS手机上,当前则于CDMA手机上最为常见;IMEI则最常使用在GSM制式的手机上
    展开全文
  • 如何获取Android设备唯一识别码

    千次阅读 2015-05-04 11:17:18
    如何获取Android设备唯一识别码? 如果我们想唯一识别一台...IMEI (International Mobile Equipment Identity Number,国际移动设备识别码) 用于在手机网络中识别每一部独立的手机对于不在手机网络的设备(如And
  • 识别用户访问客户端唯一性是必要的实现,对于web前端获取的设备信息,一般容易想到的是通过navigator.userAgent,但相同设备及浏览器ua就相同了,故ua的辨识度很低,那么web前端识别浏览器设备唯一性是否有其他好...
  • 应用设备唯一识别码的解决方案 设备唯一识别码.png 唯一标识必须满足两个特性才能完美解决定位唯一设备的问题,但这个问题的解决却注定只能极限接近完美 唯一性:标识必须在所有使用该应用的设备上保持唯一性 ...
  • (International Mobile Equipment Identity) 是国际移动设备身份的缩写,国际移动装备辨识,只有Android手机才获取的到,是由15位数字组成的"电子串号",比如像这样 359881030314356,它与每台移动电话机一一...
  • ==苹果手机imei修改器篇一:修改手机串号IMEI2标题:修改手机串号IMEI你如果想能一键修改手机的各种信息比如串号IMEI,定位,联网方式,WIFI信息,MAC地址,驱动ID,手机硬件,安卓ID,屏幕等等信息,用下面的...
  • IMEI:国际移动设备识别码 (International Mobile Equipment Identity)。 由15位数字组成,全球唯一ID,用来区别每一部移动通信设备。与手机是绑定关系。 第一部分 TAC,Type Allocation Code,类型分配码。86为...
  • 最近在项目中遇到一个需求:app需要获取用户手机的唯一识别码然后上传到后台。在此我使用了react-native-device-info 插件,从名字可以看出这个插件的作用是获取设备的信息。使用react-native-device-info 安装简单...
  • iPhone xs max源码 网上很多人都来倒卖赚钱 一款不需要苹果手机越狱的 又可以让苹果手机修改机型的一款源代码
  • 如何获取Android设备唯一标识教程

    千次阅读 2020-12-18 20:37:54
    ID是表示着标签的身份,在JS脚本中会用到id,当JS要修改一个标签的属性时,JS会将id名作为该标签的唯一标识进行操作。也就是说ID只是页面元素的标识,供其他元素脚本等引用。概述有时需要对用户设备进行...
  • 使用Xposed框架修改手机imei的Demo; 控制端通过一个按钮,动态修改指定app的imei,内部使用ContentProvider进行进程间通信.
  • 这个是由于移动运营商没有把手机号码的数据写入到sim卡中.SIM卡只有唯一的编号,供网络与设备识别那就是IMSI号码,手机的信号也可以说是通过这个号码在网络中传递的,并不是手机号码。试想,你的SIM丢失后,补办一张...
  • 手机底部壳上查看imei方式2.我的设备中查看步骤一、首先打开手机后,在手机桌面上找到“设置”按钮,点击进入手机设置页面。步骤二、在手机设置界面中,找到“我的设备”选项,点进去。步骤三、在我的设备界面中,...
  • 前言:设备登陆时提供设备序列号信息传到后端,安卓设备日新月异,一些设备仅支持...1.DEVICE_ID,不同的手机设备返回IMEI,MEID或者ESN; DEVICE_ID可以通过下面的方法获取: TelephonyManager tm = (Telephon...
  • 虽然Android系统中提供了这样设备识别码,但是由于Android系统版本、厂商定制系统中的Bug等限制,稳定性和唯一性并不理想。而通过其他硬件信息标识也因为系统版本、手机硬件等限制存在不同程度的问题。 下面汇总了...
  • IMSI国际移动用户识别码(IMSI) international mobile subscriber identity  全称为 International Mobile Subscriber Identity,中文翻译为国际移动用户识别码。它是在公众陆地移动电话
  • 应用程序可以获取我们这些参数来判断我们手机的唯一性,由此我们可以通过修改androidid或者imei等参数,让手机变成一个新的设备。我们这里使用强大的琢石模拟器来帮我们虚拟androidid,达到模拟的效果,他不会真的...
  • android10 获得设备唯一标识

    千次阅读 2020-05-18 10:48:02
    ANDROID_ID(恢复出厂+刷机...特点: 如果格式化或者刷机,这个设备ID会更改(这个也是合理的)。 完善:可以在第一次生成后放入到内部存储和外部存储,下次进入先从内部存储获取,如果没有在去外部存储比较(App卸载,
  • 下面我从安卓开发的角度,简单写一下如何获取手机设备信息和手机号码 准备条件:一部安卓手机、手机SIM卡确保插入手机里、eclipse ADT和Android-sdk开发环境 第一步:新建一个android工程(JinshanTest)...
  • 如何获取手机设备信息和手机号码

    千次阅读 2016-07-12 16:28:14
    下面我从安卓开发的角度,简单写一下如何获取手机设备信息和手机号码 准备条件:一部安卓手机、手机SIM卡确保插入手机里、eclipse ADT和Android-sdk开发环境 第一步:新建一个android工程(JinshanTest), ...
  • 移动设备手机)的唯一ID有哪些

    千次阅读 2018-07-30 20:21:40
    移动设备手机)的唯一ID有哪些 在移动广告领域,设备的ID 是用来追踪一个人的最重要的标识。 对于APP自身产品而言,使用设备唯一ID可以追踪到用户从下载到激活、注册、使用、流失、回归的全流程数据,对产品运营...
  • 最近在做一个OA考勤项目,里面有个需求是一个账号只允许绑定一台设备, 这就需要将设备唯一标识与账号绑定在一起,咋一听 这还不So Easy啊,直接获取deviceID 不就好了。。。 问题 private String getSerial() { ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,563
精华内容 9,025
关键字:

修改手机设备识别码