skip to Main Content

I have used webview_flutter to load my site url, and used a JavaScriptChannel for two way communication between javascript and dart, as i want some native result from Android/IOS platform to javascript.

In Flutter

controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..addJavaScriptChannel('FlutterChannel',
      onMessageReceived: (JavaScriptMessage message) async {
    
        //Here i am doing some operation and returning a result as
        controller.runJavaScriptReturningResult('window.function($result)');
    
  })
  ..loadRequest(
    Uri.parse(
        'https://demo.com/')
  );

In JavaScript to interact with flutter channel-

var params = {'key':'alternate_preference','value': ''}; 
var data = { plugin: 'SharedPref', method: 'fetch', params: [params] };
FlutterChannel.postMessage(JSON.stringify(data))

To capture result in javascript-

function flutterResponseFunc(flutterResult) {
   console.log(flutterResult);
}
window.function= flutterResponseFunc;

How can i capture the result in callback of FlutterChannel.postMessage itself instead of creating a different function for result in js. Like Promise.then function in javascript.

enter image description here

I have gone through this answer

But it seems like a platform specific(i.e. for web platform only), as i can not use dart:js_interop & dart:html libs for Android/IOS platform. Any help will be appreciated. Thanks !!

2

Answers


  1. you don’t need to translate the function between languages. You can run simple codes through flutter. I left an example from my own use for easier understanding.

    ..addJavaScriptChannel(
        'consolePrint',
        onMessageReceived: (value) {
          final fileName = DateTime.now().toString().replaceAll(':', '-');
          final Map linkList = jsonDecode(value.message.toString());
    
          int totalCalculate(Map returnValue) {
            if (returnValue.containsValue(null)) {
              returnValue.removeWhere((key, value) => value == null);
              return returnValue.length;
            }
            return returnValue.length;
          }
    
          ProgressBar.total = 0;
          ProgressBar.progressValue.value = 0;
          ProgressBar.total = totalCalculate(linkList);
          linkList.forEach((key, value) {
            if (value != null) {
              downloadJpg(
                  index: int.parse(key),
                  url: value,
                  fileNmae: fileName,
                  total: linkList.length);
            }
          });
        },
      );
    

    Run and create a function from flutter. Then return the result to a channel.
    consolePrint is the name of my channel here

    void getLinkMap(WebViewController controller) async {
      try {
        await controller.runJavaScript('''
                      function getImages() {
                        var json = {};
                        var liList = document.querySelectorAll("body > div.main-content > div.ng-scope > div.content > div:nth-child(3) > div.modal-content.mega-image > section > ul > li")
                        liList.forEach(function list(value, index) {
                          var img = value.querySelector('img');
                          var hdImage = img.getAttribute("hd-image");
                          json[index] = hdImage;
                        });
                        consolePrint.postMessage(JSON.stringify(json));
                      };
                      window.onload = getImages();
                  ''');
      } catch (e) {
        log('error code: $e',
            time: DateTime.now(), name: 'func:getLinkMap');
      }
    }
    
    Login or Signup to reply.
  2. Considering the signature of the addJavaScriptChannel function it’s not possible to provide a result to postMessage().

    Future<void> addJavaScriptChannel(
        String name,
        {required void onMessageReceived(
            JavaScriptMessage
        )}
    ) 
    

    The onMessageReceived doesn’t return any value after invocation and JavaScriptMessage doesn’t provide a callback to invoke with data.

    So any aproach you could take would require you to build a custom solution with non-enforcable contracts within JS. As this is complex and error prone, it might be easier to just handle the result as you’re doing already.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search