Reputation: 13
I’m encountering a MissingPluginException
when trying to use MethodChannel
in Flutter to send SMS in my Android app. Even though I’ve implemented the native code correctly, the app throws this error at runtime.
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
and rebuilt the APK.channel_name
matches between Flutter and Android code.MethodChannel
is set up inside configureFlutterEngine
.The app should successfully send an SMS via MethodChannel
, even when the app is running in the background, without throwing the MissingPluginException
error.
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!
What could be causing this MissingPluginException
and how can I resolve it? Is there something I missed in the method channel configuration or manifest setup?
Upvotes: 0
Views: 161
Reputation: 180
You need to use .equals inside of == operator in kotlin this is basic programming so i want be getting into it, there is alot which explains when to use == or .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()
}
Upvotes: 0