Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variables and functions from injectedJavaScript not available on Android #554

Closed
svdo opened this issue May 5, 2019 · 6 comments
Closed

Comments

@svdo
Copy link

svdo commented May 5, 2019

Bug description:
On Android, variables and functions declared in injectedJavaScript are not available in code run by injectJavaScript, whereas on iOS they are. Please note that I'm using source={{ html: ... }}, not loading an external URI. I believe the behaviour on iOS is correct, that on Android is not.

To Reproduce:
I created a repo that demonstrates this issue. I was careful to create a descriptive git history, so I hope it is pretty self-explanatory: https://github.com/svdo/VarIssue. This repo contains a complete react native project that you should be able to run yourself (make sure Android emulator is running):

yarn
yarn react-native start --reset-cache
yarn react-native run-ios
yarn react-native run-android

Environment:

  • OS: Android 9 and iOS 11
  • react-native-webview version: 5.8.1
  • react-native info:
    React Native Environment Info:
      System:
        OS: macOS 10.14.4
        CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
        Memory: 18.87 MB / 16.00 GB
        Shell: 5.3 - /bin/zsh
      Binaries:
        Node: 11.14.0 - /var/folders/0d/5_t6qk7s06qf94jnypzwh6yh0000gp/T/yarn--1557086445011-0.06815149805556375/node
        Yarn: 1.15.2 - /var/folders/0d/5_t6qk7s06qf94jnypzwh6yh0000gp/T/yarn--1557086445011-0.06815149805556375/yarn
        npm: 6.9.0 - ~/.homebrew/bin/npm
      SDKs:
        iOS SDK:
          Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
      IDEs:
        Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
      npmPackages:
        react: 16.8.3 => 16.8.3
        react-native: 0.59.5 => 0.59.5
    

Note

svdo added a commit to svdo/han that referenced this issue May 11, 2019
Works around issue react-native-webview/react-native-webview#554.
Note that with this method the REPL inside the webview works for iOS; on Android
it immediately says "shadow-cljs - Connection closed!".
@github-actions
Copy link

github-actions bot commented Sep 2, 2019

Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

@zenpi-me
Copy link

zenpi-me commented Oct 9, 2019

I have the same problem right now. Did you find a solution or workaround for this?

@svdo
Copy link
Author

svdo commented Oct 9, 2019

@its-wufu I have not further pursued this. I noticed this comment the other day though, it may be the workaround you're looking for (but I didn't try):

#445 (comment)

@zenpi-me
Copy link

zenpi-me commented Oct 10, 2019

I couldn't make this work unfortunatly. Maybe I show what I did, so someone may find something to add here.

I created a Test App and just used Test Credentials from WireCard. This is how my App.js looks like:

import React, {useRef, useEffect, useState} from 'react';
import {StyleSheet, View, Text, SafeAreaView, Button} from 'react-native';
import {WebView} from 'react-native-webview';
import base64 from 'base-64';
import uuid from 'uuid';

import INJECTED_JAVASCRIPT from './paymentPage';

export default function App() {
  const webViewRef = useRef();

  // Beispiel: https://wpp-test.wirecard.com/seamless?wPaymentToken=emRvVkFXAdge7xs2mr0C21mPO_Bf3INlsO2p4uRFSsc
  const [redirectUrl, setRedirectUrl] = useState(null);

  useEffect(() => {
    const url = 'https://wpp-test.wirecard.com/api/payment/register';
    const data = {
      payment: {
        'merchant-account-id': {
          value: 'cad16b4a-abf2-450d-bcb8-1725a4cef443',
        },
        'request-id': uuid(),
        'transaction-type': 'authorization-only',
        'requested-amount': {
          value: 0,
          currency: 'EUR',
        },
        'payment-methods': {
          'payment-method': [
            {
              name: 'creditcard',
            },
          ],
        },
      },
      options: {
        mode: 'seamless',
        'frame-ancestor': 'https://example.com',  // not sure what to put here either...
      },
    };
    getData(url, data);
  }, []);

  const getData = (url, data) => {
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization:
          'Basic ' + base64.encode('70000-APILUHN-CARD:8mhwavKVb91T'),
      },
      body: JSON.stringify(data),
    })
      .then(res => res.json())
      .then(resJson => {
        if (resJson['payment-redirect-url']) {
          setRedirectUrl(resJson['payment-redirect-url']);
          console.log(resJson['payment-redirect-url']);
        } else {
          console.log(resJson);
        }
      });
  };

  const onSubmit = () => {
    // https://github.com/react-native-community/react-native-webview/issues/554
    webViewRef.current.injectJavaScript(`
        WPP.seamlessSubmit({
            onSuccess: function (response) { 
                window.ReactNativeWebView.postMessage('success'); 
                window.ReactNativeWebView.postMessage(response);
            },
            onError: function (response) {
                window.ReactNativeWebView.postMessage('failed');
                window.ReactNativeWebView.postMessage(response);
            }
        });
    `);
  };

  const onMessage = event => {
    console.log('onMessage:');
    console.log(event.nativeEvent.data);
  };

  return (
    <SafeAreaView style={styles.container}>
      {redirectUrl ? (
        <View style={{flex: 1}}>
          <WebView
            ref={webViewRef}
            onMessage={onMessage}
            javaScriptEnabledAndroid={true}
            textZoom={100}
            mixedContentMode={'compatibility'}
            originWhitelist={['*']}
            injectedJavaScript={INJECTED_JAVASCRIPT}
            source={{
              uri: redirectUrl,
            }}
          />
          <Button onPress={onSubmit} title="Submit" />
        </View>
      ) : (
        <Text>Loading...</Text>
      )}
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 30,
  },
});

The Payment Page is from https://wpp-test.wirecard.com/loader/paymentPage.js and I made a String out of it to insert it into the injectedJavaScript property.

Should this not work? Any ideas? Maybe this issue should be opened again...

@zenpi-me
Copy link

I solved this by using the onLoad prop.
I load the following function into onLoad:

  const injectJSFileFromWeb = () => {
    webViewRef.current.injectJavaScript(
      `var corescript = document.createElement('script');
        corescript.type = 'text/javascript';
        corescript.src = "https://url/to/code.js";
        var parent = document.getElementsByTagName('head').item(0);
        parent.appendChild(corescript);
        console.log('loaded...')`,
    );
  };

I red that you should care about the linebreaks.

Using this method I can access variables when calling the injectJavaScript method.

@ccfz
Copy link

ccfz commented Apr 15, 2020

This is still a problem on version: 9.1.4. I could not try 9.2.0 because of another known build error. Once the fix for 9.2.0 is released I try it as well. But for the moment the workaround that @svdo posted above worked for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants