PhoneGap: определить, запущен ли он в браузере рабочего стола

118

Я разрабатываю веб-приложение, использующее PhoneGap: Build для мобильной версии и хочу иметь единую базу кода для «настольной» и мобильной версий. Я хочу иметь возможность определять, будут ли работать вызовы PhoneGap (т. Е. Есть ли у пользователя мобильное устройство, поддерживающее PhoneGap).

Я искал и не могу поверить, что нет простого способа сделать это. Многие люди предлагали свои предложения;

Ничего из этого не сработает, если вы не удалите файл Javascript PhoneGap из настольной версии приложения, что противоречит моей цели иметь единую базу кода.

Пока что единственным решением, которое я придумал, является обнюхивание браузера / пользовательского агента, но это, мягко говоря, не надежно. Приветствуются любые лучшие решения!

РЕДАКТИРОВАТЬ: немного лучшим решением является попытка вызвать функцию PhoneGap после небольшого тайм-аута - если это не сработает, предположим, что пользователь находится в настольном веб-браузере.

aaronsnoswell
источник
Поскольку вы используете Build, см. Ответ @bt ниже: stackoverflow.com/a/18478002/241244 . Похоже, это может быть лучше, чем принятые и получившие наибольшее количество голосов ответы.
Я избегаю обнаружения во время выполнения в пользу явной конфигурации во время сборки, потому что это на 100% эффективно. Я просто передаю локальную переменную в свой шаблон index.jade, например {isPhonegap: true}, затем в шаблон я могу условно включить сценарий phonegap.js и выполнить все необходимые инициализации для телефонных разговоров.
Джесси Хаттабо

Ответы:

115

Я использую этот код:

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

ОБНОВИТЬ

Есть много других способов определить, работает ли телефонная связь в браузере или нет, вот еще один отличный вариант:

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

как показано здесь: обнаружение между мобильным браузером или приложением PhoneGap

sirmdawg
источник
Спасибо за это - после долгого ожидания, чтобы увидеть, что предложили другие люди, это кажется лучшим решением. Приветствия.
aaronsnoswell
35
Это неточно, потому что, если я открою ту же страницу в обзоре устройства, onDeviceReady () никогда не вызовет. Кроме того, если я изменю UserAgent в браузере (для целей отладки), onDeviceReady () тоже никогда не будет вызывать.
Славик Мельцер
3
Не уверен, что вы говорите, но похоже, что вы подразумеваете, что это вызовет проблемы с использованием браузера телефона ... Это решение для тестирования в браузере вашего компьютера, а не на телефоне.
sirmdawg 07
7
Это не помогает, когда вы открываете приложение в браузере устройства. Лучшее решение: проверьте window.cordova. Тестирование в iPhone Simulator (браузер) или на устройстве Android (браузер) также должно обнаружить PhoneGap. Так я развиваюсь. Но есть много возможностей добиться желаемого. ;-) Спасибо за размещение вашего решения!
Марио
Я запутался, а как насчет других платформ, таких как Windows Phone? У них есть агент пользователя, соответствующий этому регулярному выражению? Быстрый поиск в Google не означает: madskristensen.net/post/Windows-Phone-7-user-agents.aspx
пришвартован
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
  • BlackBerry -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 05
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 06
1
@rblakeley, ты прав. Я переключил первую строчку на:return ( typeof cordova !== undefined || typeof PhoneGap !== undefined || typeof phonegap !== undefined )
ethanpil
1
@rojobuffalo: Похоже, что с тех пор ответ был изменен, поэтому он снова работает так, как ожидалось ( т.е. он больше не выдает a 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 для каждого целевого устройства.

fredericrous
источник
18
Это неверно, потому что window.PhoneGap или window.cordova всегда будут определены, если вы включите сценарий cordova-xxxjs, даже если он загружен в браузере.
Славик Мельцер
Можете ли вы помочь мне на примере. Чтобы просто загрузить index.html. Я загружаю все файлы в папку www на моем локальном сервере, я загружаю index.html. Но устройство готово не уволен.
Nassif
5
Теперь это кажется правильным ответом (по крайней мере, с Cordova 3.4). Все остальные методы - пустая трата времени, так как cordova.js теперь вводится в приложение с помощью простого <script type = "text / javascript" src = "cordova.js"> </script>. На самом деле вы не указываете на настоящий файл, поэтому он не загружается при запуске в браузере. Он есть только в сборке Cordova, работающей на мобильном устройстве.
Майкл Орил
Похоже, что это будет особенно хорошо работать при использовании PhoneGap Build.
4
@SlavikMe Не включайте сценарий Cordova в сборки, отличные от Cordova.
Джексон
21

Самый надежный способ узнать, находимся ли мы в приложении cordova / phonegap, - это изменить пользовательский агент этого приложения с помощью этой конфигурации 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 часто представляют собой настраиваемые веб-просмотры.
jrobichaud
источник
2
И мы даже можем добавить туда версию приложения! (в идеале с некоторой автоматической логикой изменения версии) ex; Cordova AppName/v0.0.1<3 Таким образом, вы даже можете каким-то образом использовать это для отслеживания (но учтите, что любой может изменить его пользовательский агент, поэтому не полагайтесь на него для критически важных проверок безопасности)
GabLeRoux
Это кажется наиболее надежным методом. Второе место, занявшее второе место, похоже, проверяет отсутствие http: // или https: // в URL-адресе документа, но я могу представить себе возможные сценарии, в которых это не сработает.
Джей Ди Смит,
14

Думаю, это проще всего: var isPhoneGap = (location.protocol == "file:")

ИЗМЕНИТЬ Для некоторых людей это не сработало. Тогда вы можете попробовать (не тестировали)

var isPhoneGap = ! /^http/.test(location.protocol);
Юваль
источник
1
Я думал, что PhoneGap запускает внутренний сервер для всех файлов на устройстве?
aaronsnoswell
Мне это нравится. При разработке на localhost это лучшее решение. (После многих попыток я надеюсь, что это сработает во всех сценариях, надеюсь.) Спасибо!
Марио
1
это не работает в эмуляторе пульсации, когда я тестирую удаленный файл,
Джесси Хаттабо
Также не работает в WP8, протокол - «x-wmapp0:». Не могу точно знать, какие еще «протоколы» будут использоваться в будущем.
Адриан
Ну, вы могли бы такжеvar isPhoneGap = ! /^http/.test(document.location.protocol)
Юваль
8

Это работает для меня (работает 1.7.0)

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

Проверено на настольных компьютерах Chrome и Safari.

обкрадывать
источник
3
Это почти то же самое, что и привязка к событию deviceready. Если window.device не определен, вы не можете определить, загружается ли phonegap / cordova медленно или событие никогда не сработает.
Wytze
8
window.device не определяется до запуска события «deviceready».
Славик Мельцер
2
И молитесь, чтобы ни у одного другого программиста не возникло счастливой идеи определить новую глобальную переменную под названием «устройство».
Мистер Смит
7

Как и в оригинальном плакате, я использую службу создания телефонных разговоров. После двух дней и почти 50 тестовых сборок я придумал элегантное решение, которое мне отлично подходит.

Я не мог использовать сниффинг UA, потому что хотел протестировать и запустить в мобильных браузерах. Изначально я остановился на довольно функциональной технике cobberboy. У меня это не сработало, потому что задержка / тайм-аут "howPatientAreWe: 10000" слишком мешала разработке в браузере. А установка более низкого значения иногда проваливала бы тест в режиме приложения / устройства. Должен был быть другой способ ...

Служба сборки телефонной связи требует, чтобы phonegap.jsфайл был исключен из репозитория кода перед отправкой файлов вашего приложения в службу. Поэтому я могу проверить его существование, чтобы определить, работает ли он в браузере или в приложении.

Еще одно предостережение: я также использую jQueryMobile, поэтому и jQM, и phonegap должны быть инициализированы, прежде чем я смогу начать любой пользовательский скрипт. Следующий код помещен в начало моего настраиваемого файла index.js для приложения (после jQuery, перед jQM). Также в документации по сборке телефонного разговора говорится, что нужно разместить <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 он будет использовать ФАЙЛ. Обнаружение этого даст вам возможность предположить, что ваше приложение было загружено локально.

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

3 - Используйте событие загрузки скрипта Cordova для определения контекста. Включение скрипта можно легко удалить в процессе сборки, иначе загрузка скрипта в браузере просто не удастся. Так что эта глобальная переменная не будет установлена.

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

Благодарим Дэмиена Антипа из Adobe

Frodik
источник
5

Я использую такой способ:

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

debugбудет trueв среде браузера falseна устройстве.

andreszs
источник
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/

Deminetix
источник
3

Суть проблемы заключается в том, что пока cordova.device не определен, ваш код не может быть уверен, что это потому, что cordova установила, что ваше устройство не поддерживается, или потому, что cordova все еще готовится, а deviceready сработает позже. (или третий вариант: кордова не загрузилась должным образом).

Единственное решение - определить период ожидания и решить, что после этого периода ваш код должен предполагать, что устройство не поддерживается. Я бы хотел, чтобы кордова установила параметр где-нибудь, чтобы сказать «Мы пытались найти поддерживаемое устройство, но отказались», но похоже, что такого параметра нет.

Как только это будет установлено, вы можете захотеть сделать что-то конкретное именно в тех ситуациях, когда нет поддерживаемого устройства. В моем случае вроде скрытия ссылок на магазин приложений устройства.

Я собрал по кусочкам эту функцию, которая должна охватывать практически любую ситуацию. Он позволяет вам определять обработчик готовности устройства, обработчик готовности устройства и время ожидания.

//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
источник
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% верен независимо от протоколов, агентов пользователя или библиотеки. переменные (которые могут измениться). Могут быть и другие вещи, которые мне следует включить в cordova.js, но я еще не знаю, что это такое.

BT
источник
Очень интересный подход.
Хотя вам действительно не нужен исходный сценарий. Вы можете просто проверить, установлен ли он вообще: .. if ( typeof __cordovaRunningOnBrowser__ !== 'undefined' ) { stuff(); } правильно?
Верно, хотя значение undefined может означать, что что-то еще не так.
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" />. Пока что это работает, и это, безусловно, лучшее решение, предлагаемое здесь.
Мартин М.
2

Чтобы сохранить единую базу кода, нас интересует «платформа», на которой выполняется код. Для меня эта «платформа» может быть тремя разными вещами:

  • 0: компьютер-браузер
  • 1: мобильный браузер
  • 2: телефонная связь / кордова

Способ проверки платформы:

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% необходимых мне дел. Вы всегда можете заменить эту строку чем-нибудь более надежным.

Nik
источник
1
Я предлагаю использовать typeof cordova !== 'undefined'вместо рыбалки для исключения.
krakatoa
1

Ааронс, попробуй

if (PhoneGap.available){
    do PhoneGap stuff;
}
GeorgeW
источник
Нет, я не. Посмотрите исходный код phonegap-1.1.0.js. PhoneGap.available = DeviceInfo.uuid! == undefined;
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 ищет решение для производственного веб-сайта, а не только для разработчиков.
Джесси Хаттабо
1

У меня такая же проблема.

Я склоняюсь к добавлению # cordova = true к URL-адресу, загружаемому клиентом cordova, и тестированию на location.hash.indexOf ("cordova = true")> -1 на моей веб-странице.

Остин Франция
источник
В конце концов, я пошел по пути, предложенному Аль Рено в его 4-м пункте, и предоставил решение сценарию сборки. Он раскомментирует флаг в index.html при копировании кода веб-сайта в папку ресурсов Android. // ОТКРЫТИЕ ПРИ РАЗВЕРТЫВАНИИ: window._appInfo.isCordova = true; Когда сценарий сборки копирует index.html в мою папку с ресурсами / www android, я запускаю на нем 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 в своей кодовой базе даже при использовании настольного или мобильного браузера. Таким образом, это отвечает на вопрос ОП.
  • 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"));
}
cobberboy
источник
1

