How to get access to phonegap API from a remote pa

2019-01-22 02:57发布

I have to following situation: I have a already existing remote webpage and i want to develope an app which uses this page. So far, so good. When I start the app the local index.html is loaded and it redirects (window.open target: _self) to the external website. This website is opened in the phonegap webview. On the external website I added the cordova.js in order to get access to the native phonegap API. But it doesn't work correctly. The deviceReady event is triggered correctly, but I have no access to the phonegap API, for example navigator.camera.

How can I get it done, to get access to the API?

Please do not comment that it will be rejected by AppStore etc. etc.

Thank you for your help!

6条回答
smile是对你的礼貌
2楼-- · 2019-01-22 03:17

This plugin solves the problem without having to code yourself an android solution.

https://www.npmjs.com/package/cordova-plugin-remote-injection

https://github.com/TruckMovers/cordova-plugin-remote-injection

The remote injection plugin allows a remote site to interact with cordova's javascript APIs when loaded within your cordova app.

  • Injects cordova and installed plugin JS into the webview for any remotely browsed page allowing them the same access to the cordova object and its plugins as a packaged cordova app.

  • Support for iOS and Android platforms.

I tested it and it works just fine. The only thing you need to remember is that you'll need to wait for cordova to be ready, like this:

<html>
  <head>
  </head>
  <body>
    <script>
      document.addEventListener("deviceready", function() {
          document.write("Now you can use plugins"); 
      }, false);
    </script>
  </body>
</html>
查看更多
干净又极端
3楼-- · 2019-01-22 03:20

I have worked to make it work for a very long time for phoneGap quick-debugging but could not find a way to make the API working without having the cordova.js together with the app (not on a remote location).

I don't know exactly why this does not work. If you know the internal workings I'm looking forward to hearing it...

The last thing I've tried was to put a 100% by 100% iframe in the main html and load the local cordova.js in the same document. Then I was able to use the API but there were some scaling issues on iOS, which is another question...

I do not remember the exact way I've implemented and structered this, but I'll edit if I can find it.

查看更多
再贱就再见
4楼-- · 2019-01-22 03:25

I've had this problem as well and changing things in config.xml(content and access tags) didn't work. I inspected the app while it was running on the phone and I discovered that when I loaded the remote site there were some files missing.

First off it's the file called cordova_plugins.js which you can find for each platform in the platform folder. Then you also need some plugin specific files. You can find these by doing a build and extracting them from there. For android the path is as follows APK/assets/www/plugins. Just copy the contents on your server and you're good to go.

NOTE: you can also find the plugin specific files in the platform folder, but they are incomplete as they're missing cordova.define("... at the beginning. This leads to required and module being undefined, so just do a build and get them from there.

查看更多
混吃等死
5楼-- · 2019-01-22 03:26

Well, for me the solution was a mixture of several sources, but most of the solution was found here.

What you should do is the following:

  1. Define your config.xml to point directly to the remote index.html.

    <content src="http://your-remote-location/index.html" />
    
  2. In your index.html any reference to a local android device resource prepend with some unique prefix like **injection**. For instance for cordova.js you'll come up with something like:

    <script type="text/javascript" src="**injection**www/cordova.js"></script>
    
  3. Find SystemWebViewClient.java under the following location: your-project-location\platforms\android\CordovaLib\src\org\apache\cordova\engine.

  4. Add the following enum declaration in the private members section of the class at the top:

    private enum WebExtension {
        PNG, MP3, MP4, TTF, SVG, JS, ICO, HTML, CSS, EOT, WOFF, JSON;
    }
    
  5. Locate the shouldInterceptRequest method and add the following right after the try { line:

    if(url != null && url.contains(INJECTION_TOKEN)) {
        String assetPath = url.substring(url.indexOf(INJECTION_TOKEN) + INJECTION_TOKEN.length(), url.length());
        try {
            String mimeType = "text/plain";
    
            String ext = assetPath.substring(assetPath.lastIndexOf(".") + 1, assetPath.length());
            WebExtension extension = WebExtension.valueOf(ext.toUpperCase());
    
            switch(extension) {
                case PNG:
                    mimeType = "image/png";
                    break;
                case MP3:
                    mimeType = "audio/mpeg";
                    break;
                case MP4:
                    mimeType = "video/mp4";
                    break;
                case TTF:
                    mimeType = "application/x-font-ttf";
                    break;
                case SVG:
                    mimeType = "image/svg+xml";
                    break;
                case JS:
                    mimeType = "application/javascript";
                    break;
                case ICO:
                    mimeType = "image/x-icon";
                    break;
                case HTML:
                    mimeType = "text/html";
                    break;
                case CSS:
                    mimeType = "text/css";
                    break;
                case EOT:
                    mimeType = "application/vnd.ms-fontobject";
                    break;
                case WOFF:
                    mimeType = "application/x-font-woff";
                    break;
                case JSON:
                    mimeType = "application/json";
                    break;
            }
    
            WebResourceResponse response = new WebResourceResponse(
                mimeType,
                "UTF-8",
                parentEngine.webView.getContext().getAssets().open(assetPath)
            );
            return response;
        } catch (IOException e) {
            e.printStackTrace(); // Failed to load asset file
        }
    }
    

The result of all of it will be interception of every resource request and in case it will contain the **injection** string in it, it will cut down the resource location and will request it from local device location under which the application is running. The mimeType is necessary to load the resource in the correct manner by the app browser.

Hope it helps someone.

查看更多
爷的心禁止访问
6楼-- · 2019-01-22 03:27

It is a Cordova/PhoneGap imposed limitation here:

    if (startFilePath == nil) {
        loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", self.wwwFolderName, self.startPage];
        NSLog(@"%@", loadErr);
        self.loadFromString = YES;
        appURL = nil;
    }

I have disabled this check in the past to let Cordova work with non-local file addresses.

查看更多
小情绪 Triste *
7楼-- · 2019-01-22 03:36

Including the cordova.js script in the remote site is going to be tricky, because there's a different cordova.js for each platform. You could modify the server so that it returns the correct cordova.js based on the user agent, but this is also tricky because it will include this script when you view the site from a mobile browser, and this is undesirable because javascript errors might be shown to the user. Same story when viewing the site from a desktop computer, the cordova.js should not be included.

It looks to me that you have a local web page (with the cordova script included) and from there you change to the remote page (that also includes the script). I'm not sure this page change is going to work. If it worked, you might have to wait for the second deviceready event.

But you can just set the remote site page as the root page in the cordova app, no need for an intermediate "loader" page. Just set it in the config.xml file:

<content src="http://your.website.fake/index.html" />

You need to make sure that you allow loading your site in the app. In this same file, you should add:

<access origin="http://your.website.fake" subdomains="true"/> 
查看更多
登录 后发表回答