Flutter应用关闭时如何接收SMS消息?已试Telephony包无效
解决Flutter Telephony包后台接收SMS的问题
要让应用在未运行时也能后台接收SMS,得针对Android和iOS的平台特性分别配置,同时注意Telephony包的回调规则,以下是具体方案:
一、先搞懂后台回调的硬性要求
onBackgroundMessage必须是顶级函数或者静态函数,不能是类的成员函数(你的代码里已经写了顶级函数,但要确保它不依赖任何Flutter上下文或类成员变量)- 后台回调里不能做依赖Flutter引擎的操作(比如
setState),只能做轻量处理:打印日志、写入本地存储、发送本地通知等
二、Android平台关键配置
1. 权限与清单配置
在android/app/src/main/AndroidManifest.xml里添加:
<!-- 基础短信权限 --> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <!-- 后台服务必要权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Android 12+ 通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <application ...> <!-- 注册Telephony的短信广播接收器 --> <receiver android:name="com.shahxad.telephony.SmsReceiver" android:exported="true"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> </application>
2. 豁免电池优化
Android系统会自动杀死后台耗电应用,必须引导用户把你的应用加入电池优化白名单,代码里可以直接触发申请:
await telephony.requestIgnoreBatteryOptimizations();
三、iOS平台限制与配置
iOS的后台机制更严格,应用被完全杀死后基本无法接收SMS,仅在挂起状态下有有限支持,配置如下:
- 在
ios/Runner/Info.plist添加权限说明:
<key>NSSMSUsageDescription</key> <string>需要访问短信权限来接收消息</string>
- 在Xcode中开启后台模式:
- 打开项目Runner -> Signing & Capabilities -> 添加Background Modes
- 勾选"Remote notifications"(iOS需要这个权限支持后台唤醒)
四、修正后的完整代码示例
// 必须是顶级函数,不能放在类内部 void onBackgroundMessage(SmsMessage message) { // 后台只能做轻量操作,比如打印、发本地通知 print("onBackgroundMessage: ${message.body}"); } void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { String _message = ""; final telephony = Telephony.instance; @override void initState() { super.initState(); initPlatformState(); } void onMessage(SmsMessage message) { setState(() { _message = message.body ?? "读取消息内容失败"; }); } Future<void> initPlatformState() async { // 请求短信和电话权限 final bool? permissionsGranted = await telephony.requestPhoneAndSmsPermissions; if (permissionsGranted != null && permissionsGranted) { // 请求Android电池优化豁免 await telephony.requestIgnoreBatteryOptimizations(); // 开启短信监听 telephony.listenIncomingSms( onNewMessage: onMessage, onBackgroundMessage: onBackgroundMessage, listenInBackground: true, ); } if (!mounted) return; } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text("短信接收器")), body: Center(child: Text("收到的消息: $_message")), ), ); } }
五、常见排查点
- 测试时不要用模拟器,部分模拟器不支持真实SMS接收
- Android上务必确认应用在电池优化白名单内,否则后台进程会被系统杀死
- 检查
onBackgroundMessage里有没有调用Flutter相关API(比如setState),这些操作在后台会失效
内容的提问来源于stack exchange,提问作者Harsh Singh
相关产品推荐
相关产品推荐

