Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 1887 сообщений
Cообщения с меткой

разработка мобильных приложений - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

Опубликована программа Droidcon Moscow 2016

Понедельник, 29 Августа 2016 г. 14:35 (ссылка)



Опубликована предварительная программа крупнейшей евразийской Android-конференции —

https://habrahabr.ru/post/308748/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

MVP на стероидах: заставляем робота писать код за вас

Понедельник, 29 Августа 2016 г. 14:35 (ссылка)

В статье «Moxy — реализация MVP под Android с щепоткой магии» мы рассказывали, как побороть проблему жизненного цикла и разделить код своего Android-проекта на слои. Однако MVP (даже при умной кодогенерации view state в Moxy) заставляет писать огромное количество лишнего кода (создавать связанные друг с другом классы и интерфейсы presenter и view). На самом деле эту работу за вас должен делать робот! :) Настало время еще сильнее уменьшить boilerplate при помощи кастомизации шаблонов Android Studio под Moxy.





Структура проекта



Для того чтобы начать кодогенерацию, нужно зафиксировать структуру проекта.




  • model

  • presentation


    • presenter

    • view


  • ui


    • activity

    • fragment




Содержимое пакетов presenter, view, activity и fragment, в свою очередь, делится на логические модули. Часто такими модулями выступают разделы приложения (к примеру, intro, offers, feed). Ниже — пример структуры проекта с двумя Activity (CarActivity и HomeActivity) и одним фрагментом (CarDetailsFragment)



image



Наша цель — научиться генерировать эти классы



Настройка шаблонов



Как создавать шаблоны в Android Studio можно прочитать в статье от Fi5t про Тотальную шаблонизацию



Добавляем в проект шаблоны для Moxy:




  • Скачиваем шаблоны с Github либо по ссылке

  • Копируем содержимое архива в ANDROID_STUDIO_DIR/plugins/android/lib/templates/activities

  • Перезапускаем Android Studio, чтобы изменения вступили в силу



Настраиваем hot keys для быстрого доступа к шаблонам:


  • Открываем настройки-> Keymap

  • В поисковом окне вводим Moxy

  • Добавляем комбинации клавиш (я использую Alt + A для активити и Alt + F для фрагмента)





image



Использование шаблонов




  • Выделяем корневой пакет и нажимаем Alt + A.

  • В поле Activity Name пишем «MyFirstMoxyActivity»



Остальные поля наберутся сами.



image



Далее меняем в поле Package Name слово blank на имя подпакета и нажимаем Finish. Ваш пакет классов готов! Стоит отметить, что при обновлении Android Studio может снести все кастомные шаблоны. В этом случае придется их импортировать заново.



Что в итоге



Концепция MVP подразумевает разделение логики приложения на слои и, как следствие, увеличение кодовой базы. Использование шаблонов и кодогенерации максимально избавляет вас от boilerplate, предохраняет от случайных ошибок и позволяет сосредоточиться на бизнес-логике. Пусть код за вас пишет робот!



Материалы по теме




Original source: habrahabr.ru.

https://habrahabr.ru/post/305798/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Оптимизируем свои трудозатраты при разработке приложения в Google Material Design

Воскресенье, 28 Августа 2016 г. 18:04 (ссылка)



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



Итак, перед нами стоит задача: опираясь на готовые решения в открытом доступе, максимально оптимизировать затраченный труд на разработку приложения в стиле Google Material Design.



Стадия раз: прототипирование



Оно нужно, как минимум, для представления объемов приложения и состава экранов. Очень помогает в продумывании tap/click-путей (переходы между экранами). Я предпочитаю Axure, т.к. многие hot-keys сделаны 1 в 1 как в Adobe Photoshop (про остальные похожие продукты читайте в других статьях (в разделе “Дизайн” каждый третий пост на эту тему).



В него нужно установить три библиотеки:



Android_MaterialDesignV1.1 (Я.диск)



Достаточно навороченная библиотека, которая позволит составить прототип по всем гайдлайнам GMD. Особенность: многие элементы уже “приведены в действия”. Например pull to refresh работает сразу в скомпилированном html. Я думаю подойдет больше тем, кто хочет в прототипе уже “покликать”.





material-design-8 (Я.диск)



Более лёгкая и простая библиотека. Минимум готовых компонентов, но всё основное есть: чёрная и светлая темы, списки, карточки, кнопки, табы, диалоги, слайдеры и т.п… Отдаю ей предпочтение, так как чем меньше выбора, тем быстрее находится нужный элемент и перетягивется в прототип.





google-material-design-icons (Я.диск)



~750 векторных иконок от Google. Конечно можно использовать и дефолтный для Axure: Font awersome. Однако, реальные иконки придадут реальности прототипу.





Стадия два: дизайн



Как я упомянул выше, я отдаю предпочтение графическим пакетам Adobe. Значит нужно воззвать к дизайнерскому коммьюнити. Стоит поискать энтузиазтов, которые уже собрали GMD UI kit, в котором элементы расставлены и выглядят в соответствии со спецификацией гугла. Отступы, шрифты, размеры и т.п. Из бесплатных мне понравилось два:



sepia_ui_kit (Я.диск 142mb)





Есть всё необходимое, но мало кастомных идей. Тем не менее, прорисовано все экраны 1 в 1, которые сам Гугл использовал в своей официальной документации по GMD. Минус только в том, что долго искать по подпапкам нужный элемент в собственном отдельном исходнике.



Cooking (Я.диск 434mb)





Этот ui kit наоборот чрезмерно богат кастомными идеями. Но авторы немного перегнули планку. Явный педант в этом исходнике заметит, что как минимум интенсивность шрифта кое-где не совпадает с документацией. Есть немного графиков, фривольных кнопок. Поможет “скреативить” собственный элемент, но остаться в стиле.

Суперская навигация: из первью есть ссылка в отдельный исходник по каждому экрану. Достаточно сделать двойной клик. Просто прекрасно!



Стадия три: разработка



Ваш безответственный дизайнер не хочет отдавать все иконки отдельными файлами строго по спецификациям? Я Вас очень понимаю. Идите на materialdesignicons.com и спокойно скачивайте либо SVG с нужной иконкой, либо полноценный zip-архив с png под все разрешения смартфонов. Можно найти и не только сеты гугловских родных иконок. В базе много кастомных пиктограмм, выполненных членами дизайнерского сообщества. Как говорится “Это Бесплатно, и это всегда будет Бесплатно”. Непосредственно для девелоперов удалось вообще найти праздник готовых решений (github). Например таких:





Или вот таких:





Должно хватить…



Рад, если Вам пригодился этот пост! Ну а если хотите, почитать как я проецировал GMD на десктопный продукт и какие выводы сделал, то начните с первой части (всего их четыре).




Original source: habrahabr.ru.

https://habrahabr.ru/post/308684/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Дайджест интересных материалов для мобильного разработчика #168 (22-28 августа)

Воскресенье, 28 Августа 2016 г. 15:55 (ссылка)

В новом выпуске просто прекрасная история про Альтернативную Аугментативную Коммуникацию, анализ Prisma и ее конкурентов, за и против MVVM, выход Android 7.0 и таблица Менделеева в материальном дизайне, которая должна вернуть вам интерес к химии.










Как узнать какие цветы дарить девушке, если у нее двигается только голова и она не может говорить?

ААС (Альтернативная Аугментативная Коммуникация) – средства, способы, системы, которые помогают детям и взрослым с серьёзными проблемами в развитии вербальной речи выразить себя и лучше понимать происходящее.




Я заглянул в приложение Prisma, и вы не поверите, что я там нашёл

Логично, что у любого популярного продукта сразу начинают плодиться конкуренты. Призме в этом плане повезло больше всех — благодаря стечению некоторых обстоятельств, основным конкурентом призме стали Mail.ru Group, которые почти сразу выпустил аж 2 похожих продукта со схожими функциями: Vinci (от команды vk.com) и Artisto (от команды my.com).



Теперь дайджест доступен и в виде рассылки. Подписаться вы можете тут.



iOS





Android





Windows





Разработка





Аналитика, маркетинг и монетизация





Устройства и IoT





<- Предыдущий дайджест. Если у вас есть другие интересные материалы или вы нашли ошибку — пришлите, пожалуйста, в почту.
Original source: habrahabr.ru.

https://habrahabr.ru/post/308674/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Crosswalk Project — замена Android WebView. Развитие проекта

Четверг, 25 Августа 2016 г. 17:24 (ссылка)

CrosswalkProject

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



Напомню, что Crosswalk Project — это runtime построенный на технологиях open source для HTML приложений. Основой для Crosswalk Project служит Google Chromium. Crosswalk Project также является open source проектом и распространяется под BSD License. В общем, если вы всё ещё поддерживаете ранние версии Android, то это неплохая замена для системного Android WebView.





Предыдущие статьи вы можете найти по следующим ссылкам:





Изменения в Crosswalk.



С версии 14 до версии 20 в проект внесли очень много изменений и доработок, все не имеет смысла перечислять. Вы сами можете ознакомиться с ними в release notes.



Я перечислю только некоторые, наиболее заинтересовавшие меня:




  • Rebase to Chromium 50

  • Support external extensions for Crosswalk Webview on Android

  • Add ability to intercept touch events on the XWalkView

  • When onReceivedLoadError occurs, a Toast notification is displayed to the user instead of a dialog (as the user cannot do anything to respond to the error)

  • New helper class XWalkInitializer to initialize XWalkView asynchronously

  • Size optimizations (Enable ProGuard for Crosswalk to compress APK size, LZMA support etc.)



Также в проект внесли большое количество исправлений, наиболее критичные перечислены там же.



Дополнительные детали.



В предыдущих статьях я описывал ряд проблем и их решений для предыдущих версий Crosswalk. Радует, что многие из них решены в самом проекте и теперь не нужны «танцы с бубном».



Классы XWalkCookieManager и XWalkSettings перенесли в более подходящие для них пакеты:



org.xwalk.core.internal.XWalkCookieManager; -> org.xwalk.core.XWalkCookieManager
org.xwalk.core.internal.XWalkSettings -> org.xwalk.core.XWalkSettings


XWalkSettings доступен напрямую через метод в объекте XWalkView. Также сам XWalkView нам может вернуть и свой User-Agent. Теперь для всего этого нет необходимости прибегать к использованию reflection.



Добавился в Crosswalk (в класс XWalkResourceClient) и новый вызов для обработки запросов к ресурсам:



public XWalkWebResourceResponse shouldInterceptLoadRequest(XWalkView view, XWalkWebResourceRequest request)


Аналог очень удобного и доступного с Android API 21 вызова в стандартном WebView:



public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)


Теперь можно легко узнать с помощью какого метода был сделан запрос: GET или POST.



Также в XWalkView был добавлен специальный метод для получения изображения контента:



public void captureBitmapAsync(XWalkGetBitmapCallback callback)


Стал корректно вызываться метод onBackPressed() и появилась возможность использовать метод setOnTouchListener(OnTouchListener l). Так что теперь нет нужды перехватывать нажатие кнопки Back и touch events в dispatch методах.



Документацию по последней и всем предыдущим версиям API вы можете найти здесь.



Некоторые проблемы в новых версиях.



На данный момент последняя доступная версия в репозитории 20.50.533.12, но в отличие от предпоследний версии 19.49.514.5, она уже имеет значение minSdkVersion равное API 16. Crosswalk 19 же всё ещё поддерживает все версии Android начиная с API 14.



Несмотря на то, что ещё для Crosswalk 16 было заявлено: «Android support libraries (e.g. support-v4, support-v7 etc) are no longer bundled by Crosswalk...». С версии 16 и до последней 20 некорректно прописан импорт для библиотеки support-v4, поэтому, если вы используете в своём проекте конкретную версию этой библиотеки и не хотите, чтобы проект автоматически собирался с последний версией, то необходимо исключить её при добавлении Crosswalk в ваш проект:



compile('org.xwalk:xwalk_core_library:19.49.514.5') {
// avoid pulling incorrect version of support library
exclude group: 'com.android.support', module: 'support-v4'
}


Crosswalk Lite, уменьшаем размер сборки.



В прошлых статьях я не упомянул о достаточно существенной проблеме — увеличении размера сборки при добавлении Crosswalk. Сам Crosswalk собирается для двух архитектур: x86 и armv7. Соответственно библиотеки для каждой из них имеют размер ~20Mb, т.е. если собирать универсальный билд, то overhead составит порядка 40Mb.



Есть 2 возможности улучшить ситуацию с дополнительным размером: собирать отдельные apk для каждой архитектуры или использовать облегченную версию Crosswalk — Crosswalk Lite. Crosswalk Lite — это попытка решить проблему путём отказа от некоторых возможностей библиотеки.



Вот более точные данные по размеру Lite и обычной версии Crosswalk: Crosswalk Lite 10-15Mb vs. Crosswalk 20Mb.



Однако, кроме ограниченного набора возможностей, у Crosswalk Lite есть ещё ряд минусов:




  • Activity необходимо наследовать от XWalkActivity;

  • Application необходимо наследовать от XWalkApplication;

  • инициализацию необходимо проводить асинхронно в специальном методе, при этом на первом запуске распаковывается сама библиотека и пользователь видит сообщение об этом.



К сожалению последняя доступная на данный момент версия Crosswalk Lite 17.46.460.1 отказалась запускаться с ошибкой (как и 2 её предшественницы):



W/XWalkInternalResources: org.xwalk.core.R$styleable.ButtonCompat is not int.
E/SysUtils: ApplicationContext is null in ApplicationStatus
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 22829 (osswalkembedded)


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



Примеры добавлены в обновлённый тестовый проект, доступный на GitHub.



Выводы.



В последних версиях учтены многие, в том числе и упоминаемые мной, недочёты предыдущих релизов. И, если вы уже используете Crosswalk, то вам однозначно стоит перейти на новые версии.



Однако, остаётся другой вопрос. Может ли Crosswalk сейчас послужить хорошей заменой системному WebView? Если вы поддерживаете старые версии Android (в том числе версии Android 4 Jelly Bean и KitKat), то, очевидно, Crosswalk может вам пригодиться. Если же вы планируете поддерживать только Android 5+, то здесь ответ не очевиден.



С 5ой версии Android стало доступно обновление системного WebView из Google Play (и появились новые, удобные запросы в API), а с 7ой версии Android приложение Google Chrome призвано заменить стандартный системный компонент. Насколько необходима дополнительная библиотека в таком случае сложно сказать. Возможно, для некоторых проектов полная идентичность поведения на всех версиях ОС перевесит увеличение размера и необходимость обновления ещё одной библиотеки.


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308538/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Осталось 7 дней для покупки Early Bird билетов на MBLTdev 16

Четверг, 25 Августа 2016 г. 15:47 (ссылка)

17 ноября в Москве пройдет третья Международная конференция мобильных разработчиков MBLTdev 16.

Приглашенные эксперты из Великобритании, США, Германии, Румынии, Дании и России поделятся опытом разработки для iOS и Android.







Программа будет поделена на несколько потоков:



Для разработчиков


Хардкорные доклады, практические воркшопы и live coding:


  • особенности выбора дизай-паттернов на Swift 3 для юнит тестирования и TDD,

  • фишки Google Cardboard и Daydream SDK,

  • детальный разбор Firebase,

  • тестирование с помощью Espresso,UiAutomator, Appium и использование Firebase Test Lab и Amazon Device Farm,

  • повышение читаемости кода через грамотную организацию коллбэков,

  • обеспечение консистентность хранимых данных с помощью синхронизации доступа,

  • обработка зависимостей асинхронными методами,

  • особенности Robolectric

  • работа с данными, которые пока не существуют, при создании интерфейсов,

  • альтернативные варианты разработки приложения без использования фрагментов,









Для дизайнеров


Трек с лекциями и воркшопами от преподавателей курса дизайна мобильных приложений Британской высшей школы дизайна — специалисты известных компаний, обладающие значительным опытом работы в сфере UX/UI сервисных приложений и цифровых продуктов, мобильных разработок и маркетинга.







До 1 сентября вы можете приобрести Early Bird билет по самой низкой цене — 2500 руб. Подробности на официальном сайте.



Следите за новостями на Facebook.

До встречи на MBLTdev 16!



Организаторы конференции: e-Legion и РАЭК.

Партнёры: Google, Aviasales, Avito.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308452/

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Обзор метрик мобильного приложения

Четверг, 25 Августа 2016 г. 15:29 (ссылка)





Итак, вы опубликовали в сторе своё первое приложение. Начались первые скачивания, и сейчас самое время начать снимать метрики, чтобы проанализировать их и выявить возможные слабые места. Аналитика — важнейший инструмент в мире мобильных приложений. Она позволяет понять психологию пользователя, понять, как он взаимодействует с мобильным приложением, и в результате поможет сделать ваше детище лучше и прибыльнее.



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




  • Источник установки приложения: информация о том, откуда пользователь узнал о вашем приложении;

  • Удержание пользователей: сколько человек запустило ваше приложение спустя разное количество дней после установки;

  • Количество уникальных пользователей: сколько людей пользуются вашим приложением в течение дня, недели и месяца, как регулярно они это делают;

  • Сессия: продолжительность взаимодействия с приложением, какие экраны приложения посещал пользователь, когда и как завершена сессия;

  • Взаимодействие с интерфейсом: какие кнопки и в какой последовательности были нажаты, А/Б тесты и т.д.;

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



Давайте разберем более детально каждый пункт.



Источник установки приложения



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



Удержание пользователей



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



Чтобы оценить привлекательность для пользователей, чаще всего снимаются метрики:




  • 1-day retention. Метрика означает долю пользователей (%), открывших ваше приложение на следующий день после установки. То есть это количество тех, кого ваш продукт заинтересовал настолько, что они очень быстро к нему вернулись. Низкое значение этого показателя говорит о том, что пользователей что-то не устраивает в вашем приложении. Чаще всего плохой «1-day retention» говорит о проблемах с интерфейсом: он может быть неудобен и/или непонятен, это первое, чем нужно заняться для исправления ситуации. Ведь если пользователь не вернулся на следующий день, то с высокой вероятностью не вернётся совсем. Так что повышение значения этой метрики — одна из важнейших задач после выкладывания приложения.



    Вычисляется по формуле:



    1DR = X1 / Z, где X1 — количество пользователей, запустивших приложение на следующий день, Z — общее количество установивших.

  • 7-day retention. Доля пользователей, вернувшихся спустя неделю после установки. Если этот показатель ниже «1-day retention», значит пора сесть и проанализировать, что пользователей может не устраивать после более продолжительного, недельного знакомства с приложением. Возможно, стоит пересмотреть подход к use cases.



    Вычисляется по формуле:



    7DR = X7 / Z, где X7 — количество пользователей, запустивших приложение на седьмой день, Z — общее количество установивших.

  • 28-day retention. Доля тех, кто воспользовался приложением на 28-й день после установки. Если даже месяц спустя люди возвращаются к вашему продукту, то это говорит о том, что он их «зацепил». Уменьшение значения этой метрики по сравнению с предыдущей свидетельствует о каких-то глубоких, неявных, стратегических недостатках.



    Вычисляется по формуле:



    28DR = X28 / Z, где X28 — количество пользователей, запустивших приложение на седьмой день, Z — общее количество установивших.



Все три метрики снимаются ежедневно, при каждом запуске приложения сравниваются текущая дата и дата установки. Анализ динамики изменения каждой из метрик позволит также понимать реакцию пользователей на те или иные изменения, вносимые вами в приложение. Например, уровень 1-day retention обычно свидетельствует о том, как пользователи реагируют на интерфейс вашего приложения. И если этот показатель начал снижаться, то в первую очередь необходимо проверить, что не так с интерфейсом.







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



Если динамика прироста будет отрицательная, то необходимо активнее заняться продвижением и рекламой. Подробнее об этом мы расскажем в одной из будущих публикаций.







Количество уникальных пользователей в течение определённого периода



Итак, вам удалось добиться более-менее устойчивого прироста аудитории, проект тепло принят пользователями и набирает популярность. Пора задуматься о степени активности пользователей: сколько человек в день запускают ваше приложение? А в неделю? В месяц? Причём речь идёт именно об уникальных пользователях. На эти вопросы отвечают три метрики:




  • DAU (Daily Active Users): количество уникальных пользователей в день.

  • WAU (Weekly Active Users): количество уникальных пользователей в неделю. Не пытайтесь получить эту метрику, сложив семь разных DAU — вы неизбежно посчитаете несколько раз тех пользователей, которые запускали приложение более одного раза в течение недели.

  • MAU (Monthly Active Users): количество уникальных пользователей в месяц. Предупреждение такое же, как и с DAU — это не сумма более мелких метрик, а самостоятельно измеряемый параметр.



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







Также можно вычислять производную метрику Sticky Factor = DAU/WAU или DAU/MAU. Её название можно перевести как «степень липкости». Она характеризует регулярность использования вашего приложения в течение недели или месяца, то есть позволяет оценить, насколько людям нравится ваше приложение на основании частоты использования. Если все пользователи будут запускать программу каждый день, то DAU будет равен и WAU, и MAU, а их отношение будет равно 100%. Но так не бывает, и потому Sticky Factor позволяет оценить, насколько часто люди обращаются к вашему приложению в течение недели или месяца. Логично, что снижение этих показателей — неприятный сигнал, говорящий об охлаждении аудитории.



Сессия



Сессия — это время, которое пользователь провел в мобильном приложении с момента запуска до окончания его использования. Применительно к сессиям снимается обычно две метрики:




  • Общее количество сессий за период.

  • Средняя продолжительность сессии (Average Session Length, ASL): среднее арифметическое всех длин сессий за некоторый временной интервал. Вычисляется по формуле:



    ASL = T / N, где T — суммарная продолжительность сессий за период, N — общее количество сессий за тот же период.



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






Однако не стоит гнаться за высокими значениями этой метрики, потому что она сильно зависит от типа вашего приложения. Например, для игр данный показатель достаточно критичен, и чем он больше, тем лучше. А для приложений-виджетов или фитнес-трекеров данный показатель будет незначительным, поскольку по большей части они работают в фоновом режиме. Гораздо важнее знать, какие экраны в течение сессии посещал пользователь. Благодаря этой метрике вы можете определить наиболее интересные для пользователей разделы вашего приложения. А заодно и узнаете, какие можно вовсе убрать и в дальнейшем не заниматься их развитием.



Очень полезная метрика — на каком экране заканчивается сессия пользователя. Этот показатель важен, например, если у вас в приложении есть авторизация. Она зачастую отпугивает пользователей, особенно если приложение не дает посмотреть контент, а сначала требует логин и пароль. В этом случае сессия будет чаще всего обрываться на экране регистрации. Если вы добавите какой-то контент до авторизации, то благодаря этой метрике сразу увидите результат.



Другой пример: если у вас есть форма заказа товара, состоящая из 3-4 экранов, то эта метрика покажет, на каком шаге большинство пользователей покидает приложение. В качестве решения уменьшите количество шагов, оптимизируете их порядок или оформление.



Взаимодействия с элементами интерфейса



Пытаясь поднять значения тех или иных метрик, очень часто приходится корректировать пользовательский интерфейс и менять функциональность программы. Оценить эффективность этих шагов можно с помощью A/B-тестирования (тестирование в режиме реального времени, когда группе пользователей предлагается одна версия функциональности/контента, а остальным пользователей — другая версия). В нашем случае тестирование подразумевает выкатывание новой версии приложения с изменённым UI для некоторой контрольной группы пользователей. Остальные продолжают пользоваться текущей версией. И мы регистрируем, как контрольная группа реагирует на нововведения, снимая метрики взаимодействия с интерфейсом приложения: например, какая из двух кнопок даёт бо

https://habrahabr.ru/post/308438/

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Метод Super Mario World: дополнения и расширения

Четверг, 25 Августа 2016 г. 15:08 (ссылка)

Это продолжение первого урока по использованию метода Nintendo для создания уровней. Работая над игрой Super Mario World, команда разработчиков из Nintendo сформировала (возможно, интуитивно) весьма эффективный метод построения уровней и организации их контента. Я называю этот метод «Испытание, модуляция, серия препятствий», или ИМСП.







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



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



