PhoneGap: Rileva se in esecuzione su browser desktop


118

Sto sviluppando un'applicazione web che utilizza PhoneGap: Build per una versione mobile e desidero avere un'unica base di codice per le versioni "desktop" e mobile. Voglio essere in grado di rilevare se le chiamate PhoneGap funzioneranno (cioè, l'utente su un dispositivo mobile che supporterà PhoneGap).

Ho cercato e non riesco a credere che non ci sia un modo semplice per farlo. Molte persone hanno offerto suggerimenti;

Nessuno dei quali funziona, a meno che non rimuovi il file Javascript PhoneGap dalla versione desktop dell'app, il che sconfigge il mio obiettivo di avere una base di codice.

Finora l'unica soluzione che ho escogitato è lo sniffing del browser / user agent, ma questo non è a dir poco robusto. Qualsiasi soluzione migliore è benvenuta!

MODIFICA: una soluzione leggermente migliore è provare a chiamare una funzione PhoneGap dopo un breve timeout: se non funziona, supponi che l'utente sia su un browser web desktop.


Dato che stai usando Build, vedi la risposta di @ bt di seguito: stackoverflow.com/a/18478002/241244 . Sembra che potrebbe essere migliore delle risposte accettate e più votate.

Evito il rilevamento in fase di esecuzione a favore della configurazione esplicita in fase di compilazione perché è efficace al 100%. Passo semplicemente una var locale al mio template index.jade come {isPhonegap: true}, quindi nel template posso includere condizionatamente lo script phonegap.js ed eseguire tutte le init specifiche di phonegap che desidero.
Jesse Hattabaugh

Risposte:


115

Uso questo codice:

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

AGGIORNARE

Esistono molti altri modi per rilevare se phonegap è in esecuzione su un browser o meno, ecco un'altra ottima opzione:

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

come mostrato qui: Rileva tra un browser mobile o un'applicazione PhoneGap


Grazie per questo - dopo aver atteso a lungo per vedere cosa hanno suggerito altre persone, questa sembra essere la soluzione migliore. Saluti.
Aaronsnoswell,

35
Questo non è accurato, perché se aprirò la stessa pagina sulla navigazione del dispositivo, onDeviceReady () non chiamerà mai. Inoltre, se cambierò UserAgent nel browser (per scopi di debug), onDeviceReady () non chiamerà mai neanche.
Slavik Meltser

3
Non sei sicuro di quello che stai dicendo, ma sembra che tu stia insinuando che ciò causerà problemi utilizzando il browser dei telefoni ... Questa è una soluzione per testare sul browser del tuo desktop non sui tuoi telefoni.
sirmdawg

7
Questo non aiuta quando apri l'app nel browser del dispositivo. Soluzione migliore: verifica la presenza di window.cordova. Anche il test in iPhone Simulator (browser) o su un dispositivo Android (browser) dovrebbe rilevare PhoneGap. È così che mi sviluppo. Ma ci sono molte possibilità per fare le cose. ;-) Grazie per aver postato la tua soluzione!
Mario

Sono confuso, che dire di altre piattaforme come Windows Phone? Hanno un userAgent che corrisponde a tale espressione regolare? Una rapida ricerca su Google non implica: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
ormeggi

49

Ho scritto un post a riguardo qualche giorno fa. Questa è la migliore soluzione che puoi trovare (fino a quando PhoneGap non rilascerà qualcosa, forse o forse no), è breve, semplice e perfetta (l'ho controllata in ogni modo e piattaforma possibile).

Questa funzione farà il lavoro per il 98% dei casi.

/**
 * 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!");
}

Per completare il restante 2% dei casi, segui questi passaggi (comporta una leggera modifica al codice nativo):

Crea un file chiamato __phonegap_index.html , con l'origine:

<!-- __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>

Ora, su native cambia semplicemente la pagina iniziale da index.html a __phonegap_index.html su tutte le tue piattaforme PhoneGap. Diciamo che il nome del mio progetto è di esempio , i file che devi modificare sono (come per PhoneGap versione 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(linea 56)
  • Window Phone 7 - Non ho idea di dove (qualcuno sta ancora sviluppando su quella piattaforma ?!)

Infine, puoi usarlo ovunque sul tuo sito, se è in esecuzione su PhoneGap o meno:

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

Spero che sia d'aiuto. :-)


4
Ho trovato questa risposta la migliore!
blong824

3
sì, funziona ma a volte la parte successiva del codice non è vera /^file:\/{3}[^\/]/i.test(window.location.href)ma stiamo usando PhoneGap, ad esempio quando si carica index.html da un'altra pagina, su config.xml qualcosa del genere<content src="http://10.100.1.147/" />
vudduu

3
L'espressione (cordova || PhoneGap || phonegap) genererà un'eccezione ReferenceError se una di queste variabili non è definita. Dovresti provare con typeof cordova !== undefined, giusto?
rojobuffalo

1
@rblakeley hai ragione. Ho cambiato la prima riga in:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
ethanpil

1
@rojobuffalo: Sembra che la risposta sia stata modificata da allora, facendola funzionare di nuovo come previsto ( cioè non lancia ReferenceErrorpiù un a causa del windowprefisso). Ho solo pensato di farlo notare, poiché in realtà rende la catena di commenti obsoleta (e quindi errata).
Priidu Neemre

27

So che è stato risposto tempo fa, ma "PhoneGap.available" non esiste più. Dovresti usare:

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

o dalla 1.7, preferisci:

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

EDIT 2019: come detto nei commenti, funziona solo se non includi cordova lib nella build del tuo browser desktop. E ovviamente è una buona pratica includere solo i file javascript / html / css minimi rigorosi per ogni dispositivo target


18
Questo non è vero, perché window.PhoneGap o window.cordova saranno comunque definiti se includi lo script cordova-xxxjs, anche se è caricato sul browser.
Slavik Meltser

Potete aiutarmi con un esempio. Per caricare semplicemente index.html. Quello che sto facendo è che ho caricato tutti i file nella cartella www nel mio server locale, sto caricando index.html. Ma il dispositivo è pronto non viene licenziato.
Nassif

5
Questa sembra essere la risposta corretta ora (con Cordova 3.4, almeno). Tutti gli altri metodi sono solo una perdita di tempo poiché cordova.js viene iniettato nell'applicazione con un semplice <script type = "text / javascript" src = "cordova.js"> </script> ora. In realtà non si punta al file reale, quindi non viene caricato durante l'esecuzione in un browser. È presente solo in una build Cordova in esecuzione su un dispositivo mobile.
Michael Oryl

Sembra che funzionerebbe particolarmente bene se si utilizza PhoneGap Build.

4
@ SlavikMe Non includere lo script cordova in build non cordova.
Jackson

21

Il modo più affidabile che abbiamo trovato per sapere se siamo in un'applicazione cordova / phonegap è modificare l'agente utente dell'applicazione cordova utilizzando questa configurazione AppendUserAgent .

Inoltre config.xml:

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

Quindi chiama:

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

Perché?

  1. window.cordovae document.addEventListener('deviceready', function(){});sono soggetti alle condizioni di gara
  2. navigator.standalonenon funziona quando <content src="index.html" />è un sito Web (Es: <content src="https://www.example.com/index.html" />o con cordova-plugin-remote-injection )
  3. Cercare di inserire nella whitelist gli user agent per indovinare se si tratta di un vero browser è molto complicato. I browser Android sono spesso visualizzazioni web personalizzate.

2
E possiamo anche aggiungere la versione dell'applicazione lì! (idealmente con una logica di bump della versione automatizzata) ex; Cordova AppName/v0.0.1<3 Quindi, in questo modo, puoi persino usarlo in qualche modo per il monitoraggio (ma nota che chiunque può modificare il suo agente utente, quindi non fare affidamento su questo per le verifiche critiche di sicurezza)
GabLeRoux

Questo sembra essere il metodo più infallibile. Il secondo classificato sembra testare l'assenza di http: // o https: // nell'URL del documento, ma posso immaginare possibili scenari in cui ciò non funzionerebbe.
JD Smith

14

Penso che questo sia il più semplice: var isPhoneGap = (location.protocol == "file:")

EDIT Per alcune persone che non hanno funzionato. Allora potresti provare (non testato)

var isPhoneGap = ! /^http/.test(location.protocol);

1
Pensavo che PhoneGap gestisse un server interno per tutti i file sul dispositivo?
Aaronsnoswell

Mi piace. Quando si sviluppa su localhost, questa è la soluzione migliore. (Dopo aver provato molto, spero che funzioni in tutti gli scenari, si spera.) Grazie!
Mario

1
questo non funziona nell'emulatore di ondulazione quando sto testando un file remoto
Jesse Hattabaugh

Inoltre non funziona in WP8, il protocollo è "x-wmapp0:". Non si può sapere con certezza quali altri "protocolli" verranno utilizzati in futuro.
Adrian

Bene, potresti anchevar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval

8

Questo funziona per me (in esecuzione 1.7.0)

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

Testato su desktop Chrome e Safari.


3
Questo è quasi lo stesso del vincolo all'evento "deviceready". Se window.device non è definito, non puoi dire se phonegap / cordova è lento nel caricamento o se l'evento non si attiverà mai.
Wytze

8
window.device non è definito prima dell'attivazione dell'evento "deviceready".
Slavik Meltser

2
E pregate che nessun altro programmatore abbia la felice idea di definire una nuova variabile globale chiamata "dispositivo".
Mister Smith

7

Come il poster originale, sto usando il servizio di compilazione phonegap. Dopo due giorni e quasi 50 build di test, ho trovato una soluzione elegante che funziona alla grande per me.

Non potevo usare UA sniffing perché volevo testarlo ed eseguirlo nei browser mobili. Inizialmente avevo scelto la tecnica abbastanza funzionale di Cobberboy. Questo non ha funzionato per me perché il ritardo / timeout "howPatientAreWe: 10000" era troppo fastidioso per lo sviluppo nel browser. E impostarlo su un valore inferiore occasionalmente fallirebbe il test in modalità app / dispositivo. Doveva esserci un altro modo ...

Il servizio di compilazione phonegap richiede che il phonegap.jsfile venga omesso dal tuo repository di codice prima di inviare i file della tua app al servizio. Pertanto sono in grado di testarne l'esistenza per determinare se è in esecuzione in un browser o in un'app.

Un altro avvertimento, sto anche usando jQueryMobile, quindi sia jQM che phonegap dovevano essere inizializzati prima che potessi iniziare qualsiasi script personalizzato. Il codice seguente viene inserito all'inizio del mio file index.js personalizzato per l'app (dopo jQuery, prima di jQM). Anche i documenti di compilazione phonegap dicono di posizionarli <script src="phonegap.js"></script>da qualche parte nell'HTML. Lo tralascio completamente e lo carico usando $ .getScript () per testarne l'esistenza.

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

6

È interessante notare che molte risposte, ma non includono queste tre opzioni:

1 - Il cordova.js imposterà l'oggetto cordova nell'ambito globale. Se è lì, molto probabilmente stai correndo in un ambito Cordova.

var isCordovaApp = !!window.cordova;

2 - Cordova eseguirà la tua applicazione come apriresti un documento HTML dal desktop. Invece del protocollo HTTP utilizzerà FILE. Rilevarlo ti darà la possibilità di presumere che la tua app sia stata caricata localmente.

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

3 - Utilizza l'evento di caricamento dello script cordova per rilevare il contesto. L'inclusione dello script può essere facilmente rimossa nel processo di compilazione o il caricamento dello script fallirà semplicemente in un browser. In modo che questa variabile globale non venga impostata.

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

Il merito va a Damien Antipa di Adobe


5

Uso questo metodo:

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

debugsarà truenell'ambiente del browser, falsesul dispositivo.



3

L'essenza del problema è che fintanto che cordova.device è indefinito, il tuo codice non può essere sicuro se è perché cordova ha stabilito che il tuo dispositivo non è supportato, o se è perché cordova si sta ancora preparando e deviceready si attiverà più tardi (o terza opzione: cordova non è stata caricata correttamente).

L'unica soluzione è definire un periodo di attesa e decidere che dopo questo periodo il codice deve presumere che il dispositivo non sia supportato. Vorrei che Cordova impostasse un parametro da qualche parte per dire "Abbiamo provato a trovare un dispositivo supportato e ci siamo arresi", ma sembra che non ci sia tale parametro.

Una volta stabilito questo, potresti voler fare qualcosa di specifico proprio in quelle situazioni in cui non è presente alcun dispositivo supportato. Come nascondere i collegamenti al mercato delle app del dispositivo, nel mio caso.

Ho messo insieme questa funzione che dovrebbe coprire praticamente ogni situazione. Ti consente di definire un gestore pronto per il dispositivo, un gestore che non è mai pronto per il dispositivo e un tempo di attesa.

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

}

3

Il modo in cui lo sto facendo è usare una variabile globale che viene sovrascritta da una versione solo browser di cordova.js. Nel tuo file html principale (di solito index.html) ho i seguenti script che dipendono dall'ordine:

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

E dentro cordova.jsho semplicemente:

__cordovaRunningOnBrowser__ = true

Quando si crea per un dispositivo mobile, cordova.js non verrà utilizzato (e verrà utilizzato invece il file cordova.js specifico della piattaforma), quindi questo metodo ha il vantaggio di essere corretto al 100% indipendentemente dai protocolli, dagli userAgents o dalla libreria variabili (che possono cambiare). Potrebbero esserci altre cose che dovrei includere in cordova.js, ma non so ancora cosa siano.


Approccio molto interessante.

Tuttavia, non hai davvero bisogno dello script iniziale. Potresti semplicemente testare che sia impostato: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } .. giusto?

Giusto, anche se non è definito potrebbe indicare che qualcos'altro non va.
BT

3

Un altro modo, basato sulla soluzione di SlavikMe:

Usa semplicemente un parametro di query passato a index.htmldalla tua fonte PhoneGap. Cioè, in Android, invece di

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

uso

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

SlavikMe ha un ottimo elenco su dove farlo su altre piattaforme.

Quindi index.htmlpuoi semplicemente farlo:

if (window.location.href.match(/phonegap=1/)) {
  alert("phonegap");
}
else {
  alert("not phonegap");
}

1
Sto usando Cordova 3.4.1 e da lì è ancora più semplice: devi solo modificare l' <content src="index.html" />opzione nel file config.xml in <content src="index.html?cordova=1" />. Finora sembra funzionare ed è di gran lunga la migliore soluzione suggerita qui.
Martin M.

2

Per mantenere una base di codice, ciò che interessa è la "piattaforma" su cui è in esecuzione il codice. Per me questa "piattaforma" può essere tre cose diverse:

  • 0: browser del computer
  • 1: browser per dispositivi mobili
  • 2: phonegap / cordova

Il modo per verificare la piattaforma:

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

Nota:

  • Deve essere eseguito solo dopo che cordova.js è stato caricato (body onload (...), $ (document) .ready (...))

  • "ontouchstart" in document.documentElement sarà presente nei laptop e nei monitor desktop che dispongono di uno schermo abilitato al tocco, quindi segnalerebbe un browser mobile anche se è un desktop. Ci sono diversi modi per fare un controllo più preciso, ma lo uso perché si occupa comunque del 99% dei casi di cui ho bisogno. Puoi sempre sostituire quella linea con qualcosa di più robusto.


1
Suggerisco di usare typeof cordova !== 'undefined'invece di pescare per un'eccezione.
krakatoa

1

Aarons, prova

if (PhoneGap.available){
    do PhoneGap stuff;
}

No, non l'ho fatto. Guarda il codice sorgente di phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == undefined;
GeorgeW

1

La soluzione di GeorgeW è OK, ma anche sul dispositivo reale, PhoneGap.available è vero solo dopo che le cose di PhoneGap sono state caricate, ad esempio onDeviceReady in document.addEventListener ('deviceready', onDeviceReady, false) è stato chiamato.

Prima di quel momento, se vuoi sapere, puoi fare così:

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

Questa soluzione presuppone che la maggior parte degli sviluppatori sviluppi utilizzando Chrome o Firefox.


OP sta cercando una soluzione per un sito Web di produzione, non solo per sviluppatori.
Jesse Hattabaugh

1

Ho lo stesso problema.

Sono propenso ad aggiungere # cordova = true all'URL caricato dal client cordova e testare location.hash.indexOf ("cordova = true")> -1 nella mia pagina web.


Alla fine, ho seguito il percorso suggerito da Al Renaud nel suo quarto punto e ho lasciato che fosse lo script di build a decidere. Rimuove un flag in index.html quando si copia il codice del sito Web nella cartella delle risorse Android. // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true; Quando lo script di compilazione copia index.html nella mia cartella degli asset Android / www, ho eseguito ed su di esso per rimuovere la stringa // UNCOMMENT-ON-DEPLOY:. # Massaggiare index.html per dire che è in esecuzione cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin France

1

Quanto segue funziona per me con il più recente PhoneGap / Cordova (2.1.0).

Come funziona:

  • Molto semplice nel concetto
  • Ho invertito la logica di alcune delle soluzioni di timeout di cui sopra.
  • Registrati per l'evento device_ready (come consigliato dai documenti di PhoneGap )
    • Se l'evento NON si è ancora attivato dopo un timeout, eseguire il fallback assumendo un browser.
    • Al contrario, le altre soluzioni sopra si basano sul test di alcune funzionalità di PhoneGap o su altre e sul guardare la loro interruzione di prova.

vantaggi:

  • Utilizza l'evento device_ready consigliato da PhoneGap.
  • L'app mobile non ha ritardi. Non appena si attiva l'evento device_ready, procediamo.
  • Nessuno sniffing di user-agent (mi piace testare la mia app come sito web per dispositivi mobili, quindi lo sniffing del browser non era un'opzione per me).
  • Nessun affidamento su funzioni / proprietà PhoneGap non documentate (e quindi fragili).
  • Mantieni il tuo cordova.js nella tua base di codice anche quando usi un browser desktop o mobile. Quindi, questo risponde alla domanda dell'OP.
  • Wytze ha affermato sopra: "Vorrei che cordova impostasse un parametro da qualche parte per dire" Abbiamo provato a trovare un dispositivo supportato e ci siamo arresi ", ma sembra che non ci sia tale parametro." Quindi ne fornisco uno qui.

svantaggi:

  • I timeout sono icky. Ma la nostra logica dell'app per dispositivi mobili non si basa su un ritardo; piuttosto, viene utilizzato come riserva quando siamo in modalità browser web.

==

Crea un nuovo progetto PhoneGap vuoto. Nell'esempio index.js fornito, sostituisci la variabile "app" in basso con questa:

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"));
}

1

Mi sono imbattuto in questo problema diversi mesi fa quando ho iniziato la nostra app, perché volevamo che anche l'app fosse " browser-compatible" (con la consapevolezza che alcune funzionalità sarebbero state bloccate in quello scenario: registrazione audio, bussola, ecc.).

L'unica 100%(e insisto sulla condizione del 100%) per determinare PRE-determinare il contesto di esecuzione dell'app era questa:

  • inizializza una variabile "flag" JS su true e cambiala in false quando in un contesto tutto web;

  • quindi puoi usare una chiamata come " willIBeInPhoneGapSometimesInTheNearFuture()" (che è PRE-PG, ovviamente hai ancora bisogno di un metodo POST-PG per verificare se puoi chiamare le API PG, ma quello è banale).

  • Quindi dici: " but how do you determine the execution context?"; la risposta è: "tu non" (perché non credo che tu possa essere affidabile, a meno che quei brillanti ragazzi di PG non lo facciano nel loro codice API);

  • scrivi uno script di build che lo faccia per te: un codebase con due varianti.


1

Non è proprio una risposta alla domanda, ma quando eseguo il test in un browser desktop, imposto semplicemente un valore localstorage per far caricare al browser l'app nonostante il dispositivo pronto a non attivarsi.

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();
    }
});

1

Nessuno dei quali funziona, a meno che non rimuovi il file Javascript PhoneGap dalla versione desktop dell'app, il che sconfigge il mio obiettivo di avere una base di codice.

Un'altra opzione potrebbe essere quella di utilizzare la cartella Merge , vedi screenshot qui sotto.

È possibile aggiungere file specifici della piattaforma / sovrascrivere quelli predefiniti.

(dovrebbe fare il trucco in alcuni scenari)

inserisci qui la descrizione dell'immagine


In altre parole: invece di rilevare il browser, semplicemente non includi determinati file per la creazione del desktop / alleghi determinati file solo per iOS.


1

Rileva il browser desktop anche se il dispositivo di emulazione è attivo

Funziona su macchine Windows e Mac. Necessità di trovare una soluzione per Linux Visualizza i dettagli

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
}

0

In realtà ho trovato che una combinazione di due delle tecniche elencate qui ha funzionato al meglio, in primo luogo controlla che sia possibile accedere a cordova / phonegap controlla anche se il dispositivo è disponibile. Così:

function _initialize() {
    //do stuff
}

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

0

Prova questo approccio:

/**
 * 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);
        }
    });
}

0

Uso una combinazione di quanto suggerito da GeorgeW e mkprogramming :

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

0

Immagino che in qualche modo non siano così diversi, vero? Ah ah ... non è divertente. Chi non pensava che questo non sarebbe stato un problema? Ecco la soluzione più semplice per le tue considerazioni. Spingi file diversi sul tuo server e poi su PhoneGap. Vorrei anche andare temporaneamente con il controllo http: suggerito sopra.

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

Il mio interesse è spingere verso l'alto la barra di navigazione del browser, quindi posso semplicemente eliminare il tag dello script isolato e premere ricostruisci [in DW] (ci sarà comunque un po 'di pulizia per la distribuzione, quindi questa può essere una di quelle attività.) Comunque mi sento è una buona opzione (considerando che non è disponibile molto altro) per commentare manualmente in modo efficiente le cose con isMobileBrowserAndNotPhoneGap quando si spinge su PG). Anche in questo caso per me nella mia situazione cancellerò semplicemente il tag per il file (codice isolato) che spinge verso l'alto la barra di navigazione quando è un browser mobile (sarà molto più veloce e più piccolo). [Quindi sì, se riesci a isolare il codice per quella soluzione ottimizzata ma manuale.]


0

Leggermente modificato, ma per me funziona perfettamente senza problemi.

L'intento è caricare Cordova solo su un dispositivo incorporato, non su un desktop, quindi evito completamente Cordova su un browser desktop. Il test e lo sviluppo dell'interfaccia utente e di MVVM è quindi molto comodo.

Metti questo codice ad es. nel file 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);
}

Quindi, invece di includere cordova javascript stesso, includere 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> 

Facilita il tuo lavoro! :)



0

Solo per info il modo in 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();
} );

e nel framework YASMF

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


0

Stavo provando con gli oggetti finestra ma non ha funzionato mentre stavo aprendo l'URL remoto in InAppBrowser. Impossibile farlo. Quindi il modo migliore e più semplice per ottenerlo era aggiungere una stringa all'URL che devi aprire dall'app phonegap. Quindi controlla se alla posizione del documento è stata aggiunta una stringa.

Di seguito è riportato il semplice codice per esso

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

Vedrai che viene aggiunta una stringa all'URL "#phonegap". Quindi nell'URL del dominio aggiungi il seguente script

if(window.location.indexOf("#phonegap") > -1){
     alert("Url Loaded in the phonegap App");
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.