PhoneGap:检测是不是在桌面浏览器上运行

Posted

技术标签:

【中文标题】PhoneGap:检测是不是在桌面浏览器上运行【英文标题】:PhoneGap: Detect if running on desktop browserPhoneGap:检测是否在桌面浏览器上运行 【发布时间】:2011-12-25 11:11:13 【问题描述】:

我正在开发一个使用 PhoneGap:Build 移动版本的 Web 应用程序,并希望为“桌面”和移动版本提供一个代码库。我希望能够检测 PhoneGap 呼叫是否可以正常工作(即用户是否使用支持 PhoneGap 的移动设备)。

我已经搜索过了,无法相信没有简单的方法可以做到这一点。很多人提出了建议;

http://www.sencha.com/forum/showthread.php?144127-Checking-if-running-in-PhoneGap-or-Mobile-Web-Browser http://groups.google.com/group/phonegap/browse_thread/thread/322e80bd41bb1a54/a421300eb2a2029f?lnk=gst&q=detect+desktop#a421300eb2a2029f http://groups.google.com/group/phonegap/browse_thread/thread/8a95dfeb0f313792/3ff10d8f35211739?lnk=gst&q=detect+desktop+browser#3ff10d8f35211739

这些都不起作用,除非您从应用程序的桌面版本中删除 PhoneGap javascript 文件,这违背了我拥有一个代码库的目标。

到目前为止,我想出的唯一解决方案是浏览器/用户代理嗅探,但至少可以说这并不可靠。欢迎任何更好的解决方案!

编辑:稍微好一点的解决方案是在一些小的超时后尝试调用 PhoneGap 函数 - 如果它不起作用,则假设用户在桌面网络浏览器上。

【问题讨论】:

由于您使用的是 Build,请参阅下面的 @b-t 答案:***.com/a/18478002/241244。似乎它可能比接受和投票最多的答案更好。 我避免运行时检测以支持显式构建时配置,因为它是 100% 有效的。我只需将本地变量传递给我的 index.jade 模板,例如 isPhonegap: true,然后在模板中我可以有条件地包含 phonegap.js 脚本,并执行我想要的所有 phonegap 特定的初始化。 【参考方案1】:

亚伦,试试

if (PhoneGap.available)
    do PhoneGap stuff;

【讨论】:

不,我没有。查看 phonegap-1.1.0.js 源代码。 PhoneGap.available = DeviceInfo.uuid !== 未定义;【参考方案2】:

GeorgeW 的解决方案是可以的,但是即使在真实设备上,PhoneGap.available 也只有在 PhoneGap 的东西加载后才为真,例如document.addEventListener('deviceready', onDeviceReady, false) 中的 onDeviceReady 已被调用。

在那之前,如果你想知道,你可以这样做:

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

此解决方案假定大多数开发人员使用 Chrome 或 Firefox 进行开发。

【讨论】:

OP 正在为生产网站寻找解决方案,而不仅仅是开发。【参考方案3】:

我知道它已在不久前得到答复,但“PhoneGap.available”不再存在。 你应该使用:

if (window.PhoneGap) 
  //do stuff

或者从 1.7 开始,更喜欢:

if (window.cordova) 
  //do stuff

EDIT 2019:如 cmets 中所述,这仅在您未将 cordova lib 包含到桌面浏览器构建中时才有效。当然,最好只为您定位的每个设备包含严格的最低限度的 javascript/html/css 文件

【讨论】:

这不是真的,因为如果你包含脚本cordova-x.x.x.js,window.PhoneGap或window.cordova总是会被定义,即使它是在浏览器上加载的。 你能帮我举个例子吗?简单地加载 index.html。我正在做的是我已经上传了本地服务器 www 文件夹下的所有文件,我正在加载索引.html。但是准备好的设备没有被触发。 这似乎是现在的正确答案(至少在 Cordova 3.4 中)。所有其他方法都只是浪费时间,因为现在使用简单的 将 cordova.js 注入应用程序。您实际上并不指向真实文件,因此在浏览器中运行时不会加载它。它仅存在于在移动设备上运行的 Cordova 构建中。 如果使用PhoneGap Build,这似乎会特别好。 @SlavikMe 不要在非cordova构建中包含cordova脚本。【参考方案4】:

我使用这个代码:

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

更新

还有很多其他方法可以检测 phonegap 是否在浏览器上运行,这是另一个不错的选择:

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

如此处所示:Detect between a mobile browser or a PhoneGap application

【讨论】:

感谢您 - 在等了很长时间后看到其他人的建议,这似乎是最好的解决方案。干杯。 这不准确,因为如果我将在设备浏览器上打开同一页面,onDeviceReady() 将永远不会调用。另外,如果我要更改浏览器中的 UserAgent(出于调试目的),onDeviceReady() 也永远不会调用。 不确定您在说什么 - 但您似乎在暗示这会导致使用手机浏览器出现问题...这是在您的桌面浏览器而不是手机上进行测试的解决方案。跨度> 当您在设备浏览器中打开应用程序时,这无济于事。更好的解决方案:检查 window.cordova。在 iPhone 模拟器(浏览器)或 Android 设备(浏览器)上进行测试也应该检测到 PhoneGap。我就是这样发展的。但是有很多可能性可以完成工作。 ;-) 感谢您发布您的解决方案! 我很困惑,其他平台比如windows phone呢?他们是否有与该正则表达式匹配的 userAgent?快速的谷歌搜索并不意味着:madskristensen.net/post/Windows-Phone-7-user-agents.aspx【参考方案5】:

这对我有用(运行 1.7.0)

if (window.device) 
  // Running on PhoneGap

在桌面 Chrome 和 Safari 上测试。

【讨论】:

这与绑定到 'deviceready' 事件几乎相同。如果 window.device 没有定义,你无法判断 phonegap/cordova 是否加载缓慢,或者事件是否永远不会触发。 window.device 在“deviceready”事件触发之前没有定义。 并祈祷没有其他程序员有定义一个名为“device”的新全局变量的快乐想法。【参考方案6】:

问题的本质在于,只要 cordova.device 未定义,您的代码就无法确定这是因为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
                    
                
            
    


【讨论】:

【参考方案7】:

我实际上发现这里列出的两种技术的组合效果最好,首先检查是否可以访问cordova / phonegap,并检查设备是否可用。像这样:

function _initialize() 
    //do stuff


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

【讨论】:

【参考方案8】:

试试这个方法:

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

【讨论】:

【参考方案9】:

我认为这是最简单的: var isPhoneGap = (location.protocol == "file:")

编辑 对于一些没有工作的人。那你可以试试(没测试过)

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

【讨论】:

我认为 PhoneGap 为所有设备上的文件运行了一个内部服务器? 我喜欢。在 localhost 上开发时,这是最好的解决方案。 (经过大量尝试,我希望这适用于所有场景。)谢谢! 当我测试远程文件时,这在波纹模拟器中不起作用 在 WP8 中也不起作用,协议是“x-wmapp0:”。无法确定将来会使用哪些其他“协议”。 嗯,你也可以 --try var isPhoneGap = ! /^http/.test(document.location.protocol)【参考方案10】:

我使用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.')
   

【讨论】:

【参考方案11】:

我也有同样的问题。

我倾向于将 #cordova=true 添加到由 cordova 客户端加载的 URL 并在我的网页中测试 location.hash.indexOf("cordova=true") > -1。

【讨论】:

最后,我按照 Al Renaud 在第 4 点建议的路线,让构建脚本决定。将网站代码复制到 android assets 文件夹时,它会取消 index.html 中的标志。 // UNCOMMENT-ON-DEPLOY: window._appInfo.isCordova = true;当构建脚本将 index.html 复制到我的 android assets/www 文件夹中时,我在其上运行 ed 以删除 // UNCOMMENT-ON-DEPLOY: 字符串。 # 按摩 index.html 告诉它正在运行 cordova ed "$DEST/index.html" 【参考方案12】:

以下适用于我最新的 PhoneGap / Cordova (2.1.0)。

它是如何工作的:

概念非常简单 我颠倒了上述一些超时解决方案的逻辑。 注册 device_ready 事件(如recommended by the PhoneGap docs) 如果事件在超时后仍未触发,则回退到假设浏览器。 相比之下,上述其他解决方案依赖于测试某些 PhoneGap 功能或其他功能,并观察它们的测试中断。

优点:

使用 PhoneGap 推荐的 device_ready 事件。 移动应用程序没有延迟。一旦 device_ready 事件触发,我们就会继续。 没有用户代理嗅探(我喜欢将我的应用程序作为移动网站进行测试,因此浏览器嗅探不是我的选择)。 不依赖未记录的(因此脆弱的)PhoneGap 功能/属性。 即使在使用桌面或移动浏览器时,也可以将 cordova.js 保存在代码库中。因此,这回答了 OP 的问题。 Wytze 上面说过:“我希望科尔多瓦在某处设置一个参数来说明“我们已尝试找到支持的设备并放弃了”,但似乎没有这样的参数。所以我在这里提供一个。

