В этой статье я хотел бы рассказать о замечательном событии, произошедшем с 27 по 30 июля – летней школе Sailfish OS, организованной «открытой мобильной платформой» при поддержке университета Иннополис. Если вам интересна перспектива развития Sailfish OS, настоящего Linux на смартфонах или просто интересна еще одна сфера применения QML/C++ — прошу под хабракат.







Прежде всего хотел бы сказать, что для меня эта история с Sailfish OS началась 1 апреля 2016 года. Не шучу, именно в этот день я получил свой долгожданный Jolla на руки. И понеслось… Копание в ОС, чтение руководств, публикация пары статей на geektimes и первого собственного приложения в официальном магазине.

Однажды, сидя дома, читая Хабр, увидел пост-аннонс о Летней Школе Sailfish OS и сразу решил, что я должен там быть. Через пару недель я уже стоял в г. Иннополис на их главной улице – Университетской.


Картинки кликабельны.

Что это было за место! Что за сообщество разработчиков! Это было невероятно! Кхм… Ладно, отбросим эмоции, давайте по порядку.

27 июля


Это был день знакомств, день вступительных речей, день размещения…



Поселили участников в комфортабельные комнаты на двоих:



В комнатах было все необходимое для небольших перерывов между «порциями» кодинга: кровати, душ, кондиционер, стол. Единственное, в моей комнате было 4 тумбочки на двоих и ноль(!) стульев, я думаю, что Вы догадались как мы использовали 2 «лишние» тумбочки.

Почему не было стульев
Как нам объяснил представитель университета Иннополис, что этот кампус еще не до конца готов для студентов. Хм, а я бы пожил в таком «недострое».

С соседом мне особенно повезло, я жил со всеми уважаемым, повелителем патчей для Sailfish OS, Андреем Кожевниковым, более известным под ником CodeRus. У Sailfish OS как раз небольшая проблемка с документацией, в частности с ее структурой и недостаточным покрытием некоторых деталей и тут меня поселили с ходячей базой знаний по Sailfish OS, надеюсь, что моя радость на тот момент понятна? :) Спасибо, Андрей, за все исчерпывающие ответы на мои вопросы.

К 15.00 все собрались в аудитории №307, где мы фактически и обитали следующие 48 часов.



Мы слушали вступительные речи, общие слова о Sailfish OS, её перспективах в России, о роли «Открытой Мобильной Платформы». Ректор позвал учиться в Иннополис.

Потом выступали партнеры:

Александр КиселёвВстраивание решений VipNet в Sailfish OS. Говорят, что очень востребованное решение для корпоративного рынка.

Георгий МартиросовБезопасный браузер Спутник. Интересно получилось, делали поиск, а в итоге делают браузер… Что же, лично я буду не против, если на Sailfish OS появится конкурент стандартному браузеру.

Егор Левичев, Александр СержантовActive Sync на платформе Sailfish OS. Очень интересные ребята. Насчет качества реализации, слышал от пользователей, что очень стабильно работает, жрет мало батарейку, все интегрировано в систему, нативно и «пользователи Android завидуют».

Пётр БарбанягаМобильный платёжный кассовый терминал (Sailfish OS).

Вечером нас повели на экскурсию по городу Иннополис:





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

28 — 29 июля


С этого дня напряжение начинает нарастать в геометрической прогрессии!



С 09.00 начались лекции, перед нами выступали:

Кирилл Чувилин (представитель «Открытой Мобильной Платформы» по связям с сообществом, основатель MaemoWorld.ru) – Обзор Sailfish OS SDK + Мастер-класс разработки графического интерфейса приложения для Sailfish OS. Он рассказывал про особенности SDK, про то, как делать правильно интерфейсы для Sailfish OS, так как ОС выгодно отличается от других: почти все здесь выполняется свайпами, а не нажатием на экран, что требует некой сноровки от разработчика.

Андрей Васильев (представитель FRUCT) – Мастер-класс по работа с основным API Sailfish OS. Это был интересный доклад о том, как «дергать» GPS, управлять различными датчиками, воспроизводить звуки, фотографировать.

Павел Горянский (представитель «Открытой Мобильной Платформы») – аппаратная адаптация Sailfish OS. Павел рассказывал о том, как «завести» Sailfish OS на не поддерживаемых устройствах, что для этого нужно и т. д.

