PhoneGap: ตรวจจับว่าทำงานบนเบราว์เซอร์เดสก์ท็อปหรือไม่


118

ฉันกำลังพัฒนาเว็บแอปพลิเคชันที่ใช้ PhoneGap: สร้างสำหรับเวอร์ชันมือถือและต้องการมีโค้ดเบสเดียวสำหรับ "เดสก์ท็อป" และเวอร์ชันมือถือ ฉันต้องการตรวจสอบว่าการโทรของ PhoneGap ใช้งานได้หรือไม่ (กล่าวคือเป็นผู้ใช้บนอุปกรณ์เคลื่อนที่ที่รองรับ PhoneGap)

ฉันได้ค้นหาและไม่อยากจะเชื่อเลยว่าไม่มีวิธีง่ายๆในการทำเช่นนี้ หลายคนเสนอข้อเสนอแนะ;

ไม่มีสิ่งใดทำงานได้เว้นแต่คุณจะลบไฟล์ PhoneGap Javascript ออกจากแอปเวอร์ชันเดสก์ท็อปซึ่งเอาชนะเป้าหมายของฉันในการมีโค้ดเบสเดียว

จนถึงตอนนี้วิธีแก้ปัญหาเดียวที่ฉันคิดคือการดมกลิ่นของเบราว์เซอร์ / ตัวแทนผู้ใช้ แต่ก็ไม่ได้มีประสิทธิภาพที่จะพูดอย่างน้อยที่สุด ยินดีต้อนรับทางออกที่ดีกว่า!

แก้ไข: ทางออกที่ดีกว่าเล็กน้อยคือลองเรียกใช้ฟังก์ชัน PhoneGap หลังจากหมดเวลาเล็กน้อย - หากไม่ได้ผลให้ถือว่าผู้ใช้อยู่บนเว็บเบราว์เซอร์บนเดสก์ท็อป


เนื่องจากคุณกำลังใช้รูปร่างให้ดูคำตอบ @ BT ด้านล่าง: stackoverflow.com/a/18478002/241244 ดูเหมือนว่าอาจจะดีกว่าคำตอบที่ได้รับการยอมรับและได้รับคะแนนสูงสุด

ฉันหลีกเลี่ยงการตรวจจับเวลาทำงานเพื่อสนับสนุนการกำหนดค่าเวลาสร้างอย่างชัดเจนเนื่องจากมีประสิทธิภาพ 100% ฉันเพียงแค่ส่ง var ท้องถิ่นไปยังเทมเพลต index.jade ของฉันเช่น {isPhonegap: true} จากนั้นในเทมเพลตฉันสามารถรวมสคริปต์ phonegap.js ตามเงื่อนไขและดำเนินการเริ่มต้นเฉพาะ phonegap ทั้งหมดที่ฉันต้องการ
Jesse Hattabaugh

คำตอบ:


115

ฉันใช้รหัสนี้:

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

UPDATE

มีวิธีอื่น ๆ อีกมากมายในการตรวจสอบว่า phonegap ทำงานบนเบราว์เซอร์หรือไม่นี่เป็นอีกหนึ่งตัวเลือกที่ยอดเยี่ยม:

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

ดังที่เห็นที่นี่: ตรวจจับระหว่างเบราว์เซอร์มือถือหรือแอปพลิเคชัน PhoneGap


ขอบคุณสำหรับสิ่งนี้ - หลังจากรอมานานเพื่อดูสิ่งที่คนอื่นแนะนำนี่น่าจะเป็นทางออกที่ดีที่สุด ไชโย
aaronsnoswell

35
สิ่งนี้ไม่ถูกต้องเพราะถ้าฉันจะเปิดหน้าเดียวกันในการเรียกดูของอุปกรณ์ onDeviceReady () จะไม่โทร นอกจากนี้ถ้าฉันจะเปลี่ยน UserAgent ในเบราว์เซอร์ (เพื่อจุดประสงค์ในการดีบัก) onDeviceReady () ก็จะไม่เรียกเช่นกัน
Slavik Meltser

3
ไม่แน่ใจว่าคุณกำลังพูดอะไร - แต่ดูเหมือนว่าคุณกำลังบอกว่าสิ่งนี้จะทำให้เกิดปัญหาในการใช้เบราว์เซอร์ของโทรศัพท์ ... นี่เป็นวิธีการทดสอบเบราว์เซอร์บนเดสก์ท็อปของคุณไม่ใช่โทรศัพท์ของคุณ
sirmdawg

7
สิ่งนี้ไม่ได้ช่วยเมื่อคุณเปิดแอปในเบราว์เซอร์ของอุปกรณ์ ทางออกที่ดีกว่า: ตรวจสอบ window.cordova การทดสอบใน iPhone Simulator (เบราว์เซอร์) หรือบนอุปกรณ์ Android (เบราว์เซอร์) ควรตรวจพบ PhoneGap ด้วย นั่นคือวิธีที่ฉันพัฒนา แต่มีความเป็นไปได้มากมายที่จะทำสิ่งต่างๆให้ลุล่วง ;-) ขอบคุณสำหรับการโพสต์วิธีแก้ปัญหาของคุณ!
Mario

ฉันสับสนแล้วแพลตฟอร์มอื่น ๆ เช่น windows phone ล่ะ? พวกเขามี userAgent ที่ตรงกับนิพจน์ทั่วไปหรือไม่? การค้นหาโดย Google อย่างรวดเร็วไม่ได้หมายความว่า: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
mooreds

49

