PhoneGap: Wykryj, czy działa w przeglądarce na komputerze

118

Tworzę aplikację internetową, która korzysta z PhoneGap: Build dla wersji mobilnej i chcę mieć jedną bazę kodów dla wersji „desktopowej” i mobilnej. Chcę móc wykryć, czy połączenia PhoneGap będą działać (tj. Czy użytkownik urządzenia mobilnego będzie obsługiwał PhoneGap).

Szukałem i nie mogę uwierzyć, że nie ma na to prostego sposobu. Wiele osób przedstawiło sugestie;

Żadne z nich nie zadziała, chyba że usuniesz plik PhoneGap Javascript z wersji aplikacji na komputery, co jest sprzeczne z moim celem, jakim jest posiadanie jednej bazy kodu.

Jak dotąd jedynym rozwiązaniem, które wymyśliłem, jest węszenie przeglądarki / agenta użytkownika, ale nie jest to co najmniej solidne. Wszelkie lepsze rozwiązania mile widziane!

EDYCJA: Nieznacznie lepszym rozwiązaniem jest próba wywołania funkcji PhoneGap po krótkim czasie - jeśli to nie zadziała, załóżmy, że użytkownik korzysta z przeglądarki internetowej na komputerze.

aaronsnoswell
źródło
Ponieważ używasz Build, zobacz odpowiedź @ bt poniżej: stackoverflow.com/a/18478002/241244 . Wygląda na to, że może być lepsze niż zaakceptowane i najwyżej ocenione odpowiedzi.
Unikam wykrywania w czasie wykonywania na rzecz jawnej konfiguracji w czasie kompilacji, ponieważ jest w 100% skuteczny. Po prostu przekazuję lokalną zmienną do mojego szablonu index.jade, na przykład {isPhonegap: true}, a następnie w szablonie mogę warunkowo dołączyć skrypt phonegap.js i wykonać wszystkie specyficzne dla phonegap inicjalizacje.
Jesse Hattabaugh

Odpowiedzi:

115

Używam tego kodu:

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

AKTUALIZACJA

Istnieje wiele innych sposobów wykrywania, czy phonegap działa w przeglądarce, czy nie, oto kolejna świetna opcja:

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

jak widać tutaj: Wykryj między przeglądarką mobilną a aplikacją PhoneGap

sirmdawg
źródło
Dzięki za to - po długim oczekiwaniu na to, co zasugerowały inne osoby, wydaje się, że jest to najlepsze rozwiązanie. Twoje zdrowie.
aaronsnoswell
35
To nie jest dokładne, ponieważ jeśli otworzę tę samą stronę w przeglądarce urządzenia, onDeviceReady () nigdy nie zadzwoni. Dodatkowo, jeśli zmienię UserAgent w przeglądarce (w celu debugowania), onDeviceReady () również nigdy nie będzie wywoływać.
Slavik Meltser
3
Nie jestem pewien, co mówisz - ale wydaje się, że sugerujesz, że spowoduje to problemy podczas korzystania z przeglądarki w telefonie ... Jest to rozwiązanie do przetestowania w przeglądarce na komputerze, a nie w telefonach.
sirmdawg
7
To nie pomaga, gdy otwierasz aplikację w przeglądarce urządzenia. Lepsze rozwiązanie: sprawdź plik window.cordova. Testowanie w symulatorze iPhone'a (przeglądarka) lub na urządzeniu z Androidem (przeglądarka) powinno również wykryć PhoneGap. W ten sposób się rozwijam. Ale jest wiele możliwości załatwienia sprawy. ;-) Dziękujemy za wysłanie rozwiązania!
Mario
Jestem zdezorientowany, a co z innymi platformami, takimi jak Windows Phone? Czy mają userAgent, który pasuje do tego wyrażenia regularnego? Szybkie wyszukiwanie w Google oznacza, że ​​nie: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
mooreds
49

Napisałem posta o tym kilka dni temu. To najlepsze rozwiązanie, jakie możesz znaleźć (dopóki PhoneGap coś nie wyda, może lub nie), jest krótkie, proste i doskonałe (sprawdziłem to pod każdym możliwym sposobem i platformą).

