PhoneGap: détecte s'il est exécuté sur un navigateur de bureau

118

Je développe une application Web qui utilise PhoneGap: Build pour une version mobile et je souhaite avoir une base de code unique pour les versions «bureau» et mobile. Je veux pouvoir détecter si les appels PhoneGap fonctionneront (c'est-à-dire si l'utilisateur sur un appareil mobile prend en charge PhoneGap).

J'ai cherché et je ne peux pas croire qu'il n'y ait pas de moyen simple de faire cela. De nombreuses personnes ont offert des suggestions;

Rien de tout cela ne fonctionne, à moins que vous ne supprimiez le fichier Javascript PhoneGap de la version de bureau de l'application, ce qui va à l'encontre de mon objectif d'avoir une base de code.

Jusqu'à présent, la seule solution que j'ai trouvée est le reniflement du navigateur / agent utilisateur, mais ce n'est pas robuste pour dire le moins. Toutes les meilleures solutions sont les bienvenues!

EDIT: Une solution légèrement meilleure consiste à essayer d'appeler une fonction PhoneGap après un petit délai d'expiration - si cela ne fonctionne pas, supposez que l'utilisateur est sur un navigateur Web de bureau.

Aaronsnoswell
la source
Puisque vous utilisez Build, consultez la réponse de @ bt ci-dessous: stackoverflow.com/a/18478002/241244 . Il semble que ce soit mieux que les réponses acceptées et les mieux votées.
J'évite la détection au moment de l'exécution en faveur d'une configuration explicite au moment de la construction car elle est efficace à 100%. Je passe simplement une variable locale à mon modèle index.jade comme {isPhonegap: true}, puis dans le modèle je peux inclure conditionnellement le script phonegap.js, et effectuer toutes les init spécifiques à phonegap que je veux.
Jesse Hattabaugh

Réponses:

115

J'utilise ce code:

if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/)) {
  document.addEventListener("deviceready", onDeviceReady, false);
} else {
  onDeviceReady(); //this is the browser
}

METTRE À JOUR

Il existe de nombreuses autres façons de détecter si phonegap fonctionne ou non sur un navigateur, voici une autre excellente option:

var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
if ( app ) {
    // PhoneGap application
} else {
    // Web page
}  

comme vu ici: Détecter entre un navigateur mobile ou une application PhoneGap

sirmdawg
la source
Merci pour cela - après avoir attendu longtemps pour voir ce que d'autres personnes ont suggéré, cela semble être la meilleure solution. À votre santé.
aaronsnoswell
35
Ce n'est pas exact, car si j'ouvre la même page sur la navigation de l'appareil, onDeviceReady () n'appellera jamais. De plus, si je change le UserAgent dans le navigateur (à des fins de débogage), onDeviceReady () n'appellera jamais non plus.
Slavik Meltser
3
Je ne sais pas ce que vous dites - mais il semble que vous sous-entendez que cela causera des problèmes lors de l'utilisation du navigateur des téléphones ... C'est une solution à tester sur votre navigateur de bureau et non sur vos téléphones.
sirmdawg
7
Cela n'aide pas lorsque vous ouvrez l'application dans le navigateur de l'appareil. Meilleure solution: recherchez window.cordova. Les tests dans iPhone Simulator (navigateur) ou sur un appareil Android (navigateur) devraient également détecter PhoneGap. C'est comme ça que je me développe. Mais il existe de nombreuses possibilités pour faire avancer les choses. ;-) Merci de publier votre solution!
Mario
Je suis confus, qu'en est-il des autres plates-formes comme Windows Phone? Ont-ils un userAgent qui correspond à cette expression régulière? Une recherche rapide sur Google n'implique pas: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
mooreds
49