ฉันเขียนโพสต์เกี่ยวกับเรื่องนี้เมื่อสองสามวันก่อน นี่เป็นทางออกที่ดีที่สุดที่คุณจะพบได้ (จนกว่า PhoneGap จะปล่อยบางอย่างอาจจะหรืออาจจะไม่ก็ได้) มันสั้นง่ายและสมบูรณ์แบบ (ฉันได้ตรวจสอบในทุก ๆ วิธีและแพลตฟอร์มแล้ว)

ฟังก์ชันนี้จะทำงานได้ 98% ของเคส

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

ในการดำเนินการอีก 2% ของเคสให้ทำตามขั้นตอนเหล่านี้ (เกี่ยวข้องกับการเปลี่ยนแปลงเล็กน้อยในโค้ดเนทีฟ):

สร้างไฟล์ชื่อ__phonegap_index.htmlโดยมีแหล่งที่มา:

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

ตอนนี้ในเนทีฟเพียงแค่เปลี่ยนหน้าเริ่มต้นจากindex.htmlเป็น__phonegap_index.htmlบนแพลตฟอร์ม PhoneGap ทั้งหมดของคุณ สมมติว่าชื่อโครงการของฉันเป็นตัวอย่างไฟล์ที่คุณต้องเปลี่ยนคือ (สำหรับ PhoneGap เวอร์ชัน 2.2.0):

  • iOS -CordovaLibApp/AppDelegate.m
  • Android -src/org/apache/cordova/example/cordovaExample.java
  • Windows 8 -example/package.appxmanifest
  • แบล็กเบอร์รี่ -www/config.xml
  • WebOS -framework/appinfo.json
  • บาดา - src/WebForm.cpp(สาย 56)
  • Window Phone 7 - ไม่รู้ว่าที่ไหน (มีใครยังพัฒนาบนแพลตฟอร์มนั้นอยู่?!)

สุดท้ายคุณสามารถใช้งานได้ทุกที่บนไซต์ของคุณหากทำงานบน PhoneGap หรือไม่:

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

หวังว่าจะช่วยได้ :-)


4
พบคำตอบนี้เป็นที่สุด!
blong824

3
ใช่มันใช้งานได้ แต่บางครั้งโค้ดส่วนถัดไปไม่เป็นความจริง/^file:\/{3}[^\/]/i.test(window.location.href)แต่เรากำลังใช้ PhoneGap ตัวอย่างเช่นเมื่อโหลด index.html จากหน้าอื่นบน config.xml อะไรทำนองนี้<content src="http://10.100.1.147/" />
vudduu

3
นิพจน์(cordova || PhoneGap || phonegap) จะส่ง ReferenceError หากไม่ได้กำหนดตัวแปรเหล่านั้น คุณควรทดสอบด้วยtypeof cordova !== undefinedใช่ไหม?
rojobuffalo

1
@rblakeley คุณพูดถูก ฉันเปลี่ยนบรรทัดแรกเป็น:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
ethanpil

1
@rojobuffalo: ดูเหมือนว่าคำตอบจะได้รับการแก้ไขแล้วทำให้มันทำงานได้ตามที่คาดไว้อีกครั้ง ( กล่าวคือจะไม่โยนReferenceErrorอีกต่อไปเนื่องจากwindowคำนำหน้า) แค่คิดว่าฉันจะชี้ให้เห็นสิ่งนี้เนื่องจากสิ่งนี้ทำให้ห่วงโซ่ความคิดเห็นล้าสมัย (และไม่ถูกต้อง)
Priidu Neemre

27

ฉันรู้ว่าได้รับคำตอบเมื่อสักครู่แล้ว แต่ "PhoneGap.available" ไม่มีอยู่แล้ว คุณควรใช้:

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

หรือตั้งแต่ 1.7 ชอบ:

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

แก้ไข 2019: ตามที่กล่าวไว้ในความคิดเห็นสิ่งนี้ใช้ได้เฉพาะเมื่อคุณไม่รวม Cordova lib ไว้ในเบราว์เซอร์เดสก์ท็อปของคุณ และแน่นอนว่าเป็นแนวทางปฏิบัติที่ดีในการรวมเฉพาะไฟล์ javascript / html / css ขั้นต่ำที่เข้มงวดสำหรับแต่ละอุปกรณ์ที่คุณกำหนดเป้าหมาย


18
สิ่งนี้ไม่เป็นความจริงเนื่องจาก window.PhoneGap หรือ window.cordova จะถูกกำหนดทั้งหมดหากคุณรวม script cordova-xxxjs แม้ว่าจะโหลดบนเบราว์เซอร์ก็ตาม
Slavik Meltser

คุณช่วยยกตัวอย่างได้ไหมเพียงโหลด index.html สิ่งที่ฉันกำลังทำคือฉันได้อัปโหลดไฟล์ทั้งหมดภายใต้โฟลเดอร์ www ในเซิร์ฟเวอร์ภายในของฉันฉันกำลังโหลด index.html แต่อุปกรณ์พร้อม ไม่ได้ถูกไล่ออก
Nassif

5
ตอนนี้ดูเหมือนจะเป็นคำตอบที่ถูกต้องแล้ว (อย่างน้อยก็มี Cordova 3.4) วิธีการอื่น ๆ ทั้งหมดเป็นเพียงการเสียเวลาเนื่องจาก Cordova.js ถูกฉีดเข้าไปในแอปพลิเคชันด้วย <script type = "text / javascript" src = "cordova.js"> </script> แบบธรรมดาในตอนนี้ คุณไม่ได้ชี้ไปที่ไฟล์จริงดังนั้นจึงไม่ได้รับการโหลดเมื่อทำงานในเบราว์เซอร์ มีเฉพาะใน Cordova build ที่ทำงานบนอุปกรณ์มือถือ
Michael Oryl

