【问题标题】:Detect between a mobile browser or a PhoneGap application在移动浏览器或 PhoneGap 应用程序之间进行检测
【发布时间】:2012-04-27 08:44:25
【问题描述】:

是否可以检测用户是否通过浏览器或使用 JavaScript 的应用程序进行访问?

我正在通过一个网页和一个 PhoneGap 应用程序为多个移动操作系统开发一个混合应用程序,目标是:

  1. 独立于部署目标使用相同的代码
  2. 仅当用户代理是应用程序时才添加 PhoneGap.js 文件

【问题讨论】:

    标签: javascript jquery mobile cordova


    【解决方案1】:

    您可以检查当前 URL 是否包含http 协议。

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

    【讨论】:

    • 这样你就不需要等待PhoneGap/Cordova加载后就可以查看了。
    • 我已经测试过并且工作正常!这正是我一直在寻找的解决方案类型,仅当它是应用程序时才导入 PhoneGap。
    • 更短的检查:var fromBrowser = document.URL.match(/^https?:/)
    • 在我的构建中,document.URL 是 http://local/,所以 http 协议测试仍然是积极的。我必须添加以稍微更改此代码以使其适合我...
    • 如果我们在网络上托管科尔多瓦代码并将应用程序指向它,这也不起作用。
    【解决方案2】:

    想到的快速解决方案是,

    onDeviceReady
    

    会帮助你的。由于此 JS 调用仅由本机桥(objC 或 Java)调用,因此 safari 移动浏览器将无法检测到这一点。因此,您的设备上应用(电话间隙)源库将从 onDeviceReady 开始。

    如果 Phonegap 的任何 JS 调用(如 Device.platform 或 Device.name)为 NaN 或 null,那么它显然是移动网络调用。

    请检查并告诉我结果。

    【讨论】:

    • OK 在看到您对 Zvona 的回复后,现在我明白您甚至想决定是否加载或不加载 phonegap。让我再检查一遍
    • 此解决方案的唯一问题是在部署网页时会执行额外请求以获取 phonegap 文件。
    • 如果您真的可以对 Phonegap 源 (JS) 进行逆向工程。触发 onDeviceReady 本机调用的一段代码。这将使其重量相对较轻。您可以在设备上加载 Phonegap 的 JS 的其余部分。一个昂贵的测试操作。如果可能,请尝试。
    【解决方案3】:

    我想出了一种方法来做到这一点,而不是依赖于 deviceready 事件,从而保持网络代码库的完整性......

    当前使用内置 deviceready 事件的问题是,当页面加载时,您无法告诉应用:“嘿,这不是在移动设备上运行的,无需等待设备准备开始”。

    1.- 在代码的本机部分,例如对于 iOS,在 MainViewController.m 中有一个方法 viewDidLoad,我正在发送一个 javascript 变量,我稍后会在 Web 代码中检查该变量,如果该变量在附近,我将等待为我的页面启动代码,直到一切准备就绪(例如,导航器地理位置)

    在 MainViewController.m 下:

    - (void) viewDidLoad
    {
        [super viewDidLoad];
        NSString* jsString = [NSString stringWithFormat:@"isAppNative = true;"];
        [self.webView stringByEvaluatingJavaScriptFromString:jsString];
    }
    

    2.- index.html 代码如下:

    function onBodyLoad()
    {
        document.addEventListener("deviceready", onDeviceReady, false);
    }
    
    function onDeviceReady(){;
        myApp.run();
    }
    
    try{
        if(isAppNative!=undefined);
    }catch(err){
        $(document).ready(function(){
            myApp.run();
        });
    }
    

    【讨论】:

    • 我们还可以更进一步,将用户代理更改为 MyAppLoader XXHDPI。这将有助于加载更好的图像。很遗憾,cordova 没有这个功能。
    • 这个解决方案对我来说非常有效,但请注意there are a couple small changes needed for Cordova 4if ([self.webView isKindOfClass:[UIWebView class]]) { [(UIWebView*)self.webView stringByEvaluatingJavaScriptFromString:jsString]; }
    【解决方案4】:

    PhoneGap 具有 window.PhoneGap(或在 Cordova 中为 window.cordova 或 window.Cordova)对象集。检查该对象是否存在并施展魔法。

    【讨论】:

    • 该解决方案的问题是我必须包含或不包含PhoneGap 文件,具体取决于我是否正在构建页面或应用程序。目标是独立于部署目标使用相同的代码。
    • 那么这听起来有问题,因为我认为 UIWebView 包含相同的 Mobile Safari。让我看看我以后有没有发现。
    【解决方案5】:

    在加载 phonegap 应用程序的 url 的本机调用中,添加一个参数 target,其值为 phonegap。所以对android的调用变成了这样。

    super.loadUrl("file:///android_asset/www/index.html?target=phonegap");
    使用此代码的网站不会使用额外参数调用,因此我们现在在两个部署平台之间有一些不同。
    在 javascript 中,我们检查参数是否存在,如果存在,我们为 phonegap/cordova 添加脚本标签。 var urlVars = window.location.href.split('?'); if(urlVars.length > 1 && urlVars[1].search('target=phonegap') != -1){ //phonegap 用于通话 $('head').append(''); } 一个小警告:此方法需要为每个不同的目标移动平台更改 phonegap 中对 index.html 的调用。对于大多数平台,我不熟悉在哪里执行此操作。

    【讨论】:

      【解决方案6】:

      我对 phonegap 应用和我们的网络客户端使用相同的代码。这是我用来检测 phonegap 是否可用的代码:

      window.phonegap = false;
      $.getScript("cordova-1.7.0.js", function(){
          window.phonegap = true;
      });
      

      请记住,phonegap js 文件是异步加载的。您可以通过设置漂亮的 jquery $.getScript 函数的正确选项来同步加载它。

      请注意,即使在您的网络客户端中,该方法也会发出额外的 GET 请求来获取 phonegap js 文件。就我而言,它并没有影响我的网络客户端的性能;所以它最终成为了一种很好/干净的方法。至少在其他人找到快速的单线解决方案之前:)

      【讨论】:

      • 并非所有 phonegap 应用程序都是用 cordova 构建的。检测 phonegap.js 可能会更好。
      【解决方案7】:

      在 Phonegap 应用程序中启动 web 视图后,您似乎正在加载另一个网页,对吗?如果是这样,那么您可以根据配置向请求 url 添加一个参数。

      例如,假设 PHP,

      App.Config = {
        target: "phonegap"
      };
      
      <body onload="onbodyload()">
      
      var onbodyload = function () {
        var target = App.Config.target;
        document.location = "/home?target=" + target;
      };
      

      然后在服务器端,如果目标是phonegap,则包含phonegap js。

      无法使用用户代理检测差异。

      【讨论】:

        【解决方案8】:

        我这样做的方式是使用一个全局变量,该变量被仅浏览器版本的 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 中包含其他内容,但我还不知道它们是什么。

        【讨论】:

        • 我很高兴我一直滚动到底部 - 在此处列出的方法中,这是我最喜欢的。
        【解决方案9】:

        我也一直在努力解决这个问题,我知道这是一个旧线程,但我还没有在任何地方看到我的方法,所以认为 id 分享以防它对某人有所帮助。

        我在实际用户代理之后设置了一个自定义用户代理:

        String useragent = settings.getUserAgentString();
        settings.setUserAgentString(useragent + ";phonegap");
        

        这只是添加了 phonegap 字符串,因此其他依赖检测您的移动用户代理的网站仍然可以工作。

        然后你可以像这样加载phonegap:

        if( /phonegap/i.test(navigator.userAgent) ) 
        {
        //you are on a phonegap app, $getScript etc
        } else {
        alert("not phonegap");
        }
        

        【讨论】:

          【解决方案10】:

          如果你尝试以下方法:

          if(window._cordovaNative) {
            alert("loading cordova");
            requirejs(["...path/to/cordova.js"], function () { 
                   alert("Finished loading cordova");
            });
          }
          

          【讨论】:

          • 检查window._cordovaNative 为我工作!至少在安卓上。在 cordova.js 的其他地方有一条评论暗示它不适用于 Android
          【解决方案11】:

          在我看来,你试图为自己制造问题。您没有提到您的开发平台,但它们中的大多数都有不同的部署配置。您可以定义两种配置。并设置指示代码部署方式的变量。 在这种情况下,您无需关心部署应用的设备。

          【讨论】:

            【解决方案12】:

            短而有效:

            if (document.location.protocol == 'file:') { //Phonegap is present }
            

            【讨论】:

              【解决方案13】:

              类似于B T's solution,但更简单:

              我的 www 文件夹中有一个空的 cordova.js,它在构建时会被 Cordova 覆盖。不要忘记在您的应用脚本文件之前包含cordova.js(我花了一个小时才发现它们的顺序错误......)。

              然后您可以检查 Cordova 对象:

              document.addEventListener('DOMContentLoaded', function(){
                  if (window.Cordova) {
                      document.addEventListener('DeviceReady', bootstrap);
                  } else {
                      bootstrap();
                  }
              });
              
              function bootstrap() {
                 do_something()
              }
              

              【讨论】:

                【解决方案14】:

                新解决方案:

                var isPhoneGapWebView = location.href.match(/^file:/); // returns true for PhoneGap app
                

                旧解决方案:
                使用jQuery,这样运行

                $(document).ready(function(){
                   alert(window.innerHeight);
                });
                

                以 iPhone 作为您的移动应用程序的示例,

                使用 PhoneGap 或 Cordova 时,您将获得 460px 的 WebView,但在 safari 中,由于浏览器的默认页眉和页脚,您会失去一些高度。

                如果window.innerHeight等于460,可以加载phonegap.js,调用onDeviceReady函数

                【讨论】:

                • 这似乎是一个很好的解决方案,我怎样才能使其通用?我正在为多个移动设备进行部署。
                • 您可以对所有设备使用导航器对象来设置条件
                • 我认为您可以使用 navigator.userAgent 检测浏览器,请在此处查看答案stackoverflow.com/questions/3514784/…
                • 这将是一个非常脆弱的解决方案
                【解决方案15】:

                还没有人提到这一点,但 Cordova 现在似乎支持将浏览器添加为平台:

                cordova platforms add browser
                

                这将在运行时自动添加cordova.js,其中包含onDeviceReady 事件,因此您无需伪造它。此外,许多插件都支持浏览器,因此您的代码中不再有浏览器黑客攻击。

                要在浏览器中使用您的应用程序,您应该使用cordova run browser。如果您想部署它,您可以使用与其他平台相同的命令进行部署。

                编辑:忘记提及my source

                【讨论】:

                  【解决方案16】:

                  解决方案:在 Cordova 中修补 index.html 并将 cordova-platform="android" 添加到 &lt;html&gt; 标记,这样 cordova-platform 属性将仅存在于 Cordova 构建中,并且在用于 Cordova 之外的 Web 的原始 index.html 中缺失。

                  优点:不依赖于用户代理、url 架构或 cordova API。不需要等待 deviceready 事件。可以通过各种方式进行扩展,例如可以包含或不包含cordova-platform="browser",以便区分Cordova 之外的Web 应用程序与Cordova 的浏览器平台构建。

                  与 config.xml 合并

                      <platform name="android">
                          <hook src="scripts/patch-android-index.js" type="after_prepare" />
                      </platform>
                  

                  添加文件脚本/patch-android-index.js

                  module.exports = function(ctx) {
                      var fs = ctx.requireCordovaModule('fs');
                      var path = ctx.requireCordovaModule('path');
                  
                      var platformRoot = path.join(ctx.opts.projectRoot, 'platforms/android');
                      var indexPath = platformRoot + '/app/src/main/assets/www/index.html';
                  
                      var indexSource = fs.readFileSync(indexPath, 'utf-8');
                  
                      indexSource = indexSource.replace('<html', '<html cordova-platform="android"');
                  
                      fs.writeFileSync(indexPath, indexSource, 'utf-8');
                  }
                  

                  注意:对于非android,路径platforms/android/app/src/main/assets/www/index.html需要调整。

                  应用可以通过

                  检查cordova-platform
                  if (! document.documentElement.getAttribute('cordova-platform')) {
                    // Not in Cordova
                  }
                  

                  if (document.documentElement.getAttribute('cordova-platform') === 'android') {
                    // Cordova, Android
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2016-12-26
                    • 1970-01-01
                    • 2011-07-11
                    • 2011-10-01
                    • 2019-10-09
                    • 2016-10-17
                    • 2014-06-25
                    • 1970-01-01
                    相关资源
                    最近更新 更多