Андрей Кожевников (aka CodeRus, представитель сообщества) – сколько волка ни корми, он в лес смотрит мастер-класс по модификации Sailfish OS. О, это был очень занимательное выступление, на тему «как из Sailfish OS сделать MyOwn OS». Серьезно, благодаря QML можно почти полностью переписать интерфейс оригинала под себя! Надеюсь, что в будущем Андрей осветит эту тему лично, так как она достойна отдельной статьи.

Петр Вытовтов (aka Osanwe, разработчик нативного клиента для Vkontakte и анализатора Wi-Fi сетей, представитель сообщества) — мастер-класс по работе с сервисами распознавания речи. Проинформировал как можно использовать Yandex Speechkit на Sailfish OS.

Алексей Андреев (победитель хакатона Sailfish OS в Санкт-Петербурге, участник semiot.ru ) – мастер-класс по работе с IoT-устройствами. Было приятно встретить «родственную душу» — человека, который тоже занимается Semantic Web.

В 19.30 начались презентации идей для хакатона, в конечно итоге жизнеспособными оказались следующие проекты:
FriendlyARM порт — проект по адаптации Sailfish OS на плату для разработчиков;
MyFirstProgram — инструментарий для взаимодействия смартфонов и роботехнических конструкторов, таких как ТРИК и Lego NXT;
Battery Stats — утилита для наблюдения за расходом аккумулятора;
GEO-location share — обмен данными о местоположении между устройствами;
Guitar Tuner — настройщик для гитары;
CryptoFish — шифрование файлов по паролю;
Suburban Trains — расписание электричек, основанное на данных Яндекса;
Погода — информация о погоде с учётом местоположения;
Killer — ролевая игра по мотивам психологической игры «Киллер»;
AppCleaner — удаление ненужных данных и приложений;
WatchFox — шифрование домашнего раздела пользователя;
CryptoContainer — защищённое хранение файлов в контейнере;
Timelapse — приложение для интервальной съемки фото и видео.

Да, нынче модны темы с приставкой «крипто», а если серьезно, многих волновала тема безопасности.

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

— Выбор жертвы происходит на сервере (в команде был один из создателей «Killer» под android, поэтому сервер уже был готов);
— Запросы и авторизация в Vkontakte для получения фотографии и имени жертвы;
— «Убийство» «жертвы» с помощью «выстрела» по Bluetooth;
— с помощью GPS программа указывает жертву на Google Maps;
— демон для отслеживания местоположения игрока.

В общем, планы были большие…

Что у нас получилось или как мы не выиграли хакатон, но приобрели огромный опыт


В своей команде я был ответственен за UI, поэтому часть статьи будет посвящена именно ему. Первом делом набросали примерный образ всех страниц (так в Sailfish OS называется каждое «окно») и способы переходов между ними:



Первое испытание началось со страницы выбора жертвы, для этого лучше всего подходил компонент Dialog, оказывается, что разработчики фреймворка Silica не предполагали, что страница с Dialog будет первой страницей приложения и из-за этого Cancel (свайп слева направо работал и выглядел не совсем корректно). Поэтому пришлось схитрить: первой страницей будет пустая страница, с которой будет быстрый переход на DialogPage (пустая страница прорисовывается очень быстро, поэтому пользователю такая «обман» не будет виден).



Исходный код первой страницы:

?import QtQuick 2.0
import Sailfish.Silica 1.0
import "../js/server_request.js" as ServerRequest

Dialog {
    id: dialogFirstPage
    property string name: "Вася"
    property string surname: "Пупкин"
    property string imagePath: "../images/avatarUnknown.png"
    property string uniqueKey: "Waiting..."

    onAccepted: {
        console.log("accepted")

        // Открываем новую страницу и передаем несколько переменных
        pageStack.push(Qt.resolvedUrl("SecondPage.qml"), { "name": name, "surname": surname, "imagePath": imagePath, "uniqueKey": uniqueKey}, PageStackAction.Animated)
    }
    onRejected: {
        console.log("declined")

	// Опять открываем эту же страницу
        pageStack.push(Qt.resolvedUrl("FirstPage.qml"), {}, PageStackAction.Immediate)

	// Делаем запрос к серверу, чтобы получить новую "жертву"
	ServerRequest.server_getNextRandomTargetId("34853940", callback_getNextRandomTargetId)  
    }

    function callback_getNextRandomTargetId(responseText) {
        uniqueKey = responseText;
    }
	
    Column {
        anchors.fill: parent

        DialogHeader {
            acceptText: "Accept"
            cancelText: "Cancel"
        }

        Text {
            id: victimText
            width: parent.width
            horizontalAlignment: Text.Center
            color: Theme.highlightColor
            font.bold: true
            wrapMode: Text.Wrap
            font.pixelSize: Theme.fontSizeExtraLarge
            text: "Choose new victim:"
        }

        Image {
            id: avatar
            source: imagePath
            anchors.horizontalCenter: parent.horizontalCenter
            width: 400
            height: 400
        }

        Text {
            id: nameText
            width: parent.width
            horizontalAlignment: Text.Center
            color: Theme.highlightColor
            font.bold: false
            wrapMode: Text.Wrap
            font.pixelSize: Theme.fontSizeExtraLarge
            text: name
        }
        Text {
            id: surnameText
            width: parent.width
            horizontalAlignment: Text.Center
            color: Theme.highlightColor
            font.bold: false
            wrapMode: Text.Wrap
            font.pixelSize: Theme.fontSizeExtraLarge
            text: surname
        }

        Text {
            id: keyText
            width: parent.width
            horizontalAlignment: Text.Center
            color: Theme.highlightColor
            font.bold: false
            wrapMode: Text.Wrap
            font.pixelSize: Theme.fontSizeExtraLarge
            text: "Victim code:\n" + uniqueKey
        }
    }
}

