Communicating Between Flutter and Android (Java) Overview

Communicating Between Flutter and Android (Java)

Overview

Flutter provides a powerful way to communicate with platform-specific code through platform channels and event channels. This document outlines how to set up such communication between Flutter and Android (Java) using method channels for direct method invocation and event channels for continuous data streams.

Table of Contents

  1. Introduction to Platform and Event Channels

  2. Setting Up the Flutter Project

  3. Implementing Platform Channels

    • Dart Side (Flutter)

    • Android Side (Java)

  4. Implementing Event Channels

    • Dart Side (Flutter)

    • Android Side (Java)

  5. Running the App

  6. Conclusion

1. Introduction to Platform and Event Channels

Platform Channels

Platform channels allow Flutter to communicate with the native platform by sending and receiving messages. Method channels facilitate direct method calls and responses between Flutter and native code.

Event Channels

Event channels enable continuous communication from the native platform to Flutter, often used for streaming data like sensor readings or call state changes.

 

2. Setting Up the Flutter Project

First, create a new Flutter project or use an existing one:

flutter create flutter_native_communication

cd flutter_native_communication

 

3. Implementing Platform Channels

Dart Side (Flutter)

Create a method channel for sending messages from Flutter to the native code and an event channel for receiving continuous updates.

 

 

  static const platform = MethodChannel('com.example.call10/toast');

  static const eventChannel = EventChannel('com.example.call10/events');

 

 

 

    _eventSubscription =

        MyApp.eventChannel.receiveBroadcastStream().listen((event) {

      _handleEvent(event);

    });

  }

 

  void _handleEvent(dynamic event) {

    if (event == 'incoming_call') {

      Navigator.push(

          context, MaterialPageRoute(builder: (context) => TargetScreen()));

    }

  }

 

 

 

 

  void _showToast() async {

    try {

      await MyApp.platform

          .invokeMethod('showToast', {'message': 'Hello from Flutter!'});

    } on PlatformException catch (e) {

      print("Failed to show toast: '${e.message}'.");

    }

  }

}

 

class TargetScreen extends StatelessWidget {

  void _callAnswer() async {

    try {

      final result = await MyApp.platform.invokeMethod('answer');

      log("Answer method result: $result");

    } on PlatformException catch (e) {

      log("Failed to answer call: '${e.message}'.");

    }

  }

 

  void _callReject() async {

    try {

      final result = await MyApp.platform.invokeMethod('reject');

      log("Answer method result: $result");

    } on PlatformException catch (e) {

      log("Failed to answer call: '${e.message}'.");

    }

  }

 

 

 

 

 

 

 

 

 

Android Side (Java)

Set up the native side to handle the method and event channels.

Modify MainActivity.java

Navigate to android/app/src/main/java/com/example/flutter_native_communication/MainActivity.java and modify it as follows:

 

 

 

 

 

 

public class MainActivity extends FlutterActivity {

    private static final String CHANNEL = "com.example.call10/toast";

    private static final String EVENT_CHANNEL = "com.example.call10/events";

 

    @Override

    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {

        super.configureFlutterEngine(flutterEngine);

        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)

            .setMethodCallHandler(

                (call, result) -> {

                    if (call.method.equals("showToast")) {

                        String message = call.argument("message");

                        showToast(message);

                        result.success(null);

                    } else if (call.method.equals("answer")) {

                        answerCall();

                        result.success("Call answered");

                    } else if (call.method.equals("reject")) {

                        rejectCall();

                        result.success("Call rejected");

                    } else {

                        result.notImplemented();

                    }

                }

            );

 

        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), EVENT_CHANNEL)

            .setStreamHandler(

                new EventChannel.StreamHandler() {

                    @Override

                    public void onListen(Object arguments, EventChannel.EventSink events) {

                        // Emit events to Flutter

                        events.success("incoming_call");

                    }

 

                    @Override

                    public void onCancel(Object arguments) {

                        // Handle cancel event

                    }

                }

            );

    }

 

    private void showToast(String message) {

        // Code to show a toast message

    }

 

    private void answerCall() {

        // Code to answer the call

    }

 

    private void rejectCall() {

        // Code to reject the call

    }

}

 

4. Running the App

Ensure that your Android device or emulator is set up and running. Then, run your Flutter app using the following command:

 

flutter run

 

When the app launches:

  • Click the "Show Toast" button to invoke the native showToast method.

  • The app listens for incoming_call events and navigates to the TargetScreen when such an event is received.

5. Conclusion

By following these steps, you have successfully implemented communication between Flutter and Android (Java) using platform and event channels. This approach can be extended to handle more complex interactions and data exchange, enabling your Flutter app to leverage native Android functionality effectively.

 

This document has been developed by Phonon.io for the sole and exclusive use of the customer / prospective customer with whom this document is being shared. Further, this document has been provided by Phonon.io to the recipient in good faith and based on request from the recipient for the same. This document is a confidential document and contains confidential product technology, workflow and commercial details that are for the sole usage of the intended recipients of this document. Recipients are advised not to share this document with any third party that is not the intended recipient of this document and neither to bring this document in full or parts into the public domain. Any unauthorized access may be brought to Phonon.io’s notice immediately. Phonon.io is free to take any legal action it deems necessary against any person or entity that violates this confidentiality agreement. Phonon.io is bound and governed by the rules of the state of Gujarat in India. In case you are not in agreement with the terms set in this clause or are not an intended recipient of this document, please destroy the document and intimate us of the same at info@phonon.io.