How to use Cordova InAppBrowser into a HostedWebAp

2019-08-31 15:39发布

问题:

I have a website with 2 mobile-apps displayed with Cordova, and they works really great. But I have a problem :

When an external link is triggered by the user, he go out of the application and don't have any possibility to come back on the App... (except close and reopen).

I have installed inappbrowser according to this tutorial. Sounds very simple but not working...

Console :

cordova plugin add cordova-plugin-inappbrowser

Link (supposed to trigger InAppBrowser - not working) :

 <a href="#" onclick="window.open('http://www.google.com', '_blank', 'location=yes', 'toolbar=yes'); return false;">www.google.com</a>

And I just remembered, that my apps are displayed with a technique named Hosted Web App. And maybe it's what InAppBrowser does not work : we are already in a webbrowser ?!

I will snip my config & js code bellow, here's the tutorial of Microsoft who helped me on the App setting.

Goal : find a way to use InAppBrowser, because we have a lot of external links in our website.

Any ideas please ? Many thanks !

Here is the code :

Index.js

var app = {
    // Application Constructor
    initialize: function() {
    this.bindEvents();
    },
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        app.receivedEvent('deviceready');

        // Here, we redirect to the web site.
        var targetUrl = "https://www.website.test/";
        var bkpLink = document.getElementById("bkpLink");
        bkpLink.setAttribute("href", targetUrl);
        bkpLink.text = targetUrl;
        window.location.replace(targetUrl);
},
    // Note: This code is taken from the Cordova CLI template.
    receivedEvent: function(id) {
        var parentElement = document.getElementById(id);
        var listeningElement = parentElement.querySelector('.listening');
        var receivedElement = parentElement.querySelector('.received');

        listeningElement.setAttribute('style', 'display:none;');
        receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    }
};

app.initialize();

App.js

/*global app, $on */
(function () {
  'use strict';

  /**
   * Sets up a brand new Todo list.
   *
   * @param {string} name The name of your new to do list.
   */
  function Todo(name) {
    this.storage = new app.Store(name);
    this.model = new app.Model(this.storage);
    this.template = new app.Template();
    this.view = new app.View(this.template);
    this.controller = new app.Controller(this.model, this.view);
  }

  var todo = new Todo('todos-vanillajs');

  function setView() {
    todo.controller.setView(document.location.hash);
  }
  $on(window, 'load', setView);
  $on(window, 'hashchange', setView);

    var onSuccess = function(position) {
        var geotext = document.getElementById('geotext');
        geotext.textContent = 'Latitude: ' + position.coords.latitude + '\n' +
          'Longitude: ' + position.coords.longitude;
    };

    var onError = function onError(error) {
    alert('code: '    + error.code    + '\n' +
          'message: ' + error.message + '\n');
    }

    var button = document.getElementById('geo');
    button.addEventListener("click", function(){
                          navigator.geolocation.getCurrentPosition(onSuccess, onError);
                          });


    function myOnDeviceReady() {
        if (navigator.connection.type == Connection.NONE) {
            navigator.notification.alert('An internet connection is required to continue');
        } else {
            window.location="https://www.website.test/";
        }
    }
    document.addEventListener("deviceready", myOnDeviceReady, false);

})();

Index.html

<!DOCTYPE html>
<html>
<head>

  <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
  <meta name="format-detection" content="telephone=no">
  <meta name="msapplication-tap-highlight" content="no">
  <meta name="viewport" content="viewport-fit=cover, initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://www.website.test/ https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
  <title>mysite</title>
  <link rel="stylesheet" href="node_modules/todomvc-common/base.css">
  <link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
  <link rel="stylesheet" type="text/css" href="css/overrides.css" />
</head>
<a id="bkpLink" href="https://www.website.test/" class="mysite_font">mysite</a>

  <div class="app">
      <img src="img/logo_gradient.png" style="width: 200px;">
      <div id="deviceready" class="blink">
          <p class="mysite_font event listening">Chargement de l'app...</p>
          <p class="mysite_font event received">Chargement...<br/>Merci de patienter quelques instants.</p>
      </div>
  </div>
  <script type="text/javascript" src="scripts/index.js"></script>
  <script type="text/javascript" src="cordova.js"></script>
  <script src="node_modules/todomvc-common/base.js"></script>
  <script src="js/helpers.js"></script>
  <script src="js/store.js"></script>
  <script src="js/model.js"></script>
  <script src="js/template.js"></script>
  <script src="js/view.js"></script>
  <script src="js/controller.js"></script>
  <script src="js/app.js"></script>
  <script type="text/javascript" src="js/index.js"></script>
</html>

回答1:

From your question and follow ups, I'm assuming you are loading in yourwebsite.com into your mobile app, then on yourwebsite.com you want to open external links but keep otherwebsite.com within your app. If I'm understanding correctly, you can load yourwebsite.com in your mobile app and open external links with inAppBrowser by sending a postMessage() back to your mobile app with the external link.

First, loading in yourwebsite.com within an <iframe> on your mobile app:

<iframe src="https://www.yourwebsite.com">

On yourwebsite.com, when an external link is clicked (in my example, this anything with . external_url class and you'll most likely have to use querySelectorAll instead for multiple links), capture it with JS and send the href value back to the mobile app with postMessage():

document.querySelector('.external_url').addEventListener('click', function(event) {
  event.preventDefault(); // stops the user from loading this link
  var data = {'external_url': event.target.href};
  window.parent.postMessage(data, '*');
});

Back on your mobile app, you need to listen to incoming postMesssage(). And trigger inAppBrowser to open the external url that was passed back from yourwebsite.com.

window.addEventListener('message', function(event) {
  if (event.data.external_url) {
    window.cordova.InAppBrowser.open(event.data.external_url, '_blank', 'location=no');
  }
}, true);

I have not tested this code, but it should get you pointed in the right direction with a few changes.