Мой пример



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









ID уровня: 1288 0000 00EC F5A2



Использование дополнений



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



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







Перед нами обыкновенный Твомп, который пытается раздавить Марио каждый раз, когда тот оказывается слишком близко. Идея довольно проста, и применить к ней дополнение тоже нетрудно.







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



Добавление одного элемента к другому – это самая базовая форма дополнения. Динамика проста: испытание становится сложнее, когда в нем появляется больше препятствий. Но оно также может стать частью еще более сложного испытания.



В следующем примере я добавил новое препятствие – пропасть слева от Твомпа.







Она не просто вынуждает игрока сделать прыжок – она заставляет его прыгнуть прямо под удар Твомпа. Как видите, это дополнение ненамного сложнее предыдущего – что вполне нормально. Оба эти дополнения – просто ответвления самого первого испытания.



Далее я решил ввести дополнение для пропасти: я добавил огненный шар, выстреливающий через равные интервалы. Теперь игрок должен ждать подходящего момента, чтобы перепрыгнуть пропасть и уклониться от Твомпа. Это тоже усложняет предыдущее испытание – правда, по-прежнему ненамного.







В следующем испытании я объединю всё, что мы использовали до настоящего момента:







Пока что это самое сложное испытание: в нем присутствуют сразу 3 препятствия. В играх от Nintendo редко можно встретить больше трех препятствий за раз. Данный пример действительно непростой и более-менее соответствует самым трудным испытаниям в играх от Nintendo. Конечно, вы можете пойти дальше в вашей игре (или в ваших уровнях Mario Maker); я всего лишь показываю принцип.



В следующих двух испытаниях я решил немного понизить сложность и сосредоточиться на качественных изменениях. Обратите внимание: сложность уровней в игре не должна всегда возрастать линейно. Сложность может снижаться и повышаться – иногда вполне достаточно делать испытания разнообразными, а не более и более сложными.



С учетом этого факта я убрал пропасть и добавил вместо нее Чейн Чомп.







А затем я вернул пропасть с огненным шаром, но убрал огненный барьер.







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



Использование расширений



Прежде чем перейти к важнейшему выводу, касающемуся дополнений, хотелось бы остановиться на правильном использовании расширений. В предыдущей статье я определил расширение как дополнение, но с количественными (а не качественными) изменениями предыдущего испытания. Рассмотрим простой пример:







Это первое расширение. Мы вернулись к самому первому испытанию уровня и просто удвоили количество Твомпов.



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



У расширений есть один важный принцип: они меняют сложность испытания не линейно. Расширения так же зависят от контекста, как и дополнения, несмотря на их принципиальную разницу.



Еще один пример расширения:







Удвоенное число огненных барьеров, в отличие от удвоенного числа Твомпов, существенно усложняет испытание (особенно за счет их несинхронного вращения). В принципе, это испытание можно назвать самым сложным на всем уровне. Получается, мы имеем дело с точно таким же видом расширения, как и прежде, но опыт совершенно другой.



А что, если применить этот прием к другому элементу? Например, к ширине пропасти:







Этот вид расширения немного сложнее распознать. Я решил увеличить ширину пропасти до двух блоков вместо одного (то есть удвоил её, как и все элементы до этого), чтобы игрок точно ощутил разницу в длине прыжка, даже если не сразу увидит её.



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







Оказывается, прыжок через более широкую пропасть решает эту проблему, так как траектория движения Марио меняется: он берет больший разгон и потому быстрее уклоняется от падения Твомпа, оставаясь в безопасности. Сам прыжок немного сложнее по технике, но в целом испытание остается таким же простым. На такие вещи стоит обращать внимание при тестировании игры, если вы применяете принцип ИМСП.

Теперь применим такое же расширение к огненным шарам:







Испытание вышло труднее, чем с двумя Твомпами, но проще, чем с огненными барьерами. Временной промежуток для удачного прыжка слегка сократился, но по сложности данный пример несопоставим с предыдущим.



Вывод: хотя расширения легко применять, их эффект сложно контролировать. Удвоение одного элемента и удвоение другого – не одно и то же, независимо от того, насколько они похожи.



Расширение за счет сжатия



Существуют и иные способы усложнить испытания. Один из них я называю расширением за счет сжатия. Звучит парадоксально, но это отлично передает суть приема. Рассмотрим пример:







Я сократил расстояние между Марио и Твомпами. Это определенно количественное изменение сложности самого первого испытания и может считаться расширением. Но достигается оно путем уменьшения значений. Расширение за счет сжатия почти всегда подразумевает сокращение расстояния между Марио и угрозой, иногда приближая его к ней, а иногда – уменьшая ширину платформы под ним. Всё зависит от контекста.

Опаснее всего переусердствовать со сжатием – игрок просто не сможет пройти испытание, не получив урона. Я специально создал такую ситуацию в своем последнем испытании: крайний Твомп так низко нависает над землей, что в любом случае задевает Марио при падении.







Из этого следует 2 очень важных наблюдения по поводу расширений.



Во-первых, есть предел расширения каждого элемента уровня. Иначе пропасти будут слишком широкими, врагов слишком много, а безопасные зоны станут чересчур узкими. Если же вы хотите нащупать максимальный порог расширения, вероятно, имеет смысл пойти от обратного: начать с максимальной сложности уровня и двигаться назад к его упрощению.



Во-вторых, нужно понимать, что иногда расширения усложняют испытание только на уровне психологии. К примеру, в последнем испытании 3 первых Твомпа на самом деле не заденут Марио, если он не сбросит скорость. Выходит, опасность не так велика. Если игроку показалось, что он только что выполнил что-то суперсложное и замысловатое, то дизайнер уровня отлично справился со своей работой.



Выводы и советы



Это длинная и немного запутанная статья, поэтому хотелось бы повторить все ключевые тезисы. Главная мысль такова: хоть четкие стандарты по разработке контента для уровней и существуют, они не делают контент полностью предсказуемым. И это очень здорово – значит, принцип ИМСП оставляет много места для творчества. Он нужен не для того, чтобы делать уровни под трафарет, а для правильной организации контента, благодаря которой ваши уровни будут органичными, интересными и сложными.




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

  • Используйте несколько разных дополнений для вашей основной идеи.

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

  • Расширения – это изменения количественного характера, но их влияние на игровой опыт может быть неожиданным. Удвоив какой-либо элемент, вы не повысите сложность испытания ровно в 2 раза. Она может вырасти как на 10 %, так и на 400 % – всё зависит от того, что вы расширяете.

  • Есть предел расширения элементов дизайна. Если вы хотите поэкспериментировать с этим пределом, практикуйте дизайн уровней от обратного: сделайте непроходимо сложный уровень и постепенно упрощайте его, пока не найдете баланс.

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





Компания Nintendo создала несколько игр, используя этот метод с незначительными вариациями. Более того, принцип ИМСП (расширения и дополнения) прослеживается во многих других играх, не только от Nintendo и не только в жанре платформер. В конечном счете, он нужен для организации контента вашей игры, а не для того, чтобы менять её суть.
Original source: habrahabr.ru.

https://habrahabr.ru/post/303772/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

5 UI фишек для современного Андроид приложения. Код, идеи и живой пример

Среда, 24 Августа 2016 г. 23:06 (ссылка)

image



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



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





1. Извлекаем доминантный цвет из изображения



Иногда хочется добавить немного разнообразия в цветовую схему приложения, к примеру подбирать цвета динамически, в зависимости от определённой картинки. Специально для таких случаев существует библиотека от Google — Palette. Давайте посмотрим на один из примеров её использования:



image




// Не забудте добавить Palette в build.gradle :
// compile 'com.android.support:palette-v7:+'

public static int getDominantColor(Bitmap bitmap) {
List swatchesTemp = Palette.from(bitmap).generate().getSwatches();
List swatches = new ArrayList(swatchesTemp);
Collections.sort(swatches, new Comparator() {
@Override
public int compare(Palette.Swatch swatch1, Palette.Swatch swatch2) {
return swatch2.getPopulation() - swatch1.getPopulation();
}
});
// если по какой-то причине не удалось извлечь цвета из изображения, выбираем просто случайный цвет
return swatches.size() > 0 ? swatches.get(0).getRgb() : getRandomColor();
}

public static int getRandomColor() {
Random rnd = new Random();
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
return color;
}




2. Генерируем разноцветные квадраты с буквами прямо в коде



Такие квадраты часто встречаются в популярных приложениях. Их можно легко создать прямо в коде, в виде обычного Bitmap, без дополнительной графики или xml layout-ов. Я использовал их в качестве «заглушки» когда оригинальное изображение отсутствует. Для их создания вам понадобится всего одни класс LetterBitmap. Пример его использования и конечный результат ниже:



image


int COVER_IMAGE_SIZE = 100; //in pixels
LetterBitmap letterBitmap = new LetterBitmap(context);
Bitmap letterTile = letterBitmap.getLetterTile("string for letter", "string for color", COVER_IMAGE_SIZE, COVER_IMAGE_SIZE);
ImageView imgAnyImageView = (ImageView) view.findViewById(R.id.imgAnyImageView);
imgAnyImageView.setImageBitmap(letterTile);




3. Масштабируем изображение на лету



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



image


// Функция масштабирования
public static Bitmap createScaledBitmap(Bitmap bitmap, float scaleFactor) {
Matrix m = new Matrix();
m.setRectToRect(new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()),
new RectF(0, 0, bitmap.getWidth() * scaleFactor, bitmap.getHeight() * scaleFactor), Matrix.ScaleToFit.CENTER);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
}

// Пример использования:
float COVER_SCALE_FACTOR = 2f;
final Bitmap scaledBitmap = UIHelper.createScaledBitmap(regularBitmap, COVER_SCALE_FACTOR);

// В фоновом потоке
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap scaledBitmap = UIHelper.createScaledBitmap(regularBitmap, COVER_SCALE_FACTOR);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
anyImageView.setImageBitmap(scaledBitmap);
}
});
}
}).run();




А это ссылка на Gist с вышеперечисленными примерами + примером для популярной библиотеки подгрузки картинок — Glide.



4. Программно меняем цвет текста поискового поля внутри Toolbar



Я потратил кучу времени пытаясь поменять цвет стандартной строки поиска внутри Toolbar не создавая отдельного layout. Большинство советуют настроить стили темы в styles.xml, иногда это помогает для Андрода 5.0+, но не работает на более ранних версиях. Поэтому я предлагаю простое и универсальное программное решение:



image


    public static void changeSearchViewTextColor(View view, int color) {
if (view != null) {
if (view instanceof TextView) {
((TextView) view).setTextColor(color);
return;
} else if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
changeSearchViewTextColor(viewGroup.getChildAt(i), color);
}
}
}
}

// Пример использования:
Toolbar toolbar = (Toolbar) findViewById(R.id.your_toolbar);
MenuItem searchMenuItem = toolbar.getMenu().findItem(R.id.action_search);
SearchView searchView = (SearchView) searchMenuItem.getActionView();
setSearchViewStyle(searchView);
changeSearchViewTextColor(searchView, Color.WHITE);




5. Кнопки с закруглёнными краями



Завершить пятерку я решил примером layouta для кнопок с закруглёнными краями, такие кнопки использовались в одной из последних версий и Google Play и уж очень мне приглянулись. Возможно, и Вы сможете найти им применение в своем приложении:



image




Для Андроид 5.0+:














Для более ранних версий:


























Для применения разложите XML файлы по папкам drawable и drawable-v21 соответственно, а потом просто задайте как фон для любой кнопки.



P.S Как и обещал, оставляю ссылку на репозиторий приложения, в котором применялись все вышеперечисленные «фишки» — Github
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308378/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Я заглянул в приложение Prisma, и вы не поверите, что я там нашёл

Среда, 24 Августа 2016 г. 18:25 (ссылка)

2016 год ещё не кончился, но продолжает радовать нас крутыми продуктами по обработке изображений. Сначала все болели FaceSwap, потом появился MSQRD, теперь у нас есть Prisma. Ещё больше радости/гордости, конечно, от того, что последние 2 продукта — наши, родные. MSQRD делают ребята из Беларусии, Prisma же вообще родом из Москвы. Логично, что у любого популярного продукта сразу начинают плодитьяся конкуренты. Призме в этом плане повезло больше всех — благодаря стечению некоторых обстоятельств, основным конкурентом призме стали Mail.ru Group, которые почти сразу выпустил аж 2 похожих продукта со схожими функциями: Vinci (от команды vk.com) и Artisto (от команды my.com).







А лично мне стало интересно посмотреть на эти «клоны» изнутри. Зачем мне всё это и к каким выводам я пришёл — об это я рассказал на roem.ru, повторяться не вижу смысла. На Хабре же я бы хотел поделиться техникой детального анализа приложений для iOS на примере Prisma.



Что нам предстоит? Во-первых, мы узнаем, что есть приложение для iOS и из чего оно состоит, какую информацию можно оттуда извлечь. Во-вторых, я расскажу как снифать траффик client-server приложений, даже если их авторы этого очень сильно не хотят. По факту я не расскажу вам ничего нового, я не придумал никакого ноу-хау, это просто вектор известных техник и умений на приложения. Но будет интересно. Погнали.



iOS-приложение, IPA-файл



iOS-приложение представляет собой .ipa-файл. По факту это zip-архив и может открываться любым архиватором (да да, mobilz обещал научить ломать приложения, а на самом деле покажет, как пользоваться архиватором). Сам .ipa-файл проще всего получить с помощью iTunes — в разделе «Программы» есть вкладка AppStore, которая является аналогом AppStore в iPhone. Соответственно, вам потребуется аккаунт (AppleID); загрузив приложение с помощью iTunes мы можем перейти в директорию к нему.









Далее .ipa-файл, как я уже говорил, открывается любым архиватором. Внутри мы найдём помимо прочего директорию Payload и файл iTunesMetadata.plist. В Payload находится наше приложение, а точнее директория с расширением .app, которую MacOS будет пытаться запустить, но нам достаточно просто открыть содержимое. iTunesMetadata содержит метаинформацию из AppStore. Какой аккаунт скачал приложение, в каком разделе приложение находится и т.д. и т. п. Ничего интересного в нём для нашего анализа нет, идём непосредственно к .app. Разберём сразу на конкретном приложении, Prisma 2.3 — Payload/Prisma.app.



В разных проектах мы можем увидеть разную структуру, но всегда точно будет Info.plist (Payload/Prisma.app/Info.plist). Это основные настройки приложения, такие как минимальная версия для запуска, поддерживаемые ориентации, поддержка iPad и прочее. Тут уже интереснее:






 
   UIRequiredDeviceCapabilities
   
     armv7
   

   DTCompiler
   com.apple.compilers.llvm.clang.1_0
   CFBundleInfoDictionaryVersion
   6.0
   DTPlatformVersion
   9.3
   DTSDKName
   iphoneos9.3
   CFBundleName
   prisma
   UIViewControllerBasedStatusBarAppearance
   
   CFBundleIcons
   
     CFBundlePrimaryIcon
     
       CFBundleIconFiles
       
         AppIcon29x29
         AppIcon40x40
         AppIcon60x60
       

     

   

   UIStatusBarStyle
   UIStatusBarStyleLightContent
   LSRequiresIPhoneOS
   
   CFBundleDisplayName
   Prisma
   LSApplicationQueriesSchemes
   
     instagram
     fb
     fbauth2
     fbshareextension
     fbapi
     fb-profile-expression-platform
     vk
     vk-share
     vkauthorize
   

   DTSDKBuild
   13E230
   CFBundleShortVersionString
   2.3
   CFBundleSupportedPlatforms
   
     iPhoneOS
   

   UISupportedInterfaceOrientations
   
     UIInterfaceOrientationPortrait
   

   Pushwoosh_APPID
   46F12-BE2E4
   BuildMachineOSBuild
   15G31
   DTPlatformBuild
   13E230
   CFBundlePackageType
   APPL
   MinimumOSVersion
   8.0
   CFBundleDevelopmentRegion
   en
   DTXcodeBuild
   7D1014
   CFBundleVersion
   40
   UIStatusBarHidden
   
   FacebookAppID
   582433738573752
   UILaunchStoryboardName
   LaunchScreen
   UIDeviceFamily
   
     1
   

   Fabric
   
     Kits
     
       
         KitName
         Crashlytics
         KitInfo
         
       

     

     APIKey
     8e17945e7d29d1c775f321348caef29075f5ab9a
   

   FacebookDisplayName
   Prisma.AI
   CFBundleIdentifier
   com.prisma-ai.app
   DTXcode
   0731
   NSAppTransportSecurity
   
     NSExceptionDomains
     
       vk.com
       
         NSExceptionRequiresForwardSecrecy
         
         NSExceptionAllowsInsecureHTTPLoads
         
         NSIncludesSubdomains
         
       

       cdninstagram.com
       
         NSExceptionAllowsInsecureHTTPLoads
         
         NSIncludesSubdomains
         
       

     

   

   CFBundleExecutable
   prisma
   CFBundleSignature
   ????
   DTPlatformName
   iphoneos
   CFBundleURLTypes
   
     
       CFBundleURLSchemes
       
         fb582433738573752
       

     

     
       CFBundleURLSchemes
       
         vk5530956
       

     

     
       CFBundleURLSchemes
       
         prisma
       

     

   

 



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



Во-первых, мы можем добыть API-ключи для сторонних продуктов (вроде crashlytics), идентификаторы групп/страниц в vk/facebook. Во-вторых, мы можем точно знать детальные настройки урлов, куда ходит приложение:



LSApplicationQueriesSchemes



LSApplicationQueriesSchemes

 instagram
 fb
 fbauth2
 fbshareextension
 fbapi
 fb-profile-expression-platform
 vk
 vk-share
 vkauthorize


Видим, что приложение захочет работать с инстаграмом, фейсбуком и вконтактом. Эта информация никаким образом, конечно, не поможет «сломать» приложение, но даст нам дополнительную информацию.



NSAppTransportSecurity



NSAppTransportSecurity

 NSExceptionDomains
 
   vk.com
   
     NSExceptionRequiresForwardSecrecy
     
     NSExceptionAllowsInsecureHTTPLoads
     
     NSIncludesSubdomains
     
   

   cdninstagram.com
   
     NSExceptionAllowsInsecureHTTPLoads
     
     NSIncludesSubdomains
     
   

 



Если не ошибаюсь, флаг появился с 9-ой версии iOS. Рассказывает нам, куда приложение будет ломиться по http-протоколу (https доступен любой домен). Т.е. при всём желании приложение не сможет обратиться на http, если не настроен NSAppTransportSecurity.



Ключ в целом тоже нам особо ничего не даёт, кроме как информации. Но курочка по зёрнышку. Видим, что приложение хочет ломиться по http на vk.com и cdninstagram.com. Ок.



CFBundleURLTypes



CFBundleURLTypes

 
   CFBundleURLSchemes
   
     fb582433738573752
   

 

 
   CFBundleURLSchemes
   
     vk5530956
   

 

 
   CFBundleURLSchemes
   
     prisma
   

 



Пожалуй, самый интересный из бесполезных ключей. Опять же, он нам ничего особо полезного не даёт, но рассказывает о зарегистрированных урлах на этом конкретном приложении. Например, если в мобильном сафари вы наберёте fb582433738573752:// вас перекинет в приложение (если оно установлено, конечно). Данную информацию, повторюсь, тоже можно отнести к условно-бесполезной. Но пару раз я натыкался на приложения, где помимо стандартных урлов соцсетей я находил урлы типа «app-admin» или «app-dev». При переходе на которые можно было получить скрытые настройки приложения. В одном приложении я получил редакторский доступ к одному изданию, в котором можно было публиковать статьи, пихать их на главную, удалять, менять местами итп.



Далее нас интересует директория Frameworks: Payload/Prisma.app/Frameworks



В ней мы найдём ещё немного бесполезной информации об используемых внешних фреймворках и SDK.





Подробнее я напишу чуть ниже про каждый фреймворк, но заранее могу сказать, что, например, отсюда можно тоже выцепить интересную информацию. Среди прочих фреймворков видим FLAnimatedImage, который работает с анимированными GIF — невольно напрашивается вывод, что Prisma всё же будет и с видео.



Также в метафайлах часто можно найти какой-то мусор, забытый разработчиками. Часто я нахожу README.md, .gitignore, лицензии и прочее. Опять же, Prisma хороший пример, т.к. с версии 2.3 в ней появилась просто забытая разработчиками фотка одного из друзей. Те, кто докопаются, прошу не выкладывать имя человека в комментах, он очень просил.



Также находим USERTrustRSAAddTrustCA.cer — уже интересней. Насколько я понял это запароленный сертификат, аналоговый брутфорс профита не дал.



Непосредственно в бинарнике часто находятся скрытые plist, которые могут быть интересными. Также, если приложение собрано на webview-технологиях (типа Cordova), мы найдём config.xml кордовы и, собственно, исходник приложения. Например, приложение Sworkit, которое помимо прочего предлагает пользователям оплатить дополнительные видеоуроки, уже имеет их в исходниках в удобном .mp4-формате. Хочешь удобно — плати. Хочешь неудобно, но бесплатно — читай на Хабре эту статью.



Пожалуй, это основное, что можно добыть из пакета с приложением. Точнее основное, что удалось добыть мне. Уверен, вы ребята умные и найдёте ещё больше полезного — пишите в комментарии и мы добавим это в статью. Но, опять же, всё индивидуально. В некоторых приложениях можно найти очень многое, в том числе и целиком исходники.



Ну и чуть подробнее о самом приложении. Призма (2.3) 17.6Мб. Нативный swift, поддержка русского и английского языка. Фреймворки:

Alamofire.framework — http-клиент

AlamofireImage.framework

AlamofireNetworkActivityIndicator.framework

Bolts.framework — вспомогательный набор инструментов для разработчика

FBSDKCoreKit.framework — facebook

FBSDKShareKit.framework — facebook

FLAnimatedImage.framework — библиотека для работы с видео

KeychainAccess.framework — враппер авторизации. Чаще всего используется для работы с touchid

Obfuscator.framework — обфускатор, тут, думаю, объяснять не нужно

PINCache.framework — key/value хранилище для больших объектов с поддержкой работы в разных потоках.

PINRemoteImage.framework — модуль picache

pop.framework — библиотека для работы с анимацией. Чаще всего используется для UI-анимации.

RHBOrientationObjC.framework — работа с акселерометром, точнее, с ориентацией устройства.

SDWebImage.framework — ещё один http_клиент/кешер для изображений

SwiftyJSON.framework — удобная работа с json

Swinject.framework — DI паттерн разработки

VK_ios_sdk.framework — vk.com


Что в итоге мы имеем? Мы собрали кучу информации о работе приложения и понимаем, чего от него ожидать. Мы нашли некий сертификат и сохранили его себе. Мы узнали, что нас скоро ждёт видео и нашли классную фотку друга основателя Prisma. Двигаемся дальше.



Сниффаем HTTP



Prisma и тут оказалась хорошим примером для статьи. Если те же Artisto и Vinci ходят по голому http и нет труда их сниффать, Prisma ходит по https с проверкой подлинности сертификата. И тут начинаются танцы с бубнами. Но давайте по порядку.



1. Для начала нам нужен http(s)-прокси. Я пользуюсь Charles, он достаточно простой и функциональный.

2. Нам нужно iOS-устройство. Эмуляторы не подойдут.

3. Нам нужна одна сеть между устройствами. Самое простое — Wi-Fi.



На своём терминале запускаем прокси, заодно включаем и https-прокси. На устройстве, соответственно, в настройках Wi-Fi-сети прописываем руками прокси (IP нашего терминала и порт):





Дальше чаще всего достаточно подсунуть в iOS свой сертификат. Как это сделать хорошо написано на том же сайте Charles. Но в случае с Prisma этого сделать не получилось — разработчики не лыком шиты и проверяют подлинность сертификата. Но делается это средствами устройства, а мы тоже хитрюги те ещё. Однако для того, чтобы заставить iOS не проверять сертификат на подлинность, нам потребуется jailbreak.



