Android 13环境下Flutter获取SIM序列号问题求助
解决Flutter在Android 13下无法获取SIM序列号(ICCID)的问题
问题原因
Android 13(API 33)收紧了权限管控,原READ_PHONE_STATE权限不再包含读取SIM卡ICCID的权限,普通应用需申请READ_SMS权限才能获取该信息。sim_data_plus包可能未适配这一权限变更,导致在Android 13设备上读取失败。
解决方案
1. 配置适配权限
修改android/app/src/main/AndroidManifest.xml,添加分版本权限配置:
<!-- Android 12及以下版本所需权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" android:maxSdkVersion="32" /> <!-- Android 13及以上版本获取ICCID所需权限 --> <uses-permission android:name="android.permission.READ_SMS" android:maxSdkVersion="33" />
2. 动态申请权限并调用sim_data_plus
用permission_handler包动态申请对应权限后,再尝试获取SIM数据:
import 'package:permission_handler/permission_handler.dart'; import 'package:sim_data_plus/sim_data_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:device_info_plus/device_info_plus.dart'; Future<String?> getSimIccid() async { PermissionStatus permissionStatus; if (defaultTargetPlatform == TargetPlatform.android) { final androidInfo = await DeviceInfoPlugin().androidInfo; // 根据Android版本选择对应权限申请 permissionStatus = androidInfo.version.sdkInt >= 33 ? await Permission.sms.request() : await Permission.phone.request(); } else { return null; } if (permissionStatus.isGranted) { try { final simData = await SimDataPlus.getSimData(); // 返回首张SIM卡ICCID,多SIM卡场景可自行遍历处理 return simData.cards.firstOrNull?.iccid; } catch (e) { debugPrint('获取SIM数据失败: $e'); return null; } } else { debugPrint('权限未授予,无法获取ICCID'); return null; } }
3. 替代方案:自定义MethodChannel实现
如果sim_data_plus仍无法正常工作,可直接通过原生API实现ICCID读取:
原生Android代码(Kotlin)
在android/app/src/main/kotlin/[你的包名]/SimSerialPlugin.kt中添加:
import android.content.Context import android.telephony.TelephonyManager import android.os.Build import androidx.annotation.NonNull import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel class SimSerialPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { private lateinit var channel: MethodChannel private lateinit var context: Context override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { context = flutterPluginBinding.applicationContext channel = MethodChannel(flutterPluginBinding.binaryMessenger, "sim_serial_channel") channel.setMethodCallHandler(this) } override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) { when (call.method) { "getIccid" -> { val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager try { val iccid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { telephonyManager.iccid } else { @Suppress("DEPRECATION") telephonyManager.iccid } result.success(iccid) } catch (e: SecurityException) { result.error("PERMISSION_DENIED", "缺少读取ICCID的权限", null) } catch (e: Exception) { result.error("FETCH_FAILED", "获取ICCID失败", null) } } else -> result.notImplemented() } } override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler(null) } }
在MainActivity.kt中注册插件:
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) flutterEngine.plugins.add(SimSerialPlugin()) } }
Flutter端调用代码
import 'package:flutter/services.dart'; final MethodChannel _simSerialChannel = MethodChannel('sim_serial_channel'); Future<String?> getIccid() async { try { return await _simSerialChannel.invokeMethod('getIccid'); } on PlatformException catch (e) { debugPrint('获取ICCID出错: ${e.message}'); return null; } }
内容的提问来源于stack exchange,提问作者Kirthana
相关产品推荐
相关产品推荐

