• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

代码获取Android DeviceId

互联网 diligentman 2小时前 2次浏览

目录

DeviceId是什么?

基础知识

国际移动设备识别码(IMEI)

移动设备识别码(MEID )

AndroidID

设备MAC地址

代码获取Android DeviceId?

参考文章


  • DeviceId是什么?

DeviceIdD是用来标识一台Android物理设备的唯一id(后续统称DID)。那么如何获取它呢?

Google提供了TelephonyManager.getDeviceId方法来获取Android的DID。该API是获取GSM手机的国际移动设备识别码(IMEI)或者 CDMA手机的移动设备识别码(MEID )。但该API存在一些限制。

因此,各大互联网公司都有生产、维护DID的基建SDK,本文旨在梳理清DID的相关上下文。

  • 基础知识

  • 国际移动设备识别码(IMEI)

全称“International Mobile Equipment Identity”,是通常所说的手机序列号、手机“串号”。用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证,序列号共有15~17位数字,通过在手机拨号键盘中输入*#06#即可查询。

但存在以下限制:

​1.自API23(Android 6.0)开始,获取IMEI需要用户予"android.permission.READ_PHONE_STATE";
2.自API29(Android 10.0)开始,您的应用必须是设备或个人资料所有者应用具有特殊运营商权限或具有 READ_PRIVILEGED_PHONE_STATE 特许权限,才能访问这些标识符。
3.某些小厂商某型号的手机IMEI可能相同。
  • 移动设备识别码(MEID )

全称“Mobile Equipment Identifier”,是CDMA手机的身份识别码,也是每台CDMA手机或通讯平板唯一的识别码。通过这个识别码,网络端可以对该手机进行跟踪和监管。用于CDMA制式的手机。MEID的数字范围是十六进制的,和IMEI的格式类似。

存在的限制同IMEI的限制。

  • AndroidID

又称SSAID。设备启动时,随机生成一个 64 位数字(表示为十六进制字符串),对于应用签名密钥、用户和设备的每个组合都是唯一的。 ANDROID_ID 的值受签名密钥和用户的限制。

但存在如下限制:

1.如果在设备上执行恢复出厂设置或 APK 签名密钥更改,则该值可能会更改。
2.某些小厂商的Android手机可能为null或相同。
  • 设备MAC地址

MAC 地址具有全局唯一性,无法由用户重置,在恢复出厂设置后也不会变化。

但存在如下限制:

在 Android 6.0(API 级别 23)到 Android 9(API 级别 28)中,本地设备 MAC 地址(如 WLAN 和蓝牙)无法通过第三方 API 使用。WifiInfo.getMacAddress() 方法和BluetoothAdapter.getDefaultAdapter().getAddress() 方法会返回02:00:00:00:00:00。

不过业界也有一些hack的做法,不建议使用。

其他诸如BuildSerial、GoogleAID也有各种各样的限制,在这里不做统一赘述。

  • 代码获取Android DeviceId?

该段代码参考自:I am getting IMEI null in Android Q?,简化代码&添加注释。

Android版本号参考:Android历史版本

需要说明的是,这段代码仅适用于Demo级产品的大多数场景,并不能完全保证DID的唯一性。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String deviceId = getIMEIDeviceId(this);
        Log.i("deviceId is:", deviceId);
    }

    public static String getIMEIDeviceId(Context context) {
        String deviceId;
        //当APK运行在Android10(API>=29)及以上时,获取到的是AndroidID
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        } else {
            final TelephonyManager mTelephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            //当APK运行在Android6.0(API>=23)及以上时,需要check有无READ_PHONE_STATE权限。
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                    return "";
                }
            }
            assert mTelephony != null;
            //如果TelephonyManager获取到的DeviceId不为null
            if (mTelephony.getDeviceId() != null) {
                //获取GSM手机的国际移动设备识别码(IMEI)或者 CDMA手机的移动设备识别码(MEID).
                deviceId = mTelephony.getDeviceId();
            } else {
                //如果DeviceId为null,我们的DID依然是AndroidID。
                deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            }
        }
        return deviceId;
    }
}
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • 参考文章

唯一标识符最佳做法

TelephonyManager

I am getting IMEI null in Android Q?

Android 10 使用getDeviceId()和getIMEI()的问题及方案


程序员灯塔
转载请注明原文链接:代码获取Android DeviceId
喜欢 (0)