You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Android 8.1设备的IMEI号?telephonyManager.getDeviceId已废弃

获取Android 8.1设备IMEI的正确方法及代码评估

嗨,我来帮你梳理下Android 8.1(对应API 27,即Build.VERSION_CODES.O_MR1)设备获取IMEI的正确方式,同时分析你提供的代码是否可行~

核心前提:权限要求

要获取IMEI,必须申请READ_PHONE_STATE权限:

  • 先在AndroidManifest.xml中声明权限:
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
  • 对于Android 6.0(API 23)及以上设备,还需要动态申请权限,不能只依赖Manifest声明。你的代码里用了@SuppressLint("MissingPermission"),这会跳过权限检查,非常危险——如果用户没授权,调用相关方法会直接抛出SecurityException导致崩溃。

你的代码存在的问题

我们逐条拆解你提供的代码:

  1. 废弃方法的使用:你先调用了telephonyManager.getDeviceId(),这个方法在Android 8.0(API 26)就已被废弃。虽然在8.1上可能暂时还能运行,但它返回的可能是IMEI或MEID(取决于设备类型),语义不如getImei()明确,不推荐继续使用。
  2. 版本判断冗余:你写的Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT完全没必要——getImei()是API 26才引入的,只要判断Build.VERSION.SDK_INT >= Build.VERSION_CODES.O就足够覆盖Android 8.0+(包括8.1)的场景。
  3. TelephonyManager未初始化:代码里的telephonyManager没有显示初始化逻辑,要确保是通过getSystemService(Context.TELEPHONY_SERVICE)获取的实例,否则会触发空指针异常。
  4. Android ID的局限性:当IMEI获取不到时你用Android ID替代,但要注意:Android ID是系统生成的字符串,恢复出厂设置会改变,部分设备可能返回相同的ID,它不能完全替代IMEI的硬件唯一性。

修正后的可行代码

结合Android 8.1的特性,我整理了一份更严谨的代码,包含权限检查、动态申请兼容、双卡支持(可选):

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.core.app.ActivityCompat;

public class DeviceImeiHelper {
    private static final String TAG = "DeviceImeiHelper";

    /**
     * 获取设备唯一标识(优先IMEI,失败则返回Android ID)
     */
    public static String getDeviceIdentifier(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String imei = null;

        // 1. 检查权限是否已授予
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            Log.w(TAG, "未获取READ_PHONE_STATE权限,无法获取IMEI");
            // 这里建议触发动态权限申请,而不是直接返回Android ID
            // 示例:如果是在Activity中,可以调用ActivityCompat.requestPermissions()
            return getAndroidID(context);
        }

        // 2. 根据Android版本选择正确的方法获取IMEI
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Android 8.0+ 使用getImei(),支持双卡(传入卡槽索引,0为第一个卡槽)
                imei = telephonyManager.getImei(0);
            } else {
                // 低于Android 8.0,使用已废弃的getDeviceId()做兼容
                imei = telephonyManager.getDeviceId();
            }
        } catch (SecurityException e) {
            Log.e(TAG, "获取IMEI失败:", e);
        }

        // 3. 如果IMEI为空, fallback到Android ID
        if (imei == null || imei.isEmpty()) {
            imei = getAndroidID(context);
            Log.d(TAG, "IMEI获取失败,使用Android ID替代:" + imei);
        }

        return imei;
    }

    /**
     * 获取Android ID
     */
    private static String getAndroidID(Context context) {
        return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
    }
}

额外注意事项

  • 双卡设备处理:如果你的应用需要支持双卡设备,可以通过getImei(int slotIndex)指定卡槽索引(0或1),获取对应卡槽的IMEI。
  • 非蜂窝设备:如果设备没有蜂窝模块(比如WiFi平板),getImei()会返回null,此时只能依赖Android ID或其他标识(比如设备序列号,但序列号也需要权限)。
  • 隐私合规:获取IMEI属于敏感用户数据,需要符合地区隐私法规(如GDPR),必须获得用户明确授权,且告知用户数据用途。

内容的提问来源于stack exchange,提问作者Priyanka Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:34