Flutter中从MainActivity跳转原生Activity后回调Flutter页面的实现方法
Got it, let's tackle how to send callbacks from your native Camera Activity back to the Flutter page. Since you already have MethodChannel set up for launching the Camera Activity, we can extend this approach in two common ways depending on your needs:
Option 1: Callback after Camera Activity closes (Activity Result API)
This is ideal if you need to send data back only once when the Camera Activity finishes (e.g., after taking a photo and closing the camera).
Step 1: Update MainActivity to use Activity Result API
Replace the direct startActivity call with the modern Activity Result API to capture the result from Camera Activity, then forward it to Flutter via MethodChannel:
public class MainActivity extends FlutterActivity { final String CHANNEL = "flutter.native/helper"; private ActivityResultLauncher<Intent> cameraLauncher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize Activity Result Launcher to handle Camera Activity result cameraLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { // Extract data from Camera Activity's result String cameraResult = result.getData().getStringExtra("camera_result"); // Send the data to Flutter via MethodChannel new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), CHANNEL) .invokeMethod("onCameraCallback", cameraResult); } }); } @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL) .setMethodCallHandler((call, result) -> { if (call.method.equals("showNativeView")) { Intent intent = new Intent(MainActivity.this, Camera.class); cameraLauncher.launch(intent); // Launch Camera Activity via launcher } else { result.notImplemented(); } }); } }
Step 2: Modify Camera Activity to return result
In your Camera Activity, set the result data when the user completes an action (e.g., taking a photo, pressing a "Done" button) and finish the activity:
public class Camera extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); // Example: Button to trigger callback and close activity Button doneButton = findViewById(R.id.btn_done); doneButton.setOnClickListener(v -> { Intent resultIntent = new Intent(); // Pass your actual data (e.g., photo path, success status) resultIntent.putExtra("camera_result", "Photo captured successfully! Path: /sdcard/photo.jpg"); setResult(RESULT_OK, resultIntent); finish(); // Close Camera Activity to send result back }); } }
Step 3: Listen for callback in Flutter
Set up a MethodChannel handler in your Flutter code to receive the data from native:
import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; class CameraDemoPage extends StatefulWidget { const CameraDemoPage({super.key}); @override State<CameraDemoPage> createState() => _CameraDemoPageState(); } class _CameraDemoPageState extends State<CameraDemoPage> { static const platform = MethodChannel('flutter.native/helper'); String _cameraCallbackMessage = "Waiting for camera callback..."; @override void initState() { super.initState(); // Register handler to receive native callbacks platform.setMethodCallHandler((MethodCall call) async { if (call.method == 'onCameraCallback') { setState(() { _cameraCallbackMessage = call.arguments as String; }); } }); } // Trigger native Camera Activity Future<void> _openNativeCamera() async { try { await platform.invokeMethod('showNativeView'); } on PlatformException catch (e) { setState(() { _cameraCallbackMessage = "Error: ${e.message}"; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Flutter Native Camera Callback")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _openNativeCamera, child: const Text("Open Native Camera"), ), const SizedBox(height: 20), Text(_cameraCallbackMessage), ], ), ), ); } }
Option 2: Real-time Callback from Camera Activity
If you need to send data to Flutter while the Camera Activity is still open (e.g., live camera preview data, real-time status updates), you can directly use MethodChannel in the Camera Activity.
Step 1: Share Flutter BinaryMessenger from MainActivity
Store the FlutterEngine's BinaryMessenger in a static variable (or pass it via Intent) so Camera Activity can access it:
public class MainActivity extends FlutterActivity { final String CHANNEL = "flutter.native/helper"; public static BinaryMessenger flutterBinaryMessenger; @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); flutterBinaryMessenger = flutterEngine.getDartExecutor().getBinaryMessenger(); new MethodChannel(flutterBinaryMessenger, CHANNEL) .setMethodCallHandler((call, result) -> { if (call.method.equals("showNativeView")) { Intent intent = new Intent(MainActivity.this, Camera.class); startActivity(intent); } else { result.notImplemented(); } }); } @Override protected void onDestroy() { super.onDestroy(); // Avoid memory leaks by clearing the static reference flutterBinaryMessenger = null; } }
Step 2: Send real-time messages from Camera Activity
Initialize MethodChannel in Camera Activity and send messages to Flutter whenever needed:
public class Camera extends AppCompatActivity { private MethodChannel methodChannel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); // Initialize MethodChannel using the shared BinaryMessenger if (MainActivity.flutterBinaryMessenger != null) { methodChannel = new MethodChannel(MainActivity.flutterBinaryMessenger, "flutter.native/helper"); } // Example: Send real-time update when capture button is pressed Button captureButton = findViewById(R.id.btn_capture); captureButton.setOnClickListener(v -> { if (methodChannel != null) { // Send real-time data (e.g., temporary photo path) methodChannel.invokeMethod("onRealTimeCameraUpdate", "Captured photo: /sdcard/temp_photo.jpg"); } }); // Send callback when activity closes findViewById(R.id.btn_close).setOnClickListener(v -> { if (methodChannel != null) { methodChannel.invokeMethod("onCameraClosed", "Camera activity closed"); } finish(); }); } }
Step 3: Listen for real-time callbacks in Flutter
Update the Flutter MethodChannel handler to handle the new real-time methods:
// Inside _CameraDemoPageState's initState platform.setMethodCallHandler((MethodCall call) async { switch(call.method) { case 'onCameraCallback': setState(() { _cameraCallbackMessage = call.arguments as String; }); break; case 'onRealTimeCameraUpdate': setState(() { _cameraCallbackMessage = "Real-time update: ${call.arguments}"; }); break; case 'onCameraClosed': setState(() { _cameraCallbackMessage = "Status: ${call.arguments}"; }); break; } });
Key Notes
- Memory Leaks: For Option 2, make sure to clear the static
flutterBinaryMessengerreference in MainActivity'sonDestroyto avoid memory leaks. - Data Types: You can pass more complex data (like byte arrays for images) by converting them to supported types (e.g., base64 strings, maps).
- Error Handling: Add null checks for
methodChannelin native code to avoid crashes if the FlutterEngine is destroyed.
内容的提问来源于stack exchange,提问作者Aryanbudhiraja

