PhoneGap: detecta si se ejecuta en el navegador de escritorio


118

Estoy desarrollando una aplicación web que usa PhoneGap: Build para una versión móvil y quiero tener una única base de código para las versiones de 'escritorio' y móviles. Quiero poder detectar si las llamadas de PhoneGap funcionarán (es decir, si el usuario de un dispositivo móvil admitirá PhoneGap).

He buscado y no puedo creer que no haya una forma sencilla de hacer esto. Mucha gente ha ofrecido sugerencias;

Ninguno de los cuales funciona, a menos que elimine el archivo PhoneGap Javascript de la versión de escritorio de la aplicación, lo que frustra mi objetivo de tener una base de código.

Hasta ahora, la única solución que he encontrado es el rastreo del agente de usuario / navegador, pero esto no es robusto por decir lo menos. ¡Cualquier solución mejor bienvenida!

EDITAR: Una solución ligeramente mejor es intentar llamar a una función PhoneGap después de un pequeño tiempo de espera; si no funciona, suponga que el usuario está en un navegador web de escritorio.


Como está utilizando Build, consulte la respuesta de @ bt a continuación: stackoverflow.com/a/18478002/241244 . Parece que podría ser mejor que las respuestas aceptadas y mejor votadas.

Evito la detección en tiempo de ejecución a favor de la configuración explícita en tiempo de compilación porque es 100% eficaz. Simplemente paso una var local a mi plantilla index.jade como {isPhonegap: true}, luego en la plantilla puedo incluir condicionalmente el script phonegap.js y realizar todo el init específico de phonegap que desee.
Jesse Hattabaugh

Respuestas:


115

Yo uso este código:

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

ACTUALIZAR

Hay muchas otras formas de detectar si phonegap se está ejecutando en un navegador o no, aquí hay otra gran opción:

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

como se ve aquí: Detecta entre un navegador móvil o una aplicación PhoneGap


Gracias por esto, después de esperar mucho tiempo para ver qué han sugerido otras personas, esta parece ser la mejor solución. Salud.
aaronsnoswell

35
Esto no es exacto, porque si abro la misma página en el navegador del dispositivo, onDeviceReady () nunca llamará. Además, si cambio el UserAgent en el navegador (con fines de depuración), onDeviceReady () nunca llamará a ninguno de los dos.
Slavik Meltser

3
No estoy seguro de lo que está diciendo, pero parece que está insinuando que esto causará problemas al usar el navegador del teléfono ... Esta es una solución para probar en su navegador de escritorio, no en sus teléfonos.
sirmdawg

7
Esto no ayuda cuando abre la aplicación en el navegador del dispositivo. Mejor solución: busque window.cordova. Las pruebas en iPhone Simulator (navegador) o en un dispositivo Android (navegador) también deberían detectar PhoneGap. Así es como me desarrollo. Pero hay muchas posibilidades de hacer las cosas. ;-) ¡Gracias por publicar su solución!
Mario

Estoy confundido, ¿qué pasa con otras plataformas como Windows Phone? ¿Tienen un userAgent que coincide con esa expresión regular? Una búsqueda rápida en Google implica que no: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
mooreds

49

Escribí una publicación al respecto hace unos días. Esta es la mejor solución que puede encontrar (hasta que PhoneGap lance algo, tal vez o no), es breve, simple y perfecta (la he comprobado de todas las formas y plataformas posibles).

Esta función hará el trabajo en el 98% de los casos.

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

Para completar el otro 2% de los casos, siga estos pasos (implica un ligero cambio en el código nativo):

Cree un archivo llamado __phonegap_index.html , con la fuente:

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

Ahora, en nativo, simplemente cambie la página de inicio de index.html a __phonegap_index.html en todas sus plataformas PhoneGap. Digamos que el nombre de mi proyecto es un ejemplo , los archivos que necesita cambiar son (como para PhoneGap versión 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(línea 56)
  • Window Phone 7 : no tengo idea de dónde (¿alguien todavía está desarrollando en esa plataforma?)

Finalmente, puede usarlo en cualquier lugar de su sitio, si se ejecuta en PhoneGap o no:

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

Espero eso ayude. :-)


4
¡Encontré que esta respuesta es la mejor!
blong824

3
sí, funciona, pero algunas veces la siguiente parte del código no es cierta, /^file:\/{3}[^\/]/i.test(window.location.href)pero estamos usando PhoneGap, por ejemplo, cuando cargamos el index.html desde otra página, en config.xml algo como esto<content src="http://10.100.1.147/" />
vudduu

3
La expresión (cordova || PhoneGap || phonegap) arrojará un ReferenceError si alguna de esas variables no está definida. Deberías probar typeof cordova !== undefined, ¿verdad?
rojobuffalo

1
@rblakeley tienes razón. return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
Cambié

1
@rojobuffalo: Parece que la respuesta ha sido modificado desde, por lo que es funciona como se espera de nuevo ( es decir, que no lanza una ReferenceErrormás debido al windowprefijo). Solo pensé en señalar esto, ya que esto en realidad hace que la cadena de comentarios esté desactualizada (y por lo tanto, incorrecta).
Priidu Neemre

27

Sé que ha sido respondida hace un tiempo, pero "PhoneGap.available" ya no existe. Deberías usar:

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

o desde 1.7, prefiera:

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

EDITAR 2019: como se dijo en los comentarios, esto solo funciona si no incluye cordova lib en la compilación de su navegador de escritorio. Y, por supuesto, es una buena práctica incluir solo los archivos javascript / html / css mínimos estrictos para cada dispositivo al que se dirija


18
Esto no es cierto, porque window.PhoneGap o window.cordova siempre se definirán si incluye el script cordova-xxxjs, incluso si está cargado en el navegador.
Slavik Meltser

¿Me pueden ayudar con un ejemplo? Para simplemente cargar el index.html. Lo que estoy haciendo es que he subido todos los archivos en la carpeta www en mi servidor local, estoy cargando el index.html. Pero el dispositivo está listo no se dispara.
Nassif

5
Esta parece ser la respuesta correcta ahora (con Cordova 3.4, al menos). Todos los demás métodos son solo una pérdida de tiempo ya que cordova.js se inyecta en la aplicación con un simple <script type = "text / javascript" src = "cordova.js"> </script> ahora. En realidad, no apunta al archivo real, por lo que no se carga cuando se ejecuta en un navegador. Solo está allí en una compilación de Cordova que se ejecuta en un dispositivo móvil.
Michael Oryl

Esto parece funcionar particularmente bien si se usa PhoneGap Build.

4
@SlavikMe No incluya el script cordova en compilaciones que no sean cordova.
Jackson

21

La forma más confiable que encontramos para saber si estamos en una aplicación cordova / phonegap es modificar el agente de usuario de la aplicación cordova usando esta configuración AppendUserAgent .

Además config.xml:

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

Luego llame:

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

¿Por qué?

  1. window.cordovay document.addEventListener('deviceready', function(){});están sujetos a condiciones de carrera
  2. navigator.standaloneno funciona cuando <content src="index.html" />es un sitio web (ej .: <content src="https://www.example.com/index.html" />o con cordova-plugin-remote-injection )
  3. Intentar incluir agentes de usuario en la lista blanca para adivinar si se trata de un navegador real es muy complicado. Los navegadores de Android suelen ser vistas web personalizadas.

2
¡E incluso podemos agregar la versión de la aplicación allí! (idealmente con alguna lógica de salto de versión automatizada) ex; Cordova AppName/v0.0.1<3 Entonces, de esta manera, incluso puede usar esto de alguna manera para el seguimiento (pero tenga en cuenta que cualquiera puede modificar su agente de usuario, así que no confíe en esto para verificaciones críticas de seguridad)
GabLeRoux

Este parece ser el método más infalible. El segundo finalista parece estar probando la ausencia de http: // o https: // en la URL del documento, pero puedo imaginar posibles escenarios en los que eso no funcionaría.
JD Smith

14

Creo que esto es lo más simple: var isPhoneGap = (location.protocol == "file:")

EDITAR Para algunas personas que no funcionó. Entonces podrías intentarlo (no lo he probado)

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

1
Pensé que PhoneGap ejecutaba un servidor interno para todos sus archivos en el dispositivo.
aaronsnoswell

Me gusta. Al desarrollar en localhost, esta es la mejor solución. (Después de intentar mucho, espero que esto funcione en todos los escenarios, con suerte). ¡Gracias!
Mario

1
esto no funciona en el emulador de ondulación cuando estoy probando un archivo remoto
Jesse Hattabaugh

Tampoco funciona en WP8, el protocolo es "x-wmapp0:". No puedo saber con certeza qué otros "protocolos" se utilizarán en el futuro.
Adrian

Bueno, también podría --tryvar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval

8

Esto funciona para mí (ejecutando 1.7.0)

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

Probado en Chrome y Safari de escritorio.


3
Esto es casi lo mismo que vincularse al evento 'deviceready'. Si window.device no está definido, no puede saber si phonegap / cordova tarda en cargarse o si el evento nunca se activará.
Wytze

8
window.device no se define antes de que se active el evento "deviceready".
Slavik Meltser

