当我尝试在 Flutter 中使用
MissingPluginException
在我的 Android 应用程序中发送短信时,遇到了 MethodChannel
。即使我已经正确实现了本机代码,应用程序也会在运行时抛出此错误。
E/flutter (10616): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method sendSMS on channel channel_name)
E/flutter (10616): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332:7)
E/flutter (10616): <asynchronous suspension>
E/flutter (10616): #1 SmsService.sendSms (package:muteify/services/sms_service.dart:8:30)
E/flutter (10616): <asynchronous suspension>
E/flutter (10616): #2 phoneStateBackgroundCallbackHandler (package:muteify/services/phone_state_bg_helper.dart:16:19)
E/flutter (10616): <asynchronous suspension>
import 'package:flutter/services.dart';
const platform = MethodChannel('channel_name');
class SmsService {
Future<String?> sendSms(String phone, String message) async {
try {
final String? result = await platform.invokeMethod<String?>('sendSMS', {
'phone': phone,
'message': message,
});
print("SMS result: $result");
return result;
} on PlatformException catch (e) {
return "Failed to send SMS: '${e.message}'.";
}
}
}
@file:Suppress("DEPRECATION")
package com.example.muteify
import android.telephony.SmsManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.Result
class MainActivity : FlutterActivity() {
private val channel = "channel_name"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler { call, result ->
if (call.method=="sendSMS"){
val customerPhone = call.argument<String>("phone")
val customerMessage = call.argument<String>("message")
if (customerPhone != null && customerMessage != null) {
sendSMS(customerPhone, customerMessage, result)
} else {
result.error("INVALID_ARGUMENT", "Phone number or message is null", null)
}
}
else {
result.notImplemented()
}
}
}
private fun sendSMS(phone: String, message: String, result: Result) {
return try {
val smsManager: SmsManager = SmsManager.getDefault()
smsManager.sendTextMessage(phone, null, message, null, null)
result.success("SMS sent successfully")
} catch (e: Exception) {
result.error("SMS_SEND_FAILED", "Failed to send SMS: ${e.message}", null)
}
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:label="muteify"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name="me.sodipto.phone_state_background.PhoneStateBackgroundServiceReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
flutter clean
并重建 APK。channel_name
是否匹配。MethodChannel
是否设置在configureFlutterEngine
内部。即使应用程序在后台运行,应用程序也应该通过
MethodChannel
成功发送短信,而不会抛出 MissingPluginException
错误。
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on Pop!_OS 22.04 LTS
6.9.3-76060903-generic, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.93.1)
[✓] Connected device (3 available)
[✓] Network resources
• No issues found!
这可能是什么原因造成的
MissingPluginException
我该如何解决?我在方法通道配置或清单设置中遗漏了什么吗?
您需要在 kotlin 中的 == 运算符内部使用 .equals 这是基本编程,所以我想深入了解它,有很多解释何时使用 == 或 .equals。
if (call.method.equals("sendSMS")){
val customerPhone = call.argument<String>("phone")
val customerMessage = call.argument<String>("message")
if (customerPhone != null && customerMessage != null) {
sendSMS(customerPhone, customerMessage, result)
} else {
result.error("INVALID_ARGUMENT", "Phone number or message is null", null)
}
}
else {
result.notImplemented()
}