PhoneGap: detecta se está em execução no navegador de desktop

118

Estou desenvolvendo um aplicativo da web que usa PhoneGap: Build para uma versão móvel e quero ter uma única base de código para as versões 'desktop' e móvel. Quero ser capaz de detectar se as chamadas do PhoneGap funcionarão (ou seja, se o usuário está em um dispositivo móvel compatível com o PhoneGap).

Eu procurei e não consigo acreditar que não existe uma maneira simples de fazer isso. Muitas pessoas deram sugestões;

Nada disso funciona, a menos que você remova o arquivo Javascript do PhoneGap da versão desktop do aplicativo, o que anula meu objetivo de ter uma base de código.

Até agora, a única solução que encontrei foi farejar o navegador / agente do usuário, mas isso não é robusto para dizer o mínimo. Quaisquer soluções melhores são bem-vindas!

EDIT: Uma solução marginalmente melhor é tentar chamar uma função PhoneGap após um pequeno tempo limite - se não funcionar, suponha que o usuário esteja em um navegador da web de desktop.

Aaronsnoswell
fonte
Como você está usando o Build, consulte a resposta de @bt abaixo: stackoverflow.com/a/18478002/241244 . Parece que pode ser melhor do que as respostas aceitas e mais votadas.
Evito a detecção de tempo de execução em favor da configuração explícita de tempo de construção porque é 100% eficaz. Eu simplesmente passo um var local para meu modelo index.jade como {isPhonegap: true}, então no modelo posso incluir condicionalmente o script phonegap.js e executar todas as init específicas do phonegap que eu quiser.
Jesse Hattabaugh

Respostas:

115

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

ATUALIZAR

Existem muitas outras maneiras de detectar se o phonegap está sendo executado em um navegador ou não; aqui está outra ótima opção:

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

como visto aqui: Detectar entre um navegador móvel ou um aplicativo PhoneGap

sirmdawg
fonte
Obrigado por isso - depois de esperar muito tempo para ver o que outras pessoas sugeriram, esta parece ser a melhor solução. Felicidades.
aaronsnoswell
35
Isso não é preciso, pois se eu abrir a mesma página no navegador do dispositivo, o onDeviceReady () nunca chamará. Além disso, se eu alterar o UserAgent no navegador (para fins de depuração), onDeviceReady () nunca chamará nenhum deles.
Slavik Meltser
3
Não tenho certeza do que você está dizendo - mas parece que você está insinuando que isso causará problemas ao usar o navegador do telefone ... Esta é uma solução para testar no navegador do seu desktop, não nos telefones.
sirmdawg
7
Isso não ajuda quando você abre o aplicativo no navegador do dispositivo. Melhor solução: verifique se há window.cordova. O teste no iPhone Simulator (navegador) ou em um dispositivo Android (navegador) também deve detectar o PhoneGap. É assim que me desenvolvo. Mas há muitas possibilidades de fazer as coisas. ;-) Obrigado por postar sua solução!
Mario
Estou confuso, o que acontece com outras plataformas como o Windows Phone? Eles têm um userAgent que corresponda a essa expressão regular? Uma pesquisa rápida no Google indica que não: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
mooreds
49

Eu escrevi um post sobre isso há alguns dias. Esta é a melhor solução que você pode encontrar (até que o PhoneGap lance algo, talvez ou talvez não), é curta, simples e perfeita (eu verifiquei de todas as formas e plataformas possíveis).

Esta função fará o trabalho para 98% dos 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 os outros 2% dos casos, siga estas etapas (envolve uma ligeira mudança no código nativo):

Crie um arquivo chamado __phonegap_index.html , com a fonte:

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