Ta funkcja będzie działać w 98% przypadków.

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

Aby ukończyć pozostałe 2% przypadków, wykonaj następujące kroki (wymaga to niewielkiej zmiany w kodzie natywnym):

Utwórz plik o nazwie __phonegap_index.html , którego źródło:

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

Teraz w wersji natywnej wystarczy zmienić stronę początkową z index.html na __phonegap_index.html na wszystkich platformach PhoneGap. Powiedzmy, że nazwa mojego projektu to przykład , pliki, które musisz zmienić, to (jak w przypadku PhoneGap w wersji 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(wiersz 56)
  • Window Phone 7 - Nie mam pojęcia gdzie (ktoś wciąż rozwija się na tej platformie ?!)

Wreszcie, możesz go używać w dowolnym miejscu w swojej witrynie, niezależnie od tego, czy działa na PhoneGap, czy nie:

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

Mam nadzieję, że to pomoże. :-)

Slavik Meltser
źródło
4
Ta odpowiedź jest najlepsza!
blong824,
3
tak to działa, ale czasami kolejna część kodu nie jest prawdą /^file:\/{3}[^\/]/i.test(window.location.href)ale używamy PhoneGap, na przykład podczas ładowania index.html z innej strony, na config.xml coś takiego<content src="http://10.100.1.147/" />
vudduu
3
Wyrażenie (cordova || PhoneGap || phonegap) zgłosi błąd ReferenceError, jeśli którakolwiek z tych zmiennych nie jest zdefiniowana. Powinieneś przetestować typeof cordova !== undefined, prawda?
rojobuffalo
1
@rblakeley masz rację. return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
Przerzuciłem
1
@rojobuffalo: Wygląda na to, że odpowiedź została od tego czasu zmodyfikowana, dzięki czemu działa zgodnie z oczekiwaniami ( tj . nie wyrzuca ReferenceErrorjuż z powodu windowprefiksu). Pomyślałem, że zwrócę na to uwagę, ponieważ to faktycznie sprawia, że ​​łańcuch komentarzy jest nieaktualny (a zatem nieprawidłowy).
Priidu Neemre
27

Wiem, że udzielono na to odpowiedzi jakiś czas temu, ale „PhoneGap.available” już nie istnieje. Powinieneś użyć:

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

lub od 1.7, wolę:

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

EDYTUJ 2019: jak wspomniano w komentarzach, działa to tylko wtedy, gdy nie uwzględnisz cordova lib w kompilacji przeglądarki na komputerze. Oczywiście dobrą praktyką jest uwzględnienie tylko ścisłego minimum plików javascript / html / css dla każdego docelowego urządzenia

fredericrous
źródło
18
To nie jest prawda, ponieważ window.PhoneGap lub window.cordova będą zawsze zdefiniowane, jeśli dołączysz skrypt cordova-xxxjs, nawet jeśli jest załadowany w przeglądarce.
Slavik Meltser
Czy możesz mi pomóc na przykładzie. Aby po prostu załadować plik index.html. Robię to, że załadowałem wszystkie pliki z folderu www na moim lokalnym serwerze, ładuję plik index.html, ale urządzenie jest gotowe nie jest zwolniony.
Nassif,
5
Wydaje się, że teraz jest to poprawna odpowiedź (przynajmniej w przypadku Cordova 3.4). Wszystkie inne metody to tylko strata czasu, ponieważ cordova.js jest teraz wstrzykiwany do aplikacji za pomocą prostego <script type = "text / javascript" src = "cordova.js"> </script>. W rzeczywistości nie wskazujesz prawdziwego pliku, więc nie ładuje się on podczas uruchamiania w przeglądarce. Jest tylko w wersji Cordova działającej na urządzeniu mobilnym.
Michael Oryl
Wygląda na to, że działałoby to szczególnie dobrze, jeśli używasz PhoneGap Build.
4
@SlavikMe Nie dołączaj skryptu cordova do kompilacji innych niż Cordova.
Jackson,
21

Najbardziej wiarygodnym sposobem stwierdzenia, czy korzystamy z aplikacji cordova / phonegap, jest zmodyfikowanie agenta użytkownika aplikacji cordova przy użyciu tej konfiguracji AppendUserAgent .

Dodatkowo config.xml:

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

Wtedy zadzwoń:

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

Czemu?

  1. window.cordovai document.addEventListener('deviceready', function(){});podlegają warunkom wyścigowym
  2. navigator.standalonenie działa, gdy <content src="index.html" />jest to strona internetowa (np. <content src="https://www.example.com/index.html" />lub z cordova-plugin-remote-injection )
  3. Próba dodania agentów użytkownika do białej listy, aby odgadnąć, czy jest to prawdziwa przeglądarka, jest bardzo skomplikowana. Przeglądarki w systemie Android to często niestandardowe widoki internetowe.
jrobichaud
źródło
2
I możemy tam nawet dodać wersję aplikacji! (najlepiej z pewną automatyczną logiką bump wersji) ex; Cordova AppName/v0.0.1<3 Więc w ten sposób możesz nawet w jakiś sposób użyć tego do śledzenia (ale pamiętaj, że każdy może modyfikować swojego agenta użytkownika, więc nie polegaj na tym w przypadku weryfikacji krytycznych dla bezpieczeństwa)
GabLeRoux
Wydaje się, że jest to najbardziej niezawodna metoda. Wydaje się, że drugie miejsce zajmuje testy pod kątem braku http: // lub https: // w adresie URL dokumentu, ale mogę wyobrazić sobie możliwe scenariusze, w których to nie zadziała.
JD Smith
14

Myślę, że to jest najprostsze: var isPhoneGap = (location.protocol == "file:")

EDYCJA Dla niektórych osób, które nie działały. Wtedy możesz spróbować (nie testowałem)

var isPhoneGap = ! /^http/.test(location.protocol);
Yuval
źródło
1
Myślałem, że PhoneGap uruchomił wewnętrzny serwer dla wszystkich plików na urządzeniu?
aaronsnoswell
Lubię to. Podczas programowania na hoście lokalnym jest to najlepsze rozwiązanie. (Mam nadzieję, że po wielu próbach zadziała to we wszystkich scenariuszach.) Dzięki!
Mario
1
to nie działa w emulatorze ripple, gdy
testuję
Nie działa również w WP8, protokół to „x-wmapp0:”. Nie wiem na pewno, jakie inne „protokoły” będą używane w przyszłości.
Adrian
Cóż, możesz teżvar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval,
8

To działa dla mnie (działa 1.7.0)

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

Przetestowano na komputerowej przeglądarce Chrome i Safari.

Obrabować
źródło
3
Jest to prawie to samo, co powiązanie ze zdarzeniem „urządzenie gotowe”. Jeśli window.device nie jest zdefiniowane, nie można stwierdzić, czy phonegap / cordova ładuje się wolno, czy też zdarzenie nigdy się nie uruchomi.
Wytze
8
Okno.device nie zostało zdefiniowane przed wyzwoleniem zdarzenia „deviceready”.
Slavik Meltser
2
I módlcie się, aby żaden inny programista nie wpadł na szczęśliwy pomysł zdefiniowania nowej globalnej zmiennej zwanej „urządzeniem”.
Mister Smith
7

Podobnie jak w przypadku oryginalnego plakatu, korzystam z usługi kompilacji phonegap. Po dwóch dniach i prawie 50 kompilacjach testowych wymyśliłem eleganckie rozwiązanie, które świetnie się sprawdza.

Nie mogłem użyć węszenia UA, ponieważ chciałem przetestować i uruchomić w przeglądarkach mobilnych. Początkowo zdecydowałem się na dość funkcjonalną technikę cobberboya. To nie zadziałało, ponieważ opóźnienie / przekroczenie limitu czasu „howPatientAreWe: 10000” było zbyt uciążliwe przy programowaniu w przeglądarce. A ustawienie go na niższy czasami powodowałoby niepowodzenie testu w trybie aplikacji / urządzenia. Musiał być inny sposób ...

Usługa kompilacji phonegap wymaga phonegap.jspominięcia pliku z repozytorium kodu przed przesłaniem plików aplikacji do usługi. Dlatego mogę przetestować jego istnienie, aby określić, czy działa w przeglądarce czy aplikacji.

