在 React Native WebView 中从注入的 JavaScript 接收消息

Posted

技术标签:

【中文标题】在 React Native WebView 中从注入的 JavaScript 接收消息【英文标题】:Receiving message from injected JavaScript in a React Native WebView 【发布时间】:2018-10-19 14:08:27 【问题描述】:

在我的 React Native 应用程序中,我使用“injectedjavascript”道具使用 WebView 来显示谷歌广告 (AdSense)。问题是我无法提前知道广告的高度。所以我一开始给它一个随机高度,当它的样式更新时,我打算正确设置它的高度。

我假设我必须在注入的 JS 代码中获取高度,然后使用“window.postMessage()”方法通过“onMessage”属性将其发送到 WebView。

MutationObserver 结合 promise 似乎非常适合这种情况。现在,我只想接收来自 webview 的消息。所以这是我现在的代码,但没有发送任何消息:

export default class App extends Component 
constructor(props) 
    super(props);


_onMessage(e) 
    console.warn(e.nativeEvent.data);


render() 
    const jsCode = ` 
        window._googCsa('ads', pageOptions, adblock1);

        function waitForAdSense(id) 
            var config = 
                attributes: true,
                attributeFilter: ['style'],
            ;

            return new Promise((resolve, reject) => 
            var adSenseElement = document.body.getElementById(id);
            if (adSenseElement.style) 
                resolve(adSenseElement.style.height);
                return;
            
            var observer = new MutationObserver(function(mutations) 
                mutations.forEach(function(mutation) 
                if (mutation.attributeName === 'style') 
                    observer.disconnect();
                    resolve(adSenseElement);
                    return;
                
            );
        );
        observer.observe(adSenseElement, config);
    );
    

    waitForAdSense('afscontainer1').then(height => 
    window.postMessage(height, '*');
    );
    `;
    return (
    <ScrollView>
        <WebView
        key='AdSense'
        ref='webview2'
        style= height: 300 
        source=
            uri: isandroid
            ? 'file:///android_asset/widget/adSense.html'
            : './widget/index.html',
        
        javaScriptEnabled=true
        mixedContentMode="compatibility"
        injectedJavaScript=jsCode
        scrollEnabled=false
        domStorageEnabled=true
        onMessage=this._onMessage
        scalesPageToFit
        startInLoadingState=true
        automaticallyAdjustContentInsets=false
        />
        ;
    </ScrollView>
    );


虽然,我可以让它与这段代码一起工作,但 setTimeout 不是最好的解决方案:

  window._googCsa('ads', pageOptions, adblock1);

  var adSenseContainer = document.getElementById("afscontainer1");

  setTimeout(function() window.postMessage(adSenseContainer.style.height, '*'); ,1000); 

你有什么想法吗?我认为我的函数 waitForAdSense() 可能会以某种方式被窃听。提前致谢!

【问题讨论】:

为什么使用 AdSense 而不是 AdMob? 此特定广告是 iframe,需要在 WebView 中实现。 那么这个特定的广告可能需要使用移动标准实施到移动设备上 【参考方案1】:

最好的解决方案是在 React Native 移动应用程序上使用 AdMob 而不是 AdSense。由于 AdSense javascript 没有考虑到这个用例,因此处理这些问题是毫无意义的。这是一个 library,可轻松将 AdMob 集成到您的应用中。

【讨论】:

【参考方案2】:

我设法使它与注入代码中的这些更改一起工作:

window._googCsa('ads', pageOptions, adblock1);

  function waitForAdSense() 
      var config = 
          attributes: true,
          attributeFilter: ["style"]
      ;

      var adSenseContainer = document.getElementById("afscontainer1");

      return new Promise((resolve, reject) => 
          var observer = new MutationObserver(function (mutations) 
              mutations.forEach(function (mutation) 
                  if (mutation.attributeName === 'style' && adSenseContainer.style.height) 
                      var height = adSenseContainer.style.height;
                      resolve(height);
                      observer.disconnect();
                      return;
                  ;
              );
          );
          observer.observe(adSenseContainer, config);
      );
  ;

    waitForAdSense().then(height => 
        window.postMessage(height, '*');
    );

感谢您的建议!

【讨论】:

以上是关于在 React Native WebView 中从注入的 JavaScript 接收消息的主要内容,如果未能解决你的问题,请参考以下文章

从 React Native App 中的 WebView 打开动态链接

WebView(react-native-webview)在 Expo SDK36 中获取错误代码 -1

React Native WebView 状态栏

React-native:如何自动保存 webview 当前网页?

有啥方法可以在 react-native-webview 中禁用 hapticFeedback

如何在 iOS 的 WebView(react-native-webview) 中设置自定义字体?