И столкнулся с невообразимой штукой - не смог из UI-приложения просто тупо ... запустить браузер дефолтный с URL, ну страничку открыть с описанием программы.
Пробовал:
getHostServices().showDocument - штатная классика для JavaFX
java.awt.Desktop.browse
getRuntime.exec или из шелла пробуя утилиты xdg-open, x-www-browser
Это какой-то трэш и угар - все варианты под Виндой (ясно дело кроме запуска линуховых утилит) работают, а в Mint 21, который есть под рукой - всяческий набор ошибок недостатка прав, gtk, ограничений (--no-sandbox), зависания приложения при попытке это сделать.
java.awt.Desktop.browse сработал ОДНОКРАТНО, а при повторном вызове - зависание приложения, с системным диалогом "прибить или подождать"...
Как же из графических приложений это в Линуксе делают, жмакая по кнопочке ? Да и конечно, хотелось бы чтобы на максимуме дистрибутивов работало б...
2. Находим в нем строку: myWeb.loadUrl("file:///android_asset/index.html");
3. Вместо "file:///android_asset/index.html" Прописываем онлайн-путь(веб-адрес) на ваш интернет-сайт, который должен запуститься при открытии вашего андроид-приложения.
Рубрика «сам себе экосистема» уже успела стать постоянной в моем блоге. Для тех, кто читает меня в первый раз, расскажу: одним из основных направлений блога всегда был моддинг и попытка использования устройств прошлых лет в современных реалиях. Именно поэтому я пишу клиенты нужных мне сервисов с нуля, дабы иметь возможность пользоваться такими замечательными смартфонами, как Xperia Pro, Xperia Play, Desire Z и конечно же Motorola Droid, а в статьях я делюсь с вами не только причинами своей мотивации, но и рассказываю, как разрабатываются приложения для 10+ летних смартфонов с нуля и с минимальным набором зависимостей и детали реализации тех или иных фишек. В сегодняшнем материале мы подведем с вами промежуточные итоги и узнаем, справляются ли смартфоны 14 летней давности с современными сервисами?
❯ Предисловие
Наверняка у многих читателей за последние годы сложилось впечатление, мол пользоваться смартфоном, которому 5+ лет просто невозможно: ОЗУ и постоянной памяти мало, дисплей «низкого» разрешения, смартфон лагучий и отнюдь не плавный, а разработчики приложений давным-давно забыли о том, что такое поддержка 10-летнего Android 5.1. Я лично так не считаю: при определенной сноровке, наличии запала и энтузиазма, а также истинной любви к интересным смартфонам, выясняется, что все необходимые в повседневной жизни приложения можно разработать и самому, с нуля и даже без зависимостей!
Изначально я и не думал писать материал в таком формате, вроде бы всё очевидно: кто ищет приложения под старенький смартфон, может найти их чуть ли не по первым ссылкам в гугле на 4pda, а кому интересны детали реализации — переходят по линкам на соответствующие статьи из первого сообщения в теме.
Подписчики, которые давно читают мой блог, уже более года просили попробовать начать выпускать материал и в видео-формате. Именно поэтому я решился экранизировать рубрику «сам себе экосистема» и запилить видео, где наглядно показываю, на что способны «старички» в современном мире с самопальными приложениями, дабы популяризовать такой вот своеобразный «техно-дауншифтинг» :)
Если вам нравятся мои статьи — можете и на YouTube подписаться!
Реакция зрителей была очень приятной и я решил написать статью в «простом и понятном» формате о том, как и где взять такие приложения и показать, как они работают на реальных смартфонах тех лет.
Все приложения можно взять либо в соответствующих топиках (см. подпись) на 4pda (на форуме обязательна регистрация для скачивания файлов, иначе будет ошибка 404), либо на моём GitHub в релизах.
❯ На чём тестируем?
Для тестов я выбрал 4 легенды своих лет и каждый по своему может быть интересен читателям даже для покупки в 2024 году. Все смартфоны, перечисленные ниже, стоят до 1 500 рублей по рынку на вторичке!
Первым будет Sony Ericsson Xperia Pro, основная фишка которого — выдвижная QWERTY-клавиатура и достаточно компактные размеры. К сожалению, выдвижных сайд-слайдеров уже давно не делают и ценителям QWERTY-устройств остается лишь использовать Б/У устройства или переходить на смартфоны а-ля UniHertz Titan. Смартфон вышел в 2011 году и работал на базе чипсета Qualcomm MSM8255 с одним ядром Scorpion (на базе Cortex A8) на частоте 1.5ГГц и имел 512Мб ОЗУ и 512Мб постоянной флэш-памяти. Из коробки смартфон работал на Android 2.3, есть апдейт до 4.0.4. Казалось бы, характеристики совсем слабые по сравнению даже с современными реалми по 5 000 рублей. В среднем, сейчас эти смартфоны можно найти за 1 000 рублей на онлайн-барахолках.
Вторым будет не менее легендарный Sony Ericsson Xperia Play. Это единственный в своем роде смартфон с выдвижным геймпадом и при этом реально удобным! На устройстве есть адаптированные под аппаратный геймпад эксклюзивы и я частенько люблю поиграть на Play в классические Android-игры 2010-2011 годов. Именно благодаря уникальности смартфона я продоолжаю время от времени использовать его и сейчас в качестве портативной игровой консоли. Характеристики практически идентичны Xperia Pro, за исключением наличия того самого геймпада, где роль стиков выполняют маленькие тачпады с контроллером Synaptics! Не исключено, что смартфоны строились на одной платформе, конструктивно они похожи. Сейчас Play можно найти на барахолках за 2-3 тысячи рублей (это адекватная цена), иногда дешевле. Я время от времени покупаю нерабочие Play'и по 500 рублей и собираю из десяти ещё один — поскольку много плеев в коллекции не бывает и я их очень люблю :)
Третьим будет Samsung Galaxy Ace — в своё время очень популярный смартфон, о котором я когда-то мечтал, будучи юнцом. Отличный смартфон, сбалансированный и недорогой по меркам Samsung в те годы. За 15 000 рублей можно было получить 384Мб ОЗУ, Qualcomm MSM7227 и неплохоий дисплей. Сейчас их можно найти на барахолках буквально по 200-300 рублей рабочими и с аккумуляторами, они практически не ценятся и их очень много поскольку модель была крайне массовой и успешной.
Четвёртым будет диковинка сегодняшней статьи — Samsung Galaxy Pocket. Это очень бюджетный смартфон, «топ за свои деньги» тех лет, который может быть интересен читателю благодаря очень компактным размерам. Смартфон легко помещается в кармашек рубашки и его удобно носить в качестве второго. Интересны и характеристики: чипсет Broadcom на частоте 832МГц, родственный процессору Raspberry Pi 1, 256Мб ОЗУ, 4Гб встроенной памяти, работает смартфон на базе Android 2.3 и дисплей всего 2.8". Да, пусть всего 240x320, но всё равно! Какой-же он крошечный :)
Вот такие интересные и необычные смартфоны собрались в сегодняшнем тесте. Их всех объединяет одно: примерно похожий уровень производителньости, который в разы уступает любому современному бюджетнику. Но значит ли это что эти «ретро» смартфоны бесполезны? Давайте посмотрим на практике!
❯ Практика
Начинаем с ВК. На смартфонах Xperia приложения работают крайне плавно, а в случае Xperia Pro можно без проблем чатиться с помощью встроенной QWERTY-клавиатуры. Несмотря на то, что функционал клиента совсем базовый, тем не менее он вполне функционален и, что немаловажно, практически не потребляет и без того небольшие ресурсы смартфонов в фоне. Анимация чуть-чуть подлагивает лишь на Galaxy Pocket в силу не самого мощного железа.
YouTube тоже работает нормально, однако есть важный нюанс: в смартфоны Xperia для работы нужно обязательно вставить MicroSD-флэшку (поскольку как таковой пользовательской памяти в них нет, только под приложения). YouTube пока что отдаёт видео в h263, который поддерживают большинство смартфонов тех лет и не сваливаются в программный декодер. Так что всё работает очень быстро — хоть и видео необходимо загружать перед началом просмотра.
Клиент Telegram работает также быстро, хоть и реализован с костылем в виде прокси-сервера. Контакты и аватарки прогружаются моментально, никаких лагов при скроллинге нет. В целом, учитывая, что телега один из самых популярных мессенджеров в СНГ и большинство контактов уже есть там, это вполне себе новая жизнь для смартфонов тех лет!
❯ А на что ещё способны?
Помимо клиентов основных приложений, такие смартфоны пригодятся и для других задач.
Например, для использования электронной почты. Клиент в Android 2.3 до сих пор работает при условии включения опции «разрешить все SSL-сертификаты»:
Простой серфинг. Да, большинство сайтов с динамикой уже «отваливаются», но пока что Opera Mini ещё работает на 2.3, позволяя почитать Хабр или зайти на лор.
Ну и, конечно-же, послушать музыку.
❯ Заключение
Вот мы и узнали с вами, на что способны смартфоны которым более 13 лет! Как я уже говорил, немножечко сноровки, энтузиазма и любви к гаджетам тех лет и можно вполне пользоваться ими как основными каждый день! А какие смартфоны были у вас? Пишите в комментариях! Если вам интереса тематика программирования, моддинга и ремонта гаджетов прошлых лет, подписывайтесь на мой Telegram-канал, куда я вовремя публикую ссылки на новые статьи, а также различные мысли и фото-отчеты о ремонте гаджетов!
Также я реализовал подобные приложения и для Windows Phone, когда снова хотел ими пользоваться как основными. Уж очень мне понравилась Lumia 640, купленная за 100 рублей в своё время, с которой я ходил как с основным смартфоном :)
Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, дабы не пропускать новые статьи каждый день!
С момента выхода первой части статьи из рубрики «сам себе экосистема» прошёл уже практически год! За это время, мы успели с вами реализовать клиенты VK и YouTube, которые работают на Android 2.2+, а также на Windows Phone 8, написать небольшую 2D-игру с нуля весом менее 1Мб, которая работает практически везде и довести существующее приложение до ума, дабы оно работало даже на смартфоне с дисплеем 240x320! Но на дворе 2024 год, люди стремительно переходят из соц. сетей в продвинутые мессенджеры и уже сложно себе представить современного человека, который не пользовался бы «телегой» или даже «вайбером» в качестве основного средства общения. Поэтому я решил реализовать клиент Telegram на смартфоне 14-летней давности на базе официальной реализации MTProto от команды Telegram — TDLib. Сегодня мы с вами: узнаем новые причины мотивации вернуть в строй смартфоны прошлых лет, напишем на C# реле-сервер, который обрабатывает пакеты MTProto и кодирует их в простой текстовый формат датасетов, который можно моментально обработать даже при нестабильном GPRS-соединении на 21-летнем Siemens C60, а также узнаем о разработке миниатюрных Android-приложений на базе «голого» API-системы, которые не тянут за собой никаких зависимостей, в том числе и AppCompat/androidx. Интересно? Тогда жду вас под катом!
На дворе уже стукнул 2024 год, современные смартфоны предлагают какие-то немыслимые мощности относительно тех, которые когда-то были в первых Android-девайсах. Сейчас за сотню баксов можно купить смартфон с хорошей 1080p IPS-матрицей, 4Гб ОЗУ и 8-ядерным шустрым чипсетом, который вполне способен плавно тянуть даже стремительно «жиреющие» на ресурсы клиенты социальных сетей, банков и прочие необходимые в повседневной жизни приложения. И казалось бы: всё хорошо, покупай себе редмик раз в год или айфон раз в несколько лет и наслаждайся всеми прелестями работы современных приложений…
Для многих людей смартфон — это лишь инструмент, повседневный компаньон, который помогает облегчить выполнение каких-то задач. Им совершенно не важно, как он выглядит, как ощущается в руках, какой у него дисплей и железо «под капотом», лишь бы работал да и нормально. Но есть и другая категория людей, для которых телефоны, смартфоны и любые портативные гаджеты — это не просто утилитарный девайс, а настоящее инженерное произведение искусства, с которого буквально сдувают пылинки и стараются до последнего пользоваться ими как повседневными устройствами. Хотите пример? Смотрите ниже:
Фактически, среди современных смартфонов по сути и нет представителей такого нынче вымершего форм-фактора, как сайдслайдеры с физической QWERTY-клавиатурой, боковые раскладушки с двумя дисплеями и даже из QWERTY-моноблоков есть только смартфоны от Unihertz. Даже среди моноблоков с тачскринами нет никакого разнообразия, лишь без-рамочные одинаковые девайсы за исключением устройств от Sony.
Galaxy S Plus
Раньше меня часто спрашивали, мол, да как ты вообще можешь пользоваться смартфоном 10-летней давности, на котором давно нет официальных клиентов популярных сервисов и только недавно, с развитием блога, мне перестали задавать этот вопрос, поняв, что это бесполезно — ведь это дело принципа и порыва энтузиазма! Смотрите сами: у нас уже есть простенькие, но вполне рабочие клиенты ВК, YouTube, сейчас я допиливаю клиент «Сбера» на СМСках, реализую карты OpenStreetMap (правда пока без адекватной навигации), а в будущем планирую написать приложение для мониторинга погоды и трекинга посылок. Кроме того, в рамках этой статьи мы реализуем с вами клиент Telegram: так чем же это не функционал современного смартфона?
Но хорошо, с функционалом разобрались, однако для многих читателей слова «старый смартфон» это прямые синонимы «тормозной смартфон», мол «фуу, да как можно пользоваться этим тормозным кирпичом, он же лагает в последней версии моей ВКшечки!». Но давайте поставим вопрос ребром: может, это не столько девайсы немощные, сколько сами приложения, с кодовой базой, которая тянется более 10 лет, откровенно жиреют, обрастают костылями и хаками после далеко не одного поколения программистов, которые над ними работали? :) Один, вот, предпочитал пользоваться чистым AppCompat'ом, другой решил притащить зависимость, которая, например, оптимизирует виртуализацию ListView, третий решил заменить всю сериализацию Json со встроенных классов в Android на что-то стороннее и реализовал это костылями и вот так, по чуть-чуть изначально оптимальный и шустрый код превращается в неповоротливое УГ, которое не рефакторили кучу лет.
На видео Galaxy Pocket Neo — очень дешёвый Android-смартфон из 2011 года с 1-ядерным чипсетом на ~800МГц и 256Мб ОЗУ. При этом всём, Android софтварно рисует все анимации на процессоре, без участия GPU.
А значит у стареньких девайсов всё равно есть шанс быть полезными и стать полноценными повседневными смартфонами даже спустя более чем десять лет после выхода! И в сегодняшнем материале, я вам расскажу об особенностях разработки самопального клиента Telegram с собственным прокси-сервером, которое концептуально допускает реализацию даже на кнопочном Siemens C60 2003 года. Как? Читаем ниже!
❯ Принцип работы
В отличии от ВК (который разрабатывали те же самые люди, что и Telegram), API которого построено на базе REST-запросов и концепции Longpolling'а для моментального получения событий с сервера, Telegram построен на базе собственного протокола под названием MTProto, который может работать поверх любого «транспорта» (протокола нижнего уровня) — TCP, HTTP, WebSocket и т.п. Сам по себе MTProto в современном виде, разработка прожженного математика Николая Дурова и его команды — протокол относительно сложный для реализации «на коленке» и в первую очередь требует довольно серьезного понимания принципов работы современной криптографии, да и документирован он всё ещё не особо хорошо. Кроме того, у MTProto весьма интересный бинарный формат пакетов, эдакий велосипед Protobuf. В долгосрочной перспективе поддерживать свой велосипед MTProto может быть весьма проблематично, учитывая не самую лучшую документацию.
Но городить велосипед и не нужно, поскольку у команды Telegram есть официальная реализация MTProto — библиотека TDLib, которая инкапсулирует в себе не только детали реализации протокола, но и сетевой ввод/вывод и выбор транспорта, хранение базы данных сообщений и авторизации, автоматическую загрузку фото и видео, конвертация объектов из бинарного формата MTProto в JSON и полная многопоточность и частичная потоко-безопасность. С одной стороны это плюс — уже готовое решение для реализации клиента на новой поддерживаемой платформе, где есть OpenSSL (можно статически слинковать), zlib (линкуется статически), сокеты и файловый ввод/вывод, а также довольно неплохой механизм JSON-based API, которое позволяет использовать библиотеку в любом языке, который поддерживает вызов C-функций, а с другой и минус — библиотека довольно много весит, в одиночку прибавляя ~20Мб веса приложения для каждой архитектуры, у неё течёт память и у нее странный механизм получения данных с сервера (например, нельзя ответить на сообщение, зная его ID, если сообщение предварительно не загружено, при том что на сервере весь ответ — это просто ID, на какое сообщение прилетел ответ).
Понятное дело, что на стареньком смартфоне использовать оригинальный TDLib будет проблематичным — даже если собрать либы современным NDK и запилить JNI-интерфейс, библиотека «жрёт» много ОЗУ (20-100Мб «вхолостую», в зависимости от числа диалогов и частоты прилетающих событий, плюс со временем течет до 1-2Гб, если не использовать базу данных сообщений. Скорее всего, это косяк в реализации пулов, объекты из которых выгружаются при сбросе в базу, но не выгружаются при высоком потреблении ОЗУ) и уж тем-более TDLib не запустить на любимых кнопочных Java-сонериках! Поэтому я решил написать прокси-сервер, который отправляет команды, слушает ивенты TDLib и предоставляет REST-like API для клиентских программ, которые просто вызывают какой-либо метод, а в ответ получают простой и короткий строковой датасет только с необходимыми полями, весом до 10Кб (что позволяет его быстро загрузить даже с GPRS-интернетом), который можно быстро распарсить даже на преусловутом Siemens C60!
К сожалению, поскольку TDLib прожорлив, я не смогу захостить на своём сервере инстансы для читателей, которые хотят поюзать приложение, поэтому вам придется ставить и запускать сервер на своём VDS/компьютере с белым IP/роутере, если под него есть .NET Core :)
Клиентом же будет выступать Android-смартфон, где приложение будет фронтэндом данных с сервера. Ничего сложного на первое время нет: первое окно — это список диалогов, второе окно — список сообщений в диалоге + поле для написания сообщения, третье окно — информация о пользователе. Всё это я реализовал за три дня не-напряжной работы «на коленке».
Давайте же перейдем к реализации сервера!
❯ Прокси-сервер
Сервер я решил писать на C#, поскольку у .NET Core сейчас всё очень хорошо с кроссплатформенностью и производительностью. Его можно даже на Raspberry Pi запустить :)
Итак, какая-же архитектура такого сервера может быть? Программа инициализирует TDLib, начинает слушать её события в отдельном потоке, пока в основном потоке крутится HTTP-сервер, который обрабатывает каждый отдельный запрос с клиентского приложения. Почему синхронно? Потому что TDLib фактически не возвращает никаких идентификаторов для возвращаемых датасетов, дабы их можно было отличить друг от друга. Приведу пример: у нас есть метод getChatHistory, который возвращает n-сообщений. При этом TDLib сам определяет, сколько хочет сообщений вернуть (и в первый вызов возвращает одно сообщение вне зависимости от настрое и отправляем пакет message n-раз. При этом в пакете message нет какого-либо ID, который позволял бы ассоциировать текущий объект с какой-либо операцией. Увы!
Начинаем с коммуникации с TDLib. Для работы с библиотекой, мы будем использовать json-интерфейс. Для .NET есть биндинги через C++/CLI, но в таком случае, сервер не будет работать на Linux. Для работы с библиотекой хватит лишь три функции: CreateClientID, которая аллокейтит новый инстанс клиента, Send, которая асинхронно отправляет JSON-объект с командой, которую затем обработает TDLib и Receive, которая ждёт N-секунд и возвращает в виде ASCII-строки (!) JSON-объект с описанием события или данными после одного из запросов. За это у нас отвечает класс TDLibInterface, который объявляет PInvoke-методы для вызова нативных методов из библиотеки. .NET Core сам подгрузит библиотеку tdjson (причём на Linux он добавит ей префикс а-ля libtdjson.so, а на Windows загрузит tdjson.dll) и сам разберется с маршаллингом аргументов функций: например, string автоматически преобразует в const char*. Тем не менее, с const char* возвратами нужно быть аккуратнее — у меня был SIGSEGV, пока я ручками не конвертировал их в обычную строку.
З.Ы: На Пикабу нет отдельного тега для кода, а вставить листинги картинками я не могу из-за ограничения на 25 медиаэлементов. Так что листинги будут совсем без табов, но алгоритм их работы понять можно :)
Позволю себе чуточку критики в сторону TDLib. Во первых, почему нет s-версии функции с возможностью указать длину входной строки, а tdjson полагается исключительно на \0 в конце строки? Во вторых, почему const char*, а не wchar_t*? Сейчас юникод во входной строке приходится escape'ами превращать в \u-последовательности. После этого, нам нужно написать обёртку над TDLib, которая будет вызывать для зарегистрированных событий специальные функции, называемые коллбэками. При этом закомментированный WriteLine снизу — это «дебаг» для того, чтобы узнать названия неизвестных мне ивентов :)
В каждом объекте, полученном с помощью receive, есть поле "@type", которое содержит в себе имя класса возвращаемого объекта. Первый же вопрос от читателей — почему я использую JObject с ручным дерганьем нужных полей и вручную пишу JSON в виде строковых литералов вместо нормальной сериализации/десериализации? Ответ прост: во-первых, для актуализации Data-классов придется писать кодогенератор из TL-схемы, а во-вторых иногда TDLib может возвращать немного разные объекты в JSON, из-за чего приходится мудрить с атрибутами на этих самых Data-классах, иначе десериализатор выбросит исключение. Это решается нормальными юнит-тестами на всех вариантах данных, но зачем себе в колени стрелять, если нужен конкретный фиксированный функционал и лишь малое число от всех полей, возвращаемых TDLib?
string recv = NativeInterface.Receive(10.0d);
if (recv != null) { JObject json = JObject.Parse(recv);
if (!handlers.ContainsKey(type)) { //Console.WriteLine("Unknown event type: {0}", type); continue; }
handlers[type](recv, json); }
Теперь переходим к самому интересному — обработке событий и реализации синхронного клиента, который позволяет без async/await просто запросить список сообщений и сразу же его получить (такой подход может быть полезен и юзерботам, которые не хотят размазывать стейты по всей программе). Почему без асинков? Честно сказать, мне они просто не нравятся: как привык к концепции wait/notify и коллбэков из Java, так их и юзаю всю жизнь :)
Сначала TDLib запрашивает параметры инициализации (стейт authorizationStateWaitTdlibParameters), затем если пользователь не авторизован — запрашивает номер телефона и код подтверждения (плюс дополнительные шаги для авторизации если они есть). В конце, TDLib возвращает стейт Ready, что означает готовность библиотеки к работе:
После этого, можно начать работу с данными. Обратите внимание, мой подход потоко-небезопасен, его нельзя дергать из нескольких потоков одновременно! В коде ниже, я вызываю метод для фетча сообщений, а затем в соответствующем коллбэке от TDLib обрабатываю данные (дабы статья не разрасталась на 20+ минут, я чуть урезал все листинги).
public List<Message> QueryMessagesInChat(long chatId, long lastMessage, int count) { messages.Clear();
public User QueryUser(long userId) { string json = Utils.Format("{\"@type\": \"getUser\", \"user_id\": \"{0}\" }", userId); NativeInterface.Send(InstanceID, json);
waitHandle.WaitOne(); return user; }
Переходим к реализации самого сервера, для наших целей хватит обычного HttpListener. Сначала мы зарегистрируем все поддерживаемые методы и занесем их в ассоциативный список ключ-значение. Сами методы реализованы в виде делегатов, которые принимают лишь один аргумент — список параметров из строки запроса, а возвращают строку — все ответы, за исключением особых (связанных с загрузкой вложений) — текстовые.
Переходим к обработке запроса. Метод ищет, зарегистрирован ли запрошенный метод и если да, то парсит строку запроса, которая начинается с "?", которую затем передаёт в виде коллекции ключ->значения обработчику метода:
А сами методы, в свою очередь, дергают соответствующие функции из клиента и формируют на их основе датасет в примитивном формате:
public staticstring QueryChats(Dictionary<string, string> args) { if(args.ContainsKey("count")) { int count = int.Parse(args["count"]); StringBuilder ret = new StringBuilder();
В результате получаем вот такой простой датасет, который, как я и говорил, легко распарсить и на Siemens C60, и на Atmega328 — да где угодно! В целом, такой сервер можно использовать для реализации бота в телеграме, который будет передавать показания каких-то датчиков, сигнализацию и прочие клевые штуки!
Переходим к реализации клиента, т.е. приложения на Android. Здесь будет не менее интересно!
❯ Пилим для Android
В геймдеве есть своеобразный мем — некоторые инди-разработчики сначала начинают делать меню, вместо основного геймплея, что становится предметом насмешек среди других разработчиков. Но в разработке приложений для смартфонов всё по другому — здесь как-раз таки хорошо заранее продумывать макет будущего приложения!
Поскольку у нас с вами мессенджер, то главный экран должен представлять из себя список чатов (ListView) и верхнюю панельку, где в будущем могут разместиться настройки и свайп-менюшка:
Такой вот простой макет.
Каждый пункт меню — это тоже отдельный layout, в котором мы по шаблону строим внешний вид будущего элемента списка. На немолодых устройствах есть смысл использовать как можно меньше контейнеров в layout'е, поскольку пересчет позиций и размеров элементов — одна из самых «тяжелых» операций в UI-фреймворке вообще. Кроме того, не стоит использовать кучу картинок и drawable — в Android 2.x всё 2D рисуется софтварно, аппаратное ускорение появилось только в 3.0 (частично).
Но дабы в списке диалогов что-то появилось, нужно сначала реализовать фетчинг (получение) этих самых диалогов с сервера! Сам объект, который занимается обработкой запросов называется ClientManager и является синглтоном — он в единственном экземпляре на все время работы программы. Помимо менеджмента «ноды» (т.е. прокси-сервера), токена для авторизации и обработчика ошибок, ClientManager реализует метод для асинхронного запроса информации с сервера и, собственно, формирует строки запросов с помощью соответствующих методов:
Подгрузка чатов и сообщений реализована через Adapter — концепция «виртуальных» списков, которая предполагает что система создаст не 50 элементов интерфейса на каждую кнопку чата, а только 5 и будет их виртуально «мотать по кругу», обновляя только данные в уже существующих элементах. Это позволяет значительно ускорить отрисовку, учитывая то, что Android 2.x Canvas рисуется программно.
Ну вы уже явно замучились видеть простыни кода, давайте посмотрим что у нас вышло!
Шустренько, да? А ведь это ультрабюджетник Alcatel OT-916D, один из последних массовых дешевых QWERTY-смартфонов за 5 000 рублей из 2012 года. Кстати, смартфон подарил мне читатель chuvakoff с Хабра!
Переходим к окну чата. Основной макет почти такой-же, как и у основного окна: только добавилась панелька для ввода сообщения снизу.
Концептуально, всё тоже самое — запрашиваем данные с сервера, парсим их и загружаем в адаптер, благодаря чему мы сможем листать наш диалог. Однако в сообщения я добавил контекстное меню с стандартными фишками типа копирования, ответа и прочих подобных действий. Поскольку у нас нет ни пушей, ни еще каких-либо средств для поулчения данных о новых сообщениях, я раз в определенный интервал просто получаю сообщения — и если новый датасет отличается от старого — обновляю окошко чата.
Переходим к реализации поля для ввода сообщения. Здесь всё просто — на серверсайде за это отвечает метод SendMessage. Однако для того, чтобы с нашего клиента можно было ответить на другие сообщения, я ввёл также «контекст ответа», в котором запоминается сообщение, на которое мы хотим ответить. Telegram также поддерживает Markdown, однако его полная поддержка пока не реализована.
В остальном же, функционал конечно пока совсем базовый, однако клиент работает очень шустро даже бюджетной X10 Mini Pro и позволяет чатится с моими читателями в Telegram. В будущем хотелось бы допилить:
Поддержка картинок: Сейчас уже есть кривоватый механизм кэширования изображений на стороне сервера, который позволяет загружать аватарки чатов. В будущем, я добавлю поддержку «галерей» с картинками!
Поддержка голосовых сообщений: Не все их любят, но они порой удобны и выручают. Реализую как прослушивание, так и запись!
Подробный просмотр профилей и менеджмент чатов: Удаление сообщений, чатов и прочие фишечки из официальных клиентов.
Казалось бы — до официальных клиентов ещё очень далеко. Но сам факт, чтобы всё это работало достаточно шустро на девайсах, которым уже более 10 лет!
❯ Звучит интересно! Как заюзать твой клиент?
Тут всё очень и очень просто! В первую очередь, нам понадобится ПК с белым IP, роутер (если под него есть сборка dotnet), либо VDS. Виртуальные сервера сейчас стоят копейки, у ТаймВеба есть тариф за 188 рублей в месяц, которого с головой хватит для нашего сервера.
Такая вот рекламная интеграция (к слову, прокси для всех приложений уже более года крутятся именно на мощностях TimeWeb Cloud)!
Программа сначала запросит номер телефона, а затем код подтверждения Telegram. После этого будет создана папка tdlib/, где будут хранится данные вашей сессии, а также файл authkey.txt, где хранится случайный ключ для сессии (md5 phone_number + response code + псевдослучайное число). Не оставляйте его в /var/www/!
Если всё нормально, программа начнёт слушать порт 13377 на всех сетевых интерфейсах, в т.ч и в локальной сети. После этого, ставим уже предварительно собранный, либо собираем сами в Android Studio APK и в окне авторизации пишем адрес ноды и ключ авторизации. Если всё настроено верно — программа запомнит сервер и будет работать без проблем! Вот так всё легко :) Как видите — всё очень и очень просто!
Кроме того, буквально за пару дней до публикации статьи я сел вечерком из интереса что-нить под Java-телефоны попилить… и, как и обещал, реализовал Proof of Concept возможности работы Telegram даже на сонериках, которым скоро 20 лет стукнет! А ведь если ещё чуть заморочится, можно запустить приложение даже на преусловутых монохромных сименсах!
❯ Заключение
Вот такой у нас получился проект с реализацией лёгкого, примитивного, но тем не менее рабочего клиента Telegram, который на клиентской части вообще не использует никаких зависимостей. Вес собранного APK в release-версии — всего 54 килобайта! Понятное дело что с ростом функционала, вес программы будет увеличиваться, но я обещаю — больше 1Мб он не вырастет :)
Ну а вам, моим читателям, надеюсь было интересно прочитать такой «двойной материал» не только о разработке сетевой части без использования Apache/nginx/IIS, но и UI-фронтэнда для Android-смартфонов, которым уже более 10 лет! Исходный код проекта можно найти на моём GitHub: как приложения, так и сервера, а также убедиться в отсутствии каких либо закладок и, если совсем не доверяете, собрать бинарники сами! Для сборки понадобится VS2017 или свежее, а также Android Studio 2.3.2 (если собираете для Android 2.1 и ниже).
Друзья! Сейчас на Хабре опросы сломаны, поэтому если у вас есть желание, вы можете проголосовать в комментариях: какой стиль статей вам больше нравится — где больше конкретики и кода с пояснением как конкретно работает та или иная часть программы, или наоборот стиль ближе к научпопу, где фрагментов кода нет, или их значительно меньше? Пишите своё мнение о проекте в комментариях!
Кроме того, у меня есть канал в Telegram, куда я публикую бэкстейдж статей, ссылки на новый материал, свои наработки, а также посты о ремонте девайсов и различные мысли.
Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!
Где я подробно рассказываю о том, как реализовал клиент современного мессенджера Telegram на Android 1.5+ и выше. Таким образом, Telegram будет работать даже на самом первом Android-смартфоне в мире, T-Mobile G1, причём на стоковой прошивке!
Время неумолимо бежит вперед: выходят новые гаджеты, постепенно заменяя старые, превращая их в тыкву или в лучшем случае, в «тапочек» для звонков. Сейчас смартфоны стали практически одинаковы во всем: дисплей на всю площадь передней панели, почти полное отсутствие аппаратных кнопок, беспроводная зарядка… Это всё, конечно, здорово, но ведь иногда так хочется взять в руки старый, но такой необычный в наше время QWERTY-смартфон и попытаться его использовать как основной, да и цены на них могут приятно удивить: БУ девайс можно купить за несколько сотен рублей (~5-10$). Одна проблема — клиенты приложений на версии Android 1.6-2.0 безбожно устарели и давно не работают. Но иногда желание воскресить старый девайс превыше потребительского качества и тут я пришёл к мысли… а почему бы не написать с нуля свои клиенты популярных приложений? ВК с музыкой, YouTube, трекинг посылок. Так я и сел писать необходимые в повседневной жизни приложения, с нуля, на голом API Android, без каких либо фреймворков (и даже AppCompat). Получилось ли у меня это? Узнаем в статье!
Мотивация
На самом деле копаться в старых девайсах и пытаться найти им применение — это очень интересное и затягивающее дело. Ведь зачастую попытки оживить девайс заключаются в прочтении большого количества мануалов, документации, копании в терминале, а иногда даже компиляции загрузчиков/ядер! И подобные занятия интересны на всех уровнях: хардварный, системный, прикладной и пользовательский. В предыдущих статьях мы с вами моддили девайсы на всех этих уровнях: ремонтировали «железные» болячки, написали несколько статей о системном моддинге и компиляции загрузчиков под неизвестные китайские устройства, а также узнавали о пользовательском опыте установки готовой кастомной прошивки на 7-летнее устройство.
Но до сегодняшнего дня мы с вами обходили прикладной уровень моддинга устройств: т. е. написание самых обычных, повседневных программ, без которых сложно представить жизнь современного человека. Ещё во времена выхода первого Galaxy S в 2010 году, многие из нас уже сутками красноглазили в Java версии «аськи», кто-то уже сидел в ВКонтакте, хоть и большинство не заглядывали в смартфон каждые пару минут для проверки нотификаций. К 2012 году смартфонная жизнь уже стала похожа на ту, к которой мы привыкли сейчас — соц. сети, мессенджеры, пуши, потоковое видео — многие из нас успели привязаться к такой жизни и… к конкретно тем самым девайсам!
2012 год давно миновал, тенденции в разработке приложений кардинально поменялись, а учитывая, что многие мои читатели не любят выбрасывать девайсы в мусорку (и правильно делают), наверняка кто-то регулярно заглядывает на полочку к своим пыльным «бывшим» гаджетам и рассматривает их с теплотой… но с сожалением понимает, что их время прошло. Или не прошло? :) Ну, тут как посмотреть. Если есть навыки и огромная мотивация, то программер может многое, в том числе и запилить все самые необходимые приложения сам! Я давно лелеял эту идею, подумывая, как бы лучше её реализовать. Да и почти всю свою жизнь, я писал на C#, практически не «щупав» API Android и его UI фрейморк. В один день у меня очень сильно зачесались руки написать что-нибудь эдакое под него и причём сразу — весьма серьёзное!
Всем этим устройствам более 10 лет. Самым молодым из них является реплика Lumia 1020, которую мы тоже успели замоддить!
Так и родилась идея написать клиент YouTube. А потом и ВК. Ну и трекинг в придачу. Ну а чего б и нет, на всё про всё я выделил себе неделю: за это время я должен успеть закончить пусть и сыроватые, но вполне юзабельные клиенты для моих любимых сервисов. И я начал думать…
Планирование
Написание приложений под старые мобильные ОС, как и под любые другие платформы, требует планирования того, что и как будет работать с учётом ограничений целевой платформы. У меня было сразу несколько ограничений, что только раззадоривало пыл:
В большинстве своём, на старых версиях Android работают одноядерные чипсеты, а значит, лимитированная многопоточность. Никакой работы в UI-потоке кроме обновления интерфейса, а поскольку в первых версиях этой системы интерфейс менее отзывчив, чем в более свежих — нужно сохранять баланс между функционалом, симпатичностью и скоростью работы. Мои приложения должны оптимально работать в следующих условиях: 256мб ОЗУ, из которых свободно в среднем 30-40мб (Сбер, привет тебе с вылетами на 2гб ОЗУ), 1 ядро ~600мгц, видео-ядро уровня Mali300-Malii400. Негусто? Ну, нам сойдет.
Вторым ограничением стало тотальное устаревание корневых сертификатов, а как многие из нас знают, просто так их на мобильных системах не обновить. Поэтому придётся идти на хаки — делать сервер-реле, который преобразует трафик из https в http там, где нельзя просто отключить проверку верификации SSL (это как раз кейс с API VK). Решено — отдельный сервер-реле, который отправляет запрос на сервер ВК и обратно возвращает нам обычный результат в JSON.
Ну а третьим ограничением стал сам Android. targetSDK = 5 (Android 1.5 Cupcake), никакого AppCompat (кушает драгоценное свободное место), никаких сервисов Google (их тут нет лет 5 уже). Всё на чистом API системы, почти в тех же условиях, в каких 13-14 лет назад писались первые приложения для Android.
Если я его раздобуду когда-нибудь, то в лепешку расшибусь, но портирую на него свои приложения. Тогда я с гордостью скажу, что мои приложения работают на 100% Android устройств %)
Полный энтузиазма я сел писать код. Основную часть статьи я решил поделить на каждое приложение отдельно с конкретными объяснениями: где, что и как я делал. Хочется заранее сказать — я не особо давно пишу под Android, зато много писал под WinForms, поэтому какие-то решения могут показаться странными. А некоторые решения обусловлены версией Android. Например, нотификации в первых версиях Android не было Notification.Builder, а сам Notification был больше похож на структуру. Приложения, конечно же, мы будем писать на Java.
ВКонтакте
Первым делом я начал писать клиент ВК и сразу определился со своими хотелками, которые были весьма скромными: возможность листать диалоги, читать сообщения и отправлять их (с полной поддержкой QWERTY-клавиатур, т. е. отправка на Enter), плюс возможность слушать музыку без ограничений. На ВК бочку ни в коем случае не гоню, просто публичного API совсем нет, даже с ограничениями, хотя было бы здорово…
Мне снова хотелось почувствовать те эмоции, которые я когда-то ощущал от прослушивания музыки будучи школяром со своим первым Android-смартфоном. В 2013 году я прилетал со школы и слушал плейлист на практически таком же девайсе с идентичным железом и версией Android. Я хорошо помню, как пользовался прелестями многозадачности Android на 2G интернете (3G чипсет просто не поддерживал): одну песню слушаешь, поставил вторую качаться, пока песня доиграет — уже и вторая скачалась. :)
Итак, хотелки выбраны, пора начинать писать приложение. Для дебага у меня было 3 устройства: Galaxy S4 (Android 4.2 JB), китайский Galaxy S3 Mini I9300 (Android 2.2, на фото выше) и Samsung Galaxy S I9000 (Android 2.3), ну и конечно же эмулятор с 4.4 KitKat. Android Studio и сейчас умеет без проблем собирать приложения вплоть до версии Android 2.2 даже с последними Build Tools и Target SDK — главное выкинуть appcompat, androidx, и юнит тесты из build.gradle. Без каких-либо проблем он цепляет и сами устройства по adb. Даже отладчик без проблем работает.
Первым делом я начал писать активити (полноэкранная форма в терминологии Android, или «экран» приложения) с диалогами — он должен раз в n секунд подгружать данные и строить «морду» для всего этого. По сути, почти весь код клиента — это получение ответа от API ВК, разбор JSON на датасет и визуализация этого датасета на экран. Для этого я ввёл два объекта: VK, который делает асинхронные запросы на сервер, оборачивает работу с сервером-реле и парсит JSON и VKObjectProcessor (это скорее всего отрефакторится до VKDataSet чуть позже).
Архитектура приложения получилось довольно простой и примитивной. При старте активити авторизации проверяет данные приложения (PersistStorage) на наличие API-токена и при его отсутствии запрашивает авторизацию. Как это уже стало классическим среди различных «самопальных» клиентов, мой клиент «прикидывается» официальным приложением ВК — для этого используется связка app_id и app_secret приложения ВКонтакте для Android.
После авторизации приложение перенаправляет нас на страницу диалогов. Поскольку у нас нет ни пушей, ни лонгполлинга, метод обновления остается один — в заданные интервалы. Для этого у нас есть Handler, который раз в 3.5сек берет список диалогов с сервера, проверяет, обновились ли данные и если да — обновляет датасет, отправляя сигнал обновления интерфейса (который построен на ListView). Кроме того, у нас есть кэш аватарок — точно так же распаралелленый на несколько потоков, а загруженные на данный момент превьюшки хранятся в хэшмапе.
При этом сообщения реализованы схожим образом — на данный момент возможности горячей подгрузки сообщений «сверху» нет, поэтому обновляются последние 50 сообщений скопом и сразу. Шустро ли всё это работает? Вполне неплохо. Конечно, основное процессорное время уходит на разбор тяжелых JSON, но тут отчасти вина ВК — мало того, что кастрировали функционал getHistory в последних версиях API, так ещё и нет возможности возвращать только те поля, которые нужны.
Как же я поступил с аудиозаписями? Музыка через API — настоящая заноза для разработчиков клиентов, с которой пришлось «подолбаться». Правда, недолго — раз у нас для основных запросов уже есть сервер-реле, то почему бы не сделать ещё и для музыки? Суть обхода простая: если сгенерировать специальный API-токен, то можно свободно обращаться к методам, связанным с музыкой без необходимости притворяться официальным клиентом и «подписывать» запросы md5 ключом. Примитивный PHP-скрипт как раз и предоставляет такую возможность, позволяя получить доступ к базе музыки ВК, однако ограничение типичное — у пользователя должны быть открыты аудиозаписи:
Тут был код на пхп, о его скушал пикабу!
По итогу у меня получился рабочий плеер с поиском музыки и добавленными треками. Опять же — производительность остаётся отличной! Ссориться с ребятами из ВК не хочу, поэтому добавлять возможность качать треки пока не стал — но вам стоило бы быть подружелюбнее к разработчикам кастомных клиентов! :)
Что мы получили по итогу? Довольно простенький клиент ВК, который практически не потребляет ОЗУ и шустро работает. Да, здесь не хватает кучи различных фич — как минимум, прсомотра ленты и стены. Но ещё успеется — если проект будет интересен не только мне, то продолжим наращивать фишечки потихоньку! Уже ближе к релизу я слегка причесал клиент, добавив более «вкшный» дизайн и приделал анимированное боковое меню. Про Animation ещё кто-то помнит? :)
YouTube
С разработкой клиента YouTube были свои особенности: во-первых, в отличии от клиента ВК, видео через реле просто так не загрузишь, слишком много трафика, а во-вторых, YouTube уже не «отдаёт» видео в форматах, которые поддерживают старые устройства — в основном, это h263 до 720p. К сожалению, потоковое видео с софтовым декодированием уложит на лопатки большинство «одноядерников» тех лет.
Ситуация осложнялась тем, что ни VideoView, ни стандартные плееры всех смартфонов, на которых я отлаживал приложение, не умели игнорировать ошибки SSL и просто валились с ошибкой. Пришлось что-то придумывать: ведь видосики хочется смотреть на крутейшем AMOLED дисплее Galaxy S!
Посидел я, подумал и придумал. Для поиска по базе YouTube, получения информации и прямых ссылок на видео я решил использовать альтернативный фронтэнд YouTube, который называется Invidous API — крутая штука со своим API, которая сама распределяет пул токенов самого ютуба и отдаёт ответы в виде JSON. Форматы запросов очень простые: <url инстанса Invidous>/api/v1/метод, например «search?q=test®ion=RU&hl=ru» — выдаст нам результат поиска «test» в Российском регионе. Очень удобно, да? А ещё Invidous — не какой-то отдельный сервис, а целая сеть т. н. инстансов — какой хочешь, такой и юзай! Поскольку большинство инстансов «прячется» за свежими сертификатами, пришлось идти на довольно известный костыль с отключением верификации хостнеймов у HttpUrlConnection:
А туть был костыль на Java.
А поскольку у нас нет возможности воспроизводить потоковое видео онлайн, то я решил его просто предварительно загружать через собственный менеджер закачек, с возможностью последующей очистки кэша. Поскольку таким устройствам 2060p качество не нужно, я выбираю 240p-360p mp4 в avc кодеке, в среднем ролики по 30 минут весят около 30-40 мегабайт. При HSDPA+, загрузка подобного видео займет около минуты-двух — не так уж и много, можно и подождать. Закинул тестовую версию в беседу любителей ретро-мобилок — люди были в восторге. ;)
Поскольку Invidous отчасти строится на анонимности — авторизации тут нет. Однако свою задачу посмотреть видосики он выполняет нормально — поэтому весь UI приложения я поделил на 4 вкладки: тренды, популярное, история и поиск. Подписки, как и историю можно реализовать на стороне клиента — для некоторых такой подход покажется плюсом, для кого-то — нет, однако минимальный задел для клиента уже есть — мы можем смотреть видео!
А где скачать?
Приложения и бэкэнд полностью открытые, исходный код доступен по лицензии GPLv3. Следить за статусом проекта можно на моём GitHub! Последние версии можно скачать в релизах проекта.
Из текущих хотелось:
Портировать на Android 1.6. Несмотря на то, что приложение в целом имеет targetSDK = 5, на 2.1 оно работать отказывается. В Android, после 2.1, слегка поменялся бинарный формат xml разметок, из-за чего приложение на старых системах вылетает с исключением. Но это решаемо: eclipse adt в зубы, импортируем проект и вперед! ;)
Кроме того, я экспериментировал с попытками как можно сильнее уменьшить нагрузку как на сеть, так и на процессор путём облегчения датасетов. Если один JSON от ВК весит в среднем 30-60кб (который 1 ядерный чипсет частотой 600мгц может «долго» жевать, негативно сказываясь на UI), то примитивный KeyValue формат, который содержит только нужные поля умещается в 5-6-7кб в текстовом виде и благодаря своей примитивности (весь парсинг — два substring, один indexof и поиск ключа по хешмапе) совсем не «налегает» на процессор. Благодаря этим наработкам, я запилил и примитивный клиент ВКшечки для j2me.
В целом, можно сделать единый формат датасетов для мессенджеров, а на бэкэнде реализовывать всё что угодно — Telegram, ВК, да хоть личные сообщения на хабре, а для платформ только делать «морды»: так можно завести современные мессенджеры и на Sailfish, и на J2ME, и на Symbian, и на WinMobile, практически без пота и крови :)
Полная адаптация под кнопочное управление. Сейчас с клиента можно без проблем писать сообщений с любой клавиатуры, в том числе и QWERTY. Однако основной интерфейс всё ещё не полностью адаптирован под кнопки и требует выполнения некоторых действий пальцем.
Заключение
Как по мне — получилось вполне неплохо. Да, приложения кое-где сыроваты и явно не дотягивают по функционалу до их больших версий. Но кое в чем они всё таки выигрывают: они лёгкие и быстрые, а самое главное — ещё могут продлить жизнь любимого девайса для кого-то. И я считаю — это классно! Среднее потребление ОЗУ обеими клиентами: 5-10мб. Вес APK: 30-50кб на момент выхода статьи. Вот что значит писать под голое API без модных фреймворков! ;) Что до остального функционала — кое-что в Android продолжает неплохо работать и в наше время. Например, DLNA-стриминг в доме, E-Mail клиент или банкинг через смски. Я уверен, это покрывает 80% потребностей большинства пользователей — так разве после этого можно назвать старые смартфоны бесполезными?
Я писал эту статью с целью показать вам, что старые девайсы отнюдь не тыква, если есть щепотка энтузиазма в глазах и любовь к гаджетам, а заодно и поделиться с вами своими приложениями. Часто в комментариях мне пишут, что хотели бы пользоваться своими смартфонами и дальше, если бы не устаревающие версии Android. А вы как считаете? Жду ваше мнение в комментариях.
Статья подготовлена при поддержке компании TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи про девайсы каждую неделю! А ещё не забудьте проставить плюсик на хабре, если статья вам понравилась - это поможет с финансированием и выходом новых статей!
В этом руководстве/инструкции, пойдет речь об ответе на следующие вопросы:
-Как конвертировать html в apk приложение Андроид?
-Как конвертировать веб-страницу в андроид приложение?
-Как конвертировать веб-сайт в apk-файл (Андроид приложение), через Android Studio
-Как создать Андроид-приложение без программирования?
Сами веб-сайты и веб-страницы, можно создать и без программирования, используя такие программы как WYSIWYGWebBuilder.
Она легка в использовании, и создает веб сайты/страницы, которые легко поддерживаются смартфоном при конвертации в APK-файл Андроид-приложения.
Важное примечание:
При создании html-сайта/страницы для конвертации в APK приложение , надо учесть что смартфоны не поддерживают такие технологии как webgl (3d графика), php и т.д.
При конвертации сайта/страницы с использование этих и подобных технологий, содержимое html-страницы может не отображаться или некорректно работать.
Спокойно конвертируются и корректно работают html-страницы с простыми js-файлами(скриптами).
Алгоритм конвертации html-сайта в APK файл андроид-приложения:
1. Запускаем Android Studio , и в меню File выбираем New-New project
В появившемся окне выбираем вариант - Empty Activity
2. Когда мы выделим вариант Empty Activity , и нажмем кнопку Next , появится следующее окно с заголовком New project .
Здесь обязательно, в пункте Language (Язык) , надо выбрать вариант Java , а не Kotlin .
Так как , далее предоставленный код , предназначен именно под язык программирования Java, и не будет работать при варианте Kotlin.
В пункте Name (Имя) , пишите название своего проекта/приложения ,но только на латинице/английскими буквами. В данном случае мы написали краткое слово: Kota.
Параметр Minimum SDK , в данном случае, трогать не нужно.
Параметр Package name , тоже не нужно трогать, т.к он автоматически подстроится под написанное вами имя в пункте Name.
Параметр Save location , показывает и решает, где будет храниться ваш проект/приложения со всеми его файлами.
Далее нажимаем кнопку Finish
3. Открываем файл MainActivity.java , найдя его в каталоге проекта в папке "java" , и в ее под-папке com.example
Оставляем только строку:
package com.example.kota;
В вашем случае, вместо слова kota , в конце строки , будет название вашего проекта!
Остальное содержимое ниже этой строки надо убрать, и вместо этого, под строкой:
package com.example.kota;
Надо разместить следующий код, чтобы получилось в итоге как на скриншоте выше:
В данном случае имеет вначале символы // , т.к в данном языке ,и в данной версии программы , можно обойтись без этой строки, она здесь лишняя.
Символы // , отключают эту строку, по факту превращая ее из кода в текстовый комментарий, чтобы активировать строку кода-достаточно убрать символы // .
4. Откройте файл AndroidManifest.xml , расположенный в папке AndroidManifest.xml
Далее:
Первый вариант:
Допишите сразу под определением «application» следующую строку:android:hardwareAccelerated="true"
Второй вариант:
Выделяем весь код в файле AndroidManifest.xml , и вставляем вместо него следующий код, чтобы получилось примерно как на скриншоте выше:
6. В главном меню File выбираем: New - Folder - Assets folder
Далее , ничего вообще не изменяя и не трогая, просто нажимаем кнопку Finish.
7. В каталоге app найдите папку assets. Кликните по ней правой кнопкой мыши, и в появившемся меню выберите пункт - Open in , а в подменю выберите пункт - Explorer.
Откроется проводник WIndows, открыв ту самую папку assets , в которую нужно положить файлы вашего html-сайта или веб-страницы.
8. Теперь можно запустить приложение , выбрав в главном меню Run - Run app , или нажав сочетание клавиш Shift+F10 , и ваша html-страница или html-сайт, откроется на весь экран эмулятора смартфона.
9. Сборка Андроид-приложения и подпись Андроид-приложения в Android Studio.
В главном меню выбираем Build - Generate Signed APK
Откроется окно с заголовком Generate Signed Bundle APK
Далее нажмите «Create New»
Откроется окно-форма New Key Store
Первое поле Key Store Patch , это путь к папке, в которой будет сохранен ключ.
При нажатии на значок папки в поле поле Key Store Patch , выйдет форма с заголовком Choose keystore file , где выбираем папку для сохранения ключа, и имя для файла ключа.
Нажав на кнопку ОК , вы снова попадете в окно Key Store Patch , и здесь надо заполнить остальные поля. Пример заполнения , показан на скриншоте ниже.
Обозначения:
Alias - псевдоним
Password - пароль , который должен состоять из не менее шести символов
Confirm - подтвердить пароль, введя ранее указанный пароль
First and Last Name - Имя и фамилия
Organizaional Unit - Организационное подразделение
Organizaion - организация
State or Province - Штат или Провинция
После заполнения полей, нажимаем на кнопку ОК.
Поле этого, снова откроется окно с заголовком Generate Signed Bundle or APK , где ряд полей будет уже заполнен. Нажимаем здесь кнопку: Next
Появится окно с заголовком Generate Signed Bundle or APK , где надо заполнить два поля:
Destination folder - папка, куда будет сохранено собранное APK-приложение.
Build Variants - (Варианты сборки) , где надо выбрать вариант Release (релиз, выпуск).
Далее, нажимаем кнопку Finish
Затем , вы можете наблюдать полосу состояния сборки приложения - Gradle Build Running , в нижнем правом углу программы Android Studio.
Когда процесс сборки закончится, в этом же нижнем правом углу появится всплывающее сообщение с заголовком Generate Signed APK содержащее текст:
APK(s) generated successfully for module'Kota. app' with 1 build variant:…
Кликаем по этому сообщению, чтобы развернуть его , и нажимаем на слово locate ,чтобы открылась папка с созданным apk-файлом андроид-приложения.
Если всплывающее сообщение со словом locate исчезло, то можно нажать на фразу - Event Log , которая находится тоже в нижнем правом углу, и тогда откроется лог-список с нужным вам словом locate.
Данный apk-файл можно скопировать на смартфон, и открыв его - запустить установку вашего собранного приложения на смартфон.