ดูเหมือนว่ามันจะทำงานได้ดีเป็นพิเศษหากใช้ PhoneGap Build

4
@SlavikMe อย่ารวมสคริปต์ Cordova ในการสร้างที่ไม่ใช่ Cordova
Jackson

21

วิธีที่น่าเชื่อถือที่สุดที่เราพบเพื่อบอกได้ว่าเราอยู่ในแอปพลิเคชัน Cordova / phonegap คือการแก้ไข User agent ของแอปพลิเคชันCordovaโดยใช้การกำหนดค่า AppendUserAgentนี้

ในconfig.xmlการเพิ่ม:

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

จากนั้นโทร:

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

ทำไม?

  1. window.cordovaและdocument.addEventListener('deviceready', function(){});อยู่ภายใต้เงื่อนไขการแข่งขัน
  2. navigator.standaloneไม่ทำงานเมื่อ<content src="index.html" />เป็นเว็บไซต์ (เช่น: <content src="https://www.example.com/index.html" />หรือด้วยCordova-plugin-remote-injection )
  3. การพยายามอนุญาตตัวแทนผู้ใช้เพื่อเดาว่าเป็นเบราว์เซอร์จริงหรือไม่นั้นซับซ้อนมาก เบราว์เซอร์ Android มักเป็นเว็บวิวที่กำหนดเอง

2
และเรายังสามารถเพิ่มเวอร์ชันแอปพลิเคชันได้อีกด้วย! (ตามหลักการแล้วกับตรรกะการชนของเวอร์ชันอัตโนมัติ) เช่น; Cordova AppName/v0.0.1<3 ด้วยวิธีนี้คุณสามารถใช้สิ่งนี้ในการติดตามได้ (แต่โปรดทราบว่าทุกคนสามารถแก้ไข useragent ได้ดังนั้นอย่าพึ่งพาสิ่งนี้เพื่อการตรวจสอบความปลอดภัยที่สำคัญ)
GabLeRoux

นี่ดูเหมือนจะเป็นวิธีที่เข้าใจผิดได้มากที่สุด รองชนะเลิศอันดับสองดูเหมือนจะทดสอบว่าไม่มี http: // หรือ https: // ใน URL ของเอกสาร แต่ฉันสามารถจินตนาการถึงสถานการณ์ที่เป็นไปได้ที่ไม่สามารถใช้งานได้
JD Smith

14

ฉันคิดว่าสิ่งนี้ง่ายที่สุด: var isPhoneGap = (location.protocol == "file:")

แก้ไข สำหรับบางคนที่ไม่ได้ผล จากนั้นคุณอาจลอง (ยังไม่ได้ทดสอบ)

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

1
ฉันคิดว่า PhoneGap ใช้เซิร์ฟเวอร์ภายในสำหรับไฟล์บนอุปกรณ์ทั้งหมดหรือไม่
aaronsnoswell

ฉันชอบมัน. เมื่อพัฒนาบน localhost นี่เป็นทางออกที่ดีที่สุด (หลังจากพยายามมามากฉันหวังว่ามันจะได้ผลในทุกสถานการณ์หวังว่าจะเป็นเช่นนั้น) ขอบคุณ!
Mario

1
สิ่งนี้ใช้ไม่ได้ในโปรแกรมจำลองการกระเพื่อมเมื่อฉันทดสอบไฟล์ระยะไกล
Jesse Hattabaugh

ยังใช้ไม่ได้ใน WP8 โปรโตคอลคือ "x-wmapp0:" ไม่สามารถทราบแน่ชัดว่าจะใช้ "โปรโตคอล" ใดอีกในอนาคต
Adrian

คุณก็ทำได้เช่นกันvar isPhoneGap = ! /^http/.test(document.location.protocol)
Yuval

8

สิ่งนี้ใช้ได้กับฉัน (วิ่ง 1.7.0)

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

ทดสอบบน Chrome บนเดสก์ท็อปและ Safari


3
เกือบจะเหมือนกับการเชื่อมโยงกับเหตุการณ์ "deviceready" หากไม่ได้กำหนด window.device คุณจะไม่สามารถบอกได้ว่า phonegap / Cordova โหลดช้าหรือไม่หรือเหตุการณ์จะไม่เริ่มทำงาน
Wytze

8
window.device ไม่ได้กำหนดไว้ก่อนที่เหตุการณ์ "deviceready" จะทริกเกอร์
Slavik Meltser

2
และขอภาวนาอย่าให้โปรแกรมเมอร์คนไหนมีความคิดที่มีความสุขในการกำหนดตัวแปรระดับโลกตัวใหม่ที่เรียกว่า "อุปกรณ์"
Mister Smith

7

เช่นเดียวกับโปสเตอร์ต้นฉบับฉันใช้บริการสร้าง phonegap หลังจากผ่านไปสองวันและสร้างการทดสอบเกือบ 50 ชิ้นฉันได้พบโซลูชันที่ยอดเยี่ยมที่เหมาะกับฉันมาก

ฉันไม่สามารถใช้การดมกลิ่น UA ได้เพราะฉันต้องการทดสอบและเรียกใช้ในเบราว์เซอร์มือถือ เดิมทีฉันได้ใช้เทคนิคที่ใช้งานได้ค่อนข้างดีของ cobberboy สิ่งนี้ไม่ได้ผลสำหรับฉันเพราะ "howPatientAreWe: 10000" ความล่าช้า / หมดเวลาสร้างความรำคาญให้กับการพัฒนาในเบราว์เซอร์มากเกินไป และการตั้งค่าให้ต่ำกว่านี้ในบางครั้งการทดสอบในโหมดแอป / อุปกรณ์จะล้มเหลว มันต้องมีวิธีอื่น ...

บริการสร้าง phonegap ต้องการนามสกุล phonegap.jsให้ละเว้นไฟล์จากที่เก็บโค้ดของคุณก่อนที่จะส่งไฟล์ของแอปไปยังบริการ ดังนั้นฉันจึงสามารถทดสอบการมีอยู่ของมันเพื่อดูว่าทำงานในเบราว์เซอร์เทียบกับแอปหรือไม่

ข้อแม้อีกประการหนึ่งฉันใช้ jQueryMobile ด้วยดังนั้นทั้ง jQM และ phonegap จึงต้องเริ่มต้นก่อนที่ฉันจะสามารถเริ่มการเขียนสคริปต์แบบกำหนดเองได้ โค้ดต่อไปนี้วางไว้ที่จุดเริ่มต้นของไฟล์ index.js ที่กำหนดเองของฉันสำหรับแอป (หลัง jQuery ก่อน jQM) นอกจากนี้เอกสารการสร้าง phonegap ยังบอกว่าจะวางไว้ที่<script src="phonegap.js"></script>ใดที่หนึ่งใน HTML ฉันทิ้งมันไว้อย่างสมบูรณ์และโหลดโดยใช้ $ .getScript () เพื่อทดสอบการมีอยู่ของมัน

isPhoneGap = false;
isPhoneGapReady = false;
isjQMReady = false;

$.getScript("phonegap.js")
.done(function () {
    isPhoneGap = true;
    document.addEventListener("deviceready", function () {
        console.log("phonegap ready - device/app mode");
        isPhoneGapReady = true;
        Application.checkReadyState();
    }, false);
})
.fail(function () {
    console.log("phonegap load failed - browser only");
    isPhoneGapReady = true;
    Application.checkReadyState();
});

$(document).bind("mobileinit", function () {
    Application.mobileInit();
    $(document).one("pageinit", "#Your_First_jQM_Page", function () {
        isjQMReady = true;
        Application.checkReadyState();
    });
});

Application = {
    checkReadyState: function () {
        if (isjQMReady && isPhoneGapReady) {
            Application.ready();
        }
    },
    mobileInit: function () {
        // jQM initialization settings go here
        // i.e. $.mobile.defaultPageTransition = 'slide';
    },
    ready: function () {
        // Both phonegap (if available) and jQM are fired up and ready
        // let the custom scripting begin!
    }
}

6

น่าสนใจคำตอบมากมาย แต่ไม่มีสามตัวเลือกเหล่านี้:

1 - Cordova.js จะตั้งค่าออบเจ็กต์ Cordova ในขอบเขตส่วนกลาง หากอยู่ที่นั่นแสดงว่าคุณมีแนวโน้มที่จะทำงานในขอบเขต Cordova

var isCordovaApp = !!window.cordova;

2 - Cordova จะเรียกใช้แอปพลิเคชันของคุณเหมือนกับที่คุณเปิดเอกสาร HTML จากเดสก์ท็อปของคุณ แทนที่จะใช้โปรโตคอล HTTP จะใช้ FILE การตรวจพบสิ่งนี้จะทำให้คุณมีโอกาสที่จะสันนิษฐานได้ว่าแอปของคุณถูกโหลดภายในเครื่อง

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

3 - ใช้เหตุการณ์โหลดของสคริปต์ Cordova เพื่อตรวจจับบริบท สคริปต์รวมสามารถลบออกได้อย่างง่ายดายในกระบวนการสร้างมิฉะนั้นการโหลดสคริปต์จะล้มเหลวในเบราว์เซอร์ เพื่อที่จะไม่ตั้งค่าตัวแปรส่วนกลางนี้

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

เครดิตตกเป็นของ Damien Antipa จาก Adobe


5

ฉันใช้วิธีนี้:

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

debugจะtrueอยู่ในสภาพแวดล้อมของเบราว์เซอร์falseบนอุปกรณ์


4

สิ่งนี้ดูเหมือนจะใช้งานได้และฉันได้ใช้มันในการผลิต:

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

ที่มา: http://tqcblog.com/2012/05/09/detecting-phonegap-cordova-on-startup/


3

สาระสำคัญของปัญหาคือตราบใดที่ Cordova.device ยังไม่ได้กำหนดรหัสของคุณจะไม่สามารถแน่ใจได้ว่านั่นเป็นเพราะ Cordova ได้ระบุว่าอุปกรณ์ของคุณไม่รองรับหรือเป็นเพราะ Cordova ยังคงเตรียมเองและอุปกรณ์จะเริ่มทำงานในภายหลัง (หรือตัวเลือกที่สาม: Cordova โหลดไม่ถูกต้อง)

ทางออกเดียวคือกำหนดระยะเวลารอและตัดสินใจว่าหลังจากช่วงเวลานี้รหัสของคุณจะต้องถือว่าอุปกรณ์ไม่รองรับ ฉันหวังว่า Cordova จะตั้งค่าพารามิเตอร์บางที่เพื่อบอกว่า "เราได้พยายามค้นหาอุปกรณ์ที่รองรับและยอมแพ้แล้ว" แต่ดูเหมือนว่าจะไม่มีพารามิเตอร์ดังกล่าว

เมื่อสร้างสิ่งนี้ได้แล้วคุณอาจต้องการทำบางสิ่งที่เฉพาะเจาะจงอย่างแม่นยำในสถานการณ์ที่ไม่มีอุปกรณ์ที่รองรับ เช่นเดียวกับการซ่อนลิงก์ไปยังตลาดแอปของอุปกรณ์ในกรณีของฉัน

ฉันได้รวบรวมฟังก์ชั่นนี้เข้าด้วยกันซึ่งควรครอบคลุมทุกสถานการณ์ ช่วยให้คุณกำหนดตัวจัดการอุปกรณ์เครื่องจัดการอุปกรณ์ที่ไม่พร้อมใช้งานและเวลารอ

//Deals with the possibility that the code will run on a non-phoneGap supported
//device such as desktop browsers. Gives several options including waiting a while
//for cordova to load after all.
//In:
//onceReady (function) - performed as soon as deviceready fires
//patience 
//  (int) - time to wait before establishing that cordova will never load
//  (boolean false) - don't wait: assume that deviceready will never fire
//neverReady 
//  (function) - performed once it's established deviceready will never fire
//  (boolean true) - if deviceready will never fire, run onceReady anyhow
//  (boolean false or undefined) - if deviceready will never fire, do nothing
function deviceReadyOrNot(onceReady,patience,neverReady){

    if (!window.cordova){
            console.log('Cordova was not loaded when it should have been')
            if (typeof neverReady == "function"){neverReady();}
        //If phoneGap script loaded...
        } else {
            //And device is ready by now...
            if  (cordova.device){
                callback();
            //...or it's loaded but device is not ready
            } else {
                //...we might run the callback after
                if (typeof patience == "number"){
                    //Run the callback as soon as deviceready fires
                    document.addEventListener('deviceready.patience',function(){
                        if (typeof onceReady == "function"){onceReady();}
                    })
                    //Set a timeout to disable the listener
                    window.setTimeout(function(){
                        //If patience has run out, unbind the handler
                        $(document).unbind('deviceready.patience');
                        //If desired, manually run the callback right now
                        if (typeof neverReady == 'function'){neverReady();}
                    },patience);
                //...or we might just do nothing
                } else {
                    //Don't bind a deviceready handler: assume it will never happen
                    if (typeof neverReady == 'function'){neverReady();} 
                    else if (neverReady === true){onceReady();} 
                    else {
                       //Do nothing
                    }
                }
            }
    }

}

3

วิธีที่ฉันทำคือใช้ตัวแปรส่วนกลางที่เขียนทับโดย Cordova.js เวอร์ชันเบราว์เซอร์เท่านั้น ในไฟล์ html หลักของคุณ (โดยปกติindex.html) ฉันมีสคริปต์ต่อไปนี้ที่ขึ้นอยู่กับลำดับ:

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

และภายในcordova.jsฉันมีเพียง:

__cordovaRunningOnBrowser__ = true

เมื่อสร้างอุปกรณ์พกพา Cordova.js จะไม่ถูกใช้ (และจะใช้ไฟล์ Cordova.js เฉพาะแพลตฟอร์มแทน) ดังนั้นวิธีนี้จึงมีประโยชน์ที่จะถูกต้อง 100% ไม่ว่าจะเป็นโปรโตคอล UserAgents หรือไลบรารี ตัวแปร (ซึ่งอาจเปลี่ยนแปลงได้) อาจมีสิ่งอื่นที่ฉันควรรวมไว้ใน cordova.js แต่ฉันยังไม่รู้ว่ามันคืออะไร


แนวทางที่น่าสนใจมาก

แม้ว่าคุณจะไม่ต้องการสคริปต์เริ่มต้นจริงๆ คุณสามารถทดสอบว่ามันถูกตั้งค่าได้เลย: if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } .. ใช่ไหม?

ถูกต้องสิ่งที่ไม่ได้กำหนดไว้อาจบ่งบอกว่ามีบางอย่างผิดปกติ
BT

3

อีกวิธีหนึ่งขึ้นอยู่กับโซลูชันของ SlavikMe:

เพียงใช้พารามิเตอร์การค้นหาที่ส่งผ่านindex.htmlจากแหล่งที่มา PhoneGap ของคุณ เช่นใน Android แทนที่จะเป็น

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

ใช้

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

SlavikMe มีรายการที่ยอดเยี่ยมในการทำสิ่งนี้บนแพลตฟอร์มอื่น ๆ

จากนั้นคุณindex.htmlสามารถทำได้:

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

1
ฉันใช้ Cordova 3.4.1 และมันง่ายกว่านั้น: คุณเพียงแค่เปลี่ยนตัว<content src="index.html" />เลือกในไฟล์ config.xml เป็นไฟล์<content src="index.html?cordova=1" />. จนถึงตอนนี้ดูเหมือนว่าจะใช้งานได้และเป็นทางออกที่ดีที่สุดที่แนะนำที่นี่
Martin M.

2

หากต้องการเก็บโค้ดเบสไว้ 1 ตัวสิ่งที่น่าสนใจคือ "แพลตฟอร์ม" ที่โค้ดกำลังทำงานอยู่ สำหรับฉัน "แพลตฟอร์ม" นี้สามารถเป็นได้สามอย่าง:

  • 0: คอมพิวเตอร์เบราว์เซอร์
  • 1: เบราว์เซอร์มือถือ
  • 2: phonegap / Cordova

วิธีตรวจสอบแพลตฟอร์ม:

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

บันทึก:

  • สิ่งนี้จะต้องทำงานหลังจากโหลด Cordova.js แล้วเท่านั้น (body onload (... ), $ (document) .ready (... ))

  • 'ontouchstart' ใน document.documentElementจะปรากฏในแล็ปท็อปและจอภาพเดสก์ท็อปที่มีหน้าจอแบบสัมผัสดังนั้นจึงรายงานเบราว์เซอร์มือถือแม้ว่าจะเป็นเดสก์ท็อปก็ตาม มีหลายวิธีในการตรวจสอบที่แม่นยำยิ่งขึ้น แต่ฉันใช้เพราะมันยังดูแล 99% ของกรณีที่ฉันต้องการ คุณสามารถแทนที่บรรทัดนั้นเพื่อสิ่งที่แข็งแกร่งกว่าได้เสมอ


1
ฉันขอแนะนำให้ใช้typeof cordova !== 'undefined'แทนการตกปลาสำหรับข้อยกเว้น
krakatoa

1

Aarons ลอง

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

ไม่ฉันไม่ได้ทำ. ดูซอร์สโค้ด phonegap-1.1.0.js PhoneGap.available = DeviceInfo.uuid! == ไม่ได้กำหนด;
GeorgeW

1

โซลูชันของ GeorgeW นั้นใช้ได้ แต่แม้กระทั่งบนอุปกรณ์จริง PhoneGap.available จะเป็นจริงหลังจากโหลดสิ่งต่างๆของ PhoneGap แล้วเช่น onDeviceReady ใน document.addEventListener ('deviceready', onDeviceReady, false) ถูกเรียก

ก่อนถึงเวลานั้นหากคุณต้องการทราบคุณสามารถทำได้ดังนี้:

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

โซลูชันนี้ถือว่านักพัฒนาส่วนใหญ่พัฒนาโดยใช้ Chrome หรือ Firefox


OP กำลังมองหาทางออกสำหรับเว็บไซต์การผลิตไม่ใช่แค่ dev
Jesse Hattabaugh

1

ฉันมีปัญหาเดียวกัน

ฉันเอนเอียงไปที่การเพิ่ม # cordova = true ลงใน URL ที่โหลดโดยไคลเอนต์ Cordova และทดสอบ location.hash.indexOf ("cordova = true")> -1 ในหน้าเว็บของฉัน


ในท้ายที่สุดฉันก็ไปตามเส้นทางที่ Al Renaud แนะนำในจุดที่ 4 ของเขาและปล่อยให้สคริปต์สร้างตัดสินใจ มันไม่ใส่เครื่องหมายแฟล็กใน index.html เมื่อคัดลอกโค้ดของเว็บไซต์ลงในโฟลเดอร์ android assets // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true; เมื่อบิลด์สคริปต์คัดลอก index.html ลงในโฟลเดอร์ android assets / www ของฉันฉันเรียกใช้ ed เพื่อลบสตริง // UNCOMMENT-ON-DEPLOY: # การนวด index.html เพื่อบอกว่ากำลังเรียกใช้ Cordova ed "$ DEST / index.html" << - EOF 1, \ $ s / \ / \ / UNCOMMENT-ON-DEPLOY: // wq EOF
Austin France

1

สิ่งต่อไปนี้ใช้ได้กับฉันกับ PhoneGap / Cordova ล่าสุด (2.1.0)

มันทำงานอย่างไร:

  • ง่ายมากในแนวคิด
  • ฉันพลิกตรรกะของโซลูชันการหมดเวลาข้างต้นบางส่วน
  • ลงทะเบียนสำหรับเหตุการณ์ device_ready (ตามคำแนะนำของเอกสาร PhoneGap )
    • หากเหตุการณ์ยังไม่เริ่มทำงานหลังจากหมดเวลาให้กลับไปใช้เบราว์เซอร์สมมติ
    • ในทางตรงกันข้ามโซลูชันอื่น ๆ ข้างต้นอาศัยการทดสอบคุณสมบัติ PhoneGap บางอย่างหรืออื่น ๆ และดูช่วงพักการทดสอบ

ข้อดี:

  • ใช้เหตุการณ์ device_ready ที่แนะนำของ PhoneGap
  • แอพมือถือไม่มีความล่าช้า ทันทีที่เหตุการณ์ device_ready เริ่มทำงานเราจะดำเนินการต่อ
  • ไม่มีการดมกลิ่นของตัวแทนผู้ใช้ (ฉันชอบทดสอบแอปของฉันเป็นเว็บไซต์บนมือถือดังนั้นการดมเบราว์เซอร์จึงไม่ใช่ตัวเลือกสำหรับฉัน)
  • ไม่ต้องพึ่งพาคุณสมบัติ / คุณสมบัติ PhoneGap ที่ไม่มีเอกสาร (และเปราะ)
  • เก็บ Cordova.js ของคุณไว้ใน codebase แม้ว่าจะใช้เบราว์เซอร์เดสก์ท็อปหรือมือถือ ดังนั้นสิ่งนี้ตอบคำถามของ OP
  • Wytze ระบุไว้ข้างต้น: 'ฉันหวังว่า Cordova จะตั้งค่าพารามิเตอร์บางที่เพื่อบอกว่า "เราได้พยายามค้นหาอุปกรณ์ที่รองรับและยอมแพ้แล้ว" แต่ดูเหมือนว่าจะไม่มีพารามิเตอร์ดังกล่าว' ฉันจึงจัดให้ที่นี่

ข้อเสีย:

  • หมดเวลาน่าเบื่อ แต่ตรรกะของแอปบนอุปกรณ์เคลื่อนที่ของเราไม่ได้อาศัยความล่าช้า แต่จะใช้เป็นทางเลือกเมื่อเราอยู่ในโหมดเว็บเบราว์เซอร์

==

สร้างโปรเจ็กต์ PhoneGap เปล่าใหม่เอี่ยม ใน index.js ตัวอย่างที่ให้มาให้แทนที่ตัวแปร "app" ที่ด้านล่างด้วยสิ่งนี้:

var app = {
    // denotes whether we are within a mobile device (otherwise we're in a browser)
    iAmPhoneGap: false,
    // how long should we wait for PhoneGap to say the device is ready.
    howPatientAreWe: 10000,
    // id of the 'too_impatient' timeout
    timeoutID: null,
    // id of the 'impatience_remaining' interval reporting.
    impatienceProgressIntervalID: null,

    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // `load`, `deviceready`, `offline`, and `online`.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        // after 10 seconds, if we still think we're NOT phonegap, give up.
        app.timeoutID = window.setTimeout(function(appReference) {
            if (!app.iAmPhoneGap) // jeepers, this has taken too long.
                // manually trigger (fudge) the receivedEvent() method.   
                appReference.receivedEvent('too_impatient');
        }, howPatientAreWe, this);
        // keep us updated on the console about how much longer to wait.
        app.impatienceProgressIntervalID = window.setInterval(function areWeThereYet() {
                if (typeof areWeThereYet.howLongLeft == "undefined") { 
                    areWeThereYet.howLongLeft = app.howPatientAreWe; // create a static variable
                } 
                areWeThereYet.howLongLeft -= 1000; // not so much longer to wait.

                console.log("areWeThereYet: Will give PhoneGap another " + areWeThereYet.howLongLeft + "ms");
            }, 1000);
    },
    // deviceready Event Handler
    //
    // The scope of `this` is the event. In order to call the `receivedEvent`
    // function, we must explicity call `app.receivedEvent(...);`
    onDeviceReady: function() {
        app.iAmPhoneGap = true; // We have a device.
        app.receivedEvent('deviceready');

        // clear the 'too_impatient' timeout .
        window.clearTimeout(app.timeoutID); 
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        // clear the "areWeThereYet" reporting.
        window.clearInterval(app.impatienceProgressIntervalID);
        console.log('Received Event: ' + id);
        myCustomJS(app.iAmPhoneGap); // run my application.
    }
};

app.initialize();

function myCustomJS(trueIfIAmPhoneGap) {
    // put your custom javascript here.
    alert("I am "+ (trueIfIAmPhoneGap?"PhoneGap":"a Browser"));
}

1

ฉันเคยเจอปัญหานี้เมื่อหลายเดือนก่อนตอนที่เริ่มแอปเพราะเราอยากให้แอป "browser-compatible " ด้วย (ด้วยความเข้าใจว่าฟังก์ชันบางอย่างจะถูกบล็อกในสถานการณ์นั้นเช่นการบันทึกเสียงเข็มทิศ ฯลฯ )

100%โซลูชันเดียว(และฉันยืนยันในเงื่อนไข 100 เปอร์เซ็นต์) เพื่อกำหนดบริบทการเรียกใช้แอปล่วงหน้าคือ:

  • เริ่มต้นตัวแปร JS "flag" เป็น true และเปลี่ยนเป็น false เมื่ออยู่ในบริบทเว็บทั้งหมด

  • ดังนั้นคุณจึงสามารถใช้การโทรเช่น " willIBeInPhoneGapSometimesInTheNearFuture()" ได้ (นั่นคือ PRE-PG แน่นอนว่าคุณยังต้องใช้วิธีการ POST-PG ในการตรวจสอบว่าคุณสามารถเรียก PG API ได้หรือไม่ แต่วิธีนั้นเป็นเรื่องเล็กน้อย)

  • แล้วคุณพูดว่า: " but how do you determine the execution context?"; คำตอบคือ: "คุณไม่" (เพราะฉันไม่คิดว่าคุณสามารถเชื่อถือได้เว้นแต่คนเก่ง ๆ ที่ PG จะทำในรหัส API ของพวกเขา);

  • คุณเขียนบิลด์สคริปต์ที่ทำเพื่อคุณ: หนึ่งโค้ดเบสที่มีสองตัวแปร


1

ไม่ได้จริงๆคำตอบสำหรับคำถามที่ทดสอบผม butwhen ในเบราว์เซอร์สก์ท็อปที่ผมเพียงแค่ตั้งค่า localStorage เพื่อให้โหลดเบราว์เซอร์ dispite แอป deviceready ไม่ fireing

function main() {

    // Initiating the app here.
};

/* Listen for ready events from pheongap */
document.addEventListener("deviceready", main, false);

// When testing outside ipad app, use jquerys ready event instead. 
$(function() {

    if (localStorage["notPhonegap"]) {

        main();
    }
});

1

ไม่มีสิ่งใดทำงานได้เว้นแต่คุณจะลบไฟล์ PhoneGap Javascript ออกจากแอปเวอร์ชันเดสก์ท็อปซึ่งเอาชนะเป้าหมายของฉันในการมีโค้ดเบสเดียว

อีกทางเลือกหนึ่งคือใช้การผสานโฟลเดอร์ดูภาพหน้าจอด้านล่าง

คุณสามารถเพิ่มไฟล์เฉพาะแพลตฟอร์ม / แทนที่ไฟล์เริ่มต้นได้

(ควรทำเคล็ดลับในบางสถานการณ์)

ใส่คำอธิบายภาพที่นี่


กล่าวอีกนัยหนึ่ง: แทนที่จะตรวจจับเบราว์เซอร์คุณเพียงแค่ไม่รวมไฟล์บางไฟล์สำหรับการสร้างเดสก์ท็อป / แนบไฟล์บางไฟล์สำหรับ iOS เท่านั้น