Я столкнулся с этой проблемой несколько месяцев назад, когда запускал наше приложение, потому что мы хотели, чтобы приложение было "browser-compatible тоже " (с пониманием того, что некоторые функции будут заблокированы в этом сценарии: запись звука, компас и т. Д.).

Единственное 100%(и я настаиваю на 100-процентном условии) решение для ПРЕДВАРИТЕЛЬНОГО определения контекста выполнения приложения было следующее:

  • инициализировать JS-переменную "flag" значением true и изменить ее на false во всем веб-контексте;

  • поэтому вы можете использовать вызов типа " willIBeInPhoneGapSometimesInTheNearFuture()" (это PRE-PG, конечно, вам все еще нужен метод POST-PG для проверки того, можете ли вы вызывать API PG, но это тривиально).

  • Затем вы говорите: « but how do you determine the execution context?»; ответ: «нет» (потому что я не думаю, что вы можете надежно, если только эти блестящие ребята из PG не сделают это в своем коде API);

  • вы пишете сценарий сборки, который сделает это за вас: одна кодовая база с двумя вариантами.

Аль Рено
источник
1

Не совсем ответ на вопрос, но когда я тестирую в браузере настольного компьютера, я просто устанавливаю значение 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();
    }
});
гирооптическая астронавигационная система
источник
1