2
Y ore para que ningún otro programador tenga la feliz idea de definir una nueva var global llamada "dispositivo".
Mister Smith

7

Al igual que el póster original, estoy usando el servicio de compilación de phonegap. Después de dos días y casi 50 compilaciones de prueba, he encontrado una solución elegante que funciona muy bien para mí.

No pude usar UA sniffing porque quería probar y ejecutar en navegadores móviles. Originalmente me había decidido por la técnica bastante funcional de cobberboy. Esto no funcionó para mí porque el retraso / tiempo de espera de "howPatientAreWe: 10000" era demasiado molesto para el desarrollo en el navegador. Y configurarlo más bajo ocasionalmente fallaría la prueba en el modo de aplicación / dispositivo. Tenía que haber otra manera...

El servicio de compilación de phonegap requiere que el phonegap.jsarchivo se omita de su repositorio de código antes de enviar los archivos de su aplicación al servicio. Por lo tanto, puedo probar su existencia para determinar si se ejecuta en un navegador o en una aplicación.

Otra advertencia, también estoy usando jQueryMobile, por lo que tanto jQM como phonegap tuvieron que inicializarse antes de que pudiera comenzar cualquier script personalizado. El siguiente código se coloca al comienzo de mi archivo index.js personalizado para la aplicación (después de jQuery, antes de jQM). Además, los documentos de compilación de phonegap dicen que se coloque <script src="phonegap.js"></script>en algún lugar del HTML. Lo dejo completamente y lo cargo usando $ .getScript () para probar su existencia.

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

Curiosamente, muchas respuestas, pero no incluyen estas tres opciones:

1: cordova.js establecerá el objeto cordova en el ámbito global. Si está allí, lo más probable es que se esté ejecutando en un ámbito de Cordova.

var isCordovaApp = !!window.cordova;

2 - Cordova ejecutará su aplicación como abriría un documento HTML desde su escritorio. En lugar del protocolo HTTP, utilizará FILE. Detectar esto le dará la oportunidad de asumir que su aplicación se cargó localmente.

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

3 - Utilice el evento de carga del script cordova para detectar el contexto. El script incluido se puede eliminar fácilmente en el proceso de compilación o la carga del script simplemente fallará en un navegador. Para que no se establezca esta variable global.

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

El crédito es para Damien Antipa de Adobe


5

Yo uso este método:

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

debugestará trueen el entorno del navegador, falseen el dispositivo.



3

La esencia del problema es que mientras cordova.device no esté definido, su código no puede estar seguro si es porque cordova ha establecido que su dispositivo no es compatible, o si es porque cordova todavía se está preparando y deviceready se activará más tarde. (o tercera opción: cordova no se cargó correctamente).

La única solución es definir un período de espera y decidir que después de este período su código debe asumir que el dispositivo no es compatible. Me gustaría que cordova estableciera un parámetro en algún lugar para decir "Intentamos encontrar un dispositivo compatible y nos rendimos", pero parece que no existe tal parámetro.

Una vez establecido esto, es posible que desee hacer algo específico precisamente en aquellas situaciones en las que no hay un dispositivo compatible. Como ocultar enlaces al mercado de aplicaciones del dispositivo, en mi caso.

He reunido esta función que debería cubrir prácticamente todas las situaciones. Le permite definir un controlador listo para el dispositivo, un controlador que nunca está listo y un tiempo de espera.

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

La forma en que lo estoy haciendo es usando una variable global que está sobrescrita por una versión de cordova.js solo para navegador. En su archivo html principal (normalmente index.html) tengo los siguientes scripts que dependen del orden:

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

Y por dentro cordova.jstengo simplemente:

__cordovaRunningOnBrowser__ = true

Al compilar para un dispositivo móvil, no se usará cordova.js (y en su lugar se usará el archivo cordova.js específico de la plataforma), por lo que este método tiene la ventaja de ser 100% correcto independientemente de los protocolos, agentes de usuario o biblioteca variables (que pueden cambiar). Puede haber otras cosas que debería incluir en cordova.js, pero todavía no sé cuáles son.


Enfoque muy interesante.

Sin embargo, realmente no necesitas el guión inicial. Podrías simplemente probar si está configurado: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } ... ¿verdad?

Bien, aunque no está definido podría indicar que algo más está mal.
BT

3

Otra forma, basada en la solución de SlavikMe:

Simplemente use un parámetro de consulta pasado a index.htmldesde su fuente PhoneGap. Es decir, en Android, en lugar de

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

utilizar

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

SlavikMe tiene una gran lista sobre dónde hacer esto en otras plataformas.