Agora, no nativo, basta alterar a página inicial de index.html para __phonegap_index.html em todas as suas plataformas PhoneGap. Digamos que o nome do meu projeto seja um exemplo , os arquivos que você precisa alterar são (como no PhoneGap versão 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(linha 56)
  • Window Phone 7 - Não faço ideia de onde (alguém ainda está desenvolvendo nessa plataforma ?!)

Finalmente, você pode usá-lo em qualquer lugar do seu site, se estiver ou não rodando no PhoneGap:

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

Espero que ajude. :-)

Slavik Meltser
fonte
4
Esta resposta é a melhor!
blong824
3
sim, funciona, mas às vezes a próxima parte do código não é verdade, /^file:\/{3}[^\/]/i.test(window.location.href)mas estamos usando PhoneGap, por exemplo, ao carregar o index.html de outra página, em config.xml algo assim<content src="http://10.100.1.147/" />
vudduu
3
A expressão (cordova || PhoneGap || phonegap) lançará um ReferenceError se alguma dessas variáveis ​​não for definida. Você deve testar com typeof cordova !== undefined, certo?
rojobuffalo
1
@rblakeley você está certo. return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
Mudei
1
@rojobuffalo: Parece que a resposta já foi modificada, fazendo com que funcione conforme o esperado novamente ( ou seja, não lança ReferenceErrormais um devido ao windowprefixo). Apenas pensei em apontar isso, já que isso torna a cadeia de comentários desatualizada (e, portanto, incorreta).
Priidu Neemre
27

Sei que foi respondido há um tempo, mas "PhoneGap.available" não existe mais. Você deveria usar:

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

ou desde 1.7, prefira:

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

EDIT 2019: como dito nos comentários, isso só funciona se você não incluir cordova lib em seu navegador de desktop. E, claro, é uma boa prática incluir apenas os arquivos javascript / html / css mínimos estritos para cada dispositivo de destino

frederico
fonte
18
Isso não é verdade, porque window.PhoneGap ou window.cordova sempre será definido se você incluir o script cordova-xxxjs, mesmo se ele estiver carregado no navegador.
Slavik Meltser
Você pode me ajudar com um exemplo. Para simplesmente carregar o index.html. O que estou fazendo é que carreguei todos os arquivos da pasta www no meu servidor local, estou carregando o index.html. Mas o dispositivo está pronto não é disparado.
Nassif
5
Esta parece ser a resposta correta agora (com Cordova 3.4, pelo menos). Todos os outros métodos são apenas uma perda de tempo, já que cordova.js é injetado no aplicativo com um <script type = "text / javascript" src = "cordova.js"> </script> simples agora. Na verdade, você não aponta para o arquivo real, então ele não é carregado ao ser executado em um navegador. Ele está lá apenas em uma construção do Cordova em execução em um dispositivo móvel.
Michael Oryl
Parece que funcionaria particularmente bem se usar o PhoneGap Build.
4
@SlavikMe Não inclua o script cordova em compilações não-cordova.
Jackson,
21

A maneira mais confiável que encontramos de saber se estamos em um aplicativo cordova / phonegap é modificar o agente do usuário do aplicativo cordova usando esta configuração AppendUserAgent .

Além disso config.xml:

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

Então ligue:

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

Por quê?

  1. window.cordovae document.addEventListener('deviceready', function(){});estão sujeitos às condições de corrida
  2. navigator.standalonenão funciona quando <content src="index.html" />é um site (Ex: <content src="https://www.example.com/index.html" />ou com cordova-plugin-remote-inject )
  3. Tentar colocar agentes de usuário na lista de permissões para adivinhar se é um navegador real é muito complicado. Os navegadores Android geralmente são visualizações da web personalizadas.
Jrobichaud
fonte
2
E podemos até adicionar a versão do aplicativo lá! (de preferência com alguma versão de lógica de colisão automatizada) ex; Cordova AppName/v0.0.1<3 Assim, desta forma, você pode até mesmo usar isso de alguma forma para rastreamento (mas observe que qualquer um pode modificar seu useragent, então não conte com isso para verificações críticas de segurança)
GabLeRoux
Este parece ser o método mais infalível. O segundo colocado parece estar testando a ausência de http: // ou https: // na URL do documento, mas posso imaginar possíveis cenários em que isso não funcionaria.
JD Smith
14

