Flutter与Kotlin实现前后台及终止状态自动发送SMS问题排查
后台无法发送短信的问题
我通过Telephony实现了短信的接收与发送功能,前台状态下运行正常,但后台状态下发送短信会出错,不过后台能正常接收短信。
现有权限配置
<uses-permission android:name="android.permission.SEND_SMS"/> <uses-permission android:name="android.permission.RECEIVE_SMS"/>
发送短信的Method Channel实现
import android.telephony.SmsManager val CHANNEL = "example.sms" override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if(call.method == "sendsms") { val phone = call.argument<String>("phone") val msg = call.argument<String>("msg") if (phone != null && msg != null) { sendSms(phone, msg) } } else { result.notImplemented() } } } private fun sendSms(phoneNumber: String, message: String) { try { val smsManager = SmsManager.getDefault() smsManager.sendTextMessage(phoneNumber, null, message, null, null) } catch (e: Exception) { e.printStackTrace() } }
问题原因及解决办法
1. 适配Android 12+权限要求
从Android 12(API 31)开始,后台发送短信需要额外申请REQUEST_SEND_SMS权限,仅SEND_SMS无法满足后台操作需求。需在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.REQUEST_SEND_SMS" />
同时要在代码中动态申请该权限,因为它属于危险权限范畴。
2. 规避后台任务限制
Android的后台调度限制会阻止非前台应用直接执行短信发送操作,建议使用WorkManager来处理后台短信发送任务,确保操作能被系统正常调度:
- 添加WorkManager依赖到
build.gradle:
implementation "androidx.work:work-runtime:2.8.1"
- 创建短信发送Worker类:
class SmsSendWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { val phone = inputData.getString("phone") val msg = inputData.getString("msg") return try { val smsManager = SmsManager.getDefault() smsManager.sendTextMessage(phone, null, msg, null, null) Result.success() } catch (e: Exception) { e.printStackTrace() Result.failure() } } }
- 修改Method Channel中的调用逻辑,替换直接发送为调度Worker:
private fun scheduleSmsSend(phoneNumber: String, message: String) { val data = Data.Builder() .putString("phone", phoneNumber) .putString("msg", message) .build() val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) // 可选,根据需求配置网络要求 .build() val smsWorkRequest = OneTimeWorkRequestBuilder<SmsSendWorker>() .setInputData(data) .setConstraints(constraints) .build() WorkManager.getInstance(applicationContext).enqueue(smsWorkRequest) }
之后在Method Channel回调里调用scheduleSmsSend(phone, msg)代替原sendSms方法。
3. 优化异常反馈机制
原代码仅在本地打印异常,无法将错误信息传递给Flutter端,建议修改Method Channel的回调逻辑,把异常信息返回:
if (phone != null && msg != null) { try { scheduleSmsSend(phone, msg) result.success("短信发送任务已调度") } catch (e: Exception) { result.error("SEND_FAILED", e.message, null) } } else { result.error("INVALID_PARAMS", "手机号或短信内容为空", null) }
内容的提问来源于stack exchange,提问作者Prem Singh
相关产品推荐
相关产品推荐