缺点:

超时很糟糕。但是我们的移动应用逻辑不依赖于延迟;相反,当我们处于网络浏览器模式时,它被用作后备。

==

创建一个全新的空白 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"));

【讨论】:

【参考方案13】:

与原始海报一样,我正在使用 phonegap 构建服务。经过两天和近 50 次测试构建后,我想出了一个非常适合我的优雅解决方案。

我无法使用 UA 嗅探,因为我想在移动浏览器中进行测试和运行。我最初选择了鞋匠的实用技术。这对我不起作用,因为“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!
    

【讨论】:

【参考方案14】:

我想在某些方面他们并没有那么不同,是吗?哈哈……不好笑。谁不认为这不会是一个问题? 这是供您考虑的最简单的解决方案。 将不同的文件推送到您的服务器,然后再推送到 PhoneGap。 我也会暂时使用上面建议的 http: 检查。

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

我的兴趣是将浏览器导航栏向上推,所以实际上我可以删除隔离脚本的标签并按下重建 [在 DW 中](无论如何它们都会对部署进行一些清理,所以这可能是其中一项任务。) 无论如何,我觉得这是一个不错的选择(考虑到没有太多可用的东西),只需在推送到 PG 时使用 isMobileBrowserAndNotPhoneGap 有效地手动注释掉内容)。 再次对我来说,在我的情况下,我将简单地删除(隔离代码)文件的标签,当它是移动浏览器时,它会向上推导航栏(它会更快更小)。 [所以,如果您可以隔离该优化但手动解决方案的代码。]

【讨论】:

【参考方案15】:

几天前我写了一封post。这是你能找到的最好的解决方案(直到 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>

现在,在原生上,只需在所有 PhoneGap 平台上将起始页从 index.html 更改为 __phonegap_index.html。假设我的项目名称是example,您需要更改的文件是(对于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 Bada - src/WebForm.cpp(第 56 行) Window Phone 7 - 不知道在哪里(有人还在那个平台上开发?!)

最后,您可以在您网站的任何地方使用它,无论它是否在 PhoneGap 上运行:

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

希望对您有所帮助。 :-)

【讨论】:

发现这个答案是最好的! 是的,它可以工作,但有时代码的下一部分不是真的/^file:\/3[^\/]/i.test(window.location.href) 但我们正在使用 PhoneGap,例如从另一个页面加载 index.html 时,在 config.xml 上类似这样&lt;content src="http://10.100.1.147/" /&gt; 如果没有定义任何这些变量,表达式(cordova || PhoneGap || phonegap) 将抛出ReferenceError。您应该使用typeof cordova !== undefined 进行测试,对吧? @rblakeley 你是对的。我将第一行改为:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined ) @rojobuffalo:看起来答案已被修改,使其再次按预期工作(ie由于window,它不再抛出ReferenceError字首)。只是想我会指出这一点,因为这实际上使评论链过时(因此不正确)。【参考方案16】:

这似乎是可行的,我已经在生产中使用它:

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/

【讨论】:

【参考方案17】:

几个月前我在开始我们的应用程序时偶然发现了这个问题,因为我们希望应用程序也是“browser-compatible”(理解在这种情况下某些功能会被阻止:录音,指南针,等等。)。

预先确定应用程序执行上下文的唯一100%(我坚持 100% 的条件)解决方案是:

初始化一个JS“flag”变量为true,在全web上下文中改为false;

1234563

然后你说:“but how do you determine the execution context?”;答案是:“你不”(因为我认为你不能可靠,除非 PG 的那些聪明人会在他们的 API 代码中做到这一点);

您编写了一个构建脚本来为您完成它:一个代码库有两个变体。

【讨论】:

【参考方案18】:

为了保持一个代码库,感兴趣的是代码运行的“平台”。对我来说,这个“平台”可以是三个不同的东西:

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(...))

document.documentElement 中的'ontouchstart' 将出现在具有触摸屏的笔记本电脑和台式机显示器中,因此即使它是台式机,它也会报告移动浏览器。有多种方法可以进行更精确的检查,但我使用它是因为它仍然可以处理我需要的 99% 的案例。你总是可以用这条线来代替更健壮的东西。

【讨论】:

我建议使用typeof cordova !== 'undefined' 而不是寻找异常。【参考方案19】:

稍作修改,但对我来说非常完美,没有任何问题。