Действуйте можно было сделать до версии iOS 9.3.3, и то на свой страх и риск — как вариант, используйте тематические ресурсы и внимательно читайте комментарии. В частности, некоторый софт «типа для джаилбрейка» может попросить AppleID вместе с паролем, что чревато исчезновением данных и денег денег с привязанной карты. Все эти тонкости подробно описаны.



Я не буду описывать как делал это я, т.к. разлочка сильно отличается в зависимости от версий устройства и iOS. Единственное, зачем нам это надо в данном случае — https://github.com/nabla-c0d3/ssl-kill-switch2/releases — крайняя версия ssl kill switch. С помощью Cydia (опять же, всю информацию можно найти в сети) ставим любой просмоторщик файлов, например iFile. И с помощью него заливаем .deb-файл последнего релиза ssl kill switch. Работать ssl kill switch после перезагрузки телефона. Важно не забыть его выключить после всех манипуляций, т.к. в противном случае мы рискуем, ведь наше устройство больше не проверяет подлинность ssl.





Прокси включён, проверка сертификата выключена, погнали смотреть на приложение. Первый запуск — как видим, приложение сначала собирает настройки. Откуда же оно их берёт? Дёргается https://cdn.neuralprisma.com/config.json обычным GET`ом, там стандартные настройки, не интересно. Потом дёргается api3.neuralprisma.com/styles POST-ом с телом



{
"codes": ["public"]
}


На выходе список фильтров. Уже интересней, поигрался с массивом [«public»]. Пытаясь подставить туда что-то вроде «dev», «new» и прочего, профита я не получил, но может у кого из вас получится. Я рекомендую использовать для этого Postman.







Ладно, идём дальше. Следующий запрос при загрузке фото опять POST на урл api3.neuralprisma.com/upload/image







И всё было в моей жизни хорошо, пока я не увидел заголовок prisma-image-sign с base64 от бинарного md5. Жизнь боль. Все мои мечты о том, что я сейчас перехвачу траффик призмы и научусь делать то же самое, что и приложение, но просто по http… рухнули. Что это значит? Таким образом разработчики защищаются от таких как я. Посылая фотку по http, приложение также вычисляет какой-то хеш с какой-нибудь солью и добавляет этот хэш в заголовок. Как сгенерить хэш знает только приложение и сервер. Фотка отправляется на сервак, сервак генерит хеш от фотки по тому же алгоритму, сверяет хэши, если они отличаются — значит запрос подделан. Есть способ обойти это, если вы сильны в ассемблере. Дизассм бинарника + анализ его на тему генерации этого заголовка может дать нам алгоритм. Но учитывая, что там md5 (минимум) + base64, на это может уйти много времени. Ну и не забываем, что всё усложняется ещё и наличием фреймворка Obfuscator.framework. В общем, как я уже писал, жизнь боль.



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



Ну да ладно, давайте не будем отчаиваться и разберём возможность перехвата API на примере другого подобного приложения Vinci. Как уже говорил, там всё ходит по голому http, поэтому нам даже не придётся коверкать наше устройство. Просто прописываем прокси сервер и смотрим что куда ходит при работе с приложением. Все запросы можно эмулировать в Postman, о котором я уже писал, или реализовать на каком-нибудь серверном языке.







Всё достаточно просто. При запуске первым запросом Vinci собирает доступные стили, далее регистрирует девайс, нам это пофиг. Затем я загрузил фото, отправляется POST-запрос на /preload с фото, с любым фото, в ответ мы получаем некий хэш нашего фото:







Ну и далее, как видно, получаем уже готовое изображение, обращаясь по урлу http://vinci.camera/process/2_gNmHxDdthLsmPtuXGxRzQnKjbbspfO/21, где 2_gNmHxDdthLsmPtuXGxRzQnKjbbspfO хеш фото, а 21 — номер фильтра, которые можно добыть из http://vinci.camera/list







Вот и всё. Итого, чему мы научились сегодня? Мы научились собирать информацию о приложении по метафайлам самого приложения и научились сниффать трафик приложения, даже если всё API ходит по https с проверкой подлинности сертификата. Мы научились собирать информацию из API: что, куда, зачем, а также я показал некоторые «тупики».



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



Кстати, интересный факт. Те же SQLinj. В вебе их сейчас уже сложно встретить, любой разработчик понимает всю опасность инъекций. Но вот мобильные разработчики, которые часто приходят в мобильную разработку не из веба (а даже когда из веба — доверяют своим API, типа «да кто его знает наше API-то, только наше приложение!») частенько забывают про веселье, что может их ждать при полном доступе к базе удалённым пользователем.
Original source: habrahabr.ru.

https://habrahabr.ru/post/123238/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Password Visibility Toggle — Android Support Library, revision 24.2.0

Вторник, 23 Августа 2016 г. 11:33 (ссылка)

Здравствуйте! Перевод статьи об обновлении Android Support Library и одном немаловажном ее новом компоненте Password Visibility Toggle .

Оригинал.



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





От себя хочу добавить, что текущее обновление Support Library считается одним из самых масштабных: разделение на несколько маленьких модулей — несомненный плюс, который поможет уменьшить вес вашего .apk файла; большое обновление API; куча deprecations ну и немножко bugfixes нам принесли.



Android Support Library была недавно обновлена с весьма интересными изменениями. Я обратила внимание на Password Visibility Toggle не случайно: буквально несколько дней назад я пыталась реализовать этот функционал в своём рабочем проекте без использования каких-либо библиотек (между прочиим, Lisa Wray разработала прекрасную либу ).



Я восхваляла это в твиттере.



image

Естественно, это было одной из первый вещей, которую я использовала, поскольку мне нужно было немедленно обновить свой проект.



Здесь очень базовый туториал как с этим работать.



Первый шаг



Первый и самый очевидный — это, конечно же, обновить версию Support Library до 24.2.0. Надеюсь, у тебя версии зависимостей прописаны в extra properties. Если да, то это означает, что тебе нужно поменять версию лишь в ОДНОМ месте. Если нет, то тебе прийдется изменять Gradle файл столько раз, сколько версия встречается.



supportLibraryVersion = '24.2.0'


Далее



Следующим шагом будет создание TextInputEditText и задание inputType одним из следующих вариантов: textPassword, numberPassword, textVisiblePassword or textWebPassword. Я пробовала все 4 типа и заметила, что иконка видимости появляется на всех кроме textVisiblePassword варианта, что довольно очевидно, поскольку эта опция изначально задает видимость пароля по умолчаниюю.












Этот же код на gist.github автора.



Есть 5 XML аттрибутов связанных с password visibility toggle.




  1. passwordToggleContentDescription позволяет нам установить строку в качестве content description

  2. passwordToggleDrawable позволяет нам установить другую иконку, кроме значка видимости visibility toggle icon

  3. passwordToggleEnabled позволяет нам определить хотим ли мы что бы пароль был переключаемый. Мне кажется, что это должно быть установлено только если ты специально не хочешь сделать поле переключаемым

  4. passwordToggleTint ползволяет нам окрасить значок в какой-либо цвет. Так же работает с custom drawable

  5. passwordToggleTintMode позволяет нам задать так называемый режим смешивания, в котором мы можем применить оттенок для фона.



Как обыкновенный Android UI компонент в XML, так же возможно реализовать это (passwordToggleContentDescription, passwordToggleDrawable, passwordToggleEnabled, passwordToggleTint and passwordToggleTintMode) непосредственно кодом: необходимо создать TextInputEditText и вызвать один из этих методов.



Замечания



После того, как я это заимплементила, я ожидала, что иконка видимости будет по умолчанию перечёркнута(ссылка на мой твит выше). Твит ниже от Nick Butcher и даже либа от Lisa Wray демонстрирует тоже самое. Это было несколько разочарование, когда я попробовала ее и обнаружила, что по-умолчанию изменение значка было лишь его затемнение. Это не достаточно очевидно, по моему мнению, так как это могло привести к заблуждению, особенно таких пользователей как я, который уже пробовали эту фичу на других платформах и ожидали такого же поведения. Мне необходимо было создать кастомный StateListDrawable и задать в passwordToggleDrawable XML аттрибуте тип эффекта, которого я хочу достигнуть.



Твит о Password Visibility Toggle от Nick Butcher.



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

Если есть предложения по улучшению качества перевода либо что-то звучит просто несуразно — критика приветствуется.

На этом всё, спасибо.



P.S. За ссылки на gist и twitter прошу прощения, не знаю как их можно прямиком вставить в текст.


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308318/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Разработка для SailfishOS: меню

Вторник, 23 Августа 2016 г. 10:48 (ссылка)

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



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

Полноразмерный скриншот




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

Полноразмерный скриншот




Если потянуть на экране вниз, то появится то самое меню:





Интересной особенностью взаимодействия с меню в SailfishOS является то, что выбрать какой-либо пункт меню можно двумя способами. Можно просто сделать свайп вниз, пока меню не появится полностью (как на скриншоте выше). Тогда оно останется на экране и можно будет просто ткнуть в нужный пункт меню. А можно потянуть вниз не до конца и тогда по мере появления меню его пункты будут подсвечиваться, как на скриншоте снизу:



Если в этот момент убрать палец с экрана, то будет выбран подсвеченный пункт меню.



PullDownMenu



Реализация такого меню в Sailfish довольно проста. Для этого в Sailfish Silica присутствует компонент PullDownMenu. Однако, данный компонент имеет ряд особенностей, которые необходимо знать перед тем как начинать его использовать.



Во-первых, поскольку само меню вызывается с помощью свайп жеста, то PullDownMenu можно использовать только внутри контейнеров, которые данный жест позволяют. В Sailfish Silica такими контейнерами являются:


  • SilicaFlickable — самый базовый контейнер, который позволяет прокручивать экран, если содержимое полностью не влезает в рамки экрана. Данный компонент наследует стандартный QML компонент Flickable и его следует использовать в тех случаях, когда необходимо меню на странице приложения, но ни один из нижеперечисленных контейнеров не подходит.

  • SilicaListView — компонент отображающий список элементов, который наследует стандартный QML компонент ListView.

  • SilicaGridView — так же как и предыдущий компонент, используется для отображения списка элементов, но не в виде вертикального списка, а в виде сетки. Наследует стандартный QML компонент GridView.

  • SilicaWebView — компонент для отображения веб содержимого, наследует стандартный QML компонент WebView.



Во-вторых, содержимым PullDownMenu должны быть компоненты типа MenuItem или MenuLabel. Первый представляет собой интерактивный пункт меню и имеет ряд следующих свойств:


  • text — непосредственно текст пункта меню.

  • color — цвет текста, определенного в предыдущем свойстве.

  • horizontalAlignment — горизонтальное выравнивание текста пункта меню. Может быть одним из следующих значений: Text.AlignLeft, Text.AlignRight, Text.AlignHCenter (используется по умолчанию) или Text.AlignJustify.

  • down — значение данного свойства равно true, когда пункт меню был выбран.



Помимо этих свойств, MenuItem так же содержит достаточно большое количество свойств вида font. для настройки шрифта пункта меню (о них можно прочитать в документации) и обработчик сигнала onClicked(), в котором определяются действия, которые необходимо выполнить при выборе данного пункта меню.



MenuLabel представляет собой статичный пункт меню, который просто отображает некоторый текст и не может быть нажат. Такие пункты используются, например, в качестве заголовка меню или как разделители между интерактивными пунктами меню. Естественно, MenuLabel содержит меньше свойств, чем PullDownMenu:


  • text — текст пункта меню.

  • color — цвет текста, определенного в предыдущем свойстве.

  • verticalOffset — вертикальный отступ.



Минимальный пример страницы с PullDownMenu будет выглядеть следующим образом:

Page {
id: page
SilicaFlickable {
anchors.fill: parent
contentHeight: column.height

PullDownMenu {
MenuItem {
text: qsTr("Пункт меню 3")
onClicked: console.log("Нажат третий пункт меню")
}
MenuLabel {
text: qsTr("Подраздел")
}
MenuItem {
text: qsTr("Пункт меню 2")
onClicked: console.log("Нажат второй пункт меню")
}
MenuItem {
text: qsTr("Пункт меню 1")
onClicked: console.log("Нажат первый пункт меню")
}
MenuLabel {
text: qsTr("Меню приложения")
}
}

Column {
id: column

width: page.width
spacing: Theme.paddingLarge
PageHeader {
title: qsTr("Моё приложение")
}
Label {
text: "Привет, Хабр!"
width: page.width
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Theme.fontSizeExtraLarge
}
}
}
}


Само же меню будет выглядеть так:





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



Свойства PullDownMenu



PullDownMenu содержит ряд свойств, которые позволяют кастомизировать его внешний вид и поведение. Например, отступы компонента можно настроить с помощью следующих свойств:


  • spacing — расстояние между нижним краем меню и верхней границей контента страницы. По умолчанию это значение равно нулю.

  • topMargin — расстояние между верхним краем меню (то же самое, что верхней кран экрана) и верхним краем самого верхнего пункта меню. По умолчанию это значение равно Theme.itemSizeSmall.

  • bottomMargin — расстояние между нижним краем самого нижнего пункта меню и нижним краем самого меню.



Интересной особенностью последнего свойства (bottomMargin) является то, что его значение по умолчанию меняется в зависимости от содержимого меню. Если самый нижний элемент меню это MenuLabel, то значение свойства равно 0. В противном же случае значение свойства равно высоте компонента MenuLabel. Посмотреть разницу можно на примерах ниже:








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



Помимо размеров можно так же менять другие параметры внешнего вида PullDownMenu с помощью следующих свойств:


  • background — позволяет описать компонент, который будет использоваться в качестве фона меню.

  • backgroundColor — цвет фона меню. Примечательно, что система сама применяет градиент к указанному цвету.

  • highlightColor — цвет подсветки выбранного элемента меню, а так же индикатора меню, отображаемого сверху экрана, когда само меню закрыто.

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



Можно изменить цвета в меню из примера выше на следующие:

backgroundColor: "red"
highlightColor: "green"


Тогда получится меню следующего вида:



Выглядит, конечно, страшновато, но зато демонстрирует как работают данные свойства. А с помощью background и menuIndicator можно установить, например, картинки в качестве фона и индикатора меню.



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


  • active — свойство логического типа, значение которого равно true, если меню полностью или частично присутствует на экране.

  • busy — так же свойство логического типа. Если его значение установить равным true, то индикатор меню вверху экрана начнет «пульсировать». При этом само меню будет все так же доступно. Данное свойство удобно использовать, если необходимо показать пользователю, что какой-то процесс все еще выполняется.

  • flickable — с помощью этого свойства можно указать flickable компонент, с помощью которого будет активироваться меню. Т.е. вместо того, чтобы помещать PullDownMenu внутри какого-либо контейнера, можно просто указать этот контейнер значением для данного свойства.

  • quickSelect — свойство логического типа, которое позволяет включить функцию быстрого выбора для меню. Данная функция работает только на меню всего с одним пунктом. Если эта функция активирована, то при любой прокрутке меню (в том числе и до конца) будет автоматически выбран его единственный пункт.



Наконец, PullDownMenu содержит два метода. После выбора какого либо пункта меню, происходит закрытие этого меню и проигрывание анимации закрытия. Эту анимацию можно отменить с помощью метода cancelBounceBack(), если, например, вызвать его в обработчике onClicked() нужного пункта меню. Это может быть полезным в редких случаях, когда закрытие меню может помешать выполнению действия, назначенного для пункта меню.



Метод close() позволяет вручную закрыть меню. При этом можно в качестве аргумента данного метода можно указать true и тогда меню закроется мгновенно, без анимации. Например, в нижеприведенном коде, при выборе пункта меню «Пункт меню 2», меню закроется без анимации:

PullDownMenu {
id: menu
MenuItem {
text: qsTr("Пункт меню 2")
onClicked: menu.close(true)
}
MenuItem {
text: qsTr("Пункт меню 1")
onClicked: console.log("Нажат первый пункт меню")
}
}




PushUpMenu



Еще один тип меню — PushUpMenu — представляет из себя то же самое PullDownMenu, с той лишь разницей, что появляется данное меню не сверху экрана, а снизу и, соответственно, активируется свайп жестом снизу вверх. PushUpMenu выглядит так же как и PullDownMenu и все его свойства и методы аналогичны таковым из PullDownMenu, поэтому в отдельном упоминании в данной статье они не нуждаются.



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



В коде такой пример будет выглядеть так:

Page {
id: page
SilicaListView {
PushUpMenu {
MenuItem {
text: qsTr("Пункт меню 3")
onClicked: console.log("Нажат третий пункт меню")
}
MenuItem {
text: qsTr("Пункт меню 2")
onClicked: console.log("Нажат второй пункт меню")
}
MenuItem {
text: qsTr("Пункт меню 1")
onClicked: console.log("Нажат первый пункт меню")
}
MenuLabel {
text: qsTr("Меню приложения")
}
}

id: listView
model: 20
anchors.fill: parent
header: PageHeader {
title: "Простой список"
}
delegate: BackgroundItem {
id: delegate
Label {
x: Theme.paddingLarge
text: "Элемент #" + index
anchors.verticalCenter: parent.verticalCenter
color: delegate.highlighted ? Theme.highlightColor : Theme.primaryColor
}
}
VerticalScrollDecorator {}
}
}


В результате, добраться до меню можно только если прокрутить весь список до конца:








ContextMenu



Последний тип меню в SailfishOS, который будет рассмотрен в данной статье, это контекстное меню. Оно реализуется с помощью компонента ContextMenu и представляет собой всплывающее меню, которое можно ассоциировать с каким-либо элементом пользовательского интерфейса. Содержимое такого меню описывается так же, как и для PushUpMenu и PullDownMenu, с помощью компонентов MenuItem и MenuLabel.



Чаще всего такие меню используются для реализации контекстного меню элементов списка. Для этого у компонента ListItem, который используется для описания делегатов списка, есть специальное свойство menu. Так можно добавить контекстное меню к элементам списка из последнего примера. Для этого придется немного изменить делегат, чтобы он был реализован через ListItem, и добавить к нему само меню:

delegate: ListItem {
id: delegate
Label {
id: label
x: Theme.paddingLarge
text: "Элемент #" + index
anchors.verticalCenter: parent.verticalCenter
color: delegate.highlighted ? Theme.highlightColor : Theme.primaryColor
}
menu: ContextMenu {
MenuLabel {
text: "Контекстное меню"
}
MenuItem {
text: "Выделить жирным"
onClicked: label.font.bold = !label.font.bold
}
MenuItem {
text: "Выделить курсивом"
onClicked: label.font.italic = !label.font.italic
}
}
}


Теперь, при долгом тапе по элементу списка, под ним появится контекстное меню:



При выборе пунктов данного меню изменится стиль текста элемента списка:








Контекстное меню закроется, если выбрать один из пунктов меню или просто тапнуть вне этого меню. Однако, компонент ListItem так же содержит методы hideMenu() и showMenu(), которые позволяют скрыть или показать контекстное меню вручную. Последнему методу можно в качестве параметра передать список свойств компонента ContextMenu, которые будут применены к меню (свойства компонента ContextMenu будут рассмотрены чуть позже). Кроме того, стандартное поведение для контекстного меню элемента списка можно изменить, установив свойству showMenuOnPressAndHold компонента ListItem значение false. В этом случае контекстное меню не будет появляться при долгом тапе по элементу. Наконец, узнать показано контекстное меню или нет можно с помощью свойства menuOpen компонента ListItem.



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

Page {
id: page
SilicaFlickable {
id: flickab
anchors.fill: parent
contentHeight: column.height

Column {
id: column

width: page.width
spacing: Theme.paddingLarge
PageHeader {
title: qsTr("Моё приложение")
}
Button {
id: button
text: "Нажми меня"
width: page.width
onClicked: contextMenu.show(label)
}
Label {
id: label
height: page.height / 2
text: "Просто текст"
verticalAlignment: Text.AlignBottom
}
}
ContextMenu {
id: contextMenu
MenuLabel {
text: "Контекстное меню"
}
MenuItem {
text: qsTr("Пункт меню 1")
onClicked: console.log("Нажат первый пункт меню")
}
}
}
}


Выглядит такая страница вот так:



А при нажатии на кнопку из нижнего края надписи выезжает меню:





Здесь нужно отметить, что высота надписи не случайно была сделана такой большой (в половину страницы). Дело в том, что контекстное меню показывается именно внутри компонента, указанного в методе show(), и если меню окажется больше этого элемента, то оно будет попросту обрезано. Для демонстрации данной особенности можно в примере выше у надписи сделать обычную высоту, а между кнопкой и надписью поместить белый прямоугольник:

Button {
id: button
text: "Нажми меня"
width: page.width
onClicked: contextMenu.show(label)
}
Rectangle {
color: "white"
height: page.height / 2
width: parent.width
}
Label {
id: label
text: "Просто текст"
}


Тогда страница будет выглядеть следующим образом:



А меню при открытии обрежется:





Закрыть контекстное меню можно с помощью метода hide(), а узнать открыто оно или нет с помощью свойства active. Кроме этого, компонент ContextMenu так же содержит свойство closeOnActivation, с помощью которого можно установить, должно ли закрываться меню при выборе какого-либо из его пунктов. А свойство hasContent поможет узнать, есть ли у меню какое-либо содержимое. Данное свойство используется и самой системой: если значение hasContent равно false, то меню не будет показано, даже при вызове метода show().



Наконец ContextMenu содержит обработчик сигнала onActivated(), который вызывается каждый раз, когда был выбран какой-либо пункт меню. Аргументом обработчика является индекс выбранного пункта меню.



На этом всё. В данной статье я описал 3 основных стандартных вида меню в SailfishOS, рассказал как их можно реализовать, а так же какие особенности имеются у каждого из типов.



Автор: Денис Лаурэ
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/308102/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Node.js и JavaScript вместо ветхого веба

Вторник, 23 Августа 2016 г. 09:20 (ссылка)

Вступление



Эта статья про экспериментальный технологический стек общего назначения. Она не просто дублирует мой доклад на конференции ОдессаJS 2016, но содержит все то, что в доклад не поместилось из-за недостатка времени и исключительного масштаба темы. Я даже перезаписал доклад голосом по тексту статьи и это можно послушать, а не читать. С этой темой я уже выступил в Уханьском Университете (Китай), а в Киевском Политехническом Институте провел целую серию семинаров в 2015-2016 годах. Основная идея состоит в том, что проблемы фрагментации технологий могут быть решены, если спроектировать весь технологический стек, сконцентрировавшись на структурах данных, синтаксисе и протоколе взаимодействия компонентов. Большинство вопросов несовместимости, отпадет само собой. Пусть даже этот подход будет альтернативным и экспериментальным, но его задача будет выполнена, если он наметит путь и продемонстрирует принципиальную возможность создания простого и элегантного решения общего назначения. Эта идея является естественным продолжением подхода Node.js, когда мы сокращаем количество языков и технологий в системе, разрабатывая и клиент и сервер на JavaScript. Несмотря на экспериментальность, протокол JSTP уже используется в коммерческих продуктах, например, для интерактивного телевидения компанией SinceTV, где позволяет подключить одновременно десятки миллионов пользователей. Это решение получило приз за инновации в области телевидения на международном конкурсе Golden Panda Awards 2015 в Ченду (Китай). Есть внедрения в сфере управления серверными кластерами, готовятся решения для медицины, интерактивных игр, электронной торговли и услуг.







Слайды: http://www.slideshare.net/tshemsedinov/metarhia-nodejs-macht-frei

Аудио версия: https://soundcloud.com/timurshemsedinov/nodejs-macht-frei



Выступление



Добрый день, меня зовут Тимур Шемсединов, я архитектор SinceTV, автор Impress Application Server для Node.js, научный сотрудник НИИ Системных Технологий и преподаватель КПИ. Сегодняшняя тема не столько про ноду, а скорее про развитие той идеи, которая легла в основу ноды.



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



Каждый шаг в вебе — это борьба, каждая минута — боль, каждая строчка — компромисс или заплатка. В интернете множество статей о том, что хаос захлестнул ветхий веб и хорошие специалисты тратят недели на простейшие задачи, как то — подвинуть кнопочку на 3 пикселя вверх или поймать блуждающий баг в зоопарке браузеров. Например статья с Медиума «I’m a web developer and I’ve been stuck with the simplest app for the last 10 days» переведенная на Хабре «Я веб-разработчик и уже 10 дней не могу написать простейшее приложение».



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



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



Представьте, что мы откажемся от HTTP, HTML, CSS, DOM, URL, XMLHttpRequest, AJAX, JSON, JSONP, XML, REST, Server-Sent Events, CORS, Cookie, MIME, WebSocket, localStorage, indexedDB, WebSQL, и всего остального, кроме одной вещи, мы оставим JavaScript и сделаем из него абсолютно все, что необходимо для разработки приложений. На первый взгляд это может показаться странным, но дальше я покажу, как мы это сделаем. Это будет целостный технологический стек на одном лишь JavaScript и вам это понравится. Мы конечно будем привлекать другие технологии для создания среды исполнения приложений, но от разработчика приложений все эти внутренности будут скрыты.



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



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



Эти системы должны быть:




  • распределенными (включающими в себя много клиентских терминальных устройств и много серверов),

  • высоконагруженными (потенциально масштабируемыми для работы с миллиардами одновременно подключенных пользовательских устройств),

  • интерактивными (поддерживающими двухстороннюю интерактивность, приближенную к реальному времени),

  • безопасными (одновременно анонимными и обеспечивающими достаточный уровень идентификации и доверия для отдельных операций),

  • гибко изменяющимися (модифицирующими экраны, функции и структуры данных на лету, без переустановки и перезапуска).



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




  • оконные и локально установленные приложения (для Linux, MacOS, Windows) с использованием AWT, SWING, WinForms, WPF, Qt и т.д.

  • мобильные приложения (iOS, Android, и другие)

  • веб-приложения, в том числе и адаптированные для мобильных версий браузеров

  • Progressive Web App (полноэкранные приложения запускаемые в скрытом браузере)

  • NW.js и Electron



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



Веб мог бы быть решением для кросплатформенности, но какой набор технологий мы имеем в ветхом вебе:



Начнем с HTTP. Думаю, ни для кого не секрет, что он блокирующий, т.е. через одно соединение, которое браузер установил, может быть одновременно отправлен только один запрос на сервер и соединение ждет, пока сервер ответит. Потому, что в HTTP нет нумерации запросов, просто обычной, примитивной, самой простой нумерации нет и открытое соединение ожидает. Ведь если послать второй запрос, то получив ответ, будет не ясно, это ответ на первый запрос или на второй. Не говоря уже про передачу ответа частями, которые смешались бы. Но при загрузке приложения нужно сделать много запросов и браузер устанавливает второе соединение для второго запроса, потом третье… В большинстве браузеров это число ограничено 6 одновременными соединениями, т.е. сделать больше параллельных запросов нельзя, ни для загрузки статики, ни для AJAX. Если конечно не соорудить костыль, создать множество поддоменов и разбрасывать запросы на поддомены, ведь ограничение на 6 соединений у браузера привязано именно к хосту. Но эти десятки и сотни соединений неэффективно используют сеть.



Вообще TCP предполагает надежную доставку и долгосрочное взаимодействие, но HTTP разрывает связь очень часто, он просто не умеет эффективно переиспользовать уже установленные соединения и постоянно их разрывает и создает новые. Есть конечно Keep Alive, но мало того, чтобы он был специфицирован, его должны поддерживать веб-сервер, браузер, и разработчики должны о нем знать, правильно формировать заголовки и обрабатывать их. Обычно чего-то не хватает, то админ без руки, то разработчики не слышали про такую возможность, да и браузеры имеют особенности, как оказалось, и Keep Alive работает очень не эффективно, из-за отхода от спецификации сервер часто не может договориться с браузером и соединение не переходит в Keep Alive режим. Я об этом уже делал доклад и писал статью год назад "Как исправить ошибку в Node.js и нечаянно поднять производительность в 2 раза" https://habrahabr.ru/post/264851/ Поведение HTTP можно проследить в средствах для разработчика, которые есть в браузере. Оптимизация в HTTP это отдельная задача, из коробки ее нет да и всем безразлично.



Установление TCP соединения это тяжелая задача, она дольше, чем передача информации по уже открытому сокету. А в добавок к TCP, при установлении новых соединений HTTP повторно присылает заголовки, в том числе cookie. А мы знаем, что заголовки HTTP не жмутся gzip, вместе с cookie в крупных проектах ходят десятки и сотни килобайт заголовков. Каждый раз, а у беззаботных людей еще и статика вся гетается с отправкой cookie в каждом запросе. Всем же безразлично.



У HTTP очень много проблем, их пробовали решать при помощи Websocket, SSE, SPDY, HTTP/2, QUIC но все они зависят от бесчисленного множества вещей, которые достались в наследство от ветхого веба и ни одна из этих технологий не достигла ни приемлемых характеристик, ни широкой поддержки. Уплотнить уже имеющийся трафик, сделать мультиплексацию внутри другого транспорта можно, но структура трафика не изменится, это будут все те же HTML, AJAX, JSON, ведь задача стояла, починить транспорт так, чтобы ничего не сломалось и чрез него продолжали ходить все те же приложения. А вот не достигнута цель, все сложно, не внедряется это массово и прирост в скорости не очень ощутим при внедрении. Кардинально и комплексно ни кто не пробовал решить проблему.



Для игр, мессенджеров и других интерактивных приложений сейчас есть только один живой вариант — это Websocket, но этот слоеный пирог из протоколов достиг предела. IP пакетный, на его основе TCP потоковый с установлением долгих соединений, сверху HTTP — он опять пакетный с постоянным отключением и поверху Websocket — и он потоковый, с долгими соединениями. А еще все это через SSL может идти. И каждый слой добавляет свои заголовки и преобразовывает данные, особенно при переходе от пакетного к потоковому и от потокового к пакетному. Это похоже на издевательство, честное слово.



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



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



HTML это конечно прекрасный язык для разметки страниц, но менее всего приспособленный для сложных пользовательских графических интерфейсов. Скорость работы DOM и отсутствие транзакционности в изменении интерфейсов приводят к залипанию веб-приложений. Сложно придумать что-то более избыточное и медленное для представления пользовательских интерфейсов в памяти и динамической модификации экранов. Это решается в Shadow DOM, React, Angular, Web components но проблем все еще больше, чем решений.



Еще немного про масштабирование. REST, который обещал всем прозрачное решение, вместо этого забрал возможность работать с состоянием, и не сделал обещанного. Мы имеем ситуацию, когда ни кто не использует REST, да ладно, мало кто понимает, что это, но все говорят, что у них REST API. URLы идентифицируют объекты или методы? PUT, PATCH и DELETE используются? Последовательность вызовов API не важна? У кого через REST работают платежи, корзина, чат, напоминания? В основном у всех AJAX API, которое так и нужно называть. А проблема с масштабирование как была, так и решается каждый раз заново.



Проблем слишком много для того, чтобы вдаваться дальше в подробности, давайте кратким списком теперь подытожим основные:




  • Платформы для прикладных программных систем фрагментированы

  • Архаичные веб технологии уже нас не удовлетворяют

  • Фреймворки и инструменты тотально нестабильны и несовместимы

  • Протоколы ветхого веба имеют большую избыточность и убивают производительность ваших серверов

  • Сплошные проблемы безопасности и заплатки



В результате наше ПО быстро устаревает, мы получаем постоянные проблемы с интеграцией систем. Мы не имеем возможности использовать наши наработки, переиспользование кода крайне усложнено, мы обречены на сизифов труд, постоянно переделывать одно и то же.



Что же нам нужно:




  • Среда исполнения приложений для серверов

  • Среда исполнения приложений для пользовательских компьютеров

  • Среда исполнения приложений для мобильных устройств

  • Межпроцессовое взаимодействие по принципам RPC и MQ с поддержкой интроспекции, потоков событий и потоковой передачи двоичных данных

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

  • Новые соглашения по именованию и идентификации данных и пользователей



Это уже не сеть веб-страниц, а сеть приложений и баз данных.

И теперь я покажу, что это возможно. Не утверждаю, что нужно делать именно так, но принципиальную возможность на прототипе наша команда продемонстрирует.



Metarhia — это новый технологический стек, который:




  • экспериментальный (только для демонстрации нового подхода),

  • альтернативный (не должен заботиться о совместимости),

  • в открытом коде (можно свободно распространять и бесплатно применять даже в коммерческих проектах, можно участвовать в разработке и отправлять запросы на доработку в сообщество).



Теперь давайте ближе к JavaScript, у него же есть прекрасный синтаксис описания структур данных, включающий хеши, массивы, скалярные величины, функции и выражения. А нам нужен универсальный сетевой протокол, который бы соответствовал структурам данных языка и исключал бы излишнюю перепаковку данных. Нам нужен сквозной протокол и он же формат сериализации, один на весь стек технологий, в базе данных, в памяти клиента, в памяти сервера и при передаче между процессами. Так зачем же нам JSON, XML, YAML и прочие, если таким форматом может быть подмножество языка JavaScript. При этом мы не выдумываем ни какого стандарта, ни какой формальной граматики, у нас уже есть все. По большому счету, заготовки для парсеров уже реализованы на всех языках и платформах. Более того, если мы возьмем V8 и заставим его быть парсером сетевых пакетов, то получим статистическую оптимизацию, скрытые классы и на порядок более быстрый парсинг, чем JSON. Тесты производительности я опубликую позже, чтобы не перегружать этот, и так объемный, доклад.



Пусть протокол станет центральным стержнем, на который цепляются все компоненты системы. Но протокола мало, нам нужна среда запуска, как клиентская, так и серверная. Развивая идеи Node.js, мы хотим, чтобы не только язык, но и среда запуска была почти идентичной на сервере и на клиенте. Одинаковое API, которое дает возможность обращаться к функциям платформы, например к сети, файловой системе, устройствам ввода/вывода. Конечно же, это API не должно быть бесконтрольно доступным приложениям, а обязано иметь ограничения безопасности. Область памяти и файловая система должны быть виртуальными, замкнутыми песочницами, не имеющими сообщения с остальной средой запуска. Все библиотеки должны подгружаться не самими программами, а внедряться средой запуска как DI через инверсию управления (IOC). Права приложений должны быть контролируемы, но не должна происходить эскалация управления до пользователя, потому, что он не способен принять адекватного решения по правам доступа. Пользователь склонен или запрещать все, руководствуясь паранойей или разрешать все, руководствуясь беспечностью.



Еще нам нужна СУБД, которая будет хранить данные в том же формате JavaScript. Нам нужен язык описания моделей (или схем) данных. Нам нужен язык запросов к структурам данных. В качестве синтаксиса этих двух языков запросов мы можем взять тот же синтаксис JavaScript. И в конце концов нам нужен язык описания интерфейсов двух видов, сетевых интерфейсов API и пользовательских интерфейсов GUI. Подмножество того же JavaScript прекрасно нам подходит для обоих целей.



Теперь можем перечислить компоненты технологического стека Metarhia:




  • JSTP — JavaScript Transfer Protocol

  • Impress Application Server — сервер приложений, серверная среда исполнения

  • GS — Global Storage — глобально распределенная система управления базами данных

  • Console — браузер приложений, тонкий клиент или среда исполнения приложений



JavaScript Transfer Protocol это не только формат представления данных, но и протокол, который имеет специальные конструкции, заголовки, пакеты, разделители, в общем, все то, что обеспечивает реализацию прозрачного для приложений взаимодействия по сети. JSTP объединяет клиентскую и серверную часть так, что они становятся одним цельным приложением. Можно расшаривать интерфейсы и делать вызовы функций совершенно так же, как если бы функции находились локально. С единственным ограничением, что локально функции могут быть синхронные и асинхронные, а расшаренные по по сети функции всегда асинхронные, т.е. возвращают данные не через return, а через callback, который принимают последним аргументом, как это принято в JavaScript. Так же JSTP поддерживает трансляцию событий по сети, обернутую в сетевой аналог EventEmitter. У JSTP много возможностей, но сейчас приведу только основные его особенности и преимущества:




  • Встроенная поддержка интерактивности (поддержка событийно-ориентированного взаимодействия),

  • Простой и понятный известный всем формат (не нужно придумывать еще одного стандарта сериализации),

  • Асинхронность вызовов (не блокирующий принцип использования одного соединения с мультиплексацией),

  • Двунаправленное взаимодействие, максимально приближенное к реальному времени,

  • Реактивный принцип взаимодействия (код в реактивном стиле может быть распределенным),

  • Оптимизация парсинга сетевых пакетов при помощи механизма скрытых классов V8,

  • Использованием метаданных, моделей (схем данных), интроспекции и скаффолдинга.



Теперь подробнее о последнем пункте. Метаданные позволят нам не только сделать систему гибче, но и оптимизировать ее еще дополнительно, кроме того, что мы уже используем оптимизацию V8 для парсинга JSTP. В большинстве форматов сериализации имена полей тоже передаются, в JSON они занимают по грубым оценкам от 20% до 40% от всего объема передаваемых данных, в XML этот процент гораздо выше половины. Имена полей нужны только для мнимой человекочитаемости, хотя как часто люди читают XML или JSON? Для JSTP есть два варианта сериализации, это полная форма и сокращенная, построенная на базе массивов с позиционных хранением ключей. Другими словами, мы один раз передаем схему, имена полей, их типы, другие вспомогательные метаданные из которых на клиенте строим прототип. Потом мы получаем множество экземпляров объектов, сериализованных в массивы, т.е. имена полей не передаются, а структура массива позиционно соответствует структуре прототипа, у которого определены геттеры и сеттеры. Мы просто присваиваем массиву прототип, он остается массивом, но мы можем работать с этим экземпляром, через имена полей.



Скаффолдинг и интроспекция применяется при построении прозрачного соединения между клиентом и сервером (и вообще между любыми процессами, двумя серверами или двумя клиентами). При подключении мы забираем метаданные, описывающие расшаренные интерфейсы с методами и их параметрами и строим на противоположной стороне прокси, структурно повторяющие удаленное API. Такой прокси можно использовать локально, работая на самом деле с удаленным интерфейсом. Для работы с предметной областью применяется метапрограммирование и динамическая интерпретация метамоделей, о чем я уже делал много статей и докладов (еще за 2014 год и даже за 2012 год), но обязательно подготовлю материалы о метапрограммировании в новом технологическом стеке.



Теперь становятся понятными основные идеи технологического стека Metarhia и JSTP, как его базовой составляющей:




  • Фокус на структурах данных, а не на алгоритмах,

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



Как говорит Линус Торвальдс: "Плохие программисты беспокоиться о коде. Хорошие программисты беспокоиться о структурах данных". А Эрик Рэймонд выразил это еще точнее "Умные структуры данных и тупой код работают куда лучше, чем наоборот".



Теперь короткие примеры JSTP:




  • Сериализация структуры данных: { name: 'Marcus Aurelius', birth: '1990-02-15' }

  • Полная сериализация объекта: { name: 'Marcus Aurelius', birth: '1990-02-15', age: () => {...} }

  • Метаданные: { name: 'string', birth: '[Date]' }

  • Краткая позиционная сериализация: ['Marcus Aurelius','1990-02-15']

  • Сетевой пакет: { call: [17, 'interface'], method: ['Marcus Aurelius', '1990-02-15' ] }



Сравним описание одних и тех же данных на XML, CLEAR, JSON и JSTP:



Пример XML




Seatingsnone
OK

Flap01open
OK

Flap02closed
overload

Jointdetach
OK




Пример CLEAR
1: PT004:OilPump Displacement[constant] Value[63] Control[automatic] Status[working]
2: #FlowMeter Substance[fluid] Recording[off] Role[master] Period[00:30] DataOutput[Parent.FT002.Verification]
2: #Outlet Pressure[180] Status[working]
2: #FailureSensors:Table [Module,Indication,Status]
3: [Seatings,none,OK]
3: [Flap01,open,OK]
3: [Flap02,closed,overload]
3: [Joint,detach,OK]


Пример JSON
{
"name": "PT004",
"type": "OilPump",
"displacement": "constant",
"value": 63,
"control": "automatic",
"status":"working",
"flowMeter": {
"substance": "fluid",
"recording": "off",
"role": "master",
"period": "00:30",
"dataOutput": "Parent.FT002.Verification"
},
"outlet": {
"pressure": 180,
"status": "working",
"failureSensors": [
["Module", "Indication", "Status"],
["Seatings", "none", "OK"],
["Flap01", "open", "OK"],
["Flap02", "closed", "overload"],
["Joint", "detach", "OK"]
]
}
}


Пример JSTP
{
name: "PT004",
type: "OilPump",
displacement: "constant",
value: 63,
control: "automatic",
status:"working",
flowMeter: {
substance: "fluid",
recording: "off",
role: "master",
period: "00:30",
dataOutput: "Parent.FT002.Verification",
},
outlet: {
pressure: 180,
status: "working",
failureSensors: [
["Module", "Indication", "Status"],
["Seatings", "none", "OK"],
["Flap01", "open", "OK"],
["Flap02", "closed", "overload"],
["Joint", "detach", "OK"]
]
}
}


Пример JSTP минимизированный с применением схемы данных:



["PT004","OilPump","constant",63,"automatic","working",
["fluid","off","master","00:30","Parent.FT002.Verification"],
[180,"working",[["Module","Indication","Status"],
["Seatings","none","OK"],["Flap01","open","OK"],
["Flap02","closed","overload"], ["Joint","detach","OK"]]]]


А теперь внимание, самый простой парсер JSTP на Node.js выглядит так:



api.jstp.parse = (s) => {
let sandbox = api.vm.createContext({});
let js = api.vm.createScript('(' + s + ')');
return js.runInNewContext(sandbox);
};


всего 5 строк, а его использование простое и очевидное:



api.fs.readFile('./person.record', (e, s) => {
let person = api.jstp.parse(s);
console.dir(person);
});


Теперь посмотрим более сложный пример JSTP, имеющий функции и выражения:



{
name: ['Marcus', 'Aurelius'].join(' '),
passport: 'AE' + '127095',
birth: {
date: new Date('1990-02-15'),
place: 'Rome'
},
age: () => {
var difference = new Date() - birth.date;
return Math.floor(difference / 31536000000);
},
address: {
country: 'Ukraine',
city: 'Kiev',
zip: '03056',
street: 'Pobedy',
building: '37',
floor: '1',
room: '158'
}
}


Как видно, функции могут обращаться к полям самого объекта, но для этого нужно немного модифицировать парсер:



api.jstp.parse = (s) => {
let sandbox = vm.createContext({});
let js = vm.createScript('(' + s + ')');
let exported = js.runInNewContext(sandbox);
for (let key in exported) {
sandbox[key] = exported[key];
}
return exported;
};


Моя команда разработчиков и независимые разработчики готовят сейчас JSTP SDK для более чем десятка языков, а для некоторых есть уже несколько альтернативных реализаций. Тестирование функциональности и производительности JSTP мы проведем в ближайшее время. На странице спецификации внизу есть собранные ссылки, но не все, ссылки будут обновляться: https://github.com/metarhia/JSTP



Сейчас есть такие реализации:




  • JavaScript для Browserа

  • JavaScript для Node.js и Impress Application Server

  • C and C++ for STL and Qt

  • Swift and Objective-C for iOS

  • Java for Android and JavaEE

  • C# for .NET

  • Python, Haskell, PHP, GoLang



Ссылки





Заключение



А в следующий раз я расскажу про другие компоненты стека технологий. Несмотря на кажущуюся простоту решений, сделать еще нужно очень много. Я обещаю периодически публиковать результаты и проводить тесты по нагрузкам и надежности, сравнение с аналогами по функциональности и эффективности. Пока я не могу рекомендовать все это к массовому внедрению, но зимой 2016-2017 мы выпустим SDK с примерами. Над этим трудится несколько десятков человек в специально созданном R&D центре в Киевском Политехническом Институте при поддержке SinceTV. Если Вы будете следить за проектом, то надеюсь, что он еще Вам пригодится. Даже частичное внедрение уже дало свои результаты. Спасибо за Ваше внимание.





Насколько Вам интересна эта технология?
















































Проголосовал 1 человек. Воздержавшихся нет.





Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306584/

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Интегрируйся или умри! Первый маркетплейс околоресторанных сервисов в СНГ

Понедельник, 22 Августа 2016 г. 11:53 (ссылка)

Привет, Хабр! Меня зовут Родион, я соучредитель компании Poster POS. Это облачная система автоматизации на планшете (point-of-sale за рубежом, касса — у нас).



Мы уже рассказывали о том, как все начиналось и как Poster стали одним из самых больших игроков среди облачных POS-систем в СНГ. Cейчас мы хотим попробовать развить всю SaaS-отрасль для такого консервативного рынка как HoReCa, в целом. И без ваших крутых толковых проектов тут не обойтись.



Но обо всем по порядку. Прошу под кат.



Рынок HoReCa очень интересный. Сейчас он активно реформируется. С одной стороны кризис, который уводит с рынка огромные неповоротливые компании, открытые в 90-е на сомнительные деньги, и на их место приводит молодые стартапы. С другой стороны — государство пытается отбелить бизнес, вводит для этого обязательную фискализацию или придумывает такие неоднозначные вещи как ЕГАИС, подталкивая тем самым бизнес все больше и больше к автоматизации.







Тем не менее, HoReCa остается одним из самых консервативных рынков, на котором немногим удается научиться работать и удержаться. За последние пять лет я видел огромное количество стартапов, которые решают задачи предзаказа, лояльности, доставки, аналитики и т.д., но только несколько из них смогли достичь отметки в 100 платных клиентов.



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



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







Для нас Маркетплейс — это возможность значительно расширить свой функционал и помочь нашим клиентам, кафе, ресторанам и магазинам, быстро подключить сторонние сервисы. Для IT-стартапов — это аудитория в 5000+ заведений, которая увеличивается каждый день и на которую они могут выйти в считанные дни, используя наш API.



iPhone никогда не стал бы iPhone, если бы Apple не запустил AppStore. Android бы никогда не догнал Apple, если бы не армия крутых разработчиков, создающих великолепные приложения в Google Play.



Мы хотим объединить усилия десятков классных существующих проектов, которые борются за выживание на этом рынке. Давайте попробуем изменить эту закостенелую отрасль вместе. Я уверен, что это даст толчок для многих новых IT-стартапов, которые только вынашивают гениальные идеи для решения тех или иных проблем рестораторов, но у которых нет аудитории, готовой все это тестировать. Теперь у вас есть эта возможность.



Более того, чтобы максимально упростить интеграцию для проектов, которые делают электронное меню, предзаказы, бронирование, конструкторы сайтов, мы запустили очень простой API, который дает возможность отправить заказ в Poster. Это делается буквально несколькими запросами к API и интеграцию можно сделать очень быстро. На видео ниже видно, как один из наших продуктов отправляет заказ в Poster, с которым дальше может работать кассир или официант:









Итог



Мы ищем проекты или стартапы, которым интересно получить доступ к 5000+ заведениям ресторанного бизнеса. Тех, кто не хочет оставаться в стороне, самостоятельно пытаясь решить общие проблемы продаж и поиска клиентов. Мы ищем реформаторов, которые хотят изменить рынок.



Мы готовы предоставить API, а для перспективных проектов — отдельного специалиста в помощь. Сейчас API еще в процессе разработки, мы постоянно добавляем новые функции. У вас есть возможность участвовать в приоритете их внедрения. В четвертом квартале мы планируем добавить поддержку REST API.



Если у вас уже есть готовый проект — пишите мне на yeroshek@joinposter.com. Если у вас нет проекта — хватит читать комментарии, у вас есть великолепная возможность поучаствовать в создании чего-то крутого :)
Original source: habrahabr.ru.

https://habrahabr.ru/post/305980/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<разработка мобильных приложений - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda