How to get access to phonegap API from a remote page

riedelinho picture riedelinho · Feb 24, 2014 · Viewed 13.8k times · Source

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!

Answer

Lentyai picture Lentyai · Apr 18, 2016

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.