十二、获取手机imei


  1. 一般获取android手机的IMEI是这样的(不推荐):
    1
    2
    3
    4
    5
    @SuppressLint("MissingPermission")
    fun getImei(ctx: Context) : String {
    val tm = ctx.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    return tm.deviceId
    }

源码中的注释已经说明了,这方法可能返回IMEI,也可能返回MEID。TelephonyManager 还有个带参数的getDeviceId(int slotId),这个slotId就是卡槽编号,双卡手机的话传0和1. 我用双卡的华为mate9
试过其中一个IMEI号码不对,获取成MEID了。而且带卡槽的getDeviceId方法得要是android 23以上才能调用。

  1. 真正有用的方法:
    TelephonyManager 还有个隐藏方法 getIMEI,(android26以上该方法可直接调用), 该方法才能获取到真正有用的双IMEI

  2. 最终解决方案(推荐):
    SystemUtils.kt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    fun getImei(ctx: Context, slotId: Int = 0) : String {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) getImei26(ctx, slotId) else getImeiReflect(ctx, slotId)
    }

    @SuppressLint("MissingPermission")
    @RequiresApi(Build.VERSION_CODES.O)
    private fun getImei26(ctx: Context, slotId : Int = 0) : String{
    val tm = ctx.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    return tm.getImei(slotId)
    }

    private fun getImeiReflect(ctx: Context, slotId : Int = 0) : String{
    return try {
    val tm = ctx.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val method = tm.javaClass.getMethod("getImei", Int::class.javaPrimitiveType)
    method.invoke(tm, slotId) as String
    } catch (e: Exception) {
    ""
    }
    }