意图是仅在嵌入式设备上加载 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> 

让您的工作轻松起来! :)

【讨论】:

【参考方案20】:

我这样做的方式是使用一个全局变量,该变量被仅浏览器版本的 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 文件),因此这种方法的好处是无论协议、userAgents 怎样都100% 正确,或库变量(可能会改变)。我可能还应该在 cordova.js 中包含其他内容,但我还不知道它们是什么。

【讨论】:

非常有趣的方法。 虽然,您并不真的需要初始脚本。你可以测试它是否被设置:if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) stuff(); ..right? 是的,虽然未定义可能表明其他问题。【参考方案21】:
if ( "device" in window ) 
    // phonegap
 else 
    // browser

【讨论】:

【参考方案22】:

另一种方式,基于 SlavikMe 的解决方案:

只需使用从 PhoneGap 源传递给 index.html 的查询参数即可。即,在 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");

【讨论】:

我使用的是 Cordova 3.4.1,它更简单:您只需将 config.xml 文件中的 &lt;content src="index.html" /&gt; 选项更改为 &lt;content src="index.html?cordova=1" /&gt;。到目前为止,它似乎有效,并且是迄今为止建议的最佳解决方案。【参考方案23】:

真的不是问题的答案,但是当我在桌面浏览器中进行测试时,我只是设置了一个 localstorage 值,以使浏览器加载应用程序,尽管设备准备就绪没有触发。

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

【讨论】:

【参考方案24】:

这些都不起作用,除非您从应用程序的桌面版本中删除 PhoneGap Javascript 文件,这违背了我拥有一个代码库的目标。

另一种选择是使用 merges 文件夹,请参见下面的屏幕截图。

您可以添加特定于平台的文件/覆盖默认文件。

(在某些情况下应该可以解决问题)


换句话说:您没有检测浏览器,只是不包含某些文件用于桌面构建/仅附加某些用于 iOS 的文件。

【讨论】:

【参考方案25】:

有趣的是,有很多答案,但它们不包括这三个选项:

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

【讨论】:

【参考方案26】:

仅供参考 PhoneGap 3.x 移动应用开发热点

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

【讨论】:

【参考方案27】:

我用这个方法:

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

debug 在浏览器环境中为true,在设备上为false

【讨论】:

【参考方案28】:

即使模拟设备处于活动状态也检测桌面浏览器

适用于 Windows 和 Mac 机器。需要找linux的解决方案View details

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

【讨论】:

【参考方案29】:

我正在尝试使用窗口对象,但它没有工作,因为我在 InAppBrowser 中打开远程 URL。没能完成。 因此,实现它的最佳和最简单的方法是将字符串附加到您需要从 phonegap 应用程序打开的 url。然后检查文档位置是否附加了字符串。

下面是它的简单代码

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");

【讨论】:

【参考方案30】:

我们发现判断我们是否在cordova/phonegap 应用程序中最可靠的方法是使用此配置AppendUserAgent 修改cordova 应用程序的用户代理。

config.xml 中添加:

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

然后调用:

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

为什么?

    window.cordovadocument.addEventListener('deviceready', function()); 受比赛条件限制 当&lt;content src="index.html" /&gt; 是网站时,navigator.standalone 不起作用(例如:&lt;content src="https://www.example.com/index.html" /&gt; 或 cordova-plugin-remote-injection) 尝试将用户代理列入白名单以猜测它是否是真正的浏览器非常复杂。 Android 浏览器通常是自定义 Web 视图。

【讨论】:

我们甚至可以在那里添加应用程序版本! (理想情况下带有一些自动版本的碰撞逻辑)例如; Cordova AppName/v0.0.1 这似乎是最万无一失的方法。亚军似乎正在测试文档 URL 中是否缺少 http:// 或 https://,但我可以设想可能出现的情况。 这毕竟是对我有用的。谢谢!

以上是关于PhoneGap:检测是不是在桌面浏览器上运行的主要内容,如果未能解决你的问题,请参考以下文章

PhoneGap 中的 screen.width/device-width 与常规浏览器不同

如何以编程方式检测是不是在 Windows 桌面应用程序中启用/禁用了 javascript? (网络浏览器控件)

在移动浏览器或 PhoneGap 应用程序之间进行检测

检测浏览器是不是在网页中有键盘/箭头键

在 PhoneGap+jQuery Mobile 中使用 ajax 的 CORS 无法在设备上运行,但在浏览器上运行

Android 设备上 Phonegap 应用程序的本地存储是不是与内置浏览器分开?