Acho que é o mais simples: var isPhoneGap = (location.protocol == "file:")

EDITAR Para algumas pessoas que não funcionou. Então você pode tentar (não testei)

var isPhoneGap = ! /^http/.test(location.protocol);
Yuval
fonte
1
Achei que o PhoneGap executasse um servidor interno para todos os arquivos do dispositivo?
aaronsnoswell,
Eu gosto disso. Ao desenvolver no localhost, esta é a melhor solução. (Depois de tentar muito, espero que funcione em todos os cenários.) Obrigado!
Mario
1
isso não funciona no emulador de ondulação quando estou testando um arquivo remoto
Jesse Hattabaugh
Também não funciona no WP8, o protocolo é "x-wmapp0:". Não posso saber com certeza quais outros "protocolos" serão usados ​​no futuro.
Adrian
Bem, você também pode --tentarvar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval
8

Isso funciona para mim (executando 1.7.0)

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

Testado em desktop Chrome e Safari.

Roubar
fonte
3
Isso é quase o mesmo que vincular ao evento 'deviceready'. Se window.device não estiver definido, você não poderá dizer se o phonegap / cordova está demorando para carregar ou se o evento nunca será disparado.
Wytze
8
window.device não é definido antes do evento "deviceready" ser disparado.
Slavik Meltser
2
E reze para que nenhum outro programador tenha a feliz idéia de definir uma nova var global chamada "dispositivo".
Senhor Smith
7

Como o autor do pôster original, estou usando o serviço de construção do phonegap. Depois de dois dias e quase 50 compilações de teste, descobri uma solução elegante que funciona muito bem para mim.

Não pude usar o UA sniffing porque queria testar e executar em navegadores móveis. Eu havia me decidido originalmente pela técnica bastante funcional do cobberboy. Isso não funcionou para mim porque o atraso / tempo limite de "howPatientAreWe: 10000" era muito incômodo para o desenvolvimento no navegador. E defini-lo para um valor mais baixo ocasionalmente falha no teste no modo app / dispositivo. Tinha que haver outra maneira...

O serviço de construção do phonegap requer que o phonegap.jsarquivo seja omitido de seu repositório de código antes de enviar os arquivos de seu aplicativo para o serviço. Portanto, posso testar sua existência para determinar se está sendo executado em um navegador ou em um aplicativo.

Outra ressalva: também estou usando o jQueryMobile, então tanto o jQM quanto o phonegap tiveram que inicializar antes que eu pudesse iniciar qualquer script personalizado. O código a seguir é colocado no início do meu arquivo index.js personalizado para o aplicativo (após jQuery, antes de jQM). Além disso, os documentos de construção do phonegap dizem para colocar <script src="phonegap.js"></script>em algum lugar no HTML. Deixo-o completamente de fora e o carrego usando $ .getScript () para testar a sua existência.

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.
fonte
6

Curiosamente, muitas respostas, mas não incluem essas três opções:

1 - O cordova.js irá definir o objeto cordova no âmbito global. Se estiver lá, provavelmente você está executando em um osciloscópio Cordova.

var isCordovaApp = !!window.cordova;

2 - O Cordova executará seu aplicativo da mesma forma que você abriria um documento HTML na sua área de trabalho. Em vez do protocolo HTTP, ele usará FILE. Detectar isso lhe dará a chance de presumir que seu aplicativo foi carregado localmente.

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

3 - Use o evento load do script cordova para detectar o contexto. O script include pode ser facilmente removido no processo de construção ou o carregamento do script simplesmente falhará em um navegador. Para que esta variável global não seja configurada.

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

O crédito vai para Damien Antipa, da Adobe

Frodik
fonte
5

Eu uso este método:

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

debugestará trueno ambiente do navegador, falseno dispositivo.

andreszs
fonte
4

Isso parece viável e eu usei na produção:

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

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

Deminetix
fonte
3

A essência do problema é que, desde que cordova.device seja indefinido, seu código não pode ter certeza se é porque cordova estabeleceu que seu dispositivo não é compatível ou se é porque cordova ainda está se preparando e o dispositivo irá disparar mais tarde (ou terceira opção: cordova não carregou corretamente).

A única solução é definir um período de espera e decidir que após esse período seu código deve assumir que o dispositivo não é compatível. Gostaria que cordova definisse um parâmetro em algum lugar para dizer "Tentamos encontrar um dispositivo compatível e desistimos", mas parece que esse parâmetro não existe.

Uma vez que isso seja estabelecido, você pode querer fazer algo específico precisamente nas situações em que não há dispositivo compatível. Como esconder links para o mercado de aplicativos do aparelho, no meu caso.

Reuni essa função que deve abranger praticamente todas as situações. Ele permite que você defina um gerenciador pronto para o dispositivo, um gerenciador que nunca está pronto para o dispositivo e um tempo 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
                    }
                }
            }
    }

}
Wytze
fonte
3

Estou fazendo isso usando uma variável global que é substituída por uma versão somente para navegador do cordova.js. Em seu arquivo html principal (geralmente index.html), tenho os seguintes scripts que dependem do pedido:

    <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 por dentro cordova.jstenho simplesmente:

__cordovaRunningOnBrowser__ = true

Ao construir para um dispositivo móvel, o cordova.js não será usado (e em vez disso o arquivo cordova.js específico da plataforma será usado), então este método tem a vantagem de ser 100% correto, independentemente dos protocolos, userAgents ou biblioteca variáveis ​​(que podem mudar). Pode haver outras coisas que eu deveria incluir em cordova.js, mas ainda não sei o que são.

BT
fonte
Abordagem muito interessante.
Porém, você realmente não precisa do script inicial. Você poderia apenas testar se ele está definido: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } .. certo?
Certo, embora seja indefinido pode indicar que algo está errado.
BT
3

Outra forma, baseada na solução do SlavikMe:

Basta usar um parâmetro de consulta passado index.htmlde sua fonte do PhoneGap. Ou seja, no Android, em vez de

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

usar

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

O SlavikMe tem uma grande lista de onde fazer isso em outras plataformas.

Então você index.htmlpode simplesmente fazer isto:

if (window.location.href.match(/phonegap=1/)) {
  alert("phonegap");
}
else {
  alert("not phonegap");
}
Andrew Magee
fonte
1
Estou usando o Cordova 3.4.1 e é ainda mais simples: você só precisa alterar a <content src="index.html" />opção no arquivo config.xml para <content src="index.html?cordova=1" />. Até agora, parece funcionar e é de longe a melhor solução sugerida aqui.
Martin M.
2

Para manter uma base de código, o que interessa é a "plataforma" em que o código está sendo executado. Para mim, essa "plataforma" pode ser três coisas diferentes:

  • 0: navegador do computador
  • 1: navegador móvel
  • 2: phonegap / cordova

A forma de verificar a 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:

  • Isso deve ser executado somente depois que cordova.js foi carregado (body onload (...), $ (document) .ready (...))

  • 'ontouchstart' em document.documentElement estará presente em laptops e monitores de desktop que possuem uma tela habilitada para toque, de forma que ele reportaria um navegador móvel, mesmo sendo um desktop. Existem diferentes maneiras de fazer uma verificação mais precisa, mas eu uso porque ainda atende 99% dos casos de que preciso. Você sempre pode substituir essa linha por algo mais robusto.

Nik
fonte
1
Eu sugiro usar em typeof cordova !== 'undefined'vez de pescar uma exceção.
krakatoa,
1

Aarons, tente

