60

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

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

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

16 回答 16

59

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

var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
if ( app ) {
    // PhoneGap application
} else {
    // Web page
}
于 2012-09-04T02:04:12.663 回答
15

想到的快速解决方案是,

onDeviceReady

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

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

请检查并让我知道结果。

于 2012-04-27T09:42:11.863 回答
11

我想出了一种方法来做到这一点,而不是依赖于 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();
    });
}
于 2012-07-08T16:24:15.197 回答
7

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

于 2012-04-27T08:51:27.857 回答
6

在加载 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('<script src="cordova.js"></script>');
    }
    
一个小警告:此方法需要为每个不同的目标移动平台更改 phonegap 中对 index.html 的调用。对于大多数平台,我不熟悉在哪里执行此操作。

于 2012-05-13T17:58:27.730 回答
4

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

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

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");
}
于 2013-11-29T09:24:32.190 回答
4

我这样做的方式是使用一个被仅浏览器版本的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% 正确变量(可能会改变)。我可能还应该在 cordova.js 中包含其他内容,但我还不知道它们是什么。

于 2013-08-28T01:29:51.893 回答
4

如果您尝试以下操作怎么办:

if(window._cordovaNative) {
  alert("loading cordova");
  requirejs(["...path/to/cordova.js"], function () { 
         alert("Finished loading cordova");
  });
}
于 2014-03-13T12:36:53.597 回答
4

一旦 webview 在 Phonegap 应用程序中启动,听起来您正在加载另一个网页,对吗?如果这是真的,那么您可以根据配置向请求 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。

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

于 2012-05-13T13:29:24.493 回答
4

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

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

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

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

于 2012-05-09T14:07:19.707 回答
1

简短而有效:

if (document.location.protocol == 'file:') { //Phonegap is present }
于 2014-02-07T16:52:55.837 回答
1

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

于 2012-05-11T11:51:19.317 回答
1

类似于B T 的解决方案,但更简单:

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

然后,您可以检查 Cordova 对象:

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

function bootstrap() {
   do_something()
}
于 2016-02-14T18:28:29.877 回答
0

新解决方案:

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

于 2012-05-11T11:19:52.193 回答
0

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

cordova platforms add browser

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

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

编辑:忘了提及我的来源

于 2016-07-21T10:12:41.370 回答
0

解决方案:在 Cordova 中修补 index.html 并添加cordova-platform="android"<html>标签中,这样 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>

添加文件 scripts/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
}
于 2019-02-12T12:02:35.597 回答