PhoneGap: Erkennen, ob im Desktop-Browser ausgeführt wird

118

Ich entwickle eine Webanwendung, die PhoneGap: Build für eine mobile Version verwendet, und möchte eine einzige Codebasis für die Desktop- und die mobile Version haben. Ich möchte erkennen können, ob PhoneGap-Anrufe funktionieren (dh der Benutzer auf einem mobilen Gerät, der PhoneGap unterstützt).

Ich habe gesucht und kann nicht glauben, dass es keinen einfachen Weg gibt, dies zu tun. Viele Leute haben Vorschläge gemacht;

Nichts davon funktioniert, es sei denn, Sie entfernen die PhoneGap-Javascript-Datei aus der Desktop-Version der App, was mein Ziel, eine Codebasis zu haben, zunichte macht.

Bisher ist die einzige Lösung, die ich gefunden habe, das Schnüffeln von Browsern / Benutzeragenten, aber das ist gelinde gesagt nicht robust. Bessere Lösungen sind willkommen!

BEARBEITEN: Eine geringfügig bessere Lösung besteht darin, nach einer kurzen Zeitüberschreitung zu versuchen, eine PhoneGap-Funktion aufzurufen. Wenn dies nicht funktioniert, wird davon ausgegangen, dass sich der Benutzer in einem Desktop-Webbrowser befindet.

aaronsnoswell
quelle
Da Sie Build verwenden, lesen Sie die Antwort von @ bt unten: stackoverflow.com/a/18478002/241244 . Es scheint besser zu sein als die akzeptierten und am besten bewerteten Antworten.
Ich vermeide die Laufzeiterkennung zugunsten einer expliziten Build-Time-Konfiguration, da diese zu 100% effektiv ist. Ich übergebe einfach eine lokale Variable an meine index.jade-Vorlage wie {isPhonegap: true}, dann kann ich in die Vorlage das Skript phonegap.js bedingt einbinden und alle gewünschten phonegap-spezifischen Initialisierungen ausführen.
Jesse Hattabaugh

Antworten:

115

Ich benutze diesen Code:

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

AKTUALISIEREN

Es gibt viele andere Möglichkeiten, um festzustellen, ob Phonegap in einem Browser ausgeführt wird oder nicht. Hier ist eine weitere großartige Option:

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

wie hier zu sehen: Erkennen zwischen einem mobilen Browser oder einer PhoneGap-Anwendung

sirmdawg
quelle
Vielen Dank dafür - nachdem Sie lange gewartet haben, um zu sehen, was andere Leute vorgeschlagen haben, scheint dies die beste Lösung zu sein. Prost.
Aaronsnoswell
35
Dies ist nicht korrekt, da onDeviceReady () niemals aufgerufen wird, wenn ich dieselbe Seite beim Durchsuchen des Geräts öffne. Wenn ich den UserAgent im Browser ändere (zu Debug-Zwecken), wird onDeviceReady () auch niemals aufgerufen.
Slavik Meltser
3
Sie sind sich nicht sicher, was Sie sagen - aber es scheint, dass dies zu Problemen bei der Verwendung des Telefonbrowsers führt ... Dies ist eine Lösung zum Testen auf Ihrem Desktop-Browser, nicht auf Ihren Telefonen.
Sirmdawg
7
Dies hilft nicht, wenn Sie die App im Gerätebrowser öffnen. Bessere Lösung: Suchen Sie nach window.cordova. Tests im iPhone Simulator (Browser) oder auf einem Android-Gerät (Browser) sollten auch PhoneGap erkennen. So entwickle ich mich. Aber es gibt viele Möglichkeiten, Dinge zu erledigen. ;-) Danke für die Veröffentlichung deiner Lösung!
Mario
Ich bin verwirrt, was ist mit anderen Plattformen wie Windows Phone? Haben sie einen userAgent, der diesem regulären Ausdruck entspricht? Eine schnelle Google-Suche impliziert nicht: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
festgemacht
49

Ich habe vor ein paar Tagen einen Beitrag darüber geschrieben. Dies ist die beste Lösung, die Sie finden können (bis PhoneGap etwas veröffentlicht, vielleicht oder vielleicht auch nicht). Sie ist kurz, einfach und perfekt (ich habe sie auf jede mögliche Weise und Plattform überprüft).