if (PhoneGap.available){
    do PhoneGap stuff;
}
GeorgeW
fonte
Não, eu não fiz. Veja o código-fonte phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == indefinido;
GeorgeW
1

A solução de GeorgeW é OK, mas mesmo em um dispositivo real, PhoneGap.available só é verdadeiro depois que as coisas do PhoneGap foram carregadas, por exemplo, onDeviceReady em document.addEventListener ('deviceready', onDeviceReady, false) foi chamado.

Antes disso, se você quiser saber, pode fazer assim:

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

Esta solução pressupõe que a maioria dos desenvolvedores desenvolve usando Chrome ou Firefox.

Ngoc Dao
fonte
OP está procurando uma solução para um site de produção, não apenas dev.
Jesse Hattabaugh
1

Eu tenho o mesmo problema.

Estou inclinado a adicionar # cordova = true ao URL carregado pelo cliente cordova e testar para location.hash.indexOf ("cordova = true")> -1 em minha página da web.

Austin França
fonte
No final, segui o caminho sugerido por Al Renaud no seu 4º ponto, e deixei o script de construção decidir. Ele remove o comentário de um sinalizador em index.html ao copiar o código do site para a pasta de ativos do Android. // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true; Quando o script de construção copia index.html para minha pasta android assets / www, eu executo o ed nele para remover a string // UNCOMMENT-ON-DEPLOY :. # Massage index.html para dizer que está executando cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin France
1

O seguinte funciona para mim com o PhoneGap / Cordova mais recente (2.1.0).

Como funciona:

  • Muito simples no conceito
  • Eu inverti a lógica de algumas das soluções de tempo limite acima.
  • Registre-se para o evento device_ready (conforme recomendado pelos documentos PhoneGap )
    • Se o evento ainda NÃO disparou após um tempo limite, volte a assumir um navegador.
    • Em contraste, as outras soluções acima dependem do teste de algum recurso do PhoneGap ou outro e da observação do intervalo do teste.

Vantagens:

  • Usa o evento device_ready recomendado pelo PhoneGap.
  • O aplicativo móvel não tem demora. Assim que o evento device_ready disparar, prosseguiremos.
  • Sem detecção de user agent (gosto de testar meu aplicativo como um site móvel, portanto, a detecção de navegador não era uma opção para mim).
  • Sem dependência de recursos / propriedades não documentados (e, portanto, frágeis) do PhoneGap.
  • Mantenha seu cordova.js em sua base de código, mesmo quando estiver usando um desktop ou navegador móvel. Assim, isso responde à pergunta do OP.
  • Wytze afirmou acima: 'Gostaria que cordova definisse um parâmetro em algum lugar para dizer' Tentamos encontrar um dispositivo compatível e desistimos ', mas parece que esse parâmetro não existe.' Então, eu forneço um aqui.

Desvantagens:

  • Os tempos limite são nojentos. Mas nossa lógica de aplicativo móvel não depende de um atraso; em vez disso, é usado como alternativa quando estamos no modo de navegador da web.

==

Crie um novo projeto PhoneGap em branco. Na amostra index.js fornecida, substitua a variável "app" na parte inferior por:

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

Eu me deparei com esse problema há vários meses, ao iniciar nosso aplicativo, porque queríamos que o aplicativo browser-compatibletambém fosse " " (com o entendimento de que algumas funcionalidades seriam bloqueadas nesse cenário: gravação de áudio, bússola, etc.).

A única 100%solução (e eu insisto na condição de cem por cento) para pré-determinar o contexto de execução do aplicativo foi esta:

  • inicializar uma variável JS "sinalizador" para verdadeiro e alterá-lo para falso quando em um contexto totalmente web;

  • portanto, você pode usar uma chamada como " willIBeInPhoneGapSometimesInTheNearFuture()" (que é PRE-PG, é claro que você ainda precisa de um método POST-PG para verificar se você pode chamar APIs de PG, mas esse é trivial).

  • Aí você diz: " but how do you determine the execution context?"; a resposta é: "você não faz" (porque eu não acho que você pode confiar, a menos que aquele pessoal brilhante do PG faria isso em seu código API);

  • você escreve um script de compilação que faz isso por você: uma base de código com duas variantes.

Al Renaud
fonte
1

Não é realmente uma resposta para a pergunta, mas quando eu testo em um navegador de desktop, apenas defino um valor de armazenamento local para fazer o navegador carregar o aplicativo, apesar de o dispositivo não disparar.

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

Nada disso funciona, a menos que você remova o arquivo Javascript do PhoneGap da versão desktop do aplicativo, o que anula meu objetivo de ter uma base de código.

Outra opção seria usar a pasta merges , veja a imagem abaixo.

Você pode adicionar arquivos específicos da plataforma / substituir os padrão.

(deve funcionar em alguns cenários)

insira a descrição da imagem aqui


Em outras palavras: em vez de detectar o navegador, você simplesmente não inclui certos arquivos para compilar / anexar certos arquivos apenas para iOS.

Mars Robertson
fonte
1

Detecta o navegador da área de trabalho mesmo se a emulação do dispositivo estiver ativa

Funciona em máquinas Windows e Mac. Precisa encontrar uma solução para linux Ver detalhes

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

Na verdade, descobri que uma combinação de duas das técnicas listadas aqui funcionou melhor. Em primeiro lugar, verifique se o cordova / fone de ouvido pode ser acessado e também se o dispositivo está disponível. Igual a:

function _initialize() {
    //do stuff
}

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

Experimente esta abordagem:

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

Eu uso uma combinação do que GeorgeW e mkprogramming sugeriu:

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

Eu acho que de alguma forma eles não são tão diferentes, são? Ha Ha ... não é engraçado. Quem não achou que isso não seria um problema? Esta é a solução mais simples para suas considerações. Envie arquivos diferentes para o seu servidor e depois para o PhoneGap. Eu também iria temporariamente com a http: verificação sugerida acima.

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

Meu interesse é aumentar a barra de navegação dos navegadores, então, na verdade, posso simplesmente excluir a tag do script isolado e pressionar reconstruir [no DW] (haverá alguma limpeza para implantação de qualquer maneira, então essa pode ser uma dessas tarefas). De qualquer forma, sinto é uma boa opção (considerando que não há muito mais disponível) de forma eficiente apenas comentar coisas manualmente com isMobileBrowserAndNotPhoneGap ao enviar para PG). Novamente, para mim, na minha situação, irei simplesmente deletar a tag do arquivo (código isolado) que empurra a barra de navegação quando é um navegador móvel (será muito mais rápido e menor). [Então, sim, se você puder isolar o código para essa solução otimizada, mas manual.]

MistereeDevlord
fonte
0

Ligeiramente modificado, mas funciona perfeitamente para mim sem problemas.

A intenção é carregar o Cordova apenas quando estiver em um dispositivo embutido, não em um desktop, então evito completamente o Cordova em um navegador de desktop. O teste e o desenvolvimento da IU e do MVVM são muito confortáveis.

Coloque este código, por exemplo. no arquivo 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);
}

Então, em vez de incluir o próprio cordova javascript, inclua 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> 

Facilite seu trabalho! :)

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

Apenas para obter informações como no 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 na estrutura YASMF

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

Whisher
fonte
0

Eu estava tentando com os objetos da janela, mas não funcionou porque estava abrindo o url remoto no InAppBrowser. Não foi possível fazer isso. Portanto, a melhor e mais fácil maneira de fazer isso é anexar uma string ao url que você precisa abrir no aplicativo phonegap. Em seguida, verifique se o local do documento tem uma string anexada a ele.

Abaixo está o código simples para isso

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

Você verá que uma string é adicionada ao url "#phonegap". Então, no url do domínio, adicione o seguinte script

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