1

ตรวจจับเบราว์เซอร์บนเดสก์ท็อปแม้ว่าจะจำลองอุปกรณ์อยู่ก็ตาม

ทำงานในเครื่อง Windows และ Mac ต้องการหาวิธีแก้ไขสำหรับ linux ดูรายละเอียด

var mobileDevice = false;
if(navigator.userAgent.match(/iPhone|iPad|iPod|Android|BlackBerry|IEMobile/))
    mobileDevice = true; 

if(mobileDevice && navigator.platform.match(/Win|Mac/i))
    mobileDevice = false; // This is desktop browser emulator

if(mobileDevice) {
    // include cordova files
}

0

ฉันพบว่าการรวมกันของสองเทคนิคที่ระบุไว้ที่นี่ได้ผลดีที่สุดอันดับแรกตรวจสอบว่าสามารถเข้าถึง Cordova / phonegap และตรวจสอบว่ามีอุปกรณ์หรือไม่ ชอบมาก:

function _initialize() {
    //do stuff
}

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

0

ลองใช้แนวทางนี้:

/**
 * Returns true if the application is running on an actual mobile device.
 */
function isOnDevice(){
    return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/);
}

function isDeviceiOS(){
    return navigator.userAgent.match(/(iPhone)/);
}

/**
 * Method for invoking functions once the DOM and the device are ready. This is
 * a replacement function for the JQuery provided method i.e.
 * $(document).ready(...).
 */
function invokeOnReady(callback){
    $(document).ready(function(){
        if (isOnDevice()) {
            document.addEventListener("deviceready", callback, false);
        } else {
            invoke(callback);
        }
    });
}

0

ฉันใช้การผสมผสานระหว่างสิ่งที่GeorgeWและmkprogrammingแนะนำ:

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

0

ฉันเดาว่าในสักวันพวกเขาก็ไม่ได้แตกต่างกันขนาดนั้นเหรอ? ฮ่าฮ่า ... ไม่ตลก ใครไม่คิดว่านี่จะไม่เป็นปัญหา? นี่คือทางออกที่ง่ายที่สุดสำหรับการพิจารณาของคุณ พุชไฟล์ต่าง ๆ ไปยังเซิร์ฟเวอร์ของคุณจากนั้นคุณไปที่ PhoneGap ฉันจะใช้ http: check ที่แนะนำไว้ข้างต้นชั่วคราวด้วย

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

ความสนใจของฉันคือการผลักดันแถบนำทางของเบราว์เซอร์ขึ้นดังนั้นฉันสามารถลบแท็กของสคริปต์ที่แยกออกมาแล้วกดสร้างใหม่ [ใน DW] (มันจะเป็นการล้างข้อมูลบางอย่างสำหรับการปรับใช้อยู่ดีดังนั้นนี่จึงเป็นหนึ่งในงานเหล่านั้น) อย่างไรก็ตามฉันรู้สึก เป็นตัวเลือกที่ดี (โดยพิจารณาว่ามีไม่มากนัก) ในการแสดงความคิดเห็นด้วยตนเองอย่างมีประสิทธิภาพด้วย isMobileBrowserAndNotPhoneGap เมื่อกดไปที่ PG) สำหรับฉันอีกครั้งในสถานการณ์ของฉันฉันจะลบแท็กสำหรับไฟล์ (รหัสแยก) ที่ดันแถบนำทางเมื่อเป็นเบราว์เซอร์มือถือ (จะเร็วและเล็กกว่ามาก) [ดังนั้นถ้าคุณสามารถแยกรหัสสำหรับโซลูชันที่ปรับให้เหมาะสมที่สุด แต่ใช้งานด้วยตนเอง]


0

แก้ไขเล็กน้อย แต่ใช้ได้กับฉันอย่างสมบูรณ์โดยไม่มีปัญหาใด ๆ

เจตนาคือการโหลด Cordova เฉพาะเมื่ออยู่บนอุปกรณ์ฝังตัวไม่ใช่บนเดสก์ท็อปดังนั้นฉันจึงหลีกเลี่ยง Cordova บนเบราว์เซอร์เดสก์ท็อปโดยสิ้นเชิง การทดสอบและพัฒนา UI และ MVVM แล้วก็สะดวกสบายมาก

ใส่รหัสนี้เช่น ในไฟล์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);
}

จากนั้นแทนที่จะรวม Cordova javascript เองให้รวม 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> 

ทำให้งานของคุณง่ายขึ้น! :)



0

สำหรับข้อมูลเพิ่มเติมใน 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();
} );

และในกรอบ YASMF

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


0

ฉันกำลังลองกับวัตถุหน้าต่าง แต่ไม่ได้ผลเนื่องจากฉันกำลังเปิด url ระยะไกลใน InAppBrowser ไม่สามารถดำเนินการได้ ดังนั้นวิธีที่ดีที่สุดและง่ายที่สุดในการบรรลุเป้าหมายคือการต่อท้ายสตริงเข้ากับ url ซึ่งคุณต้องเปิดจากแอป phonegap จากนั้นตรวจสอบว่าตำแหน่งเอกสารมีสตริงต่อท้ายหรือไม่

ด้านล่างนี้เป็นรหัสง่ายๆสำหรับมัน

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

คุณจะเห็นสตริงถูกเพิ่มใน url "#phonegap" ดังนั้นใน URL ของโดเมนให้เพิ่มสคริปต์ต่อไปนี้

if(window.location.indexOf("#phonegap") > -1){
     alert("Url Loaded in the phonegap App");
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.