Entonces index.htmlpuedes simplemente hacer esto:

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

1
Estoy usando Cordova 3.4.1 y ahí es aún más simple: solo necesita cambiar la <content src="index.html" />opción en el archivo config.xml a <content src="index.html?cordova=1" />. Hasta ahora parece funcionar y es, con mucho, la mejor solución sugerida aquí.
Martin M.

2

Para mantener una base de código, lo que interesa es la "plataforma" en la que se ejecuta el código. Para mí, esta "plataforma" puede ser tres cosas diferentes:

  • 0: navegador de computadora
  • 1: navegador móvil
  • 2: phonegap / cordova

La forma de verificar la plataforma:

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

Nota:

  • Esto debe ejecutarse solo después de que se haya cargado cordova.js (body onload (...), $ (document) .ready (...))

  • 'ontouchstart' en document.documentElement estará presente en las computadoras portátiles y monitores de escritorio que tienen una pantalla táctil, por lo que informará un navegador móvil aunque sea un escritorio. Hay diferentes formas de hacer una verificación más precisa, pero la uso porque todavía se ocupa del 99% de los casos que necesito. Siempre puedes sustituir esa línea por algo más robusto.


1
Sugiero usar en typeof cordova !== 'undefined'lugar de pescar una excepción.
Krakatoa

1

Aarons, prueba

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

No, no lo hice. Mira el código fuente de phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == undefined;
GeorgeW

1

La solución de GeorgeW está bien, pero incluso en un dispositivo real, PhoneGap.available solo es verdadero después de que se hayan cargado las cosas de PhoneGap, por ejemplo, onDeviceReady en document.addEventListener ('deviceready', onDeviceReady, false) ha sido llamado.

Antes de ese momento, si quieres saber, puedes hacer así:

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

Esta solución asume que la mayoría de los desarrolladores desarrollan usando Chrome o Firefox.


OP está buscando una solución para un sitio web de producción, no solo para desarrolladores.
Jesse Hattabaugh

1

Tengo el mismo problema.

Me inclino a agregar # cordova = true a la URL cargada por el cliente cordova y probar location.hash.indexOf ("cordova = true")> -1 en mi página web.


Al final, seguí la ruta sugerida por Al Renaud en su cuarto punto, y dejé que el script de construcción decidiera. Descomenta una bandera en index.html al copiar el código del sitio web en la carpeta de activos de Android. // SIN COMENTARIO AL DESPLEGAR: window._appInfo.isCordova = true; Cuando el script de compilación copia index.html en mi carpeta assets / www de Android, ejecuté ed en él para eliminar la cadena // UNCOMMENT-ON-DEPLOY:. # Masaje index.html para indicar que se está ejecutando cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin Francia

1

Lo siguiente funciona para mí con el PhoneGap / Cordova más reciente (2.1.0).

Cómo funciona:

  • Muy simple en concepto
  • Invertí la lógica de algunas de las soluciones de tiempo de espera anteriores.
  • Regístrese para el evento device_ready (según lo recomendado por los documentos de PhoneGap )
    • Si el evento aún NO se ha disparado después de un tiempo de espera, vuelva a asumir un navegador.
    • Por el contrario, las otras soluciones anteriores se basan en probar alguna función de PhoneGap u otra, y ver cómo se rompe la prueba.

Ventajas:

  • Utiliza el evento device_ready recomendado por PhoneGap.
  • La aplicación móvil no tiene demora. Tan pronto como se active el evento device_ready, procedemos.
  • Sin rastreo de usuario-agente (me gusta probar mi aplicación como un sitio web móvil, por lo que el rastreo del navegador no era una opción para mí).
  • No depende de las características / propiedades de PhoneGap indocumentadas (y por lo tanto frágiles).
  • Mantenga su cordova.js en su código base incluso cuando utilice un navegador de escritorio o móvil. Por lo tanto, esto responde a la pregunta del OP.
  • Wytze dijo anteriormente: "Me gustaría que Córdoba estableciera un parámetro en algún lugar para decir" Intentamos encontrar un dispositivo compatible y nos rendimos ", pero parece que no existe tal parámetro". Así que proporciono uno aquí.

Desventajas:

  • Los tiempos de espera son asquerosos. Pero nuestra lógica de aplicación móvil no depende de un retraso; más bien, se usa como respaldo cuando estamos en modo de navegador web.

==

Cree un nuevo proyecto PhoneGap en blanco. En el index.js de muestra proporcionado, reemplace la variable "aplicación" en la parte inferior con esto:

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

