简体   繁体   中英

Hybrid app with remote html and local cordova.js

I have a website that I want to enhance on mobiles with a hybrid app. Ideally the app would load the remote site over http but load the platform specific code locally. I've tried to set up a Cordova project to do this but am having lots of trouble. Cordova 4.3.1, Cordova Android 3.7.2 on a Nexus 7 Android 4.4.4 has been my environment. (The google maps plugin is for Cordova Android < 4.)

If I try to load file:///android_assets/www/cordova.js from an http site, chromium says Not allowed to load local resource . I tried to set up a local URL scheme but don't know what android-specific code to put where.

Is this the right way to make a hybrid app? Is there a cordova plugin to allow loading file: from http:?


I also tried using an iframe and passing messages to indicate cordova is enabled and which plugins are installed, but I don't want to deal with having the http server re-serve the same js files that are already available locally.

I also thought to download the website and access it over file: but I imagine I will have the same problem trying to access http resources.

I am able to load local cordova.js on remote html using cordova-plugin-file ( cdvfile:// ) plugin .

  1. Add cordova-plugin-file plugin to your cordova project https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

  2. Confirm cdvfile URI for cordova.js using below sample code(Android example)

  checkCordovaJSPath('file:///android_asset/www/cordova.js'); function checkCordovaJSPath(jsUri) { window.resolveLocalFileSystemURL(jsUri, function success(fileEntry){ console.log("got cordova.js file: " + fileEntry.fullPath); console.log('cordova.js cdvfile URI: ' + fileEntry.toInternalURL()); }); } 

  1. Load cordova.js using cdvfile://localhost on remote html.

 <script type="text/javascript" src="cdvfile://localhost/assets/www/cordova.js"/> 

I don't know if this is the right way to make a hybrid app, but I got it working by serving assets over http with https://github.com/floatinghotpot/cordova-httpd .

On the local page bundled with the app I have added:

    <script type="text/javascript">
        document.addEventListener("deviceready", function () {
            var httpd = cordova.plugins.CorHttpd;
            httpd.startServer({
                'www_root': '',
                'port': 8080,
                'localhost_only': false
            }, function (url) {
                // if server is up, it will return the url of http://<server ip>:port/
                // the ip is the active network connection
                // if no wifi or no cell, "127.0.0.1" will be returned.
                document.getElementById('url').innerHTML = "server is started: <a href='" + url + "' target='_blank'>" + url + "</a>";
                location.replace('http://192.168.0.134:9090/homechooser/beta/#' + JSON.stringify({'cordova.js': url + '/cordova.js'}));
            }, function (error) {
                document.getElementById('url').innerHTML = 'failed to start server: ' + error;
            });
        }, false);
    </script>
    <div id="url"></div>

Then on the remote webpage I have added:

(function () {
    var hash;
    if (location && location.hash)
        try {
            hash = JSON.parse(location.hash.substring(1));
        } catch (e) {
        }
    if (hash && hash['cordova.js'])
        $.getScript(hash['cordova.js'], function () {
            alert("Running cordova.js");
        });
})();

now to see if cordova can actually be used this way...

Thing is your are trying to load a web-url on the local hosted app, imagine doing the same thing on Native Android App, what would you do? you will place a web-client or a web-browser in your app. But Cordova/Phonegap already uses Web-Browser to render your pages. So its like a using web-browser inside a web browser.

You need to install InAppBrowser which will give you the ability to load 3rd party hosted web pages.

Sample Code

  document.addEventListener("deviceready", onDeviceReady, false);

    // device APIs are available
    //
    function onDeviceReady() {
         var ref = window.open('http://yourWebPage.com', '_blank', 'location=yes');
         ref.addEventListener('loadstart', function(event) { alert('start: ' + event.url); });
         ref.addEventListener('loadstop', function(event) { alert('stop: ' + event.url); });
         ref.addEventListener('loaderror', function(event) { alert('error: ' + event.message); });
         ref.addEventListener('exit', function(event) { alert(event.type); });
    }

The cdvfile solution will not work for active content (js files) because of the mixed content policy. Here is how to make it work:

For android: Disable mixed content policy by putting the following code inside the pluginInitialize method of your cordova plugin:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            final WebSettings settings = ((WebView)this.webView.getView()).getSettings();
      settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        } 

https://developer.android.com/reference/android/webkit/WebSettings.html#MIXED_CONTENT_ALWAYS_ALLOW )

Then include local cordova.js using:

<script src="cdvfile://localhost/assets/www/cordova.js"></script>

For ios: I submitted a PR to the file plugin which solves the mixed content problem on ios: apache/cordova-plugin-file#296 The fixed version is available at: https://github.com/guylando/cordova-plugin-file If you load a remote site https://example.com on the webview then it allows to access local files using the url: https://example.com/cdvfile/bundle/www/cordova.js instead of cdvfile://localhost/bundle/www/cordova.js And by this solves the mixed content problems

Include local cordova.js using:

<script src="/cdvfile/bundle/www/cordova.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM