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

如何在Flutter中获取Android设备的真实IMEI与序列号?

Android 私有应用获取IMEI/序列号的解决方案

核心结论

无论是否上架Google Play,Android 10(API 29)及以上版本对IMEI、序列号这类敏感标识符的访问限制是系统级的:

  • 普通私有应用(无系统签名、无特殊权限)无法获取真实的IMEI/序列号,调用相关API会返回null或unknown;
  • 仅满足以下条件之一的应用才能获取:
    1. 应用是系统预装应用(安装在系统分区,持有系统签名);
    2. 应用获得READ_PRIVILEGED_PHONE_STATE权限(该权限仅向系统应用或OEM签名应用开放,普通私有应用无法申请);
    3. 设备已root,应用通过root权限读取系统底层文件或执行系统命令。

可行实现方案(针对满足权限条件的场景)

1. 原生Kotlin代码实现

首先在AndroidManifest.xml中声明权限:

<!-- Android 9及以下版本使用 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="28" />
<!-- Android 10+ 仅系统应用可申请 -->
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />

然后编写获取标识符的Kotlin方法:

import android.content.Context
import android.os.Build
import android.telephony.TelephonyManager

// 获取IMEI
fun getIMEI(context: Context): String? {
    val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    return try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            telephonyManager.imei
        } else {
            telephonyManager.deviceId
        }
    } catch (e: SecurityException) {
        null
    }
}

// 获取序列号
fun getSerialNumber(): String? {
    return try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Build.getSerial()
        } else {
            Build.SERIAL
        }
    } catch (e: SecurityException) {
        null
    }
}

2. Flutter调用原生方法(MethodChannel)

Dart端代码

import 'package:flutter/services.dart';

class DeviceIdentifier {
  static const MethodChannel _channel = MethodChannel('device_identifier');

  static Future<String?> getIMEI() async {
    try {
      return await _channel.invokeMethod('getIMEI');
    } on PlatformException catch (e) {
      print("获取IMEI失败: ${e.message}");
      return null;
    }
  }

  static Future<String?> getSerialNumber() async {
    try {
      return await _channel.invokeMethod('getSerialNumber');
    } on PlatformException catch (e) {
      print("获取序列号失败: ${e.message}");
      return null;
    }
  }
}

Android原生端配置(MainActivity.kt)

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "device_identifier"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "getIMEI" -> {
                    val imei = getIMEI(this)
                    imei?.let { result.success(it) } ?: result.error("PERMISSION_DENIED", "无法获取IMEI", null)
                }
                "getSerialNumber" -> {
                    val serial = getSerialNumber()
                    serial?.let { result.success(it) } ?: result.error("PERMISSION_DENIED", "无法获取序列号", null)
                }
                else -> result.notImplemented()
            }
        }
    }

    // 粘贴上面的getIMEI和getSerialNumber方法
}

关于你尝试过的Flutter插件说明

  • device_info/device_info_plus:返回的androidId是系统生成的随机ID(恢复出厂设置会变更),并非IMEI;serial字段在Android 10+普通应用中会固定返回unknown,这是系统权限限制导致的。
  • unique_identifier插件:同样受限于系统权限规则,在Android 10+环境下无法获取真实IMEI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:42:37