Me encontré con este problema hace varios meses al comenzar nuestra aplicación, porque queríamos que fuera "browser-compatible " (entendiendo que algunas funciones se bloquearían en ese escenario: grabación de audio, brújula, etc.).

La única 100%solución (e insisto en la condición del 100%) para PRE-determinar el contexto de ejecución de la aplicación fue esta:

  • inicializar una variable de "bandera" JS a verdadero, y cambiarlo a falso cuando en un contexto de toda la web;

  • por lo tanto, puede usar una llamada como " willIBeInPhoneGapSometimesInTheNearFuture()" (eso es PRE-PG, por supuesto, todavía necesita un método POST-PG para verificar si puede llamar a las API de PG, pero ese es trivial).

  • Entonces dices: " but how do you determine the execution context?"; la respuesta es: "tú no" (porque no creo que puedas hacerlo de manera confiable, a menos que esa gente brillante de PG lo hiciera en su código API);

  • escribe un script de compilación que lo hace por usted: una base de código con dos variantes.


1

No es realmente una respuesta a la pregunta, pero cuando pruebo en un navegador de escritorio, simplemente establezco un valor de almacenamiento local para que el navegador cargue la aplicación a pesar de que el dispositivo ya no se enciende.

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

Ninguno de los cuales funciona, a menos que elimine el archivo PhoneGap Javascript de la versión de escritorio de la aplicación, lo que frustra mi objetivo de tener una base de código.

Otra opción sería usar fusiones carpeta de , vea la captura de pantalla a continuación.

Puede agregar archivos específicos de la plataforma / anular los predeterminados.

(debería funcionar en algunos escenarios)

ingrese la descripción de la imagen aquí


En otras palabras: en lugar de detectar el navegador, simplemente no incluye ciertos archivos para la compilación de escritorio / adjunta ciertos archivos solo para iOS.


1

Detecta el navegador de escritorio incluso si el dispositivo de emulación está activo

Funciona en máquinas Windows y Mac. Necesito encontrar una solución para linux Ver detalles

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

De hecho, he encontrado que una combinación de dos de las técnicas enumeradas aquí ha funcionado mejor, en primer lugar, compruebe que se puede acceder a cordova / phonegap y compruebe si el dispositivo está disponible. Al igual que:

function _initialize() {
    //do stuff
}

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

0

Prueba este enfoque:

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

Utilizo una combinación de lo que sugirieron GeorgeW y 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

Supongo que de alguna manera no son tan diferentes, ¿verdad? Ja, ja ... no es gracioso. ¿Quién no pensó que esto no sería un problema? Aquí está la solución más simple para sus consideraciones. Envíe diferentes archivos a su servidor y luego a PhoneGap. También iría temporalmente con el http: check sugerido anteriormente.

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

Mi interés es subir la barra de navegación del navegador, así que realmente puedo eliminar la etiqueta del script aislado y presionar reconstruir [en DW] (de todos modos habrá una limpieza para la implementación, por lo que esta puede ser una de esas tareas). es una buena opción (considerando que no hay mucho más disponible) para comentar las cosas manualmente de manera eficiente con isMobileBrowserAndNotPhoneGap al presionar a PG). De nuevo, para mí, en mi situación, simplemente eliminaré la etiqueta del archivo (código aislado) que empuja hacia arriba la barra de navegación cuando es un navegador móvil (será mucho más rápido y más pequeño). [Entonces, si puede aislar el código para esa solución optimizada pero manual.]


0

Ligeramente modificado, pero me funciona perfectamente sin problemas.

La intención es cargar Cordova solo cuando esté en un dispositivo integrado, no en un escritorio, por lo que evito completamente Cordova en un navegador de escritorio. Probar y desarrollar la interfaz de usuario y MVVM es muy cómodo.

Pon este código, por ejemplo. en el archivo 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);
}

Luego, en lugar de incluir cordova javascript, incluya 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 tu trabajo! :)



0

Solo para obtener información, en PhoneGap 3.x Hotshot de desarrollo de aplicaciones móviles

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

y en el marco YASMF

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


0

Estaba intentando con los objetos de la ventana pero no funcionó porque estaba abriendo la URL remota en el InAppBrowser. No pude hacerlo. Entonces, la mejor y más fácil forma de lograrlo fue agregar una cadena a la URL que debe abrir desde la aplicación phonegap. Luego, verifique si la ubicación del documento tiene una cadena adjunta.

A continuación se muestra el código simple para ello

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

Verá que se agrega una cadena a la URL "#phonegap". Por lo tanto, en la URL del dominio agregue el siguiente script

if(window.location.indexOf("#phonegap") > -1){
     alert("Url Loaded in the phonegap App");
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.