2022 latest mobile device identification code (IMEI, MEID, UDID, UUID, ANDROID_ID, GAID, IDFA, etc.) tutorial

Android articles

 

1 IMEI and MEID

(1) IMEI

(International Mobile Equipment Identity) is the abbreviation of the International Mobile Equipment Identity Code, the International Mobile Equipment Identification Code, which can only be obtained by Android phones. There is a one-to-one correspondence between mobile phones, and the code is unique in the world.

It is returned by the GSM device and is written on the motherboard. Reinstalling the APP will not change the IMEI.

2. US

(Mobile Equipment Identifier) ​​The mobile equipment identification code is the identification code of the CDMA mobile phone, and it is also the unique identification code of each CDMA mobile phone or communication tablet.

summary

IMEI is the logo of China Unicom and China Mobile, and MEID is the logo of China Telecom mobile phone

3. How to get IMEI and MEID

Add permissions

<!-- Allow programs to read and write mobile phone status and identity -->

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

java code

//实例化TelephonyManager对象

TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

Method method = telephonyManager.getClass().getMethod("getDeviceId", int.class);

//获取IMEI号

String imei1 = manager.getDeviceId();

String imei2 = (String) method.invoke(manager, 1);

//获取MEID号

String meid = (String) method.invoke(telephonyManager, 2);

某些没有电话功能的平板是获取不到IMEI和IMSI号的。且在某些设备上getDeviceId()会返回垃圾数据

Android Q(10)版本之后禁止使用



2 DeviceId

又叫设备ID。可以用系统提供的TelephonyManager服务来获取,具有唯一性。其中又包括IMEI 和 MEID/ESN。

一般情况我们获取手机的DeviceId也就是手机的IMEI码



private String getDeviceId() {

    TelephonyManager tm = (TelephonyManager) getContext().getSystemService(Service.TELEPHONY_SERVICE);

    return tm.getDeviceId();

}

一个双卡手机不止一个IMEI值,全网通双卡手机有两个IMEI和一个MEID

Android Q(10)版本之后禁止使用

网上有个通过硬件信息拼凑出来的15位号码的方法



public static String getDeviceId()

{

    String serial = null;



    String m_szDevIDShort = "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; //13 位



    try

    {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)

        {

            serial = android.os.Build.getSerial();

        }

        else

        {

            serial = Build.SERIAL;

        }

        //API>=9 使用serial号

        return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();

    }

    catch (Exception exception)

    {

        //serial需要一个初始化

        serial = "serial"; // 随便一个初始化

    }

    

    //使用硬件信息拼凑出来的15位号码

    return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();

}



3 mac地址

硬件标识符,包括WiFi mac地址和蓝牙mac地址。



WifiManager wifiManager=(WifiManager)getSystemService(Context.WIFI_SERVICE);

WifiInfowifiInfo=wifiManager.getConnectionInfo();

String mac=wifiInfo.getMacAddress();

在Android 6.0系统上,这个方法失效了,返回 “02:00:00:00:00:00” 的常量,并被判定为有害应用

另,使用Android模拟器可以很方便的修改mac地址:







4 ANDROID_ID

ANDROID_ID是设备首次启动时由系统随机生成的一串64位的十六进制数字



String ANDROID_ID = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);

1

ANDROID_ID缺点:



①.设备刷机wipe数据或恢复出厂设置时ANDROID_ID值会被重置。



②.现在网上已有修改设备ANDROID_ID值的APP应用。



③.某些厂商定制的系统可能会导致不同的设备产生相同的ANDROID_ID。



④.某些厂商定制的系统可能导致设备返回ANDROID_ID值为空。



⑤.CDMA设备,ANDROID_ID和DeviceId返回的值相同



5 UUID

(Universally Unique Identifier) 通用唯一识别码,APP重装后会改变。



6 OpenUDID

(Open Unique Device Identifier) 设备唯一标识符。APP重装,值也不变,除非root手机(普通用户做不到)

在AndroidManifest.xml中添加



<service android:name=”org.openudid.OpenUDID_service”>

