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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:27:31