Исходный код «хитрости»:

?import QtQuick 2.0
import Sailfish.Silica 1.0
import "pages"

ApplicationWindow
{
    // Если пользователь авторизировался, то загружаем FirstEmptyPage.qml (функция проверки пока не написана, поэтому эта страница будет всегда загружаться):
    initialPage: true ? Qt.createComponent(Qt.resolvedUrl("pages/FirstEmptyPage.qml")) : Qt.createComponent(Qt.resolvedUrl("pages/LoginPage.qml"))
    cover: Qt.resolvedUrl("cover/CoverPage.qml")
    allowedOrientations: Orientation.All
    _defaultPageOrientations: Orientation.All

    // После того как страница полностью подгрузилась открываем сразу нашу настоящую первую страницу:
    Component.onCompleted: {
        // immediate -> без анимации
        pageStack.push(Qt.resolvedUrl("pages/FirstPage.qml"), {}, PageStackAction.Immediate)
    }
}

Дальше все пошло легче, авторизацию в Vkontakte сделал с помощью WebView.

?import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import Sailfish.Silica 1.0
import "../js/auth.js" as AuthJS
import "../js/storage.js" as StorageJS

Dialog {
    id: loginPage

    function checkUrl(url) {
        if (AuthJS.checkUrl(url) !== 1) {
            console.log(AuthJS.accessToken)
            StorageJS.storeSettingsValue("access_token", AuthJS.accessToken)
            StorageJS.storeSettingsValue("user_id", AuthJS.userId)
            loginView.stop()
            loginPage.close()
        }
    }

    SilicaWebView {
        id: loginView
        anchors.fill: parent
        url: "https://oauth.vk.com/authorize?" +
             "client_id=4803503" +
             "&scope=messages,video,wall,audio,friends,photos,offline" +
             "&redirect_uri=https://oauth.vk.com/blank.html" +
             "&display=mobile" +
             "&response_type=token"

        onUrlChanged: checkUrl(url)
    }
}

В реализации WebView очень помог код из клиента для VK – Kat. Спасибо автору за замечательное приложение!

Затем на очереди, была страница «Wanted», по содержанию она во многом похожа на DialogPage, но используется компонент PullDownMenu для открытия карты и PullUpMenu для «убийства». Использование PullDownMenu и PullUpMenu:

?import QtQuick 2.0
import Sailfish.Silica 1.0

Page {
    // ...

    // PullDownMenu и PushUpMenu можно использовать только в SilicaFlickable, SilicaListView или SilicaGridView
    SilicaFlickable {
        anchors.fill: parent

        PullDownMenu {
            // Разукрашиваем меню:
            backgroundColor: "green"
            highlightColor: backgroundColor
            // При свайпе сразу будет выбираться option:
            quickSelect: true

            MenuItem {
                text: "Open map"
                onClicked: {
                    console.log(qsTr("Option <Open map> clicked"))
                    pageStack.push(Qt.resolvedUrl("MapPage.qml"))
                }
            }
        }

        contentHeight: column.height

        Column {
            // ...
        }

        PushUpMenu {
            backgroundColor: "red"
            highlightColor: backgroundColor
            quickSelect: true

            MenuItem {
                text: "Kill!"
                onClicked: {
                    console.log(qsTr("Option <Kill!> clicked"))
                    pageStack.push(Qt.resolvedUrl("EnterCodePage.qml"), {"uniqueKey": uniqueKey})
                }
            }
        }

    }
}




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


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

Таким образом, к концу хакатона мы не успели сделать:

— Запросы в Vkontakte для получения фотографии и имени жертвы;
— «Убийство» «жертвы» с помощью «выстрела» по Bluetooth;
— демон для отслеживания местоположения игрока.

А также провели не самую лучшую презентацию приложения… Но у нас был UI, которым, по крайней мере, лично я реально гордился (хоть он был и с небольшими багами…). Это был колоссальный шаг вперед для меня. До поездки я мог создавать только 1-2 страничное приложение с очень примитивной логикой, к примеру приложение «Chance.»:


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

29 июля. Вечер


После завершения хакатона повезли в боулинг-клуб, где всех нас ждал банкет, общение и награждение. После боулинга мы долго не шли спать, обсуждали итоги хакатона, размышляли о Sailfish OS, говорили по душам.

30 июля


Сразу после завтрака организаторы обсудили с участниками пожелания и идеи для развития Sailfish OS. Потом, на прощание, «вывезли в люди» — организовали экскурсию на остров-город Свияжск. После реально отличной экскурсии пришла пора прощаться – Летняя Школа Sailfish OS подошла к концу.

Заключение


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



Бонус №1


Пара советов для тех, кто еще не участвовал в хакатонах:

— Продумывайте и делайте презентации своих идей/творений как можно качественнее и выступайте эффектней. От этого действительно(!) зависит многое;

— Четко сформулируйте для себя и аудитории задачу минимум и максимум.

Бонус №2


Видео всех выступлений.

Полезные ссылки


» Ссылка на группу в ВК.
» Чат разработчиков в телеграм.
» Timelapse
» Suburban Trains

P.S. Спасибо моим друзьям за первые отзывы и корректуру данной статьи.

UPD: Хотелось бы добавить, что не следует воспринимать опубликованный в этой статье код строго, он был написан на хакатоне и опубликован с небольшими правками, само приложение будет развиваться, очень медленно, но будет. Так что не ругайте сильно :)
Поделиться с друзьями
-->

Комментарии (10)


  1. Segmentq
    16.08.2016 11:46

    Честно? Не впечатлился как-то… Особенно браузером Спутник.


    1. kirikch
      16.08.2016 12:55

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


      1. kirikch
        16.08.2016 13:00

        Или ActiveSync, который интегрируется в систему и не жрёт батарейку, в отличие от аналога, поставляемого с Android.
        Меня вот они впечатлили.


        1. Segmentq
          16.08.2016 13:33

          А что мешает сделать тоже самое под Android?


          1. kirikch
            16.08.2016 14:15

            Не знаю. Быть может, архитектура ОС.
            Но ситуация такая, какая есть.


            1. Segmentq
              16.08.2016 14:40
              -1

              Вот поэтому и не впечатляет…


  1. GoAlexander
    16.08.2016 12:19

    Уважаемые хабровчане, подскажите, пожалуйста, как перевернуть картинку на хабре?


  1. TreyLav
    17.08.2016 11:22

    Когда-то я менял менял телефон и смотрел на Jolla, но SailfishOS явно была еще не готова.
    Когда я последний раз менял телефон, Jolla отчиталась от сокращении половины сотрудников и я побоялся купить потенциально мёртвый девайс.
    Позже, они утверждали что нашли финансирование. А что на данный момент? Есть какие-то показатели, планы по развитию и подтверждение жизнеспособности компании? Как я понимаю, железо сейчас на аутсорсе?


    1. kirikch
      17.08.2016 11:46

      Наверное, не очень корректно говорить «на аутсорсе». Jolla лицензирует Sailfish OS для производителей железа.
      Например, Intex и Turing Robotic Industries выпустили устройства. Oysters и Mobile Inform Group на подходе.
      Сама компания занимается теперь софтом совместно с Открытой Мобильной Платформой.


    1. GoAlexander
      17.08.2016 13:29

      На этот год у них 100% есть деньги. + В Индии Aqua Fish покупают, вроде, неплохо (поправьте, если ошибаюсь). От Turing Robotic Industries и Intex Jolla уже получает деньги. То, что Открытая Мобильная Платформа подключилась — радует, так как развитие будет побыстрей идти, так как наработками они обмениваться будут. А дальше… Посмотрим как будут дела у Oysters и насколько хорошо ОМП себя покажет на B2G и B2B рынках в России :)