<intent-filter>

<action android:name=”org.openudid.GETUDID” />

</intent-filter>

</service>

获取OpenUDID的方法



public class UDID

{

    public static UDID getInstance()

    {

        return new UDID();

    }



    public String getUDID(Context context)

    {

        String UDID = "";

        OpenUDID_manager.sync(context);

        boolean isInitialized = OpenUDID_manager.isInitialized();

        if (isInitialized)

        {

            UDID = "Android"+ OpenUDID_manager.getOpenUDID();

        }

        return UDID;

    }

}

另一个通过DeviceId、ANDROID_ID和uuid来构造UDID的方法



protected static String uuid;

/**

 * 获取唯一标识码

 * 1、正常情况下可以通过((TelephonyManager) s_instance.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();  来获取,但是某些平板电脑此函数会返回空

 * 2、通过 Secure.getString(s_instance.getContentResolver(), Secure.ANDROID_ID);   也可以获取到一个id,但是android2.2或者是某些山寨手机使用这个也是有问题的,它会返回一个固定的值 9774d56d682e549c

 * 3、如果前两个都没有获取到udid,那么就在程序启动的时候创建一个随机的uuid,然后保存起来。这个算是兼容方案,当然这样的设备并不会很多。

 */

public synchronized static String getUDID(Context mContext)

{

    if( uuid ==null )

    {

        if( uuid == null)

        {

            final SharedPreferences prefs = mContext.getApplicationContext().getSharedPreferences( PREFS_FILE, Context.MODE_PRIVATE);

            final String id = prefs.getString(PREFS_DEVICE_ID, null );

            

            if (id != null)

            {

                // Use the ids previously computed and stored in the prefs file

                uuid = id;

            }

            else

            {

                final String androidId = Settings.Secure.getString(mContext.getContentResolver(), Settings.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")).toString();

                    }

                    else

                    {

                        final String deviceId = ((TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

                        uuid = deviceId!=null ? UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")).toString() : UUID.randomUUID().toString();

                    }

                }

                catch (UnsupportedEncodingException e)

                {

                    throw new RuntimeException(e);

                }

            

                // Write the value out to the prefs file

                prefs.edit().putString(PREFS_DEVICE_ID, uuid).commit();

            }

        }

    }

    return uuid;

}

7 Serial Number

设备序列号。

获取办法:



String serialNum = android.os.Build.SERIAL;

1

装有SIM卡的设备获取办法:



getSystemService(Context.TELEPHONY_SERVIEC).getSimSerialNumber();

1

注意对CDMA设备,返回的是一个空值。

在Android 2.3可以通过android.os.Build.SERIAL获取,非手机设备可以通过该接口获取。

在少数的一些设备上,会返回垃圾数据。对于没有通话功能的设备,它可能会返回一个固定的值。



8 IDFA

2014年Android2.3基于Google Play推出了IDFA,功能同IOS的IDFA一样,允许用户重置或禁用该ID,由用户决定是否愿意被追踪。

但是在中国发行的国行手机由于某些原因,google地图、Play等基础App被阉割掉了,这样导致在中国国行手机中都获取不到该IDFA。(除非用户自行Root并安装google Play)



9 GAID

在装了google play service的安卓手机上,才可以获取到GAID

广告id是用户特殊的,独特的,可重置的广告id,由Google Play Service提供,它为用户更好的控制,为开发人员提供简单、标准的系统继续使用你的应用程序,它用于广告目的的匿名标示符和或者重置起标示符或者退出以利益为基础的Google Play的医用程序。

广告ID可以通过简单的API在你的应用程序中实现。

(1) 获取Google Play Service SDK

从下载好的Android SDK的 Extras目录下找 library 下面的google-play-service.jar

(2) 接口

广告ID的API可在com.google.android.gms.ads.identifier包在Google Play Service的的库中。获得用户的广告ID和跟踪偏好,调用方法getadvertisingidinfo(),它返回一个advertisingidclient信息封装。用户当前的广告ID和跟踪偏好。




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

    {

        // Unrecoverable error connecting to Google Play services (e.g.,

        // the old version of the service doesn't support getting AdvertisingId).



    }

    catch(GooglePlayServicesAvailabilityException e)

    {

        // Encountered a recoverable error connecting to Google Play services.

    }

    catch(GooglePlayServicesNotAvailableException e)

    {

        // Google Play services is not available entirely.

    }

    final String id = adInfo.getId();

    final boolean isLAT = adInfo.isLimitAdTrackingEnabled();



}



iOS篇

1 IMEI

iOS 5 之后被禁止。写在主板上,重装APP不会改变。

示例:351710058880864



2 IDFA

广告标示符,于iOS 6 时面世,在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,同时保证用户设备不被APP追踪的折中方案。可能发生变化,如系统重置、在设置里还原广告标识符。用户可以在设置里打开“限制广告跟踪”。



#import <AdSupport/AdSupport.h>

NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

1

2

有几种情况下,会重新生成广告标示符:

(1) 如果用户完全重置系统(设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。

(2) 另外如果用户明确的还原广告 (设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成。



示例:1E2DFA89-496A-47FD-9941-DF1FC4E6484A



3 mac地址

硬件标识符,包括WiFi mac地址和蓝牙mac地址。iOS 7 之后被禁止(同时禁止的还有OpenUDID)。



4 UDID

用来标示设备的唯一性 。iOS 6 之后被禁止获取系统原生的UDID,但可以通过uuid,写入到钥匙串中,从而获得自定义的UDID(非系统原生),即使用户重装APP,只要每次都取这个钥匙串返回,就是不变的。



//UUID , 已废除

NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];

4. Why Apple opposes developers using UDID

Many developers associate UDID with the user's real name, password, address, and other data; web snoopers will collect this data from multiple applications, and then follow the clues to get a lot of private data about this person. At the same time, most applications do transmit UDID and private information frequently. In order to avoid class-action lawsuits, Apple finally decided to abolish this practice in iOS 5. Developers are guided to generate a unique identifier that can only detect applications, and other information is not provided. Now the app's attempt to obtain UDID has been banned and is not allowed to be launched.

Apple recommends using UUIDs to generate unique identification strings for apps.

The obtained UUID value is not stored in the system, and every time the UUID is called, the system will return a new unique identifier. If you want to store this identifier, you need to store it yourself in NSUserDefaults, Keychain, Pasteboard or elsewhere.

5 UUID

It will change after reinstalling the APP.

6 How to correctly obtain the unique identifier of the device

Permanently store the obtained UUID in the KeyChain of the device. This method stores the obtained UUID into the KeyChain when the application is started for the first time. Every time it is retrieved, check whether there is any in the local keychain. If not, it needs to be The obtained UUID is stored in it. When you restart the device, uninstall the app and install it again, it will not affect it, but when the device is refreshed, the KeyChain will be cleared, disappear, and become invalid.

7 What is a keychain

Use KeyChain to share data between applications

We can understand KeyChain as a Dictionary, all data is stored in the form of key-value, and four operations of add, update, get, and delete can be performed on this Dictionary. For each application, KeyChain has two access areas, private area and public area. The private area is a sandbox, and any data stored by this program is invisible to other programs. If you want to put the stored content in the public area, you need to declare the name of the public area first. The official document calls this name "keychain access group". The method of declaration is to create a new plist file with a random name. The content is as follows

"yourAppID.com.yourCompany.whatever" is the name of the public area you want to create. Except for the whatever field, which can be set arbitrarily, everything else must be filled in truthfully. The path of this file must be configured in Project->build setting->Code Signing Entitlements, otherwise the public area will be invalid. After configuration, you must use your official certificate to sign and compile before it can pass, otherwise xcode will pop up a box to tell you that code signing has question. Therefore, Apple restricts you to only share KeyChain data with the company's products, and other companies cannot access the KeyChain of your company's products.

Guess you like

Origin blog.csdn.net/weixin_46626339/article/details/126420325