J'ai écrit un post à ce sujet il y a quelques jours. C'est la meilleure solution que vous puissiez trouver (jusqu'à ce que PhoneGap publie quelque chose, peut-être ou peut-être pas), c'est court, simple et parfait (je l'ai vérifié de toutes les manières et de toutes les plates-formes possibles).

Cette fonction fera le travail dans 98% des cas.

/**
 * Determine whether the file loaded from PhoneGap or not
 */
function isPhoneGap() {
    return (window.cordova || window.PhoneGap || window.phonegap) 
    && /^file:\/{3}[^\/]/i.test(window.location.href) 
    && /ios|iphone|ipod|ipad|android/i.test(navigator.userAgent);
}

if ( isPhoneGap() ) {
    alert("Running on PhoneGap!");
} else {
    alert("Not running on PhoneGap!");
}

Pour compléter les 2% restants des cas, suivez ces étapes (cela implique une légère modification du code natif):

Créez un fichier appelé __phonegap_index.html , avec la source:

<!-- __phonegap_index.html -->
<script type="text/javascript">
    function isPhoneGap() {
        //the function's content is as described above
    }

    //ensure the 98% that this file is called from PhoneGap.
    //in case somebody accessed this file directly from the browser.
    if ( isPhoneGap() )
        localStorage.setItem("isPhoneGap","1");

    //and redirect to the main site file.
    window.location = "index.html";
</script>

Désormais, en mode natif, changez simplement la page de démarrage de index.html en __phonegap_index.html sur toutes vos plates-formes PhoneGap. Disons que le nom de mon projet est un exemple , les fichiers que vous devez modifier sont (comme pour PhoneGap version 2.2.0):

  • iOS -CordovaLibApp/AppDelegate.m
  • Android -src/org/apache/cordova/example/cordovaExample.java
  • Windows 8 -example/package.appxmanifest
  • BlackBerry -www/config.xml
  • WebOS -framework/appinfo.json
  • Bada - src/WebForm.cpp(ligne 56)
  • Window Phone 7 - Aucune idée de l'endroit (quelqu'un est encore en train de développer sur cette plate-forme?!)

Enfin, vous pouvez l'utiliser n'importe où sur votre site, qu'il fonctionne sur PhoneGap ou non:

if ( localStorage.getItem("isPhoneGap") ) {
    alert("Running on PhoneGap!");
} else {
    alert("Not running on PhoneGap!");
}

J'espère que ça aide. :-)

Slavik Meltser
la source
4
J'ai trouvé que cette réponse était la meilleure!
blong824
3
oui cela fonctionne mais parfois la partie suivante du code n'est pas vraie /^file:\/{3}[^\/]/i.test(window.location.href)mais nous utilisons PhoneGap, par exemple lors du chargement de l'index.html à partir d'une autre page, sur config.xml quelque chose comme ça<content src="http://10.100.1.147/" />
vudduu
3
L'expression (cordova || PhoneGap || phonegap) lèvera une ReferenceError si l'une de ces variables n'est pas définie. Vous devriez tester avec typeof cordova !== undefined, non?
rojobuffalo
1
@rblakeley vous avez raison. J'ai changé la première ligne pour:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
ethanpil
1
@rojobuffalo: On dirait que la réponse a depuis été modifiée, la faisant fonctionner à nouveau comme prévu ( c'est- à- dire qu'elle ne lance ReferenceErrorplus un à cause du windowpréfixe). Je pensais juste que je le soulignerais, car cela rend la chaîne de commentaires obsolète (et donc incorrecte).
Priidu Neemre
27

Je sais que cela a été répondu il y a un certain temps mais "PhoneGap.available" n'existe plus. Tu devrais utiliser:

if (window.PhoneGap) {
  //do stuff
}

ou depuis 1.7, préférez:

if (window.cordova) {
  //do stuff
}

EDIT 2019: comme indiqué dans les commentaires, cela ne fonctionne que si vous n'incluez pas cordova lib dans la version de votre navigateur de bureau. Et bien sûr, il est recommandé d'inclure uniquement les fichiers javascript / html / css minimum stricts pour chaque appareil que vous ciblez

fredericrous
la source
18
Ce n'est pas vrai, car window.PhoneGap ou window.cordova seront toujours définis si vous incluez le script cordova-xxxjs, même s'il est chargé sur le navigateur.
Slavik Meltser
Pouvez-vous m'aider un exemple.Pour simplement charger l'index.html.Ce que je fais, c'est que j'ai téléchargé tous les fichiers sous le dossier www sur mon serveur local, je charge l'index.html.Mais l'appareil est prêt n'est pas viré.
Nassif
5
Cela semble être la bonne réponse maintenant (avec Cordova 3.4, au moins). Toutes les autres méthodes sont juste une perte de temps puisque cordova.js est injecté dans l'application avec un simple <script type = "text / javascript" src = "cordova.js"> </script> maintenant. Vous ne pointez pas réellement vers le fichier réel, il n'est donc pas chargé lors de l'exécution dans un navigateur. Ce n'est que dans une version Cordova fonctionnant sur un appareil mobile.
Michael Oryl
Cela semble fonctionner particulièrement bien si vous utilisez PhoneGap Build.
4
@SlavikMe N'incluez pas le script cordova dans les versions non cordova.
Jackson
21

Le moyen le plus fiable que nous ayons trouvé pour savoir si nous sommes dans une application cordova / phonegap est de modifier l'agent utilisateur de l'application cordova à l' aide de cette configuration AppendUserAgent .

En config.xmlplus:

<preference name="AppendUserAgent" value="Cordova" />

Puis appelez:

var isCordova = navigator.userAgent.match(/Cordova/i))

