Flutter应用开发中,使用telephony包实现短信接收功能是很常见的需求,但不少开发者会遇到应用接收短信时突然崩溃的问题,这类问题大多和telephony包的兼容性相关,需要从多个维度排查处理。

常见崩溃原因分析
首先我们需要明确这类崩溃的常见诱因,才能针对性解决:
- telephony包版本和当前Flutter SDK版本不匹配,部分旧版本包不支持新版本的Flutter渲染机制
- Android端权限声明不完整,或者没有动态申请短信相关权限,系统直接拦截功能调用导致崩溃
- iOS端没有配置对应的短信功能权限描述,或者系统版本适配不到位,触发系统级异常
- 短信接收的回调逻辑中存在空指针、类型转换错误等问题,没有做异常捕获处理
具体解决步骤
1. 调整telephony包版本
首先查看当前项目使用的telephony版本,建议优先使用官方推荐的稳定版本,避免使用过旧或者测试版。在pubspec.yaml文件中调整依赖:
dependencies:
flutter:
sdk: flutter
# 使用稳定版本的telephony包,适配当前Flutter版本
telephony: ^0.2.0
调整完成后执行flutter pub get更新依赖,然后重新运行项目测试。
2. 完善Android端配置
Android端需要同时配置静态权限和动态权限申请,首先在android/app/src/main/AndroidManifest.xml中添加权限声明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sms_demo">
<!-- 短信接收相关权限 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:label="sms_demo"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- 其他配置 -->
</application>
</manifest>
然后在Dart代码中动态申请权限,避免权限不足导致崩溃:
import 'package:telephony/telephony.dart';
import 'package:permission_handler/permission_handler.dart';
final Telephony telephony = Telephony.instance;
Future<void> requestSmsPermission() async {
// 检查并申请短信权限
var status = await Permission.sms.status;
if (!status.isGranted) {
await Permission.sms.request();
}
// 检查电话状态权限
var phoneStatus = await Permission.phone.status;
if (!phoneStatus.isGranted) {
await Permission.phone.request();
}
}
3. iOS端配置适配
iOS端需要在ios/Runner/Info.plist中添加权限描述,否则系统会直接拒绝功能调用导致崩溃:
<key>NSContactsUsageDescription</key> <string>需要访问通讯录以实现短信相关功能</string> <key>NSMicrophoneUsageDescription</key> <string>需要麦克风权限以适配相关功能</string> <!-- 短信相关权限描述 --> <key>NSRemindersUsageDescription</key> <string>需要提醒权限以处理短信通知</string>
同时需要确认telephony包支持的iOS最低版本,在ios/Podfile中设置对应的版本要求:
platform :ios, '11.0'
4. 优化短信接收回调逻辑
在短信接收的回调中增加异常捕获,避免逻辑错误导致应用崩溃:
void onSmsReceived(SmsMessage message) {
try {
// 处理接收到的短信内容,避免空指针
String? body = message.body;
String? address = message.address;
if (body != null && address != null) {
print("接收到短信,发送方:$address,内容:$body");
}
} catch (e) {
print("短信处理异常:$e");
}
}
void initSmsListener() async {
// 初始化短信监听
await requestSmsPermission();
telephony.listenIncomingSms(
onNewMessage: onSmsReceived,
onBackgroundMessage: onSmsReceived,
);
}
验证与测试
完成以上配置后,可以分别在Android和iOS设备上测试短信接收功能,发送测试短信查看应用是否还会崩溃。如果仍然出现问题,可以查看崩溃日志,定位具体的错误堆栈,针对性调整配置或者代码逻辑。如果是特定系统版本的问题,可以查看telephony包的issue列表,寻找对应的临时解决方案或者等待包更新适配。