如何在Flutter中获取Android设备的真实IMEI与序列号?
Android 私有应用获取IMEI/序列号的解决方案
核心结论
无论是否上架Google Play,Android 10(API 29)及以上版本对IMEI、序列号这类敏感标识符的访问限制是系统级的:
- 普通私有应用(无系统签名、无特殊权限)无法获取真实的IMEI/序列号,调用相关API会返回
null或unknown; - 仅满足以下条件之一的应用才能获取:
- 应用是系统预装应用(安装在系统分区,持有系统签名);
- 应用获得
READ_PRIVILEGED_PHONE_STATE权限(该权限仅向系统应用或OEM签名应用开放,普通私有应用无法申请); - 设备已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
相关产品推荐
相关产品推荐

