diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java
index 6b75fa2ad6e5..1646af47fc8c 100644
--- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java
+++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java
@@ -9,7 +9,6 @@
import android.os.Handler;
import android.util.Log;
import androidx.annotation.NonNull;
-import io.flutter.embedding.engine.FlutterShellArgs;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -37,28 +36,6 @@ public static void enqueueMessageProcessing(
isHighPriority);
}
- /**
- * Starts the background isolate for the {@link FlutterFirebaseMessagingBackgroundService}.
- *
- *
Preconditions:
- *
- *
- * - The given {@code callbackHandle} must correspond to a registered Dart callback. If the
- * handle does not resolve to a Dart callback then this method does nothing.
- *
- A static {@link #pluginRegistrantCallback} must exist, otherwise a {@link
- * PluginRegistrantException} will be thrown.
- *
- */
- @SuppressWarnings("JavadocReference")
- public static void startBackgroundIsolate(long callbackHandle, FlutterShellArgs shellArgs) {
- if (flutterBackgroundExecutor != null) {
- Log.w(TAG, "Attempted to start a duplicate background isolate. Returning...");
- return;
- }
- flutterBackgroundExecutor = new FlutterFirebaseMessagingBackgroundExecutor();
- flutterBackgroundExecutor.startBackgroundIsolate(callbackHandle, shellArgs);
- }
-
/**
* Called once the Dart isolate ({@code flutterBackgroundExecutor}) has finished initializing.
*
diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java
index 63d1e0dfac0a..d3832680e80c 100644
--- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java
+++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java
@@ -23,7 +23,6 @@
import com.google.firebase.FirebaseApp;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.RemoteMessage;
-import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
@@ -421,12 +420,9 @@ public void onMethodCall(final MethodCall call, @NonNull final Result result) {
Task> methodCallTask;
switch (call.method) {
- // This message is sent when the Dart side of this plugin is told to initialize.
- // In response, this (native) side of the plugin needs to spin up a background
- // Dart isolate by using the given pluginCallbackHandle, and then setup a background
- // method channel to communicate with the new background isolate. Once completed,
- // this onMethodCall() method will receive messages from both the primary and background
- // method channels.
+ // This message is sent when the Dart side of this plugin registers a background
+ // message handler. We persist the callback handles to SharedPreferences so
+ // the background service can start the isolate later when a message arrives.
case "Messaging#startBackgroundIsolate":
@SuppressWarnings("unchecked")
Map arguments = ((Map) call.arguments);
@@ -455,19 +451,13 @@ public void onMethodCall(final MethodCall call, @NonNull final Result result) {
"Expected 'Long' or 'Integer' type for 'userCallbackHandle'.");
}
- FlutterShellArgs shellArgs = null;
- if (mainActivity != null) {
- // Supports both Flutter Activity types:
- // io.flutter.embedding.android.FlutterFragmentActivity
- // io.flutter.embedding.android.FlutterActivity
- // We could use `getFlutterShellArgs()` but this is only available on `FlutterActivity`.
- shellArgs = FlutterShellArgs.fromIntent(mainActivity.getIntent());
- }
-
+ // Only save the callback handles to SharedPreferences. Don't start the
+ // background isolate here — it will be started lazily in
+ // FlutterFirebaseMessagingBackgroundService.onCreate() when a background
+ // message actually arrives and the service is started. Starting it eagerly
+ // caused a duplicate Dart main() to appear in the call stack (#17163).
FlutterFirebaseMessagingBackgroundService.setCallbackDispatcher(pluginCallbackHandle);
FlutterFirebaseMessagingBackgroundService.setUserCallbackHandle(userCallbackHandle);
- FlutterFirebaseMessagingBackgroundService.startBackgroundIsolate(
- pluginCallbackHandle, shellArgs);
methodCallTask = Tasks.forResult(null);
break;
case "Messaging#getInitialMessage":
diff --git a/packages/firebase_messaging/firebase_messaging/example/android/app/build.gradle b/packages/firebase_messaging/firebase_messaging/example/android/app/build.gradle
index 8ebdee7a1533..3c01572f5225 100644
--- a/packages/firebase_messaging/firebase_messaging/example/android/app/build.gradle
+++ b/packages/firebase_messaging/firebase_messaging/example/android/app/build.gradle
@@ -47,7 +47,7 @@ android {
applicationId = "io.flutter.plugins.firebase.messaging.example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
- minSdk = 23
+ minSdkVersion = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName