Мобильная веб-разработка: HTML5 приложение для Android

Вступление



К счастью, есть более чем один способ написать приложение для мобильного телефона. Можно сделать сайт, упаковать его специальным образом, и вуаля, вот вам и приложение! Именно такой подход предлагает нам проект phonegap.com именно об этом методе и пойдет речь в этой статье.

Уверен что ни стоит обсуждать экономическую целесообразность данного подхода. Она на лицо. Да, знаний нужно больше чем у среднестатистического веб разработчика, но все же, это сайт! Это понятно! Это тот же HTML, это тот же броузер, тот же Javascript. Найти разработчика ни так сложно, как скажем “нативного”. А уж если умножить на кроссплатформенность данного решения, так и вообще может показаться что это панацея. Конечно, мы то с вами знаем, что ни какой “пилюли” не существует, но в ряде случае, это действительно best practic

Итак, мое рабочее задание звучало так: Разработать клиентское приложение, под ОС Android. Приложение — игра. Квест. Суть игры заключается в следующем: группа людей, желающих интересно отдохнуть, делятся на команды. Каждой команде дается по смартфону. В смартфоне приложение. Открываем приложение. Приложение соединяется с сервером и оттуда приходят вопросы. Для каждой команды они свои. Вопросы могут выглядеть как обычные вопросы с вариантами ответов, ну скажем Сколько лет городу Санкт-Петербург?, так и вопросы локации. Найдите парадный вход в инженерный замок. Команда двигается, находит вход, нажимает Мы на месте и координаты уходят на сервер. От сервера ответ, верно или нет. Есть также вопросы фотографии. Например Сфотографируйте себя на фоне инженерного замка. В сумме, все ответы оцениваются и в итоге одна из команд выигрывает, набирая больше очков. Вкратце все.

Шаг 1 — протитипы


В общем задание нам понятно. Предположим что техническое задание уже составлено. Что еще? Нужны прототипы. Вот они:

к сожалению, автор указал в качестве источника изображения вредоносный ресурс

Шаг 2 — макеты


Следующий шаг. Нужно их от рисовать. Беремся за работу, получается следующее.

к сожалению, автор указал в качестве источника изображения вредоносный ресурс

Шаг 3 — выбираем фреймворк


По сути, их две:

1. Sencha Touch
http://www.sencha.com/products/touch

2. Jquerymobile
http://jquerymobile.com/

Возьмем Sencha Touch. Фреймворк сделан на подобие ExtJS. Большое количество классов. Компонуем их, настраиваем — получаем приложение. Доступ к HTML элементам есть, но на уровне фреймворка управлять элементами крайне не разумно. Грубо говоря, поменять стандартное визуальное отображение элементов крайне затруднительно. Зато данные от сервера получать в формате JSON одно удовольствие.

И наоборот. Jquerymobile это доступ к элементам, по сути расширенный Jquery. Добавляются теги к элементам. После загрузки фреймворк по этим тегам дополняет элементы стилями и другими элементами. Вот только подружить фрейморк с JSON данными от сервера у меня не получилось. Jquerymobile ждет от сервера html код. Безусловно можно получать JSON и его на стороне клиента преобразовывать в html код, что собственно и делает Sencha. Но это ни есть хорошая практика. Это идет в разрез с идеологией фреймворка. Возникает огромное количество проблем, решить которые крайне сложно.

Стоп. А зачем нам фреймворк? Что первый, что второй, по сути, это, так сказать, готовая элементная база, готовые решения, цель которых помочь вам сделать приложение (сайт) визуально похожим на нативное приложение. А нужно нам это? Нет. А как же PhoneGap? А что он, ему все равно, что вы используете. Ни где ни каких ограничений нет. Ну тогда давайте просто сверстаем приложение, как обычный сайт и дело с концом!

Шаг 4 — верстаем


Сам процесс верстки ни чем ни отличается от стандартного. Есть безусловно нюансы, вот о них и поговорим. Первым таким нюансом являются метатеги.

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />


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

В отличии от десктоп броузера, броузер мобильного телефона (вероятно ни всех) добавляет рамку к элементам, на которых установлен фокус. Подобная рамка, при наведении фокуса, есть по умолчанию в Google Chrome, в момент когда мы вводим данные в очередное поле . Лечится это аналогично.

input:focus {
	outline: 0 none;
}

textarea:focus {
	outline: 0 none;
}
.Button:focus {
	outline: 0 none;
}


И самый последний нюанс это position:fixed. И это действительно проблема, ибо универсальных решений тут нет. Все упирается в сами мобильные броузеры, они просто не поддерживают, или поддерживают но не полностью, такой функционал. Ни получается закрепить панели управления одним решением для всех случаев. К примеру, jquerymobile, до версии 1.1, в случае если броузер не поддерживает position: fixed, эмулировал скроллирование и динамически менял позицию закреплённых элементов, что в общем-то не придавала реалистичности и порой выглядело “ни айс”.

Вот по этой ссылке есть описание мобильных броузеров, которые поддерживают position: fixed
bradfrostweb.com/blog/mobile/fixed-position
а также есть ссылки на Javascript библиотеки, которые эмулируют работу position: fixed и процесса скроллирования. К сожалению работу ни одного из них удовлетворительной назвать нельзя.

В моем конкретном случае, мобильная платформа была указана как Android 2.3, а она поддерживает position: fixed, но при этом пользовательский zoom работать не будет, что по сути в приложении ни к чему. Указываем в заголовке viewport

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />


И прописываем стили

 .Header {
	 background-color: white;
	 background-image: none;
	 border: none;
	 text-shadow: none;
	 border-bottom: white solid 3px;
	 font-weight: bold;
	 position: fixed;
	 width: 100%;
	 height: 62px;
	 top: 0;
	 left: 0;
	 z-index: 100
 }


На этом все.

Шаг 5 — эмуляторы


Очевидно, что верстать и смотреть в броузере, в окне монитора, затруднительно. Разрешение андроид приложение, скажем 320x480, а какие размеры экрана у вашего монитора? На помощь приходят эмуляторы. Самый простой эмулятор уже есть в вашем броузере! Если вы загрузите сверстанные страницы в Google Chrome и нажмете Ctrl+Shift+I, броузер покажет вам инструменты разработчика. В правом нижнем углу вы можете найти иконку с шестеренкой, нажимайте на нее. Далее выбираем вкладку Override и вот он, ваш эмулятор. Выбираем User Agent и ставим галочку Device Metric. На первом этапе этого будет достаточно.

к сожалению, автор указал в качестве источника изображения вредоносный ресурс

А еще есть эмулятор от самого PhoneGap! emulate.phonegap.com
Называется Ripple. Ставится в виде дополнений к Google Chrome. Ура! Наши возможности резко увеличились. В случае, если в своем приложении вы используете библиотеку cordova для расширения функционала приложения, скажем для работы с камерой телефона или компасом, то Ripple даст вам возможность симулировать данные процессы.

Ну и раз пошла речь про эмуляторы, нельзя ни сказать и про эмулятор, который ставиться вместе с Eclipse, если следовать инструкции от Phonegap
docs.phonegap.com/en/2.2.0/guide_getting-started_android_index.md.html#Getting%20Started%20with%20Android
Этот эмулятор уже ведет себя совсем как настоящее устройство. Все ошибки, какие были найдены на этом эмуляторе, все аналогичным образом были найдены и на устройстве. Ну и конечно нужно сказать, что пользоваться этим эмулятором оперативно сложно. Долго грузится, трудно текст набирать и т.д. Подходит он для самой последней стадии. Когда ваше приложение уже работает прекрасно на всех других ранее перечисленных эмуляторах.

Шаг 6 — программируем


Хоть статья и для программистов, размешать весь код тут просто глупо. Опишу в общем. Программирование веб приложение, по сути, ни отличается от программирование небольшого сайта. Тут те же методы и подходы, но выполнены на Javascript. Тот же MVC, те же паттерны: синглетон, компановщик и т.д.

Вот фронт контроллер

var App = {
	Init: function() {
		this.model = new Model(this.url);
		this.view = new View();
		this.controller = new Controller({
			model: this.model,
			view: this.view
		});
		return this;
	},
	Run: function(task, params) {
		if (typeof task == 'undefined') {
			this.controller.Login();
		} else if (typeof this.controller[task] == 'undefined') {
			this.controller.Login();
		} else {
			this.controller[task](params);
		}
		return this;
	},
	Done: function() {
		return this;
	}
}
$(document).ready(function() {	    
	App.Init();
	App.Run();	
	App.Done();
});


* В javascript нет магических методов. Если скажем в PHP мы можем использовать __call, и вызывать App.SomeSome(‘<параметры>’), то тут нужно будем писать App.Run(‘SomeSome’, ‘<параметры>’)

Вот пример контроллера:

var Controller = function(params) {
	this.view = params.view;
	this.model = params.model;
}
Controller.prototype = {
	Login: function() {		
		this.view.Login();
	},
	LoginSubmit: function() {
		var that = this,
			value = this.model.GetLoginFormValue(),
			errors = this.model.GetLoginFormErrors();

		if (errors !== false) {
			this.view.Login(value, errors);
		} else {
			this.model.SendToServer('teamLogin', value, function(err, data) {
				if (!err) {                    
					that.model.SetTeam(data);
					that.model.ListenServer(data.lastMessageId);
					that.Welcome();
				} else {
					that.view.ShowPopup('error', data)
				}
			});			
		}
	},
	Welcome: function() {
		var that = this;
		
		this.model.GetWelcomeContent(function(err, data) {
			if (!err) {
				that.view.Welcome(data);
			} else {
				that.view.ShowPopup('error', data);
			}			
		});
	}


Вот небольшой пример модели

var Model = function(url) {
	this.url = url;
}
Model.prototype = {
	GetHelpChat: function(callback) {
		var url = 'helpChat?team='+this.team.teamId+'&hash='+this.team.hash;
		
		this.ReciveFromServer(url, function(err, data) {
			if (err) {
				callback(true, data);
			} else {
				callback(false, data);
			}			
		});		
	},


Вот пример представления

var View = function() {
	this.page = $('.Page');
}
View.prototype = {
	TaskIndex: function(status, time, tasks) {
		var num = Util.GetRndNumber();
		
		this.Show(
			Html.Header(
				Html.IconPanel(status),
				Html.TimePanel(time)
			),
			Html.Content(
				Html.TaskPanel(tasks)
			),
			Html.Footer(
				Html.ButtonPanelBottom('task')
			)
		);
        setInterval(Timer.Total, 1000);
        setInterval(Timer.Current, 1000);            
	        Util.SetScrollToTop();		
	},


По сути, тут тоже самое, что и в случае, если бы сайт писался на PHP. За исключением фундаментального принципа, Javascript — асинхронный язык и без callback тут ни как (если не использовать специальные библиотеки конечно же)

Отдельно хочется остановится на нюансах, а именно работа с фотокамерой смартфона. Из коробки javascript не умеет этого делать. На помощь приходит библиотека Cordova, которую предлагает подключить PhoneGap. А вот ссылка, на описание работы с камерой телефона

http://docs.phonegap.com/en/2.2.0/cordova_camera_camera.md.html#Camera

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

navigator.camera.getPicture(OnSuccess, OnFail, {
	quality: 75,
            allowEdit: true,
            targetWidth: 280,
            targetHeight: 280,
	destinationType: destinationType.DATA_URL
});


Но и это оказалось еще не все. Метод getPicture возращает base64 закодированную картинку, а вот данные между сервером и клиентом передаются в виде запросов JSONP.
Очевидно что передать такое количество данных через GET запрос невозможно. Серверная часть, кстати, не помню говорил я или нет, на PHP. Да, не самое лучшее решение, про WebSocket можно забыть. Проксирование тоже не сделать. Вероятно, решение данной проблемы была одна из самых сложных. А решение нашлось следующее. Время идет и стандартные классы расширяются, добавляются новые методы. Так вот класс XMLHttpRequest обзавелся новыми событиями. Кроме стандартного onreadystatechange появилось также событие onload. Если обработчик ответа от сервера “повешать” на него, и в заголовке Content-Type указать application/x-form-urlencoded, то броузер будет делать кроссдоменный запрос методом POST, что, собственно нам и нужно. Вот пример

var xhr = new XMLHttpRequest();
            xhr.open('POST', url, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.onload = function(e) {
                if (this.readyState == 4) {
                    if (this.status == 200) {
                        var r = JSON.parse(this.responseText);
                        if (r.success) {
                            callback(false, r.data);
                        } else {
                            callback(true, r.message);
                        }
                    } else {
                        that.view.ShowPopupWindow('Error', msg.ERROR_CONNECTION);
                    }
                }
            }


И еще, очень важный момент. Кроссдоменный запрос, не важно как он реализован, является синхронным, даже не смотря на то, что выше приведенный код выглядит как асинхронный.

Столкнулся я также и с проблемой Same Origin Policy. Решение этой проблемы лежит на серверной стороне. В конфигурационных файлах прописывается разрешение на кросс доменный запрос и дело с концом.

Пробовал я также и FormData API
developer.mozilla.org/en-US/docs/Web/API/FormData?redirectlocale=en-US&redirectslug=Web%2FAPI%2FXMLHttpRequest%2FFormData
Но, к сожалению, этот API, броузер мобильного телефона не поддерживает.

Хочется также отметить, что в случае, если вам не нужны расширенные функции работы с телефоном: акселерометр, компас, камера, медиа и т.д. подключать библиотеку cordova не обязательно (а это примерно 300 килобайт). Геолокация, кстати, доступна и без нее.

Шаг 7 — отлаживаем


Вот наше приложение готово. Сверстано и прекрасно работает на эмуляторе Ripple (см. раздел про эмуляторы). Начинается самое интересное, а именно отладка на телефоне. Но сначала, попробуем запустить приложение на эмуляторе, в eclipse. Перед каждым запуском приложения на эмуляторе, система просит отчистить проект. Project -> Clean. Не забываем это делать. Нажимаем Run — поехали!

После загрузки эмулятора, в панели LogCat Eclipse будет огромное количество сообщений. Первым вопрос который возникает — какие наши? Для того, чтобы видеть только свои ошибки, и в частности, видеть сообщения которые приложение выводит в консоль console.log, нужно настроить фильтр. В панели LogCat, слева, есть отдельный блок, Saved Filters. Открыв ее, вы конечно увидите пустой список, ибо фильтров у нас пока нет. Нажимаем на плюсик и видим окно

к сожалению, автор указал в качестве источника изображения вредоносный ресурс

Вводим в Log Tag web console, как на картинке и теперь Log консоль будет показывать сообщения от вашего веб приложения.

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

к сожалению, автор указал в качестве источника изображения вредоносный ресурс

JSCallback Error: Request failed with status 0 at :1180915830


Начинаем изучать ошибку. Очевидно что ошибка вызывается в момент получения данных с сервером. Ошибка говорит что приходит статус 0. Начинаем искать решение в Google, и вот что находим
simonmacdonald.blogspot.ru/2011/12/on-third-day-of-phonegapping-getting.html
stackoverflow.com/questions/11230685/phonegap-android-status-0-returned-from-webservice

Делаем вывод: вероятно нужно добавить статус 0, как верный статус, для продолжения обработки ответа сервера. Ищем, где же это сообщения JSCallback и находим его в файле cordova.js на строке 3740 (cordova-2.1.0.js)

function startXhr() {
    // cordova/exec depends on this module, so we can't require cordova/exec on the module level.
    var exec = require('cordova/exec'),
    xmlhttp = new XMLHttpRequest();

    // Callback function when XMLHttpRequest is ready
    xmlhttp.onreadystatechange=function(){
        if (!xmlhttp) {
            return;
        }
        if (xmlhttp.readyState === 4){
            // If callback has JavaScript statement to execute
            if (xmlhttp.status === 200) {

                // Need to url decode the response
                var msg = decodeURIComponent(xmlhttp.responseText);
                setTimeout(function() {
                    try {
                        var t = eval(msg);
                    }
                    catch (e) {
                        // If we're getting an error here, seeing the message will help in debugging
                        console.log("JSCallback: Message from Server: " + msg);
                        console.log("JSCallback Error: "+e);
                    }
                }, 1);
                setTimeout(startXhr, 1);
            }

            // If callback ping (used to keep XHR request from timing out)
            else if (xmlhttp.status === 404) {
                setTimeout(startXhr, 10);
            }

            // 0 == Page is unloading.
            // 400 == Bad request.
            // 403 == invalid token.
            // 503 == server stopped.
            else {
                console.log("JSCallback Error: Request failed with status " + xmlhttp.status);
                exec.setNativeToJsBridgeMode(exec.nativeToJsModes.POLLING);
            }
        }
    };


Пробуем заменить if (xmlhttp.status === 200) на if (xmlhttp.status === 200 || xmlhttp.status === 0) и вуаля — ни какого эффекта!

Дальше не буду рассказывать как я потратил целый день, кружа вокруг этой ошибки. Скажу только, что был готов отчаяться, ибо ни что не могло мне помочь. Приложение все равно падало, пока я просто не решил закомментировать часть кода. И о чудо! Ошибка исчезла! Возвращая, по частям, свой код, я нашел его часть, которая приводила к ошибке.

var Util = {
	SetNewHash: function(hash) {
		/**
		 * Это не работает в Android 2.3!!
		 */
		//location.href = 'http://'+location.host+location.pathname+'#'+hash;		
	},


Почему смена Хеша, приводила к такой ошибке, для меня осталось загадкой. Если у кого какие будут мысли на этот счет — велком.

Шаг 8 — запускаем


Чтобы запустить приложение уже не посредственно на телефоне, достаточно войти в решим настройки, выбрать раздел Разработка и там взвести галочку напротив пункта Отладка USB. Далее, нажимая RUN в eclipse, среда определит что у вас подключен телефон к USB, а я надеюсь вы уже это сделали, и начнет запускать приложение уже на аппарате.
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 39

    +9
    «Броузер» очень режет глаз.
      +6
      А «ни стоит обсуждать» и «ни так сложно» не режет?
        +4
        а «на лицо» и «от рисовать» вообще не режет.
      +5
      Забыли упомянуть, что написанные таким образом приложения подтормаживают, если они более или менее сложные.
        0
        Запросы, кросс-доменные, синхронно выполняются. Пока идет запрос, приложение, по сути, не работает. Это самый «тормоз». Остальное вполне нормально работает. Возможно, конечно, если использоваться «тяжелые» фреймворки, броузер будет тормозить, но это не мой случай. Кода мала, верстки тоже, стилей не много.
          +1
          Списки с картинками тормозят, например.
            0
            Самотря как список реализован. Если огромной лентой, то будет тормозить, если реализация в стиле андроидной галереи (ненужные элементы списка убраны и не учавствуют в скролинге), то хоть миллиард картинок и ничего не будет тормозить (лишь бы памяти хватило).
        +1
        Ну и еще не мог не сказать — у Вас на экране в сообщении с картинкой льва должно быть «Вам должно понравитЬся» (деградирующая ошибка с мягким знаком)
          0
          А так вызывает ошибку?
          location.hash = '#' + hash;
            0
            У меня вызывала :-)
            0
            * В javascript нет магических методов. Если скажем в PHP мы можем использовать __call, и вызывать App.SomeSome(‘<параметры>’), то тут нужно будем писать App.Run(‘SomeSome’, ‘<параметры>’)

            Можно так: App['task' + taskName](params). IMHO, джаваскрипту это ближе всего идеологически.
              +7
              С какой целью в тексте сделано столько грамматических ошибок?
                +3
                Авторский стиль.
                  0
                  Чтобы отвлечь от самого материала статьи. Этот же текст написанный грамотно никому не был бы интересен)
                  0
                  я как-то возлагал большие надежды на Phonegap.
                  но моё html5 приложение для изучения языков, воспроизводит отдельные фразы из большого аудиофайла. тупо есть тег <audio id="a1"></a> и дальше есть функции, которые при клике на ту или иную фразу воспроизводят аудио с секунды X до секунды Y.

                  но оказалось что в фонгапе для аудио есть специальный объект медиа какой-то — то есть просто тэг не поддерживатся. и для этого объекта «медиа» нет возможности как в html5 audio стартовать воспроизведение с секунды X и тормознуть его на секунде Y. по-крайней мере я год назад не смог это реализовать и очень сильно разочаровался.

                  может кто знает решение?
                    0
                    Посмотрите в сторону media.seekTo.
                    +1
                    Статья хороша.

                    Но, перед тем, как писать что-нибудь, имеет смысл поискать — все упомянутые темы уже раскрыты на хабре, причем довольно хорошо.
                      0
                      Статья эта была написана более полугода назад. Сама работа, активная ее часть, была завершена примерно к концу 2012. Информации тогда совсем не было ни какой. Раньше опубликовать просто не мог по независящим от меня причинам. Так что, если какая информация совпадает со статьями которые раскрыты уже на Хабре, приношу извинение.
                      0
                      Скажите, а как вы решили проблему с различным dpi на разных устройствах?

                      Я нашел 2 решения, но оба оказались не очень удобными — либо создавать большое количество media-query css, либо использовать размеры элементов в %.
                        0
                        Я в процентах верстал.
                          0
                          Есть неплохой ресурс learnlayout.com/

                          Верстка в процентах лично мне не нравится — едет в зависимости от разрешения, я бы использовал следующий подход:
                          несколько, к примеру 3, media-query в которых прописана в пикселях высота хэдера и футера а контент вывешен на абсолют по топу и ботому совпадающему с высотой футера и хедера. Чудненько работает.
                        0
                        А вот тут есть сравнительная подборка нескольких подобных фреймворков, удобная для выбора под Ваши нужды
                          0
                          Крайне странная подборка
                          сравнивать PhoneGap и SenchaTouch или Titanium c Enyo это по крайней мере не корректно(я бы сказал «бред»). Свалили в одну кучу титаниум как платформу, фонгап или джсные либы для UI
                          0
                          Веб-разработка под Андроид это кое-что. Особенно тешат поля ввода. От всей души сочувтвую разработчикам, которым приходится писать костыли под эту платформу.
                            0
                            Если Вы пишете под фонгап и Вас смущают двойные инпуты — есть смысл обратится к нативному программисту чтобы он в методе onCreate активити повесил листенер на вэбвью — если у него появился чаилд — сделать его не видимым

                            костыли не надо пилить — надо понимать как это работает. Именно в андроиде клавиатура является СИСТЕМНЫМ СЕРВИСОМ, который пользователь может заменить, в связи с этим платформа нуждается в валидируещем прокси объекте для ввода текста. И платформа не виновата, что некоторые БЕЗГРАМОТНЫЕ ПРОИЗВОДИТЕЛИ тупо забыли вынести этот объект за пределы видимости или сделать его прозрачным
                              0
                              … если у него появился чаилд — сделать его не видимым
                              А еще не помешало бы перемещать его при скроллинге и учесть множество других факторов — опять же это костыль.
                              Системные инпуты меня тоже смущают, но кроме них есть еще куча других вещей, которые без хаков работать не будут.
                                0
                                если вы его сделаете невидимым(каковым он является по умолчанию в чистом андроиде) — его не надо перемещать — он не будет мешать

                                А хаки… Можем поговорить и о них)) если вам нравится iOS — посмотрите на его реализацию скрола при точе, который дропает зет индекс, рабер эффект или тотже позишен фиксед, если WP8 — давайте поговорим о поинтерах и т.д. можно продолжать бесконечно О ЛЮБОЙ ПЛАТФОРМЕ

                                ИДЕАЛЬНЫХ ПЛАТФОРМ НЕТ, даже в нативщине, просите андроид девелопера к примеру наверстать список который вы верстеите float:left с переходом на следующую строку. Если не хотите матов — не спрашивайте.

                                Это я к тому что если кто то за что то берется — он должен понимать что любое новое дело требует приложить усилие и разобратся.
                                  0
                                  С тем что без багов не обойтись нигде — полностью согласен.
                                  С WP8 не работал, ничего не могу сказать. Для скроллинга в iOS лучше использовать плагин (iscroll, zynga, свой). Ну это все равно лучше чем overflow:hidden по умолчаний для любого значения overflow в старых версия Андроида.
                                  Постом выше я просто хотел посочувствовать разработчикам, так как разрабатывать веб-приложения для армии андроид-устройств не просто, я бы сказал что это самая тяжелая платформа вместе со всемя производителями и версиями.
                                    0
                                    просто: СОГЛАСЕН АБСЛЮТНО
                            0
                            Смертельные ошибки:
                            1) Кроссплатформеная разработка только под одну платформу — «Итак, мое рабочее задание звучало так: Разработать клиентское приложение, под ОС Android»
                            2) Выбор фремверка — их не 2, к примеру мы перепрбоволи более 3 десятков под фонгап www.google.com.ua/search?q=js+mobile+ui+framework&oq=js+mobile+ui+&aqs=chrome.1.57j0l3j62l2.21266j0&sourceid=chrome&ie=UTF-8
                            3) Никто никогда не верстает с «И самый последний нюанс это position:fixed.» если есть поддержка iOs, на андроиде кстати вполне работает
                            4) «мобильная платформа была указана как Android 2.3» — SenchaTouch и андроид до 4.1 НЕСОВМЕСТИМЫ!

                            и.т.д.

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

                            Хотя есть и положительная сторона — четко описаны все стадии разработки
                              0
                              5) «Хочется также отметить, что в случае, если вам не нужны расширенные функции работы с телефоном: акселерометр, компас, камера, медиа и т.д. подключать библиотеку cordova не обязательно (а это примерно 300 килобайт). Геолокация, кстати, доступна и без нее.» — cordova ЭТО НЕ БИБЛИОТЕКА. cordova — это возможность запускать js/html (заметьте без 5) приложение как нативное, и только как дополнительные фитчи — позиционируются интерфейсы доступа к хардварным фитчам мобильного телефона. По сути cordova состоит из нативной части — расширенного webview, характерного именно для данной платформы и js обеспечивающего инекцию объекта доступа в яваскрипт
                                0
                                PS Не надо экономить 300 кб — вы их не качаете с инета, разница между тем что вы добавите или нет какой либо JS файл от 250мск до 300 мск и то если вы не поставили асинхронность. Читайте Закаса или читайте здесь статьи
                                  0
                                  Сначала, мы все библиотеки, грузили с интернета, с внешнего источника. Ничего локально не было. Устройств много. Как обновлять приложение? Когда начали пользоваться, возникли проблемы. Когда медленный интернет и начинает стартовать приложение, с момента нажатия на иконку и до старта приложения — черный экран. В этот момент как раз и грузились библиотеки. В случае если этот процесс долог, ОС сама закрывала приложение. Вот и встал вопрос что делать. А что тут делать? Облегчать и оптимизировать. Отсюда и появилось желание избавится от не нужного. В итоге, часть локально грузиться, часть с интернета.
                                  0
                                  Речь шла именно о файле cordova.js, которая «обеспечивающего инекцию объекта доступа в яваскрипт», то есть, как раз и дает возможность непосредственно через javascript обращаться к функциям телефона: камере, навигации, акселерометру и т.д. И вот в случае, если это не нужно, а нужно только геолокация, подключать его не обязательно. И cordova.js это именно библиотека. Если ее убрать из списка загружаемых библиотек в то все прекрасно работает. Возможность запускать js/html от нее ни как не зависит.
                                0
                                Прошу прощения за безграмотные комментарии или стиль изложения, но к сожалению статья не дает представления кроссплатформеной разработке упущены некоторые ключевые моменты, до разработки и во время.

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

                                Т.к. судя по статьям тема интересна — буду катать статью с аналитикой и легкий туториал без частностей(только с основными моментами), начну завтра.))

                                Прошу автора извинить меня — наболело.
                                  0
                                  Тема очень интересна. Но интересны в разработке как раз частности. Меня не устраивает в Фонгэпе сложная установка. Не смог разобраться со звуками. Интересно, можно ли задавать русское название приложениию, и так далее.
                                    0
                                    У меня были сложности с установкой «фонегап». Вернее с настройкой и установкой софта к Эклипсу. Постоянно были ошибки, ничего толком поставить не мог. Но. Как только я поставил на Эклипс права администратора, при запуске, все проблемы исчезли. Все легко и быстро поставилось, как по инструкции. В инструкции про права, к сожалению, ничего не написано.

                                    На счет звука я ничего не скажу. Не работал.

                                    Русское название приложению задавать — ну я как то об этом не задумывался. Необходимости не было
                                  0
                                  У вас в приложении есть звуки? Расскажете как реализовано?
                                    0
                                    Нет, звука, к счастью, нет :-)

                                  Only users with full accounts can post comments. Log in, please.