React-native: React Native WebView onMessage doesn't work on Android

Created on 18 Jun 2017  路  12Comments  路  Source: facebook/react-native

Description

WebView's onMessage function never gets called on some Android versions.

This behaviour is not consistent on the Expo simulator. Test on physical devices.

Reproduction Steps

Se line 40 on the following snack.

If you test on a physical device and call window.postMessage without the second parameter it will throw "Failed to execute 'postMessage' on 'Window': 2 arguments required, but only 1 present".

The second parameter should be '*'.

See postMessage api on Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

postMessage seems to work only after the DOMContentLoaded event but not immediately. Expo simulator catches the two last events, but on a physical device I was able to trigger and receive messages before DOMContentLoaded. I think this should've been clarified on the docs.

Sample Code

https://snack.expo.io/HybU5stmW

Solution

Update the docs. Where is stated:
"window.postMessage accepts one argument, data, which will be available on the event object, event.nativeEvent.data. data must be a string."

Should state:
window.postMessage requires two arguments, data, ...., and targetOrigin which should be '*'.

Additional Information

  • React Native version: react-native: 0.44.2
  • Platform: Android 6.0 and 5.0 (didn't tested on previous versions)
  • Development Operating System: macOS 10.12.4
  • Build tools: Xcode 8.3.3, Android Studio 2.3
Locked

Most helpful comment

My workaround:

if (window.postMessage.length !== 1) {
  window.postMessage = function(msg) {
    setTimeout(function () {
      console.log('window.postMessage not ready')
      window.postMessage(msg);
    }, 500);
  }
}

add this to WebView injectedJavaScript prop

All 12 comments

@fernandofranca I am in the exact same situation.
You mean window.postMessage (SOME_DATA, '*') should be used instead of window.postMessage (SOME_DATA). right?
But it does not work.. if I am doing something wrong, please let me know

@hjh5696 Yup.

In my environment window.postMessage(someString, '*'); works. YMMV as it's not documented and the behaviour is not consistent.

I'd suggest you to wrap your call in a try/catch and check what kind of error is being thrown.

@fernandofranca Thank you for reply. However, even if I use try/catch, how do I get an error message within the html code of webview? is it from Android studio?

@hjh5696 I didn't knew any other way and had to improvise.

Eg.: Inside your webview, use the catch block to add a new DOM element containing the stringified error.

function printStuff(stuff){
  var el = document.createElement("pre");
  var str = JSON.stringify(stuff);
  el.innerHTML = str;
  document.body.appendChild(el);
}

Don't forget: Do not use // inline comments

@fernandofranca Thank you so much! I will let you know when I figure out my problem.

@fernandofranca I solved my problem. In my case, it worked well in Android 7.1 but not in below versions. I used some arrow functions in my , and that was the problem. After I changed them to function(){ }, it works well in below versions.
Thank you for your help!

Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!

If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:

  • Does the issue still reproduce on the latest release candidate? Post a comment with the version you tested.
  • If so, is there any information missing from the bug report? Post a comment with all the information required by the issue template.
  • Is there a pull request that addresses this issue? Post a comment with the PR number so we can follow up.

If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.

My workaround:

if (window.postMessage.length !== 1) {
  window.postMessage = function(msg) {
    setTimeout(function () {
      console.log('window.postMessage not ready')
      window.postMessage(msg);
    }, 500);
  }
}

add this to WebView injectedJavaScript prop

@0x5e Confirm this hacking worked 馃槃
Remember to remove any comment, add missing semicolon in injectedJavaScript in order to work!

WebView really needs more love, on both iOS and Android sides apparently.

Om it works!!! ;D

injectedJavaScript={" setTimeout(function(){ window.postMessage('asdsa', '*'); },1000); "} onMessage={ (event)=>{ let message = event.nativeEvent.data; console.log(message); console.log('message'); } }

if (window.postMessage.length !== 1) {
window.postMessage = function(msg) {
setTimeout(function () {
console.log('window.postMessage not ready')
window.postMessage(msg);
}, 500);
}
}

how to use that ??
I have problem every one can help me??

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oney picture oney  路  3Comments

despairblue picture despairblue  路  3Comments

anchetaWern picture anchetaWern  路  3Comments

aniss picture aniss  路  3Comments

axelg12 picture axelg12  路  3Comments