Diese Funktion erledigt die Arbeit in 98% der Fälle.

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

Führen Sie die folgenden Schritte aus, um die anderen 2% der Fälle abzuschließen (dies erfordert eine geringfügige Änderung des nativen Codes):

Erstellen Sie eine Datei mit dem Namen __phonegap_index.html mit der Quelle:

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

Ändern Sie jetzt auf nativ einfach die Startseite von index.html in __phonegap_index.html auf allen Ihren PhoneGap-Plattformen. Angenommen, mein Projektname ist ein Beispiel . Die Dateien, die Sie ändern müssen, sind (wie bei PhoneGap Version 2.2.0):

  • iOS -CordovaLibApp/AppDelegate.m
  • Android -src/org/apache/cordova/example/cordovaExample.java
  • Windows 8 -example/package.appxmanifest
  • BlackBerry -www/config.xml
  • WebOS -framework/appinfo.json
  • Bada - src/WebForm.cpp(Linie 56)
  • Windows Phone 7 - Keine Ahnung wo (jemand entwickelt sich noch auf dieser Plattform?!)

Schließlich können Sie es überall auf Ihrer Site verwenden, unabhängig davon, ob es auf PhoneGap ausgeführt wird oder nicht:

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

Ich hoffe es hilft. :-)

Slavik Meltser
quelle
4
Fand diese Antwort als die beste!
Blong824
3
Ja, es funktioniert, aber manchmal ist der nächste Teil des Codes nicht wahr, /^file:\/{3}[^\/]/i.test(window.location.href)aber wir verwenden PhoneGap, zum Beispiel beim Laden der index.html von einer anderen Seite, auf config.xml so etwas<content src="http://10.100.1.147/" />
vudduu
3
Der Ausdruck (cordova || PhoneGap || phonegap) löst einen ReferenceError aus, wenn eine dieser Variablen nicht definiert ist. Du solltest mit testen typeof cordova !== undefined, oder?
Rojobuffalo
1
@rblakeley du hast recht. Ich wechselte die erste Zeile zu:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
Ethanpil
1
@rojobuffalo: Sieht so aus, als ob die Antwort inzwischen geändert wurde, sodass sie wieder wie erwartet funktioniert ( dh sie wirft ReferenceErroraufgrund des windowPräfixes keine mehr ). Ich dachte nur, ich würde darauf hinweisen, da dies die Kommentarkette tatsächlich veraltet (und damit falsch) macht.
Priidu Neemre
27

Ich weiß, dass es vor einiger Zeit beantwortet wurde, aber "PhoneGap.available" existiert nicht mehr. Du solltest benutzen:

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

oder seit 1.7 bevorzugen:

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

EDIT 2019: Wie in den Kommentaren erwähnt, funktioniert dies nur, wenn Sie cordova lib nicht in Ihren Desktop-Browser-Build aufnehmen. Und natürlich ist es eine gute Praxis, nur die strengen Mindestanforderungen an Javascript / HTML / CSS für jedes Gerät, auf das Sie abzielen, einzuschließen

brüderlich
quelle
18
Dies ist nicht der Fall, da window.PhoneGap oder window.cordova immer dann definiert werden, wenn Sie das Skript cordova-xxxjs einschließen, auch wenn es im Browser geladen ist.
Slavik Meltser
Können Sie mir mit einem Beispiel helfen? Um einfach die index.html zu laden. Was ich tue, ist, dass ich alle Dateien unter dem Ordner www auf meinem lokalen Server hochgeladen habe. Ich lade die index.html. Aber das Gerät ist bereit wird nicht gefeuert.
Nassif
5
Dies scheint jetzt die richtige Antwort zu sein (zumindest mit Cordova 3.4). Alle anderen Methoden sind nur Zeitverschwendung, da cordova.js jetzt mit einem einfachen <script type = "text / javascript" src = "cordova.js"> </ script> in die Anwendung eingefügt wird. Sie zeigen nicht auf die reale Datei, sodass sie beim Ausführen in einem Browser nicht geladen wird. Es ist nur in einem Cordova-Build vorhanden, der auf einem mobilen Gerät ausgeführt wird.
Michael Oryl
Dies scheint besonders gut zu funktionieren, wenn Sie PhoneGap Build verwenden.
4
@SlavikMe Fügen Sie das Cordova-Skript nicht in Nicht-Cordova-Builds ein.
Jackson
21

Die vertrauenswürdigste Methode, um festzustellen, ob wir uns in einer Cordova / Phonegap-Anwendung befinden, besteht darin, den Benutzeragenten der Cordova-Anwendung mithilfe dieser Konfiguration AppendUserAgent zu ändern .

In config.xmladd:

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

Dann ruf an:

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

Warum?

  1. window.cordovaund document.addEventListener('deviceready', function(){});unterliegen Rennbedingungen
  2. navigator.standalonefunktioniert nicht, wenn <content src="index.html" />es sich um eine Website handelt (Beispiel: <content src="https://www.example.com/index.html" />oder mit Cordova-Plugin-Remote-Injection )
  3. Der Versuch, Benutzeragenten auf die Whitelist zu setzen, um zu erraten, ob es sich um einen echten Browser handelt, ist sehr kompliziert. Android-Browser sind häufig benutzerdefinierte Webansichten.
jrobichaud
quelle
2
Und wir können dort sogar die Anwendungsversion hinzufügen! (idealerweise mit einer automatisierten Versions-Bump-Logik) ex; Cordova AppName/v0.0.1<3 Auf diese Weise können Sie dies sogar irgendwie für die Nachverfolgung verwenden (beachten Sie jedoch, dass jeder seinen Benutzeragenten ändern kann, sodass Sie sich bei sicherheitskritischen Überprüfungen nicht darauf verlassen können)
GabLeRoux
Dies scheint die narrensicherste Methode zu sein. Der zweite Zweitplatzierte scheint das Fehlen von http: // oder https: // in der Dokument-URL zu testen, aber ich kann mir mögliche Szenarien vorstellen, in denen dies nicht funktionieren würde.
JD Smith
14

Ich denke das ist am einfachsten: var isPhoneGap = (location.protocol == "file:")

BEARBEITEN Für einige Leute, die nicht funktionierten. Dann könnten Sie versuchen (nicht getestet)

var isPhoneGap = ! /^http/.test(location.protocol);
Yuval
quelle
1
Ich dachte, PhoneGap hat einen internen Server für alle Dateien auf dem Gerät ausgeführt.
Aaronsnoswell
Ich mag das. Bei der Entwicklung auf localhost ist dies die beste Lösung. (Nachdem ich viel versucht habe, hoffe ich, dass dies hoffentlich in allen Szenarien funktioniert.) Danke!
Mario
1
Dies funktioniert nicht im Ripple-Emulator, wenn ich eine Remote-Datei
teste
Funktioniert auch nicht in WP8, Protokoll ist "x-wmapp0:". Ich kann nicht sicher wissen, welche anderen "Protokolle" in Zukunft verwendet werden.
Adrian
Nun, man könnte auch --tryvar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval
8

Das funktioniert bei mir (läuft 1.7.0)

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

Getestet auf Desktop Chrome und Safari.

rauben
quelle
3
Dies ist fast das Gleiche wie die Bindung an das Ereignis "deviceready". Wenn window.device nicht definiert ist, können Sie nicht feststellen, ob phonegap / cordova langsam geladen wird oder ob das Ereignis niemals ausgelöst wird.
Wytze
8
window.device wird nicht definiert, bevor das Ereignis "deviceready" ausgelöst wird.
Slavik Meltser
2
Und beten Sie, dass kein anderer Programmierer die glückliche Idee hat, eine neue globale Variable namens "Gerät" zu definieren.
Mister Smith
7

Wie das Originalposter verwende ich den Phonegap-Build-Service. Nach zwei Tagen und fast 50 Testversionen habe ich eine elegante Lösung gefunden, die für mich hervorragend funktioniert.

Ich konnte UA-Sniffing nicht verwenden, weil ich es in mobilen Browsern testen und ausführen wollte. Ich hatte mich ursprünglich für Cobberboys ziemlich funktionale Technik entschieden. Dies hat bei mir nicht funktioniert, da die Verzögerung / das Timeout "howPatientAreWe: 10000" für die Entwicklung im Browser zu störend war. Wenn Sie den Wert niedriger einstellen, schlägt der Test im App- / Gerätemodus gelegentlich fehl. Es musste einen anderen Weg geben ...

Für den Phonegap-Erstellungsdienst muss die phonegap.jsDatei aus Ihrem Code-Repository entfernt werden, bevor die Dateien Ihrer App an den Dienst gesendet werden. Daher kann ich die Existenz testen, um festzustellen, ob sie in einem Browser oder in einer App ausgeführt wird.

Eine weitere Einschränkung: Ich verwende auch jQueryMobile, sodass sowohl jQM als auch Phonegap initialisiert werden mussten, bevor ich mit benutzerdefinierten Skripten beginnen konnte. Der folgende Code steht am Anfang meiner benutzerdefinierten Datei index.js für die App (nach jQuery, vor jQM). Auch die Phonegap-Build-Dokumente sagen, dass sie <script src="phonegap.js"></script>irgendwo im HTML- Code platziert werden sollen . Ich lasse es komplett weg und lade es mit $ .getScript (), um seine Existenz zu testen.

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

Interessanterweise viele Antworten, aber diese drei Optionen sind nicht enthalten:

1 - Die Datei cordova.js legt das Cordova-Objekt im globalen Bereich fest. Wenn es dort vorhanden ist, werden Sie höchstwahrscheinlich in einem Cordova-Bereich ausgeführt.

var isCordovaApp = !!window.cordova;

2 - Cordova führt Ihre Anwendung so aus, als würden Sie ein HTML-Dokument von Ihrem Desktop aus öffnen. Anstelle des HTTP-Protokolls wird FILE verwendet. Wenn Sie dies erkennen, können Sie davon ausgehen, dass Ihre App lokal geladen wurde.

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

3 - Verwenden Sie das Ladeereignis des Cordova-Skripts, um den Kontext zu erkennen. Das Skript-Include kann während des Erstellungsprozesses leicht entfernt werden, oder das Laden des Skripts schlägt in einem Browser einfach fehl. Damit diese globale Variable nicht gesetzt wird.

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

Der Kredit geht an Damien Antipa von Adobe

Frodik
quelle
5

Ich benutze diese Methode:

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

debugwird in trueder Browser-Umgebung falseauf dem Gerät sein.

andreszs
quelle
4

Dies scheint machbar zu sein und ich habe es in der Produktion verwendet:

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

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

Deminetix
quelle
3

Das Wesentliche des Problems ist, dass Ihr Code, solange cordova.device nicht definiert ist, nicht sicher sein kann, ob Cordova festgestellt hat, dass Ihr Gerät nicht unterstützt wird, oder ob Cordova sich noch vorbereitet und deviceready später ausgelöst wird (oder dritte Option: Cordova wurde nicht richtig geladen).

Die einzige Lösung besteht darin, eine Wartezeit zu definieren und zu entscheiden, dass Ihr Code nach dieser Zeit davon ausgehen muss, dass das Gerät nicht unterstützt wird. Ich wünschte, Cordova würde irgendwo einen Parameter setzen, der besagt: "Wir haben versucht, ein unterstütztes Gerät zu finden und aufgegeben", aber es scheint, als gäbe es keinen solchen Parameter.

Sobald dies eingerichtet ist, möchten Sie möglicherweise genau in Situationen Situationen ausführen, in denen kein unterstütztes Gerät vorhanden ist. In meinem Fall wie das Verstecken von Links zum App-Markt des Geräts.

Ich habe diese Funktion zusammengestellt, die so ziemlich jede Situation abdecken sollte. Hier können Sie einen Geräte-Handler, einen Handler, der niemals bereit ist, und eine Wartezeit definieren.

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

Ich verwende eine globale Variable, die von einer Nur-Browser-Version von cordova.js überschrieben wird. In Ihrer Haupt-HTML-Datei habe index.htmlich (normalerweise ) die folgenden Skripte, die auftragsabhängig sind:

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

Und drinnen habe cordova.jsich einfach:

__cordovaRunningOnBrowser__ = true

Beim Erstellen für ein mobiles Gerät wird die Datei cordova.js nicht verwendet (und stattdessen wird die plattformspezifische Datei cordova.js verwendet). Daher hat diese Methode den Vorteil, dass sie unabhängig von Protokollen, Benutzeragenten oder Bibliotheken zu 100% korrekt ist Variablen (die sich ändern können). Es mag andere Dinge geben, die ich in cordova.js aufnehmen sollte, aber ich weiß noch nicht, was sie sind.

BT
quelle
Sehr interessanter Ansatz.
Das erste Skript benötigen Sie jedoch nicht wirklich. Sie könnten einfach testen, if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } ob es überhaupt eingestellt ist: .. richtig?
Richtig, wenn es nicht definiert ist, könnte dies darauf hinweisen, dass etwas anderes nicht stimmt.
BT
3

Ein anderer Weg, basierend auf der Lösung von SlavikMe:

Verwenden Sie einfach einen Abfrageparameter, der index.htmlvon Ihrer PhoneGap-Quelle übergeben wurde. Dh in Android statt

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

verwenden

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

SlavikMe hat eine großartige Liste, wo dies auf anderen Plattformen zu tun ist.

Dann index.htmlkönnen Sie einfach Folgendes tun:

if (window.location.href.match(/phonegap=1/)) {
  alert("phonegap");
}
else {
  alert("not phonegap");
}
Andrew Magee
quelle
1
Ich verwende Cordova 3.4.1 und dort ist es noch einfacher: Sie müssen nur die <content src="index.html" />Option in der Datei config.xml in ändern <content src="index.html?cordova=1" />. Bisher scheint es zu funktionieren und ist bei weitem die beste hier vorgeschlagene Lösung.
Martin M.
2

Um eine Codebasis beizubehalten, ist die "Plattform" von Interesse, auf der der Code ausgeführt wird. Für mich kann diese "Plattform" drei verschiedene Dinge sein:

  • 0: Computer-Browser
  • 1: mobiler Browser
  • 2: Phonegap / Cordova

So überprüfen Sie die Plattform:

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

Hinweis:

  • Dies muss erst ausgeführt werden, nachdem cordova.js geladen wurde (body onload (...), $ (document) .ready (...))

  • 'ontouchstart' in document.documentElement ist in Laptops und Desktop-Monitoren vorhanden, die über einen Touchscreen verfügen, sodass ein mobiler Browser gemeldet wird, obwohl es sich um einen Desktop handelt. Es gibt verschiedene Möglichkeiten, eine genauere Prüfung durchzuführen, aber ich verwende sie, da sie immer noch 99% der Fälle erledigt, die ich benötige. Sie können diese Linie jederzeit durch etwas Robusteres ersetzen.

Nik
quelle
1
Ich schlage vor, typeof cordova !== 'undefined'anstelle einer Ausnahme zu fischen.
Krakatoa
1

Aarons, versuch es

if (PhoneGap.available){
    do PhoneGap stuff;
}
GeorgeW
quelle
Nein, habe ich nicht. Schauen Sie sich den Quellcode von phonegap-1.1.0.js an. PhoneGap.available = DeviceInfo.uuid! == undefined;
GeorgeW
1

Die Lösung von GeorgeW ist in Ordnung, aber selbst auf einem realen Gerät ist PhoneGap.available erst wahr, nachdem die Dinge von PhoneGap geladen wurden, z. B. onDeviceReady in document.addEventListener ('deviceready', onDeviceReady, false).

Wenn Sie vor dieser Zeit wissen möchten, können Sie Folgendes tun:

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

Diese Lösung setzt voraus, dass die meisten Entwickler mit Chrome oder Firefox entwickeln.

Ngoc Dao
quelle
OP sucht nach einer Lösung für eine Produktionswebsite, nicht nur für Entwickler.
Jesse Hattabaugh
1

Ich habe das gleiche Problem.

Ich neige dazu, # cordova = true zu der vom cordova-Client geladenen URL hinzuzufügen und auf location.hash.indexOf ("cordova = true")> -1 auf meiner Webseite zu testen.

Austin Frankreich
quelle
Am Ende ging ich den von Al Renaud in seinem vierten Punkt vorgeschlagenen Weg und ließ das Build-Skript entscheiden. Beim Kopieren des Website-Codes in den Ordner "Android Assets" wird ein Flag in index.html auskommentiert. // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true; Wenn das Erstellungsskript index.html in meinen Ordner "Android Assets / www" kopiert, führe ich ed darauf aus, um die Zeichenfolge // UNCOMMENT-ON-DEPLOY: zu entfernen. # Massieren Sie index.html, um festzustellen, ob Cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin, Frankreich,
1

Folgendes funktioniert für mich mit der neuesten PhoneGap / Cordova (2.1.0).

Wie es funktioniert:

  • Sehr einfach im Konzept
  • Ich habe die Logik einiger der oben genannten Timeout-Lösungen umgekehrt.
  • Registrieren Sie sich für das Ereignis device_ready (wie in den PhoneGap-Dokumenten empfohlen) ).
    • Wenn das Ereignis nach einer Zeitüberschreitung immer noch NICHT ausgelöst wurde, greifen Sie auf die Annahme eines Browsers zurück.
    • Im Gegensatz dazu basieren die anderen oben genannten Lösungen darauf, die eine oder andere PhoneGap-Funktion zu testen und ihre Testpause zu beobachten.

Vorteile:

  • Verwendet das von PhoneGap empfohlene Ereignis device_ready.
  • Die mobile App hat keine Verzögerung. Sobald das Ereignis device_ready ausgelöst wird, fahren wir fort.
  • Kein User-Agent-Sniffing (Ich teste meine App gerne als mobile Website, daher war Browser-Sniffing für mich keine Option).
  • Keine Abhängigkeit von undokumentierten (und daher spröden) PhoneGap-Funktionen / -Eigenschaften.
  • Behalten Sie Ihre cordova.js in Ihrer Codebasis, auch wenn Sie einen Desktop- oder mobilen Browser verwenden. Damit ist die Frage des OP beantwortet.
  • Wytze sagte oben: "Ich wünschte, Cordova würde irgendwo einen Parameter setzen, um zu sagen" Wir haben versucht, ein unterstütztes Gerät zu finden und haben aufgegeben ", aber es scheint, als gäbe es keinen solchen Parameter." Also biete ich hier eine an.

Nachteile:

  • Zeitüberschreitungen sind schwierig. Unsere Mobile-App-Logik basiert jedoch nicht auf einer Verzögerung. Vielmehr wird es als Fallback verwendet, wenn wir uns im Webbrowser-Modus befinden.

==

Erstellen Sie ein brandneues leeres PhoneGap-Projekt. Ersetzen Sie in der bereitgestellten Beispielindex.js die Variable "app" unten durch folgende:

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

Ich bin vor einigen Monaten auf dieses Problem gestoßen, als wir unsere App gestartet haben, weil wir wollten, dass die App "browser-compatible " ist (mit dem Verständnis, dass einige Funktionen in diesem Szenario blockiert sind: Audioaufzeichnung, Kompass usw.).

Die einzige 100%(und ich bestehe auf der 100-prozentigen Bedingung) Lösung, um den Kontext der App-Ausführung vorab zu bestimmen, war folgende:

  • Initialisieren Sie eine JS-Flag-Variable auf true und ändern Sie sie in einem All-Web-Kontext in false.

  • Daher können Sie einen Aufruf wie " willIBeInPhoneGapSometimesInTheNearFuture()" verwenden (das ist PRE-PG, natürlich benötigen Sie noch eine POST-PG-Methode, um zu überprüfen, ob Sie PG-APIs aufrufen können, aber diese ist trivial).

  • Dann sagst du: " but how do you determine the execution context?"; Die Antwort lautet: "Sie tun es nicht" (weil ich nicht glaube, dass Sie es zuverlässig können, es sei denn, diese brillanten Leute bei PG würden es in ihrem API-Code tun);

  • Sie schreiben ein Build-Skript, das dies für Sie erledigt: eine Codebasis mit zwei Varianten.

Al Renaud
quelle
1

Keine wirkliche Antwort auf die Frage, aber wenn ich in einem Desktop-Browser teste, lege ich einfach einen lokalen Speicherwert fest, damit der Browser die App lädt, obwohl das Gerät nicht ausgelöst wird.

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

Nichts davon funktioniert, es sei denn, Sie entfernen die PhoneGap-Javascript-Datei aus der Desktop-Version der App, was mein Ziel, eine Codebasis zu haben, zunichte macht.

Eine andere Möglichkeit wäre die Verwendung Merges Ordner, siehe Screenshot unten.

Sie können plattformspezifische Dateien hinzufügen / Standarddateien überschreiben.

(Es sollte in einigen Szenarien den Trick machen)

Geben Sie hier die Bildbeschreibung ein


Mit anderen Worten: Anstatt den Browser zu erkennen, fügen Sie bestimmte Dateien nicht für den Desktop ein. Erstellen / Anhängen bestimmter Dateien nur für iOS.

Mars Robertson
quelle
1

Erkennen Sie den Desktop-Browser auch dann, wenn das Emulationsgerät aktiv ist

Funktioniert auf Windows- und Mac-Computern. Sie müssen eine Lösung für Linux finden. Details anzeigen

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.
quelle
0

Ich habe tatsächlich festgestellt, dass eine Kombination aus zwei der hier aufgeführten Techniken am besten funktioniert hat. Überprüfen Sie zunächst, ob auf Cordova / Phonegap zugegriffen werden kann, und prüfen Sie, ob das Gerät verfügbar ist. Wie so:

function _initialize() {
    //do stuff
}

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

Versuchen Sie diesen Ansatz:

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

Ich verwende eine Kombination aus dem, was GeorgeW und mkprogramming vorgeschlagen haben:

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

Ich denke, irgendwie sind sie nicht so unterschiedlich, oder? Ha Ha ... nicht lustig. Wer hätte nicht gedacht, dass dies kein Problem ist? Hier ist die einfachste Lösung für Ihre Überlegungen. Übertragen Sie verschiedene Dateien auf Ihren Server und dann auf PhoneGap. Ich würde auch vorübergehend mit dem oben vorgeschlagenen http: check gehen.

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

Mein Interesse ist es, die Navigationsleiste des Browsers nach oben zu verschieben, sodass ich das Tag des isolierten Skripts einfach löschen und auf "Neu erstellen" [in DW] klicken kann (sie werden ohnehin für die Bereitstellung bereinigt, sodass dies eine dieser Aufgaben sein kann.) Wie auch immer Es ist eine gute Option (wenn man bedenkt, dass nicht viel anderes verfügbar ist), um Dinge mit isMobileBrowserAndNotPhoneGap effizient manuell zu kommentieren, wenn auf PG gedrückt wird. Wieder für mich in meiner Situation werde ich einfach das Tag für die (isolierte Code-) Datei löschen, die die Navigationsleiste nach oben drückt, wenn es sich um einen mobilen Browser handelt (es wird so viel schneller und kleiner sein). [Also ja, wenn Sie den Code für diese optimierte, aber manuelle Lösung isolieren können.]

MistereeDevlord
quelle
0

Leicht modifiziert, funktioniert aber bei mir perfekt ohne Probleme.

Cordova soll nur auf einem eingebetteten Gerät und nicht auf einem Desktop geladen werden. Daher vermeide ich Cordova in einem Desktop-Browser vollständig. Das Testen und Entwickeln der Benutzeroberfläche und der MVVM ist dann sehr komfortabel.

Geben Sie diesen Code ein, z. in der Datei 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);
}

Anstatt Cordova Javascript selbst einzuschließen, schließen Sie auch cordovaLoader.js ein

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

Erleichtern Sie Ihre Arbeit! :) :)

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

Nur zur Information den Weg in PhoneGap 3.x Mobile Application Development Hotshot

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

und im YASMF-Rahmen

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

Whisher
quelle
0

Ich habe es mit den Fensterobjekten versucht, aber es hat nicht funktioniert, als ich die Remote-URL im InAppBrowser geöffnet habe. Konnte es nicht schaffen. Der beste und einfachste Weg, dies zu erreichen, bestand darin, eine Zeichenfolge an die URL anzuhängen, die Sie über die Phonegap-App öffnen müssen. Überprüfen Sie dann, ob an den Dokumentspeicherort eine Zeichenfolge angehängt ist.

Unten ist der einfache Code dafür

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

Sie werden sehen, dass der URL "#phonegap" eine Zeichenfolge hinzugefügt wird. Fügen Sie daher in der Domänen-URL das folgende Skript hinzu

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