Pourquoi?

  1. window.cordovaet document.addEventListener('deviceready', function(){});sont soumis aux conditions de course
  2. navigator.standalonene fonctionne pas quand <content src="index.html" />est un site Web (Ex: <content src="https://www.example.com/index.html" />ou avec cordova-plugin-remote-injection )
  3. Essayer de mettre des agents utilisateurs sur liste blanche pour deviner s'il s'agit d'un vrai navigateur est très compliqué. Les navigateurs Android sont souvent des vues Web personnalisées.
jrobichaud
la source
2
Et nous pouvons même y ajouter la version de l'application! (idéalement avec une logique de bump de version automatisée) ex; Cordova AppName/v0.0.1<3 Donc, de cette façon, vous pouvez même l'utiliser pour le suivi (mais notez que n'importe qui peut modifier son useragent, alors ne vous fiez pas à cela pour les vérifications critiques de sécurité)
GabLeRoux
Cela semble être la méthode la plus infaillible. Le deuxième finaliste semble tester l'absence de http: // ou https: // dans l'URL du document, mais je peux envisager des scénarios possibles où cela ne fonctionnerait pas.
JD Smith le
14

Je pense que c'est le plus simple: var isPhoneGap = (location.protocol == "file:")

EDIT Pour certaines personnes, cela n'a pas fonctionné. Ensuite, vous pourriez essayer (pas testé)

var isPhoneGap = ! /^http/.test(location.protocol);
Yuval
la source
1
Je pensais que PhoneGap exécutait un serveur interne pour tous ses fichiers sur l'appareil?
aaronsnoswell
Je l'aime. Lors du développement sur localhost, c'est la meilleure solution. (Après avoir beaucoup essayé, j'espère que cela fonctionne dans tous les scénarios, j'espère.) Thx!
Mario
1
cela ne fonctionne pas dans l'émulateur
Ripple
Ne fonctionne pas non plus dans WP8, le protocole est "x-wmapp0:". Je ne peux pas savoir avec certitude quels autres "protocoles" seront utilisés à l'avenir.
Adrian
Eh bien, vous pouvez aussivar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval
8

Cela fonctionne pour moi (exécutant 1.7.0)

if (window.device) {
  // Running on PhoneGap
}

Testé sur les ordinateurs de bureau Chrome et Safari.

Rob
la source
3
C'est presque la même chose que la liaison à l'événement «deviceready». Si window.device n'est pas défini, vous ne pouvez pas dire si phonegap / cordova est lent à se charger ou si l'événement ne se déclenchera jamais.
Wytze
8
window.device n'est pas défini avant le déclenchement de l'événement "deviceready".
Slavik Meltser
2
Et priez pour qu'aucun autre programmeur n'ait l'heureuse idée de définir une nouvelle variable globale appelée "périphérique".
Mister Smith
7

Comme l'affiche originale, j'utilise le service de build phonegap. Après deux jours et près de 50 versions de test, j'ai trouvé une solution élégante qui fonctionne très bien pour moi.

Je ne pouvais pas utiliser UA sniffing car je voulais tester et exécuter dans des navigateurs mobiles. J'avais initialement opté pour la technique assez fonctionnelle de Cobberboy. Cela n'a pas fonctionné pour moi car le délai / délai d'expiration «howPatientAreWe: 10000» était trop gênant pour le développement dans le navigateur. Et le régler plus bas échouerait parfois le test en mode application / appareil. Il devait y avoir un autre moyen ...

Le service de build phonegap nécessite que le phonegap.jsfichier soit omis de votre référentiel de code avant de soumettre les fichiers de votre application au service. Par conséquent, je suis en mesure de tester son existence pour déterminer si elle fonctionne dans un navigateur par rapport à une application.

Une autre mise en garde, j'utilise également jQueryMobile, donc jQM et phonegap ont dû s'initialiser avant de pouvoir commencer un script personnalisé. Le code suivant est placé au début de mon fichier index.js personnalisé pour l'application (après jQuery, avant jQM). Les documents de construction de phonegap indiquent également qu'il faut placer <script src="phonegap.js"></script>quelque part dans le HTML. Je le laisse complètement de côté et le charge en utilisant $ .getScript () pour tester son existence.

isPhoneGap = false;
isPhoneGapReady = false;
isjQMReady = false;

$.getScript("phonegap.js")
.done(function () {
    isPhoneGap = true;
    document.addEventListener("deviceready", function () {
        console.log("phonegap ready - device/app mode");
        isPhoneGapReady = true;
        Application.checkReadyState();
    }, false);
})
.fail(function () {
    console.log("phonegap load failed - browser only");
    isPhoneGapReady = true;
    Application.checkReadyState();
});

$(document).bind("mobileinit", function () {
    Application.mobileInit();
    $(document).one("pageinit", "#Your_First_jQM_Page", function () {
        isjQMReady = true;
        Application.checkReadyState();
    });
});

Application = {
    checkReadyState: function () {
        if (isjQMReady && isPhoneGapReady) {
            Application.ready();
        }
    },
    mobileInit: function () {
        // jQM initialization settings go here
        // i.e. $.mobile.defaultPageTransition = 'slide';
    },
    ready: function () {
        // Both phonegap (if available) and jQM are fired up and ready
        // let the custom scripting begin!
    }
}
Jim H.
la source
6

Fait intéressant, de nombreuses réponses, mais elles n'incluent pas ces trois options:

1 - Le cordova.js définira l'objet cordova dans la portée globale. Si c'est le cas, vous utilisez probablement une lunette Cordova.

var isCordovaApp = !!window.cordova;

2 - Cordova exécutera votre application comme vous ouvririez un document HTML depuis votre bureau. Au lieu du protocole HTTP, il utilisera FILE. Détecter cela vous donnera une chance de supposer que votre application a été chargée localement.

var isCordovaApp = document.URL.indexOf('http://') === -1
  && document.URL.indexOf('https://') === -1;

3 - Utilisez l'événement load du script cordova pour détecter le contexte. Le script include peut être facilement supprimé dans le processus de construction ou le chargement du script échouera simplement dans un navigateur. Pour que cette variable globale ne soit pas définie.

<script src="../cordova.js" onload="javascript:window.isCordovaApp = true;"></script>

Le crédit revient à Damien Antipa d'Adobe

Frodik
la source
5

J'utilise cette méthode:

debug = (window.cordova === undefined);

debugsera truesur l'environnement du navigateur, falsesur l'appareil.

andreszs
la source
4

Cela semble viable et je l'ai utilisé en production:

if (document.location.protocol == "file:") {
    // file protocol indicates phonegap
    document.addEventListener("deviceready", function() { $(initInternal);} , false);
}
else {
    // no phonegap, start initialisation immediately
    $(initInternal);
}

Source: http://tqcblog.com/2012/05/09/detecting-phonegap-cordova-on-startup/

Deminetix
la source
3

L'essence du problème est que tant que cordova.device n'est pas défini, votre code ne peut pas être sûr si c'est parce que cordova a établi que votre appareil n'est pas pris en charge, ou si c'est parce que cordova se prépare toujours et que deviceready se déclenchera plus tard. (ou troisième option: cordova ne s'est pas chargé correctement).

