Проблема с динамически загруженным phonegap.js - PullRequest
5 голосов
/ 22 июля 2011

Я пытаюсь динамически загрузить файл javascript phonegap (чтобы я мог не загружать его в режиме отладки, когда я использую Ripple), но я сталкиваюсь с некоторыми проблемами.

Я загружаю библиотеки jquery и jquerymobile javascript, используя обычный тег script.В другом блоке сценария я делаю:

function onDeviceReady() { 
    alert("Device Ready!"); 
} 
$(document).ready(function() { 
    alert("doc ready!"); 
    $.getScript("js/phonegap.0.9.5.1.js", function() {alert("Got Phonegap!");}); 
    document.addEventListener("deviceready", onDeviceReady, false); 
}); 

Этот код предупреждает, что он "получил пробел!"но никогда не предупреждает "Device Ready".Используя jsconsole.com, я вижу, что объект PhoneGap javascript существует.Тем не менее, попытка вызвать device.uuid (или другие простые вызовы API PhoneGap) не удается .Это почти как PhoneGap не полностью инициализировать.Не похоже, что так должно быть.Я что-то пропустил?Спасибо!

Ответы [ 5 ]

8 голосов
/ 11 июня 2013

Наконец-то у меня все заработало без использования какой-либо внешней библиотеки.

ПРОБЛЕМА
Для многоплатформенного проекта Phonegap две части отличаются от одной платформы к другой:

  • Инкапсулирующий проект
  • Файл Phonegap Javacript.

Эти инкапсулирующие проекты обычно не сильно меняются в течение проекта. Было бы желательно иметь одну кодовую базу HTML5, которую можно было бы напрямую вставить (или использовать сценарии сборки) в зависимые от платформы проекты. Поскольку библиотека телефонного промежутка javascript находится внутри набора веб-файлов, каждый раз заменять правильный файл действительно сложно.

МОЕ РЕШЕНИЕ
В моем проекте у меня есть несколько файлов cordova, по одному для каждой целевой платформы:

  • cordova.android.js
  • cordova.ios.js
  • cordoba.bb.js ...

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

На своих страницах вместо тега скрипта для phonegap я разместил модуль загрузчика:

<script src="phonegap-loader.js"></script>

И это будет скрипт phonegap-loader.js. Я использую обнаружение пользовательского агента для динамической и синхронной загрузки скрипта:

    (function(){
        var useragent = navigator.userAgent;


        if(/Android/i.test(useragent)){
            loadScript('cordova.android.js');
        } else if((/iPhone/i.test(useragent)) || (/iPad/i.test(useragent))){
            loadScript('cordova.ios.js');
        }
        ...
        // Else desktop browser is assumed and no phonegap js is loaded


        function loadScript(url){
            // synchronous load by @Sean Kinsey 
            // https://stackoverflow.com/a/2880147/813951
            var xhrObj =  new XMLHttpRequest();
            xhrObj.open('GET', url, false);
            xhrObj.send('');
            var se = document.createElement('script');
            se.text = xhrObj.responseText;
            document.getElementsByTagName('head')[0].appendChild(se);
        }
    })();

Очень важно загрузить скрипт СИНХРОННО. Это дало мне бесчисленные головные боли. Прежде чем понять это, я попытался добавить теги scripts внизу головы и использовать $ .getScript, но ни один из них не работал, так как ondeviceReady не было запущено. Похоже, единственный действительный подход, обеспечивающий выполнение скрипта Phonegap при динамической загрузке, - это тот, который показан в этом удивительном ответе @Sean Kinsey (все ему благодарны).

Единственным недостатком является то, что скрипт встроен, но для меня это дешевая цена за то, что основное HTML5-приложение окончательно изолировано от контейнеров.

3 голосов
/ 05 марта 2012

Я столкнулся с аналогичной проблемой, когда мне нужно загрузить PhoneGap и зависимые файлы плагинов в зависимости от типа платформы.Я просмотрел источник PhoneGap и обнаружил, что он использует события windows / browser для загрузки и подготовки объектов.Если я вызываю события браузера вручную, он инициализирует объекты PhoneGap (API и плагины), необходимые для запуска моего приложения.

Следующий код, который использует Yabble, теперь работает для меня:

<html>
<head>
<script
    src="https://raw.github.com/jbrantly/yabble/master/lib/yabble.js"></script>

<script>
    require.setModuleRoot("js");
    require.useScriptTags();

    require.ensure([ "jquery", "phonegap" ], function(require) {

        // Trigger PhoneGap Initialization
        PhoneGap.onPhoneGapInit.fire();

        // Load PhoneGap Plugins
        require.ensure([ "plugin1" ], function() {
            $("#console").append("Plugin1 loaded<br>");
        });

        // Both following functions will work only if PhoneGap is loaded/initialized and Plugin is successfully registered

        // Check PhoneGap device object
        $("#checkDevice").click(function() {
            console.log(JSON.stringify(device));
        });

        // Call Native Plugin
        $("#callPlugin").click(function() {
            window.plugins.plugin1.call();
        });
    });
</script>
</head>
<body>
    <div id="console"></div>

    <input type="button" id="checkDevice" value="Check Device">
    <input type="button" id="callPlugin" value="Call Plugin">
</body>
</html>

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

Редактировать

В Phonegap 1.5 / Cordova,PhoneGap.onPhoneGapInit.fire(); недоступно из-за изменения API.В моем текущем тесте большинство необходимых объектов доступны без каких-либо изменений после динамической загрузки JS.Обновленный тест доступен в этой сущности - Cordova Lazy Load Test

0 голосов
/ 11 марта 2012

Мне удалось смоделировать правильный рабочий процесс инициализации PhoneGap после его динамического внедрения, выполнив следующий код javascript сразу после внедрения сценария phonegap.js.

if (document.readyState == "complete") {

    PhoneGap.onDOMContentLoaded.fire();
}
0 голосов
/ 28 июля 2011

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

Попробуйте это:

function onDeviceReady() { 
    alert("Device Ready!"); 
} 
$(document).ready(function() { 
    alert("doc ready!"); 
    $.getScript("js/phonegap.0.9.5.1.js", function() {
        alert("Got Phonegap!");
        document.addEventListener("deviceready", onDeviceReady, false);
    });
});
0 голосов
/ 22 июля 2011

1) вы пытались вызвать addEventListener перед getScript?

2) Кроме того, вы используете правильный phonegap.js для вашего устройства?(при использовании iphone phonegap.js на Android у меня было такое же «тихое» поведение)

...