web-dev-qa-db-fra.com

Comment accéder à l'API phonegap depuis une page distante

Je dois suivre la situation suivante: J'ai déjà une page Web distante et je veux développer une application qui utilise cette page. Jusqu'ici, tout va bien. Lorsque je lance l'application, le index.html local est chargé et il redirige (window.open target: _self) vers le site Web externe. Ce site Web est ouvert dans la vue Web de Phonegap. Sur le site Web externe, j’ai ajouté le cordova.js afin d’avoir accès à l’API native de phonegap. Mais ça ne marche pas correctement. L'événement deviceReady est déclenché correctement, mais je n'ai pas accès à l'API phonegap, par exemple navigator.camera.

Comment puis-je le faire, pour avoir accès à l'API?

Veuillez ne pas commenter qu'il sera rejeté par l'AppStore, etc.

Merci de votre aide!

23
riedelinho

Pour moi, la solution était un mélange de plusieurs sources, mais la majeure partie de la solution a été trouvée ici .

Ce que vous devez faire est le suivant:

  1. Définissez votre config.xml pour qu'il pointe directement vers le index.html distant.

    <content src="http://your-remote-location/index.html" />
    
  2. Dans votre index.html, toute référence à une ressource de périphérique Android locale est précédée d'un préfixe unique tel que **injection**. Par exemple, pour cordova.js, vous obtiendrez quelque chose comme:

    <script type="text/javascript" src="**injection**www/cordova.js"></script>
    
  3. Recherchez SystemWebViewClient.Java à l'emplacement suivant: your-project-location\platforms\Android\CordovaLib\src\org\Apache\cordova\engine.

  4. Ajoutez la déclaration d'énumération suivante dans la section private members de la classe en haut: 

    private enum WebExtension {
        PNG, MP3, MP4, TTF, SVG, JS, ICO, HTML, CSS, EOT, WOFF, JSON;
    }
    
  5. Localisez la méthode shouldInterceptRequest et ajoutez ce qui suit après la ligne try {:

    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
        }
    }
    

Le résultat de tout cela sera l'interception de chaque demande de ressource. Si elle contient la chaîne **injection**, elle coupera l'emplacement de la ressource et la demandera à l'emplacement du périphérique local sous lequel l'application est en cours d'exécution. Le mimeType est nécessaire pour charger la ressource de manière correcte par le navigateur de l'application.

J'espère que ça aide quelqu'un.

12
Lentyai

L'inclusion du script cordova.js dans le site distant sera une tâche délicate, car il existe un fichier cordova.j différent pour chaque plate-forme. Vous pouvez modifier le serveur pour qu'il renvoie le bon fichier cordova.js basé sur l'agent utilisateur, mais ceci est également délicat car il inclura ce script lorsque vous visualiserez le site à partir d'un navigateur mobile, ce qui n'est pas souhaitable car des erreurs de JavaScript peuvent être générées. montré à l'utilisateur. Même histoire lorsque vous consultez le site depuis un ordinateur de bureau, le fichier cordova.js ne doit pas être inclus.

Il me semble que vous avez une page Web locale (avec le script cordova inclus) et à partir de là, vous passez à la page distante (qui inclut également le script). Je ne suis pas sûr que ce changement de page va fonctionner. Si cela fonctionne, vous devrez peut-être attendre le deuxième événement deviceready.

Mais vous pouvez simplement définir la page du site distant en tant que page racine dans l'application Cordova, sans avoir besoin d'une page "chargeur" ​​intermédiaire. Il suffit de le définir dans le fichier config.xml:

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

Vous devez vous assurer que vous autorisez le chargement de votre site dans l'application. Dans ce même fichier, vous devriez ajouter:

<access Origin="http://your.website.fake" subdomains="true"/> 
9
Mister Smith

Ce plugin résout le problème sans avoir à vous coder vous-même une solution Android.

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

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

Le plug-in d'injection à distance permet à un site distant d'interagir avec les API javascript de cordova lorsqu'il est chargé dans votre application cordova.

  • Injecte cordova et le plugin JS installé dans la vue Web de toute page parcourue à distance, leur permettant ainsi d’obtenir le même accès à l’objet Cordova et à ses plugins qu’une application cordova fournie.

  • Prise en charge des plateformes iOS et Android.

Je l'ai testé et ça fonctionne très bien. La seule chose dont vous devez vous souvenir est que vous devez attendre que Cordova soit prête, comme ceci:

<html>
  <head>
  </head>
  <body>
    <script>
      document.addEventListener("deviceready", function() {
          document.write("Now you can use plugins"); 
      }, false);
    </script>
  </body>
</html>
9
jperelli

J'ai eu ce problème aussi et changer les choses dans config.xml (balises content et access) ne fonctionnait pas. J'ai examiné l'application pendant son exécution sur le téléphone et j'ai découvert que certains fichiers manquaient lors du chargement du site distant.

Tout d’abord, c’est le fichier cordova_plugins.js que vous pouvez trouver pour chaque plate-forme dans le dossier de la plate-forme. Ensuite, vous avez également besoin de fichiers spécifiques au plugin. Vous pouvez les trouver en construisant et en les extrayant. Pour Android, le chemin est le suivant APK/assets/www/plugins. Copiez simplement le contenu sur votre serveur et vous êtes prêt à partir. 

NOTE: vous pouvez également trouver les fichiers spécifiques au plug-in dans le dossier de la plate-forme, mais ils sont incomplets car ils manquent cordova.define ("... au début. Cela conduit à required et module étant indéfini, il suffit donc de construire et de les obtenir à partir de là.

7
sorin7486

C'est une limitation imposée par Cordova/PhoneGap ici :

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

J'ai déjà désactivé cette vérification pour permettre à Cordova de travailler avec des adresses de fichiers non locales.

0
Rivera

J'ai travaillé pendant très longtemps pour que cela fonctionne pour le débogage rapide de phoneGap, mais je ne pouvais pas trouver le moyen de faire fonctionner l'API sans avoir cordova.js avec l'application (pas sur un emplacement distant).

Je ne sais pas exactement pourquoi cela ne fonctionne pas. Si vous connaissez le fonctionnement interne, je suis impatient de l'entendre ...

La dernière chose que j'ai essayée a été de mettre un iframe 100% par 100% dans le code HTML principal et de charger le fichier cordova.js local dans le même document. Ensuite, j'ai pu utiliser l'API, mais il y avait des problèmes de dimensionnement sur iOS, ce qui est une autre question ...

Je ne me souviens pas de la manière exacte dont j'ai implémenté et structuré ceci, mais je vais l'éditer si je peux le trouver.

0
Ali Naci Erdem