13

I have standalone Android App. Then I developed smaller web app in Flutter and exported it to web server. It is loaded inside WebView as a part of that standalone App in Kotlin for Android.

Android supports postmessaging and I can send data directly to WebView through channels. My question is how to listen to these messages in Flutter Dart code (inside my Web App)?

This is code I used in Kotlin Android App:

private var port: WebMessagePort? = null
    @TargetApi(Build.VERSION_CODES.M)
    private fun initPostMessagePort(){
        val channelsAvailable = webView.createWebMessageChannel()
        port = channelsAvailable.firstOrNull()
        port?.apply {
            setWebMessageCallback(object : WebMessageCallback() {
                override fun onMessage(port: WebMessagePort, message: WebMessage) {
                    //TODO do something with message
                }
            })
        }?:kotlin.run {
            App.log("Port initialization failed - channels not available")
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private fun sendMessageToPort(message: String){
        port?.let { p->
            webView.postWebMessage(WebMessage(message, arrayOf(p)), Uri.EMPTY)
        }?:kotlin.run {
            App.log("Port not initialized")
        }
    }

So there is my Flutter Web App startup code:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await di.init();

  //listen to message from mobile app, then run code below
  runApp(MyApp());
  bloc.dispatch(GetUserProfile());
}
martin1337
  • 2,384
  • 6
  • 38
  • 85

4 Answers4

4

With dart:html library we can establish communication channel between flutter web app and its host android WebView:

import 'dart:html' as html;

//...

    html.window.onMessage.listen((event) {

      // do something with received data
      myController.text = event.data; 

      // return a response
      event.ports[0].postMessage("response data");
    });

Corresponding Kotlin code from android side:

    val webView = findViewById<WebView>(R.id.webview)
    val (receiver, sender) = webView.createWebMessageChannel()
    receiver.setWebMessageCallback(object : WebMessagePort.WebMessageCallback() {
        override fun onMessage(port: WebMessagePort, message: WebMessage) {
            Log.i("example", "Received ${message.data}")
        }
    })
    val message = WebMessage("Original message", arrayOf(sender))
    webView.postWebMessage(message, Uri.EMPTY)

Spatz
  • 18,640
  • 7
  • 62
  • 66
  • Any tips on how to handle if the page inside the WebView changes? Do you call createWebMessageChannel again per page load? There isn't really a destroy/cleanup and then replace method from what I can tell. – Brandon Ros Dec 05 '22 at 05:36
1

Not 100% sure if this will be helpful but try Interactive Webview. Using the didReceiveMessage.listen() method you should be able to listen to messages sent to the native webview.

1

You should use WebSockets (socket.io) for inter-communications. Keep a separate nodejs instance which serves as your socket server, send a socket request from android to socket server and emit that from socket server to your flutter web app

See - https://pub.dev/packages/adhara_socket_io

abhijat_saxena
  • 705
  • 5
  • 20
0

you can use from socketIO or firebase cloud messaging service for receive or send message

hosein moradi
  • 444
  • 3
  • 7