Ничего из этого не сработает, если вы не удалите файл Javascript PhoneGap из настольной версии приложения, что противоречит моей цели иметь единую базу кода.

Другой вариант - использовать слияния папку , см. Снимок экрана ниже.

Вы можете добавлять файлы для конкретной платформы / отменять файлы по умолчанию.

(он должен помочь в некоторых сценариях)

введите описание изображения здесь


Другими словами: вместо того, чтобы определять браузер, вы просто не включаете определенные файлы для сборки на рабочем столе / не прикрепляете определенные файлы только для 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

На самом деле я обнаружил, что комбинация двух методов, перечисленных здесь, работает лучше всего. Во-первых, проверьте, есть ли доступ к кордове / телефонному разговору, а также проверьте, доступно ли устройство. Вот так:

function _initialize() {
    //do stuff
}

if (window.cordova && window.device) {
    document.addEventListener('deviceready', function () {
      _initialize();
    }, false);
} else {
   _initialize();
}
andyjamesdavies
источник
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);
        }
    });
}
Zorayr
источник
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.')
   }
skybondsor
источник
0

Я думаю, что в чем-то они не такие уж разные, не так ли? Ха-ха ... не смешно. Кто не думал, что это не проблема? Вот самое простое решение для ваших соображений. Отправляйте разные файлы на свой сервер, а затем в PhoneGap. Я бы также временно использовал http: check, предложенный выше.

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

Я заинтересован в том, чтобы поднять панель навигации браузеров вверх, так что на самом деле я могу просто удалить тег изолированного скрипта и нажать rebuild [в DW] (они все равно будут очищать для развертывания, так что это может быть одной из этих задач). В любом случае, я чувствую это хороший вариант (учитывая, что больше ничего не доступно), чтобы просто вручную комментировать вещи с помощью isMobileBrowserAndNotPhoneGap при нажатии на PG). Опять же, в моей ситуации я просто удалю тег для файла (изолированного кода), который поднимает панель навигации, когда это мобильный браузер (он будет намного быстрее и меньше). [Так что, если вы можете выделить код для этого оптимизированного, но ручного решения.]

MistereeDevlord
источник
0

Немного изменен, но у меня работает отлично, без проблем.

Намерение состоит в том, чтобы загружать Cordova только на встроенном устройстве, а не на рабочем столе, поэтому я полностью избегаю Cordova в браузере для настольных компьютеров. Тестирование и разработка пользовательского интерфейса и 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);
}

Затем вместо включения самого кордовского 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> 

Упростите себе работу! :)

OSP
источник
0
if ( "device" in window ) {
    // phonegap
} else {
    // browser
}
Петар Васильев
источник
0

Просто для информации в разделе " Горячий снимок" по разработке мобильных приложений 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

Whisher
источник
0

Я пытался использовать объекты окна, но это не сработало, так как я открывал удаленный URL-адрес в InAppBrowser. Не удалось это сделать. Итак, лучший и самый простой способ добиться этого - добавить строку к 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");
}
Ashish
источник