Jeszcze jedno zastrzeżenie, używam również jQueryMobile, więc zarówno jQM, jak i phonegap musiały zostać zainicjowane, zanim mogłem rozpocząć niestandardowe skrypty. Poniższy kod jest umieszczony na początku mojego niestandardowego pliku index.js dla aplikacji (po jQuery, przed jQM). Również dokumentacja kompilacji phonegap mówi, że należy umieścić ją <script src="phonegap.js"></script>gdzieś w HTML. Całkowicie go pomijam i ładuję za pomocą $ .getScript (), aby ułatwić testowanie jego istnienia.

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.
źródło
6

Co ciekawe, wiele odpowiedzi, ale nie zawierają one tych trzech opcji:

1 - plik cordova.js ustawi obiekt cordova w zakresie globalnym. Jeśli tak jest, najprawdopodobniej korzystasz z lunety Cordova.

var isCordovaApp = !!window.cordova;

2 - Cordova uruchomi Twoją aplikację w taki sam sposób, jak otworzysz dokument HTML z pulpitu. Zamiast protokołu HTTP użyje PLIKU. Wykrywanie tego da Ci szansę na założenie, że Twoja aplikacja została załadowana lokalnie.

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

3 - Użyj zdarzenia load skryptu cordova, aby wykryć kontekst. Zawarcie skryptu można łatwo usunąć w procesie kompilacji lub ładowanie skryptu po prostu zakończy się niepowodzeniem w przeglądarce. Aby ta zmienna globalna nie została ustawiona.

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

Kredyt należy do Damiena Antipy z Adobe

Frodik
źródło
5

Używam tej metody:

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

debugbędzie truew środowisku przeglądarki, falsena urządzeniu.

andreszs
źródło
4

Wydaje się, że jest to wykonalne i użyłem go w produkcji:

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

Źródło: http://tqcblog.com/2012/05/09/detecting-phonegap-cordova-on-startup/

Deminetix
źródło
3

Istota problemu polega na tym, że dopóki cordova.device jest niezdefiniowany, twój kod nie może być pewien, czy to dlatego, że Cordova ustaliła, że ​​twoje urządzenie nie jest obsługiwane, czy też dlatego, że cordova wciąż się przygotowuje i urządzenie będzie odpalać później (lub trzecia opcja: cordova nie załadowała się poprawnie).

Jedynym rozwiązaniem jest zdefiniowanie okresu oczekiwania i zdecydowanie, że po tym okresie Twój kod musi zakładać, że urządzenie nie jest obsługiwane. Chciałbym, żeby Cordova ustawiła gdzieś parametr „Próbowaliśmy znaleźć obsługiwane urządzenie i zrezygnowaliśmy”, ale wygląda na to, że nie ma takiego parametru.

Po ustaleniu tego możesz chcieć zrobić coś konkretnego dokładnie w tych sytuacjach, w których nie ma obsługiwanego urządzenia. Jak w moim przypadku ukrywanie linków do rynku aplikacji na urządzeniu.

Ułożyłem razem tę funkcję, która powinna obejmować prawie każdą sytuację. Pozwala zdefiniować program obsługi urządzenia gotowy, moduł obsługi urządzenia nigdy nie gotowy i czas oczekiwania.

//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
źródło
3

Sposób, w jaki to robię, polega na użyciu zmiennej globalnej, która jest nadpisywana przez wersję cordova.js dostępną tylko w przeglądarce. W twoim głównym pliku html (zwykle index.html) mam następujące skrypty, które są zależne od zamówienia:

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

A w środku cordova.jsmam po prostu:

__cordovaRunningOnBrowser__ = true

Podczas tworzenia dla urządzenia mobilnego plik cordova.js nie będzie używany (zamiast tego zostanie użyty plik cordova.js specyficzny dla platformy), więc ta metoda ma tę zaletę, że jest w 100% poprawna, niezależnie od protokołów, agentów użytkownika lub biblioteki zmienne (które mogą ulec zmianie). Mogą być inne rzeczy, które powinienem zawrzeć w cordova.js, ale jeszcze nie wiem, czym one są.

BT
źródło
Bardzo ciekawe podejście.
Chociaż tak naprawdę nie potrzebujesz początkowego skryptu. Możesz po prostu przetestować, czy w ogóle jest ustawiony: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } .. dobrze?
Tak, chociaż niezdefiniowanie może oznaczać, że coś innego jest nie tak.
BT,
3

Inny sposób, oparty na rozwiązaniu SlavikMe:

Po prostu użyj parametru zapytania przekazanego index.htmlze źródła PhoneGap. To znaczy w systemie Android zamiast

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

posługiwać się

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

SlavikMe ma świetną listę miejsc, w których można to zrobić na innych platformach.

Wtedy index.htmlmożesz po prostu zrobić to:

if (window.location.href.match(/phonegap=1/)) {
  alert("phonegap");
}
else {
  alert("not phonegap");
}
Andrew Magee
źródło
1
Używam Cordova 3.4.1 i jest to jeszcze prostsze: wystarczy zmienić <content src="index.html" />opcję w pliku config.xml na <content src="index.html?cordova=1" />. Jak dotąd wydaje się, że działa i jest zdecydowanie najlepszym proponowanym tutaj rozwiązaniem.
Martin M.
2

Aby zachować jedną bazę kodu, interesująca jest „platforma”, na której działa kod. Dla mnie ta „platforma” może oznaczać trzy różne rzeczy:

  • 0: przeglądarka komputerowa
  • 1: przeglądarka mobilna
  • 2: phonegap / cordova

Sposób sprawdzenia platformy:

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

Uwaga:

  • To musi być uruchomione dopiero po załadowaniu cordova.js (body onload (...), $ (document) .ready (...))

  • Opcja „ontouchstart” w pliku document.documentElement będzie obecna w laptopach i monitorach stacjonarnych z ekranem dotykowym, więc będzie zgłaszać przeglądarkę mobilną, nawet jeśli jest to komputer stacjonarny. Istnieją różne sposoby dokładniejszego sprawdzenia, ale używam go, ponieważ nadal obsługuje 99% przypadków, których potrzebuję. Zawsze możesz zastąpić tę żyłkę czymś solidniejszym.

Nik
źródło
1
Sugeruję użycie typeof cordova !== 'undefined'zamiast łowienia na wyjątek.
krakatoa
1

Aarons, spróbuj

if (PhoneGap.available){
    do PhoneGap stuff;
}
George W.
źródło
Nie zrobiłem. Spójrz na kod źródłowy phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == undefined;
George W.
1

Rozwiązanie GeorgeWa jest OK, ale nawet na prawdziwym urządzeniu PhoneGap.available jest prawdziwe tylko po załadowaniu rzeczy PhoneGap, np. OnDeviceReady w document.addEventListener ('deviceready', onDeviceReady, false).

Wcześniej, jeśli chcesz wiedzieć, możesz zrobić tak:

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

To rozwiązanie zakłada, że ​​większość programistów tworzy programy w przeglądarce Chrome lub Firefox.

Ngoc Dao
źródło
OP szuka rozwiązania dla strony produkcyjnej, a nie tylko deweloperskiej.
Jesse Hattabaugh,
1

Mam ten sam problem.

Skłaniam się ku dodaniu # cordova = true do adresu URL załadowanego przez klienta cordova i przetestowaniu na mojej stronie internetowej pod kątem location.hash.indexOf ("cordova = true")> -1.

Austin France
źródło
W końcu poszedłem drogą zasugerowaną przez Al Renaud w jego czwartym punkcie i pozwoliłem, aby scenariusz budowy zdecydował. Odkomentowuje flagę w index.html podczas kopiowania kodu witryny do folderu zasobów Androida. // BEZ KOMENTARZY PRZY WDROŻENIU: window._appInfo.isCordova = true; Kiedy skrypt kompilacji kopiuje index.html do mojego folderu android asset / www, uruchomiłem na nim ed, aby usunąć ciąg // UNCOMMENT-ON-DEPLOY:. # Massage index.html, aby powiedzieć, że działa cordova ed „$ DEST / index.html” << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin Francja
1

Poniższe działa dla mnie z najnowszym PhoneGap / Cordova (2.1.0).

Jak to działa:

  • Bardzo prosta koncepcja
  • Odwróciłem logikę niektórych z powyższych rozwiązań dotyczących limitu czasu.
  • Zarejestruj się na zdarzenie device_ready (zgodnie z zaleceniami w dokumentacji PhoneGap )
    • Jeśli zdarzenie nadal NIE zostało uruchomione po przekroczeniu limitu czasu, wróć do zakładania przeglądarki.
    • Z drugiej strony, inne powyższe rozwiązania polegają na testowaniu niektórych lub innych funkcji PhoneGap i obserwowaniu ich przerwy w testach.

Zalety:

  • Używa zdarzenia device_ready zalecanego przez PhoneGap.
  • Aplikacja mobilna nie ma żadnych opóźnień. Gdy tylko uruchomi się zdarzenie device_ready, kontynuujemy.
  • Brak węszenia klienta użytkownika (lubię testować swoją aplikację jako witrynę mobilną, więc węszenie przeglądarki nie było dla mnie opcją).
  • Żadnego polegania na nieudokumentowanych (a tym samym kruchych) funkcjach / właściwościach PhoneGap.
  • Przechowuj cordova.js w swojej bazie kodów nawet podczas korzystania z przeglądarki na komputerze lub urządzeniu mobilnym. W ten sposób odpowiada to na pytanie PO.
  • Wytze stwierdził powyżej: „Chciałbym, żeby Cordova ustawiła gdzieś parametr„ Próbowaliśmy znaleźć obsługiwane urządzenie i zrezygnowaliśmy ”, ale wygląda na to, że nie ma takiego parametru”. Więc podaję tutaj jeden.

Niedogodności:

  • Limity czasu są obrzydliwe. Ale nasza logika aplikacji mobilnych nie polega na opóźnieniach; jest raczej używany jako rezerwowy, gdy jesteśmy w trybie przeglądarki internetowej.

==

Utwórz zupełnie nowy, pusty projekt PhoneGap. W podanym przykładowym pliku index.js zamień zmienną „app” na dole na następującą:

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
źródło
1

Natknąłem się na ten problem kilka miesięcy temu podczas uruchamiania naszej aplikacji, ponieważ chcieliśmy, aby aplikacja była „browser-compatible " (ze zrozumieniem, że w tym scenariuszu niektóre funkcje byłyby zablokowane: nagrywanie dźwięku, kompas itp.).

Jedynym 100%(i nalegam na warunek 100-procentowy), aby WSTĘPNIE określić kontekst wykonania aplikacji, było to:

  • zainicjuj zmienną „flag” JS na wartość true i zmień ją na false w kontekście obejmującym całą sieć;

  • dlatego możesz użyć wywołania takiego jak " willIBeInPhoneGapSometimesInTheNearFuture()" (to jest PRE-PG, oczywiście nadal potrzebujesz metody POST-PG do sprawdzania, czy możesz wywoływać API PG, ale ta jest trywialna).

  • Wtedy mówisz: „ but how do you determine the execution context?”; odpowiedź brzmi: „nie” (ponieważ nie sądzę, że możesz niezawodnie, chyba że ci genialni ludzie z PG zrobiliby to w swoim kodzie API);

  • piszesz skrypt budujący, który zrobi to za Ciebie: jedna baza kodu z dwoma wariantami.

Al Renaud
źródło
1

Naprawdę nie jest to odpowiedź na pytanie, ale kiedy testuję w przeglądarce na komputerze, po prostu ustawiam wartość localstorage, aby przeglądarka ładowała aplikację, ale urządzenie nie uruchamia się.

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
źródło
1

Żadne z nich nie zadziała, chyba że usuniesz plik PhoneGap Javascript z wersji aplikacji na komputery, co jest sprzeczne z moim celem, jakim jest posiadanie jednej bazy kodu.

Inną opcją byłoby użycie połączeń folderu , patrz zrzut ekranu poniżej.

Możesz dodać pliki specyficzne dla platformy / zastąpić domyślne.

(w niektórych sytuacjach powinno to załatwić sprawę)

wprowadź opis obrazu tutaj


Innymi słowy: Zamiast wykrywać przeglądarkę, po prostu nie dołączasz niektórych plików do kompilacji na komputer / dołączasz tylko niektóre pliki tylko dla iOS.

Mars Robertson
źródło
1

Wykryj przeglądarkę na komputerze, nawet jeśli emulacja urządzenia jest aktywna

Działa na komputerach z systemem Windows i Mac. Trzeba znaleźć rozwiązanie dla systemu Linux Zobacz szczegóły

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
źródło
0

Właściwie odkryłem, że połączenie dwóch z wymienionych tutaj technik działa najlepiej, najpierw sprawdź, czy można uzyskać dostęp do cordova / phonegap, sprawdź także, czy urządzenie jest dostępne. Tak jak to:

function _initialize() {
    //do stuff
}

if (window.cordova && window.device) {
    document.addEventListener('deviceready', function () {
      _initialize();
    }, false);
} else {
   _initialize();
}
andyjamesdavies
źródło
0

Wypróbuj to podejście:

/**
 * 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
źródło
0

Używam kombinacji tego, co zasugerowali GeorgeW i 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.')
   }
skybondsor
źródło
0

Myślę, że w jakiś sposób nie są aż tak różni, prawda? Ha ha ... nie zabawne. Kto nie pomyślał, że to nie będzie problem? Oto najprostsze rozwiązanie dla twoich rozważań. Wysyłaj różne pliki na swój serwer, a następnie do PhoneGap. Chwilowo też skorzystam z http: check sugerowanego powyżej.

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

Interesuje mnie przesunięcie paska nawigacyjnego przeglądarki w górę, więc naprawdę mogę po prostu usunąć tag izolowanego skryptu i nacisnąć przycisk odbuduj [w DW] (i tak będą to jakieś porządki do wdrożenia, więc może to być jedno z tych zadań). W każdym razie czuję jest to dobra opcja (biorąc pod uwagę, że niewiele więcej jest dostępnych), aby skutecznie po prostu ręcznie komentować rzeczy za pomocą isMobileBrowserAndNotPhoneGap podczas wypychania do PG). Znowu dla mnie w mojej sytuacji po prostu usunę tag dla pliku (izolowanego kodu), który wypycha pasek nawigacyjny, gdy jest to przeglądarka mobilna (będzie o wiele szybsza i mniejsza). [A więc jeśli możesz wyodrębnić kod dla tego zoptymalizowanego, ale ręcznego rozwiązania.]

MistereeDevlord
źródło
0

Nieznacznie zmodyfikowany, ale działa dla mnie idealnie bez żadnych problemów.

Intencją jest ładowanie Cordova tylko na urządzeniu wbudowanym, a nie na pulpicie, więc całkowicie unikam Cordova w przeglądarce na komputerze. Testowanie i rozwój interfejsu użytkownika i MVVM, a więc jest to bardzo wygodne.

Umieść ten kod np. w pliku 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);
}

Następnie zamiast włączać sam JavaScript cordova, dołącz 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> 

Ułatw sobie pracę! :)

OSP
źródło
0
if ( "device" in window ) {
    // phonegap
} else {
    // browser
}
Petar Vasilev
źródło
0

Tylko po informacje, jak w 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();
} );

oraz w ramach YASMF

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

Whisher
źródło
0

Próbowałem z obiektami okna, ale nie zadziałało, ponieważ otwierałem zdalny adres URL w InAppBrowser. Nie mogłem tego zrobić. Dlatego najlepszym i najłatwiejszym sposobem na osiągnięcie tego było dodanie ciągu znaków do adresu URL, który należy otworzyć z aplikacji phonegap. Następnie sprawdź, czy lokalizacja dokumentu ma dołączony ciąg.

Poniżej znajduje się prosty kod

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

Zobaczysz, że do adresu URL „#phonegap” został dodany ciąg. Dlatego w adresie URL domeny dodaj następujący skrypt

if(window.location.indexOf("#phonegap") > -1){
     alert("Url Loaded in the phonegap App");
}
Ashish
źródło