La seule solution est de définir une période d'attente et de décider qu'après cette période, votre code doit supposer que l'appareil n'est pas pris en charge. Je souhaite que cordova définisse un paramètre quelque part pour dire "Nous avons essayé de trouver un périphérique pris en charge et avons abandonné", mais il semble qu'il n'y ait pas de tel paramètre.

Une fois que cela est établi, vous voudrez peut-être faire quelque chose de spécifique précisément dans les situations où il n'y a pas de périphérique pris en charge. Comme cacher des liens vers le marché des applications de l'appareil, dans mon cas.

J'ai reconstitué cette fonction qui devrait couvrir à peu près toutes les situations. Il vous permet de définir un gestionnaire deviceready, un gestionnaire de périphérique jamais prêt et un temps d'attente.

//Deals with the possibility that the code will run on a non-phoneGap supported
//device such as desktop browsers. Gives several options including waiting a while
//for cordova to load after all.
//In:
//onceReady (function) - performed as soon as deviceready fires
//patience 
//  (int) - time to wait before establishing that cordova will never load
//  (boolean false) - don't wait: assume that deviceready will never fire
//neverReady 
//  (function) - performed once it's established deviceready will never fire
//  (boolean true) - if deviceready will never fire, run onceReady anyhow
//  (boolean false or undefined) - if deviceready will never fire, do nothing
function deviceReadyOrNot(onceReady,patience,neverReady){

    if (!window.cordova){
            console.log('Cordova was not loaded when it should have been')
            if (typeof neverReady == "function"){neverReady();}
        //If phoneGap script loaded...
        } else {
            //And device is ready by now...
            if  (cordova.device){
                callback();
            //...or it's loaded but device is not ready
            } else {
                //...we might run the callback after
                if (typeof patience == "number"){
                    //Run the callback as soon as deviceready fires
                    document.addEventListener('deviceready.patience',function(){
                        if (typeof onceReady == "function"){onceReady();}
                    })
                    //Set a timeout to disable the listener
                    window.setTimeout(function(){
                        //If patience has run out, unbind the handler
                        $(document).unbind('deviceready.patience');
                        //If desired, manually run the callback right now
                        if (typeof neverReady == 'function'){neverReady();}
                    },patience);
                //...or we might just do nothing
                } else {
                    //Don't bind a deviceready handler: assume it will never happen
                    if (typeof neverReady == 'function'){neverReady();} 
                    else if (neverReady === true){onceReady();} 
                    else {
                       //Do nothing
                    }
                }
            }
    }

}
Wytze
la source
3

La façon dont je le fais est d'utiliser une variable globale qui est écrasée par une version de cordova.js réservée au navigateur. Dans votre fichier html principal (généralement index.html), j'ai les scripts suivants qui dépendent de l'ordre:

    <script>
        var __cordovaRunningOnBrowser__ = false
    </script>
    <script src="cordova.js"></script> <!-- must be included after __cordovaRunningOnBrowser__ is initialized -->
    <script src="index.js"></script> <!-- must be included after cordova.js so that __cordovaRunningOnBrowser__ is set correctly -->

Et à l'intérieur cordova.jsj'ai simplement:

__cordovaRunningOnBrowser__ = true

Lors de la construction pour un appareil mobile, le cordova.js ne sera pas utilisé (et à la place le fichier cordova.js spécifique à la plate-forme sera utilisé), donc cette méthode a l'avantage d'être 100% correcte quels que soient les protocoles, userAgents ou bibliothèque variables (qui peuvent changer). Il y a peut-être d'autres choses que je devrais inclure dans cordova.js, mais je ne sais pas encore ce qu'elles sont.

BT
la source
Approche très intéressante.
Cependant, vous n'avez pas vraiment besoin du script initial. Vous pouvez simplement tester pour qu'il soit réglé du tout: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } .. d'accord?
Bien, bien que ce ne soit pas défini, cela pourrait indiquer que quelque chose d'autre ne va pas.
BT
3

Une autre façon, basée sur la solution SlavikMe:

Utilisez simplement un paramètre de requête transmis à index.htmlpartir de votre source PhoneGap. Ie, sous Android, au lieu de

super.loadUrl("file:///android_asset/www/index.html");

utilisation

super.loadUrl("file:///android_asset/www/index.html?phonegap=1");

SlavikMe a une excellente liste sur où faire cela sur d'autres plates-formes.

Ensuite, vous index.htmlpouvez simplement faire ceci:

if (window.location.href.match(/phonegap=1/)) {
  alert("phonegap");
}
else {
  alert("not phonegap");
}
Andrew Magee
la source
1
J'utilise Cordova 3.4.1 et là c'est encore plus simple: il vous suffit de changer l' <content src="index.html" />option dans le fichier config.xml en <content src="index.html?cordova=1" />. Jusqu'à présent, cela semble fonctionner et est de loin la meilleure solution suggérée ici.
Martin M.
2

Pour garder une base de code, ce qui est intéressant, c'est la «plate-forme» sur laquelle le code s'exécute. Pour moi, cette «plateforme» peut être trois choses différentes:

  • 0: navigateur d'ordinateur
  • 1: navigateur mobile
  • 2: phonegap / cordova

La façon de vérifier la plate-forme:

var platform;
try {
 cordova.exec(function (param) {
   platform = 2;
  }, function (err) {}, "Echo", "echo", ["test"]);
} catch (e) {
  platform = 'ontouchstart' in document.documentElement ? 1 : 0;
}

Remarque:

  • Cela ne doit être exécuté qu'après le chargement de cordova.js (body onload (...), $ (document) .ready (...))

  • 'ontouchstart' dans document.documentElement sera présent dans les ordinateurs portables et les moniteurs de bureau qui ont un écran tactile afin de signaler un navigateur mobile même s'il s'agit d'un ordinateur de bureau. Il existe différentes manières de faire un contrôle plus précis mais je l'utilise car il prend toujours en charge 99% des cas dont j'ai besoin. Vous pouvez toujours remplacer cette ligne par quelque chose de plus robuste.

Nik
la source
1
Je suggère d'utiliser typeof cordova !== 'undefined'au lieu de pêcher une exception.
krakatoa
1

Aarons, essayez

if (PhoneGap.available){
    do PhoneGap stuff;
}
GeorgeW
la source
Non je ne l'ai pas fait. Regardez le code source de phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == undefined;
GeorgeW
1

La solution de GeorgeW est correcte, mais même sur un appareil réel, PhoneGap.available n'est vrai qu'après le chargement des éléments de PhoneGap, par exemple onDeviceReady dans document.addEventListener ('deviceready', onDeviceReady, false) a été appelé.

Avant cette heure, si vous voulez savoir, vous pouvez faire comme ceci:

runningInPcBrowser =
    navigator.userAgent.indexOf('Chrome')  >= 0 ||
    navigator.userAgent.indexOf('Firefox') >= 0

Cette solution suppose que la plupart des développeurs développent en utilisant Chrome ou Firefox.

Ngoc Dao
la source
OP est à la recherche d'une solution pour un site Web de production, pas seulement pour le développement.
Jesse Hattabaugh
1

J'ai le même problème.

Je me penche pour ajouter # cordova = true à l'URL chargée par le client cordova et tester location.hash.indexOf ("cordova = true")> -1 dans ma page Web.

Austin France
la source
Au final, j'ai suivi l'itinéraire proposé par Al Renaud dans son 4ème point, et j'ai laissé le script de construction décider. Il décommente un indicateur dans index.html lors de la copie du code du site Web dans le dossier des actifs Android. // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true; Lorsque le script de construction copie index.html dans mon dossier android assets / www, j'ai exécuté ed dessus pour supprimer la chaîne // UNCOMMENT-ON-DEPLOY:. # Massage index.html pour indiquer qu'il exécute cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin France
1

Ce qui suit fonctionne pour moi avec le plus récent PhoneGap / Cordova (2.1.0).

Comment ça fonctionne:

  • Concept très simple
  • J'ai inversé la logique de certaines des solutions de temporisation ci-dessus.
  • Inscrivez-vous à l'événement device_ready (comme recommandé par la documentation PhoneGap )
    • Si l'événement ne s'est toujours pas déclenché après un délai d'attente, revenez à l'hypothèse d'un navigateur.
    • En revanche, les autres solutions ci-dessus reposent sur le test de certaines fonctionnalités de PhoneGap ou autre, et sur l'observation de leur pause de test.

Avantages:

  • Utilise l'événement device_ready recommandé par PhoneGap.
  • L'application mobile n'a aucun délai. Dès que l'événement device_ready se déclenche, nous procédons.
  • Pas de reniflement d'agent utilisateur (j'aime tester mon application en tant que site Web mobile, donc le reniflement du navigateur n'était pas une option pour moi).
  • Pas de dépendance sur les fonctionnalités / propriétés PhoneGap non documentées (et donc fragiles).
  • Gardez votre cordova.js dans votre base de code même lorsque vous utilisez un navigateur de bureau ou mobile. Ainsi, cela répond à la question du PO.
  • Wytze a déclaré ci-dessus: "Je souhaite que cordova définisse un paramètre quelque part pour dire" Nous avons essayé de trouver un périphérique pris en charge et avons abandonné "mais il semble qu'il n'y ait pas de tel paramètre." Alors j'en fournit un ici.

Désavantages:

  • Les délais d'attente sont minables. Mais notre logique d'application mobile ne repose pas sur un retard; il est plutôt utilisé comme solution de secours lorsque nous sommes en mode navigateur Web.

==

Créez un tout nouveau projet PhoneGap vierge. Dans l'exemple d'index.js fourni, remplacez la variable "app" en bas par ceci:

var app = {
    // denotes whether we are within a mobile device (otherwise we're in a browser)
    iAmPhoneGap: false,
    // how long should we wait for PhoneGap to say the device is ready.
    howPatientAreWe: 10000,
    // id of the 'too_impatient' timeout
    timeoutID: null,
    // id of the 'impatience_remaining' interval reporting.
    impatienceProgressIntervalID: null,

    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // `load`, `deviceready`, `offline`, and `online`.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        // after 10 seconds, if we still think we're NOT phonegap, give up.
        app.timeoutID = window.setTimeout(function(appReference) {
            if (!app.iAmPhoneGap) // jeepers, this has taken too long.
                // manually trigger (fudge) the receivedEvent() method.   
                appReference.receivedEvent('too_impatient');
        }, howPatientAreWe, this);
        // keep us updated on the console about how much longer to wait.
        app.impatienceProgressIntervalID = window.setInterval(function areWeThereYet() {
                if (typeof areWeThereYet.howLongLeft == "undefined") { 
                    areWeThereYet.howLongLeft = app.howPatientAreWe; // create a static variable
                } 
                areWeThereYet.howLongLeft -= 1000; // not so much longer to wait.

                console.log("areWeThereYet: Will give PhoneGap another " + areWeThereYet.howLongLeft + "ms");
            }, 1000);
    },
    // deviceready Event Handler
    //
    // The scope of `this` is the event. In order to call the `receivedEvent`
    // function, we must explicity call `app.receivedEvent(...);`
    onDeviceReady: function() {
        app.iAmPhoneGap = true; // We have a device.
        app.receivedEvent('deviceready');

        // clear the 'too_impatient' timeout .
        window.clearTimeout(app.timeoutID); 
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        // clear the "areWeThereYet" reporting.
        window.clearInterval(app.impatienceProgressIntervalID);
        console.log('Received Event: ' + id);
        myCustomJS(app.iAmPhoneGap); // run my application.
    }
};

app.initialize();

function myCustomJS(trueIfIAmPhoneGap) {
    // put your custom javascript here.
    alert("I am "+ (trueIfIAmPhoneGap?"PhoneGap":"a Browser"));
}
Cobberboy
la source
1

Je suis tombé sur ce problème il y a plusieurs mois au début de notre application, car nous voulions que l'application soit "browser-compatible " également (étant entendu que certaines fonctionnalités seraient bloquées dans ce scénario: enregistrement audio, boussole, etc.).

La seule 100%solution (et j'insiste sur la condition 100-cent-cent) pour PRE-déterminer le contexte d'exécution de l'application était la suivante:

  • initialisez une variable JS "flag" à true et changez-la en false dans un contexte entièrement Web;

  • donc vous pouvez utiliser un appel comme " willIBeInPhoneGapSometimesInTheNearFuture()" (c'est PRE-PG, bien sûr vous avez toujours besoin d'une méthode POST-PG pour vérifier si vous pouvez appeler des API PG, mais celle-ci est triviale).

  • Ensuite, vous dites: " but how do you determine the execution context?"; la réponse est: "vous ne le faites pas" (parce que je ne pense pas que vous puissiez le faire de manière fiable, à moins que ces brillants gens de PG ne le fassent dans leur code API);

  • vous écrivez un script de construction qui le fait pour vous: une base de code avec deux variantes.

Al Renaud
la source
1

Ce n'est pas vraiment une réponse à la question, mais lorsque je teste dans un navigateur de bureau, je viens de définir une valeur de stockage local pour que le navigateur charge l'application malgré le périphérique prêt à ne pas se déclencher.

function main() {

    // Initiating the app here.
};

/* Listen for ready events from pheongap */
document.addEventListener("deviceready", main, false);

// When testing outside ipad app, use jquerys ready event instead. 
$(function() {

    if (localStorage["notPhonegap"]) {

        main();
    }
});
geon
la source
1

Rien de tout cela ne fonctionne, à moins que vous ne supprimiez le fichier Javascript PhoneGap de la version de bureau de l'application, ce qui va à l'encontre de mon objectif d'avoir une base de code.

Une autre option serait d'utiliser des fusions dossier de , voir capture d'écran ci-dessous.

Vous pouvez ajouter des fichiers spécifiques à la plate-forme / remplacer ceux par défaut.

(cela devrait faire l'affaire dans certains scénarios)

entrez la description de l'image ici


En d'autres termes: plutôt que de détecter le navigateur, vous n'incluez tout simplement pas certains fichiers pour la création de bureau / attachez certains fichiers pour iOS uniquement.

Mars Robertson
la source
1

Détecter le navigateur de bureau même si le périphérique d'émulation est actif

Fonctionne sur les machines Windows et Mac. Besoin de trouver une solution pour Linux Voir les détails

var mobileDevice = false;
if(navigator.userAgent.match(/iPhone|iPad|iPod|Android|BlackBerry|IEMobile/))
    mobileDevice = true; 

if(mobileDevice && navigator.platform.match(/Win|Mac/i))
    mobileDevice = false; // This is desktop browser emulator

if(mobileDevice) {
    // include cordova files
}
Anulal S
la source
0

En fait, j'ai trouvé qu'une combinaison de deux des techniques énumérées ici fonctionnait le mieux, tout d'abord, vérifiez que cordova / phonegap est accessible, vérifiez également si l'appareil est disponible. Ainsi:

function _initialize() {
    //do stuff
}

if (window.cordova && window.device) {
    document.addEventListener('deviceready', function () {
      _initialize();
    }, false);
} else {
   _initialize();
}
andyjamesdavies
la source
0

Essayez cette approche:

/**
 * Returns true if the application is running on an actual mobile device.
 */
function isOnDevice(){
    return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/);
}

function isDeviceiOS(){
    return navigator.userAgent.match(/(iPhone)/);
}

/**
 * Method for invoking functions once the DOM and the device are ready. This is
 * a replacement function for the JQuery provided method i.e.
 * $(document).ready(...).
 */
function invokeOnReady(callback){
    $(document).ready(function(){
        if (isOnDevice()) {
            document.addEventListener("deviceready", callback, false);
        } else {
            invoke(callback);
        }
    });
}
Zorayr
la source
0

J'utilise une combinaison de ce que GeorgeW et mkprogramming ont suggéré:

   if (!navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
      onDeviceReady();
   } else if (Phonegap.available){
      onDeviceReady();
   } else {
      console.log('There was an error loading Phonegap.')
   }
skybondsor
la source
0

Je suppose que d'une certaine manière, ils ne sont pas si différents que ça? Ha Ha ... pas drôle. Qui ne pensait pas que ce ne serait pas un problème? Voici la solution la plus simple pour vos considérations. Poussez différents fichiers sur votre serveur, puis sur PhoneGap. J'irais aussi temporairement avec le http: check suggéré ci-dessus.

var isMobileBrowserAndNotPhoneGap = (document.location.protocol == "http:");

Mon intérêt est de pousser la barre de navigation des navigateurs vers le haut, donc vraiment je peux simplement supprimer la balise du script isolé et appuyer sur la reconstruction [dans DW] (ils seront de toute façon un nettoyage pour le déploiement donc cela peut être l'une de ces tâches.) Quoi qu'il en soit, je pense c'est une bonne option (étant donné qu'il n'y a pas grand chose d'autre disponible) pour commenter efficacement les choses manuellement avec isMobileBrowserAndNotPhoneGap lors du transfert vers PG). Encore une fois pour moi, dans ma situation, je supprimerai simplement la balise du fichier (code isolé) qui fait monter la barre de navigation lorsqu'il s'agit d'un navigateur mobile (ce sera beaucoup plus rapide et plus petit). [Alors si vous pouvez isoler le code de cette solution optimisée mais manuelle.]

MistereeDevlord
la source
0

Légèrement modifié, mais fonctionne parfaitement pour moi sans aucun problème.

L'intention est de charger Cordova uniquement sur un périphérique intégré, pas sur un bureau, donc j'évite complètement cordova sur un navigateur de bureau. Le test et le développement de l'interface utilisateur et MVVM sont donc très confortables.

Mettez ce code par exemple. dans le fichier cordovaLoader.js

function isEmbedded() {
    return  
    // maybe you can test for better conditions
    //&& /^file:\/{3}[^\/]/i.test(window.location.href) && 
     /ios|iphone|ipod|ipad|android/i.test(navigator.userAgent);
}

if ( isEmbedded() )
{
   var head= document.getElementsByTagName('head')[0];
   var script= document.createElement('script');
   script.type= 'text/javascript';
   script.src= 'cordova-2.7.0.js';
   head.appendChild(script);
}

Ensuite, au lieu d'inclure cordova javascript lui-même, incluez cordovaLoader.js

<head>
  <script src="js/cordovaLoader.js"></script>
  <script src="js/jquery.js"></script>
  <script src="js/iscroll.js"></script>
  <script src="js/knockout-2.3.0.js"></script>
</head> 

Facilitez votre travail! :)

OSP
la source
0
if ( "device" in window ) {
    // phonegap
} else {
    // browser
}
Petar Vasilev
la source
0

Juste pour info le chemin dans PhoneGap 3.x Mobile Application Development Hotshot

var userLocale = "en-US";
function startApp()
{
// do translations, format numbers, etc.
}
function getLocaleAndStartApp()
{
    navigator.globalization.getLocaleName (
        function (locale) {
            userLocale = locale.value;
            startApp();
        },
        function () {
            // error; start app anyway
            startApp();
        });
}
function executeWhenReady ( callback ) {
    var executed = false;
    document.addEventListener ( "deviceready", function () {
        if (!executed) {
            executed = true;
            if (typeof callback === "function") {
                callback();
            }
        }
    }, false);
    setTimeout ( function () {
        if (!executed) {
            executed = true;
            if (typeof callback === "function") {
                callback();
            }
        }
    }, 1000 );
};
executeWhenReady ( function() {
    getLocaleAndStartApp();
} );

et dans le cadre YASMF

https://github.com/photokandyStudios/YASMF-Next/blob/master/lib/yasmf/util/core.js#L152

Whisher
la source
0

J'essayais avec les objets de la fenêtre mais cela n'a pas fonctionné car j'ouvrais l'url distante dans InAppBrowser. Impossible de le faire. Le moyen le meilleur et le plus simple d'y parvenir était donc d'ajouter une chaîne à l'url que vous devez ouvrir à partir de l'application phonegap. Vérifiez ensuite si l'emplacement du document a une chaîne ajoutée.

Voici le code simple pour cela

var ref = window.open('http://yourdomain.org#phonegap', '_blank', 'location=yes');

Vous verrez qu'une chaîne est ajoutée à l'url "#phonegap" .Alors, dans l'URL du domaine, ajoutez le script suivant

if(window.location.indexOf("#phonegap") > -1){
     alert("Url Loaded in the phonegap App");
}
Ashish
la source