Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Веселая аркада с Печенькой для новогоднего настроения. Объезжайте препятствия, а подарки, варежки, конфеты и прочие приятности не объезжайте: они помогут набрать очки и установить новый рекорд.

Сноуборд

Спорт, Аркады, На ловкость

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

ВКонтакте + Электроника

С этим тегом используют

Комментарии Скриншот Переписка Юмор Не мое Девушки Мат AliExpress Гаджеты Товары Китайские товары Техника Вертикальное видео Самоделки Все
7 постов сначала свежее
58
monobogdan
monobogdan
Посты о ремонте и моддинге ретрогаджетов.
TECHNO BROTHER
1 год назад

Друзья! Вышел новый видос, статью тоже на этой неделе постараюсь успеть подготовить⁠⁠

[моё] Гаджеты Покупка Смартфон Android Программирование Java Обзор Ретро Мобильные телефоны Электроника Телефон Железо Видео YouTube ВКонтакте Telegram Олдфаги
9
417
monobogdan
monobogdan
Посты о ремонте и моддинге ретрогаджетов.
Android
1 год назад

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности?⁠⁠

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

С момента выхода первой части статьи из рубрики «сам себе экосистема» прошёл уже практически год! За это время, мы успели с вами реализовать клиенты 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. Интересно? Тогда жду вас под катом!

❯ Содержание

  1. Но зачем всё это?

  2. Архитектура приложения

  3. Реализация сервера и работа с TDLib

  4. Android-приложение

  5. Как запустить клиент?

  6. Заключение

❯ Но зачем всё это?


На дворе уже стукнул 2024 год, современные смартфоны предлагают какие-то немыслимые мощности относительно тех, которые когда-то были в первых Android-девайсах. Сейчас за сотню баксов можно купить смартфон с хорошей 1080p IPS-матрицей, 4Гб ОЗУ и 8-ядерным шустрым чипсетом, который вполне способен плавно тянуть даже стремительно «жиреющие» на ресурсы клиенты социальных сетей, банков и прочие необходимые в повседневной жизни приложения.
И казалось бы: всё хорошо, покупай себе редмик раз в год или айфон раз в несколько лет и наслаждайся всеми прелестями работы современных приложений…

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Для многих людей смартфон — это лишь инструмент, повседневный компаньон, который помогает облегчить выполнение каких-то задач. Им совершенно не важно, как он выглядит, как ощущается в руках, какой у него дисплей и железо «под капотом», лишь бы работал да и нормально. Но есть и другая категория людей, для которых телефоны, смартфоны и любые портативные гаджеты — это не просто утилитарный девайс, а настоящее инженерное произведение искусства, с которого буквально сдувают пылинки и стараются до последнего пользоваться ими как повседневными устройствами. Хотите пример? Смотрите ниже:

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Фактически, среди современных смартфонов по сути и нет представителей такого нынче вымершего форм-фактора, как сайдслайдеры с физической QWERTY-клавиатурой, боковые раскладушки с двумя дисплеями и даже из QWERTY-моноблоков есть только смартфоны от Unihertz. Даже среди моноблоков с тачскринами нет никакого разнообразия, лишь без-рамочные одинаковые девайсы за исключением устройств от Sony.

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Galaxy S Plus

Раньше меня часто спрашивали, мол, да как ты вообще можешь пользоваться смартфоном 10-летней давности, на котором давно нет официальных клиентов популярных сервисов и только недавно, с развитием блога, мне перестали задавать этот вопрос, поняв, что это бесполезно — ведь это дело принципа и порыва энтузиазма! Смотрите сами: у нас уже есть простенькие, но вполне рабочие клиенты ВК, YouTube, сейчас я допиливаю клиент «Сбера» на СМСках, реализую карты OpenStreetMap (правда пока без адекватной навигации), а в будущем планирую написать приложение для мониторинга погоды и трекинга посылок. Кроме того, в рамках этой статьи мы реализуем с вами клиент Telegram: так чем же это не функционал современного смартфона?

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Но хорошо, с функционалом разобрались, однако для многих читателей слова «старый смартфон» это прямые синонимы «тормозной смартфон», мол «фуу, да как можно пользоваться этим тормозным кирпичом, он же лагает в последней версии моей ВКшечки!». Но давайте поставим вопрос ребром: может, это не столько девайсы немощные, сколько сами приложения, с кодовой базой, которая тянется более 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 может быть весьма проблематично, учитывая не самую лучшую документацию.

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Но городить велосипед и не нужно, поскольку у команды 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!

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

К сожалению, поскольку 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 медиаэлементов. Так что листинги будут совсем без табов, но алгоритм их работы понять можно :)

[DllImport(Library, EntryPoint = "td_create_client_id", CallingConvention = CallingConvention.Cdecl)]
public static extern int CreateClientID();

[DllImport(Library, EntryPoint = "td_send", CallingConvention = CallingConvention.Cdecl)]
public static extern void Send(int id, string request);

[DllImport(Library, EntryPoint = "td_receive", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr RawReceive(double timeOut);

[DllImport(Library, EntryPoint = "td_execute")]
public static extern StringBuilder Execute(string request);

public static unsafe string Receive(double timeOut)
{
IntPtr str = RawReceive(timeOut);

return str != IntPtr.Zero ? new string((sbyte*)str.ToPointer()) : null;
}

Позволю себе чуточку критики в сторону 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);

string type = json["@type"].ToString();

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, что означает готовность библиотеки к работе:

private void OnAuthState(string raw, JObject obj)
{
JObject authState = (JObject)obj["authorization_state"];
string type = authState["@type"].ToString();

if (type == "authorizationStateWaitTdlibParameters")
{
Console.WriteLine("Preparing TDLib parameters...");
NativeInterface.Send(InstanceID,
Utils.Format("{" +
"\"@type\": \"setTdlibParameters\", " +
"\"database_directory\": \"tdlib\", " +
"\"api_id\": {0}, " +
"\"api_hash\": \"{1}\", " +
"\"use_chat_info_database\": true," +
"\"use_file_database\": true," +
"\"use_message_database\": true," +
"\"system_language_code\": \"en\", " +
"\"device_model\": \"Phone\", " +
"\"application_version\": \"1.0\" " +
"}", APIId, APIHash));
}

if (type == "authorizationStateWaitPhoneNumber")
{
Console.WriteLine("Sending phone number");
NativeInterface.Send(InstanceID, Utils.Format("{\"@type\": \"setAuthenticationPhoneNumber\", \"phone_number\": \"{0}\" }", PhoneNumber));
}

if(type == "authorizationStateWaitCode")
{
NativeInterface.Send(InstanceID, Utils.Format("{\"@type\": \"checkAuthenticationCode\", \"code\": \"{0}\" }", WaitCode));
}

if(type == "authorizationStateReady")
{
Console.WriteLine("Authorized");

waitHandle.Set();
}
}

...

Client.AttachEventHandler("updateAuthorizationState", OnAuthState);

После этого, можно начать работу с данными. Обратите внимание, мой подход потоко-небезопасен, его нельзя дергать из нескольких потоков одновременно! В коде ниже, я вызываю метод для фетча сообщений, а затем в соответствующем коллбэке от TDLib обрабатываю данные (дабы статья не разрасталась на 20+ минут, я чуть урезал все листинги).

public List<Message> QueryMessagesInChat(long chatId, long lastMessage, int count)
{
messages.Clear();

requestMessageCount = count;
string json = Utils.Format("{\"@type\": \"getChatHistory\", \"chat_id\": \"{0}\", \"from_message_id\": {1}, \"limit\": {2} }", chatId, lastMessage, count);
NativeInterface.Send(InstanceID, json);

waitHandle.WaitOne();
return messages;
}

public User QueryUser(long userId)
{
string json = Utils.Format("{\"@type\": \"getUser\", \"user_id\": \"{0}\" }", userId);
NativeInterface.Send(InstanceID, json);

waitHandle.WaitOne();
return user;
}

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

private HttpListener listener;
private List<HttpMethodHandler> methods;
private ScheduledRestart restartManager;

private void AddMethod(HttpMethodHandler info)
{
if(info != null)
{
methods.Add(info);
Console.WriteLine("Registered method: {0}", info.Method.Name);
}
}

private void PrepareMethods()
{
AddMethod(Chats.QueryChats);
AddMethod(Chats.QueryMessages);
AddMethod(Chats.SendMessage);
AddMethod(Users.QueryUserInfo);
}

private void PrepareState()
{
// We should fetch dialog list due to TDLib nature of preloading-everything
Client.QueryChats(15);
}

public HttpServer()
{
listener = new HttpListener();
listener.Prefixes.Add("http://+:13377/");

Client = new SyncClient("test");
Client.Start();
Client.WaitUntilReady();

//restartManager = new ScheduledRestart(5);
//restartManager.Start();

methods = new List<HttpMethodHandler>();
PrepareMethods();
PrepareState();
}


...

public void Start()
{
listener.Start();

while(listener.IsListening)
{
HandleRequest(listener.GetContext());
}
}

Переходим к обработке запроса. Метод ищет, зарегистрирован ли запрошенный метод и если да, то парсит строку запроса, которая начинается с "?", которую затем передаёт в виде коллекции ключ->значения обработчику метода:

private void HandleRequest(HttpListenerContext ctx)
{
string method = ctx.Request.Url.LocalPath.Substring(1).ToLower();

if (method.Length < 0)
{
SendResponse(HttpGenericResponse.MethodRequired.ToString(), ctx);
return;
}

foreach(HttpMethodHandler handler in methods)
{
if(method == handler.Method.Name.ToLower())
{
string result = "";

if (ctx.Request.Url.Query.Length > 0)
{
string[] args = ctx.Request.Url.Query.Substring(1).Split('&', StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();

foreach (string arg in args)
{
if (arg.IndexOf('=') >= 0)
keyValuePairs.Add(arg.Substring(0, arg.IndexOf('=')), arg.Substring(arg.IndexOf('=') + 1));
else
keyValuePairs.Add(arg.Substring(0, arg.IndexOf('=')), "");
}

result = handler(keyValuePairs);

if (result == null || result.Length < 1)
{
Console.WriteLine("Suspicious result from {0}", handler.Method.Name);
}
}

SendResponse(result, ctx);
return;
}
}

SendResponse(HttpGenericResponse.UnknownMethod.ToString(), ctx);
}

А сами методы, в свою очередь, дергают соответствующие функции из клиента и формируют на их основе датасет в примитивном формате:

public static string QueryChats(Dictionary<string, string> args)
{
if(args.ContainsKey("count"))
{
int count = int.Parse(args["count"]);
StringBuilder ret = new StringBuilder();

List<Chat> chats = HttpServer.Instance.Client.QueryChats(count);
ret.AppendLine(string.Format("Count={0}", chats.Count));

foreach(Chat chat in chats)
{
ret.AppendLine("Begin");
ret.AppendLine("ID=" + chat.ID);
ret.AppendLine("Date=" + chat.LastMessageDate);
ret.AppendLine("Name=" + chat.Name);
ret.AppendLine("Text=" + Uri.EscapeDataString(chat.LastMessageText));
ret.AppendLine("MsgId=" + chat.LastMessageID);
ret.AppendLine("End");
}

return ret.ToString();
}

return HttpGenericResponse.InternalException.ToString();
}

В результате получаем вот такой простой датасет, который, как я и говорил, легко распарсить и на Siemens C60, и на Atmega328 — да где угодно! В целом, такой сервер можно использовать для реализации бота в телеграме, который будет передавать показания каких-то датчиков, сигнализацию и прочие клевые штуки!

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Переходим к реализации клиента, т.е. приложения на Android. Здесь будет не менее интересно!

❯ Пилим для Android


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

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

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Такой вот простой макет.

Каждый пункт меню — это тоже отдельный layout, в котором мы по шаблону строим внешний вид будущего элемента списка. На немолодых устройствах есть смысл использовать как можно меньше контейнеров в layout'е, поскольку пересчет позиций и размеров элементов — одна из самых «тяжелых» операций в UI-фреймворке вообще. Кроме того, не стоит использовать кучу картинок и drawable — в Android 2.x всё 2D рисуется софтварно, аппаратное ускорение появилось только в 3.0 (частично).

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Но дабы в списке диалогов что-то появилось, нужно сначала реализовать фетчинг (получение) этих самых диалогов с сервера! Сам объект, который занимается обработкой запросов называется ClientManager и является синглтоном — он в единственном экземпляре на все время работы программы. Помимо менеджмента «ноды» (т.е. прокси-сервера), токена для авторизации и обработчика ошибок, ClientManager реализует метод для асинхронного запроса информации с сервера и, собственно, формирует строки запросов с помощью соответствующих методов:

public void queryChats(int count, Response resp) {
sendRequest(String.format("%s/QueryChats?count=%d&auth_key=%s", nodeAddress, count, token), resp);
}

Подгрузка чатов и сообщений реализована через Adapter — концепция «виртуальных» списков, которая предполагает что система создаст не 50 элементов интерфейса на каждую кнопку чата, а только 5 и будет их виртуально «мотать по кругу», обновляя только данные в уже существующих элементах. Это позволяет значительно ускорить отрисовку, учитывая то, что Android 2.x Canvas рисуется программно.

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

private void updateDialogList() {
ClientManager.getCurrent().queryChats(50, new ClientManager.Response() {
@override
public void onReady(String str) {
try {
List<Packets.Chat> chats = Packets.parseChatListFromQueryResponse(str);

DialogAdapter adapter = new DialogAdapter();
adapter.setChats(chats);

((ListView) findViewById(R.id.messages_view)).setAdapter(adapter);
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Упс!", Toast.LENGTH_SHORT);
}
}
});
}

Ну вы уже явно замучились видеть простыни кода, давайте посмотрим что у нас вышло!

Шустренько, да? А ведь это ультрабюджетник Alcatel OT-916D, один из последних массовых дешевых QWERTY-смартфонов за 5 000 рублей из 2012 года. Кстати, смартфон подарил мне читатель chuvakoff с Хабра!

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

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

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

view.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
// Reply to...
contextMenu.add(getString(R.string.reply)).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
setReplyContext((Packets.Message) view.getTag());

return true;
}
});

// Copy
contextMenu.add(getString(R.string.copy)).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
ViewGroup vg = (ViewGroup)view;

android.text.ClipboardManager manager = (android.text.ClipboardManager) view.getContext().getSystemService(CLIPBOARD_SERVICE);
manager.setText(((TextView)vg.findViewById(R.id.message_content)).getText());

return true;
}
});

// Send to...
contextMenu.add(getString(R.string.resend)).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
ViewGroup vg = (ViewGroup)view;
String text = ((TextView)vg.findViewById(R.id.message_content)).getText().toString();

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, null));

return true;
}
});
}
});

Переходим к реализации поля для ввода сообщения. Здесь всё просто — на серверсайде за это отвечает метод SendMessage. Однако для того, чтобы с нашего клиента можно было ответить на другие сообщения, я ввёл также «контекст ответа», в котором запоминается сообщение, на которое мы хотим ответить. Telegram также поддерживает Markdown, однако его полная поддержка пока не реализована.

EditText editText = ((EditText)findViewById(R.id.message_text));

if(editText.getText().length() > 0) {
long replyTo = replyContext != null ? replyContext.ID : 0;

ClientManager.getCurrent().sendTextMessage(chat.ID, editText.getText().toString(), replyTo, new ClientManager.Response() {
@Override
public void onReady(String str) {

}
});

editText.setText("");
setReplyContext(null);
}

В остальном же, функционал конечно пока совсем базовый, однако клиент работает очень шустро даже бюджетной X10 Mini Pro и позволяет чатится с моими читателями в Telegram. В будущем хотелось бы допилить:

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

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

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

    Казалось бы — до официальных клиентов ещё очень далеко. Но сам факт, чтобы всё это работало достаточно шустро на девайсах, которым уже более 10 лет!

❯ Звучит интересно! Как заюзать твой клиент?


Тут всё очень и очень просто! В первую очередь, нам понадобится ПК с белым IP, роутер (если под него есть сборка dotnet), либо VDS. Виртуальные сервера сейчас стоят копейки, у ТаймВеба есть тариф за 188 рублей в месяц, которого с головой хватит для нашего сервера.

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Такая вот рекламная интеграция (к слову, прокси для всех приложений уже более года крутятся именно на мощностях TimeWeb Cloud)!

Берём уже собранный TDLib и сервер под Windows, или собираем TDLib под Linux, накатываем .NET Core. Пример для Debian/Ubuntu:

sudo apt-get install dotnet

Затем запускаем сервер:

dotnet tdsrv.dll

Программа сначала запросит номер телефона, а затем код подтверждения Telegram. После этого будет создана папка tdlib/, где будут хранится данные вашей сессии, а также файл authkey.txt, где хранится случайный ключ для сессии (md5 phone_number + response code + псевдослучайное число). Не оставляйте его в /var/www/!

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Если всё нормально, программа начнёт слушать порт 13377 на всех сетевых интерфейсах, в т.ч и в локальной сети. После этого, ставим уже предварительно собранный, либо собираем сами в Android Studio APK и в окне авторизации пишем адрес ноды и ключ авторизации. Если всё настроено верно — программа запомнит сервер и будет работать без проблем! Вот так всё легко :) Как видите — всё очень и очень просто!

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Кроме того, буквально за пару дней до публикации статьи я сел вечерком из интереса что-нить под Java-телефоны попилить… и, как и обещал, реализовал Proof of Concept возможности работы Telegram даже на сонериках, которым скоро 20 лет стукнет! А ведь если ещё чуть заморочится, можно запустить приложение даже на преусловутых монохромных сименсах!

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

❯ Заключение


Вот такой у нас получился проект с реализацией лёгкого, примитивного, но тем не менее рабочего клиента Telegram, который на клиентской части вообще не использует никаких зависимостей. Вес собранного APK в release-версии — всего 54 килобайта! Понятное дело что с ростом функционала, вес программы будет увеличиваться, но я обещаю — больше 1Мб он не вырастет :)

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Ну а вам, моим читателям, надеюсь было интересно прочитать такой «двойной материал» не только о разработке сетевой части без использования Apache/nginx/IIS, но и UI-фронтэнда для Android-смартфонов, которым уже более 10 лет!
Исходный код проекта можно найти на моём GitHub: как приложения, так и сервера, а также убедиться в отсутствии каких либо закладок и, если совсем не доверяете, собрать бинарники сами! Для сборки понадобится VS2017 или свежее, а также Android Studio 2.3.2 (если собираете для Android 2.1 и ниже).

Сам себе экосистема. Часть 4: как я реализовал клиент Telegram на Android-смартфоне 14-летней давности? Программирование, Гаджеты, Смартфон, Покупка, Android, Java, Код, Приложение, Telegram, ВКонтакте, Научпоп, Клиенты, Программа, Софт, Кейс, Гик, Электроника, Видео, YouTube, Длиннопост

Друзья! Сейчас на Хабре опросы сломаны, поэтому если у вас есть желание, вы можете проголосовать в комментариях: какой стиль статей вам больше нравится — где больше конкретики и кода с пояснением как конкретно работает та или иная часть программы, или наоборот стиль ближе к научпопу, где фрагментов кода нет, или их значительно меньше? Пишите своё мнение о проекте в комментариях!

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

Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать новые статьи каждую неделю!

Показать полностью 18 2
[моё] Программирование Гаджеты Смартфон Покупка Android Java Код Приложение Telegram ВКонтакте Научпоп Клиенты Программа Софт Кейс Гик Электроника Видео YouTube Длиннопост
79
649
monobogdan
monobogdan
1 год назад
TECHNO BROTHER

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения⁠⁠

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Размер экрана — краеугольный камень мира современных смартфонов. Кто-то считает, что дисплеи должны становиться только больше, а рамки — меньше, кто-то любит «средние» дисплеи диагональю в 5+", ну а кто-то остаётся ярым поклонником и приверженцем компактных смартфонов с крошечными дисплейчиками. В наше время, купить новый смартфон с относительно небольшим дисплеем за приемлемые деньги почти нереально — самые бюджетные модели будут слишком тормозными для современного пользователя. Некоторое время назад, я купил себе бюджетный крошечный смартфон 2012 года выпуска — Samsung Galaxy Pocket, причём всего за 100 рублей. Конечно же мне захотелось довести его до ума — а доводить пришлось руками и навыками прожженного программера! Какой смартфон можно получить за 100 рублей? Читаем в статье!

Минутка предыстории

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

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Однако несмотря на всеобщее засилие больших «лопат», в мире всё ещё оставались поклонники маленьких и компактных телефонов, которыми очень удобно пользоваться одной рукой. Сейчас подобные устройства представляют только небольшие бренды, известные достаточно в узких кругах — в основном, их можно купить на маркетплейсах, в обычных салонах связи их не найти. Мне известно о нескольких подобных устройствах, которые сейчас присутствуют на рынке. Первый из них «закос» под iPhone — Soyes XS11:

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Но тут уж, если честно, хочется назвать такой смартфон не просто компактным, а совсем малюсеньким. На нём вполне удобно выполнять задачи звонилки, но совсем неудобно набирать текст — поэтому под наши задачи, он не особо подходит. Кроме того, эти девайсы работают на базе бюджетного смартфонного железа 6-7 летней давности, поэтому их производительность будет достаточно невысокой по меркам современного пользователя. Конечно же есть и более серьёзные варианты — например, компания Unihertz (да, тот самый продолжатель идей BlackBerry) делает смартфоны Jelly 2: дисплей с диагональю 3", Helio P61 под капотом и Android 11 на борту. Вот только цена, мягко говоря, кусачая — 18 тысяч рублей на момент написания статьи. Это слишком дорого!

Но если душа прямо таки лежит к компактным смартфонам, почему бы не обратиться к рынку Б/У устройств и не присмотреть что-то из… прошлого десятилетия? А вариантов ведь реально много — тут и LG Optimus L3 (3.2"), и Samsung Galaxy Pocket Neo (2.8"), Samsung Galaxy Star (3"), Samsung Galaxy Fame (3.5"), Samsung Galaxy Young. Все перечисленные девайсы стоят реально копейки — можно купить живой вариант до 400-500 рублей!

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Я решил взять себе целых два смартфона: Samsung Galaxy Mini и Samsung Galaxy Pocket первого поколения. Оба достались мне в одном лоте за 2.000 рублей (с 20 телефонами) и обошлись мне по сто рублей, причём оба смартфона были рабочими! Чуть позже я докупил отдельно Galaxy Star (250 рублей), Galaxy Fame (250 рублей) и Galaxy Pocket Neo (~400 рублей) для полноты коллекции — вышло совсем недорого. Итак, что за характеристики мы получаем в смартфоне за 100 рублей:

  • Android: 2.3 Gingerbread.

  • Чипсет: Broadcom BCM21553 с одним ядром Cortex-A5 на частоте 832мгц. Видеочип: VideoCore IV, он же использовался в Raspberry Pi.

  • ОЗУ: 256 мегабайт (предположительно — DDR1).

  • Встроенная память: 3 гигабайта + слот для SD.

  • Дисплей: 2.8", 240x320, емкостной тачскрин.

  • Сеть: Поддержка 2G/3G. Об LTE и речи не идёт.



Выглядит не особо густо, да? И разрешение весьма низкое — большинство софта не запустится, а о клиентах современных сервисов и мечтать не приходится… или приходится?

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



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

Разработка под старые версии Android

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

Даже сейчас нет никакой проблемы скачать последнюю версию Android Studio, подключить смартфон с включенной отладкой и отлаживать приложение прямо на девайсе — logcat тоже есть. Единственный нюанс — поиск драйверов и ручное закрытие приложений в таскменеджере, если вы деплоите под Android 2.x (Android Studio не умеет сам закрывать приложение, чтобы переустановить пакет).


В целом, за всё время разработки под старые устройства, я пришёл к следующим выводам:

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

  • Взаимодействие с современными веб-сервисами может быть осложнено из-за отсутствия поддержки TLS1.2 и устаревших сертификатов (проверка сертификатов легко обходится специальным костылем, а вот TLS — нет).

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

  • Пушей нет — да, вообще. Однако это ничуть не помешает нам сделать уведомления практически в реальном времени с помощью… очередного костыля!



Допиливаем ВК

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

Честно сказать, вся концепция интерфейса требовала полной переработки — боковое меню банально очень неудобно использовать на подобных устройствах из-за малых размеров каждой строчки. Поэтому я решил не изобретать велосипед, а обратился к дизайнерам Apple и первоисточнику: официальному клиенту ВК для iOS 6, родом из 2012 года!

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Приложение для Android выглядело +- также в те годы. Видите вкладки с разделами снизу? Они то нам и нужны — это самый удобный способ навигации на таких смартфонах! Накидав макет в layout'е, я приступил к реализации:

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Изначально мне хотелось, чтобы всё приложение было плавным и анимированным: для этого я обратился к фреймворку анимаций Android. Суть очень простая — это обычный интерполятор значений от a до b за определенный промежуток времени. При этом мы не можем анимировать произвольное свойство — только те, который уже реализованы в системе (переход, поворот, масштабирование, альфа-канал). Более наглядно это можно представить вот так:

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Да, это всё анимация :) Получаем примерно такой результат:

Обратите внимание, что запуск большого количества анимаций будет вызывать перерисовку даже в том случае, если элемент не видно на экране — от чего у нас будут дикие тормоза! Осторожнее с этим.

После этого, я решил доработать раздел с музыкой: я все еще пользуюсь грязными хаками для получения доступа к API музыки, поскольку «левым» клиентам такой возможности не дают. Публично его расписывать не буду, поскольку это скорее всего нелегально, да и сами ребята из ВК об этом знают (но не думаю, что будут применять какие-то санкции по отношению к «маленьким» разработчикам) — но если нужно, пишите в личку, расскажу всю концепцию.

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

В Android есть два типа служб: background (фоновые) и foreground (видимые пользователю). Первый тип служб система может прибить когда угодно — например мало памяти или экономия заряда АКБ. А вот второй тип служб система не прибивает практически никогда, поскольку они обозначают выполнение важной операции в фоне — например скачивание файла или обновление системы. Однако у них есть одно ограничение — они должны быть привязаны к собственному уведомлению, которое нельзя закрыть. В процессе реализации возникло еще пару проблем — Wakelock'и (механизм, предотвращающий уход девайса в «сон») и WiFiLock'и (тоже самое, но для WiFi).

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост

Точно таким же способом я реализовал механизм уведомлений — как я уже говорил раньше, пушей на старых смартфонах нет вообще ни в каком виде, поэтому пришлось реализовывать свой механизм «обновления»: каждые 3-5 секунд запрашиваем список последних 5 диалогов с сервера и сравниваем с предыдущим результатом, если есть новые сообщения — создаём нотификацию (листинг слишком длинный - пришлось перезалить на pastebin):

private NotificationCompat.Builder createMessageNotification(String sender, Stri - Pastebin.com

После этого, я начал рутинную работу по реализации интерфейса для данных с сервера — паблики, друзья, профили, лента и.т.п. В некотором смысле, реализация лента весьма занимательна: вообще, для очень больших списков существуют т.н виртуализация ListView — это когда ListView отображает только видимый пользователю кусок датасета (набора данных — например, список записей на стене) и на старых версиях Android она доступна. Однако мне было интересно реализовать вариант, который потреблял бы минимальное количество ОЗУ и где я точно знал бы, когда пользователь видит тот или иной фрагмент приложения. Поэтому я реализовал… пагинацию свайпами! Вот так привет из нулевых!

Для этого я использовал GestureDetector — встроенный в систему класс для обнаружения простых жестов — свайпов и.т.п. ВК при запросе ленты отдаёт специальную метку для получения следующей страницы новостей (поскольку она может динамически меняться и нужно хранить её стейт), мы эти метки просто сохраняем и переключаемся по странницам новостей с помощью обычных свайпов вправо-влево:

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост


Выглядит весьма забавно.

Юзабельно ли всё это на деле?

Давайте смотреть, может ли юзать такой смартфон в наши дни. Берём наш девайс в руки, логинимся и оцениваем его производительность «вхолостую».

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Работает весьма шустренько, учитывая что это бюджетник 2012 года. Как насчет нашего самопального клиента ВК? Смотрим:


Работает весьма бодро. Не сказать что также плавно, как последний айфон, но и совсем плохим результат явно не назвать!

Смартфонный функционал у девайса тоже вполне ничего: 1-2 SIM (в зависимости от версии), нормальная синхронизация контактов с ПК (однако Kies вроде-бы не работает на Windows 10, но есть vcf):

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Встроенный почтовый клиент продолжает работать без каких либо проблем. Однако настраивать некоторые почтовые сервисы нужно вручную и с помощью «паролей приложений» — напрямую залогинится возможности нет. В случае «покета», придется поставить стоковый клиент из Android 2.3 вручную.
Мультимедийные возможности тоже радуют: встроенный плеер тачвиза мне всегда очень нравился. Есть и настройки эквалайзера.

Единственное, что откровенно подводит — браузер. Последним вариантом осталась Opera Mini 7 — она позволяет смотреть сайты, но не поддерживает динамический контент, только статику. Ну, зайти на википедию или почитать статью на Хабре хватит. Родной браузер уже не в состоянии что либо загрузить :(

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост



Ну а в общем, производителньость смартфона весьма радует, согласитесь? Нельзя сказать, что он уж слишком тормозной — по крайней мере, современные ультрабюджетные смартфоны (до 4-5 тысяч рублей) зачастую показывают себя гораздо хуже чем и флагманы прошлых лет, и даже бюджетники!

Заключение

И всё таки, я считаю что мне удалось в каком-то смысле вдохнуть новую жизнь в старенький девайс. Если использовать подобный девайс как второй — на случай, если сел основной смартфон, то такой миниатюрный красаввчик может неождианно выручить даже в довольно сложной ситуации. Кроме того, эти смартфоны всеядны к аккумуляторам — достаточно подпаять + и — и они будут работать хоть от BL-4C.

Главная ценность Galaxy Pocket — в его компактных размерах. А поскольку по настоящему дешевых, маленьких и шустрых смартфонов становится всё меньше и меньше, то нам остаётся лишь продлять жизнь моделям прошлых лет! Есть ли в этом смысл и получил ли смартфон новую жизнь? Пишите в комментариях!

Микросмартфон за 100 рублей: Покупаем смартфон 11-летней давности и… пишем под него приложения Гаджеты, Android, Смартфон, Покупка, Galaxy, Samsung, Java, Программирование, Самопал, ВКонтакте, Ретро, Девайс, Ништяки, Мобильные телефоны, Электроника, Телефон, Linux, Видео, Без звука, Вертикальное видео, YouTube, Длиннопост


Клиент ВК можно сказать на 4pda. Там лежит самая последняя версия (для скачивания нужна регистрация на форуме). Если по каким-то причинам не хотите регистрироваться на форуме — я выложил актуальную версию в комментариях.


Эта статья поддерживается командой ITGLOBAL.COM

Мы — первый облачный провайдер в России, а также интегратор, поставщик ИТ-услуг, продуктов, сервисов и разработчик собственного ПО.

• Наш сайт
• Наш блог про виртуализацию и Enterprise IT
• Истории успеха наших клиентов

Показать полностью 13 2
[моё] Гаджеты Android Смартфон Покупка Galaxy Samsung Java Программирование Самопал ВКонтакте Ретро Девайс Ништяки Мобильные телефоны Электроника Телефон Linux Видео Без звука Вертикальное видео YouTube Длиннопост
91
4
Seviddevi
4 года назад

Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!!⁠⁠

Есть несколько причин почему я пишу сей длиннопост (рекомендую дочитать до конца):


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


Во-вторых ,если этот пост хоть кого-то разубедит покупать у данного магазина и потерять свои кровные , значит я не зря потратила  время на его написание


В-третьих , я лично убедилась ,что их комментаторы в инстаграм и люди оставляющие отзывы в обсуждениях в вк ЛИПОВЫЕ (как я недавно узнала отзывы в интернете пишутся на заказ ) Я написала около 10и людям ,оставившим отзывы в инстаграм и вк и никто из них не ответил (некоторые страницы мертвые ,а некоторые вообще читали и не отвечали ,но это все после того, как я поняла ,что меня обманули )

ВНИМАНИЕ !!!!!

ПОСТ Я ПИШУ МАКСИМАЛЬНО ПОДРОБНЫЙ ,С ПРЕДОСТАВЛЕНИЕМ ВСЕХ СКРИНШОТОВ И ЧЕКОВ ОБ ОПЛАТЕ (естественно с сокрытием моих контактных данных), ДАБЫ МЕНЯ НЕ ОБВИНИЛИ В ГОЛОСЛОВНОСТИ (не исключаю, что под этот пост могут набежать «довольные покупатели» и пытаться опровергнуть мои слова ,но я описываю свой личный опыт от 13.01.2021 года ) .

ВСЕ СКРИНЫ ПОДЛИННЫЕ ,НЕОБРЕЗАННЫЕ И НИ ОДНО СООБЩЕНИЕ В ОБЩЕНИИ С ПРОДАВЦОМ НЕ БЫЛО УДАЛЕНО !!!

ЕСЛИ НЕТ ЖЕЛАНИЯ И/ИЛИ ВРЕМЕНИ ЧИТАТЬ , ТО РЕЗЮМИРУЮ : МЕНЯ ОБМАНУЛИ НА 46 700 РУБЛЕЙ

Итак моя история : В далеком 2016 я приобрела айфон 6 S ,который служ-ил/-ит мне верой и правдой, но сейчас он на порядок устарел , поэтому я решила обновить телефон и купить себе новый . Мне приглянулся Iphone 11 purple . Скитаясь по страницам инстаграма в один из январьских праздничных вечерочков я наткнулась на страницу магазина Isclad.ru ИВАНГОРОД (таргетированная реклама все-таки свое дело делает) это было примерно 4-5 января . Я зашла на их сайт ,указанный в шапке профиля , нашла выбранный ранее мной телефон и он оказался по привлекательной цене 54.590 рублей (НО! это цена еще до скидки,о которой я узнала позже ,меня даже изначальная устроила за 128 GB) . Естественно я не ринулась покупать в тот же момент, просто подписалась и просматривала периодически их истории в инстаграм . Чуть позже , читая и просматривая отзывы на их странице , обратила внимание на формулировку «Tax free cash refund до 20%» не поняла что это и решила написать продавцу в директ (скрины с его разъяснениями прикрепляю ниже) .

последнее сообщение в директ было написано во вторник 19.01.2021 после чего они меня благополучно заблокировали

Я сталкивалась с мошенниками в интернете,но обходила их стороной (лепечут в сравнении с этими) , Isclad.ru Ивангород обошел их по убедительности ПО ВСЕМ КРИТЕРИЯМ

РАССКАЗЫВАЮ ПОЧЕМУ ПОВЕРИЛА

заморочились :

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

2. ИП на имя Ткачева Андрея Владимировича с предоставлением всех номеров (БИК, р\с , корр. счет, если загуглить ,то все кажется прозрачным )

3. С созданием на каждого покупателя ЯКОБЫ договора о купле-продаже ( в подлинном договоре ОБЯЗАТЕЛЬНО должны указываться паспортные данные обеих сторон – покупатель\продавец , я это узнала после …), который вам скидывается после оформления заказа на сайте . Договор,отправленный продавцом прикреплю ниже

4. С продумыванием истории о кэш фри ( Ивангород , Ленинградская область находится на границе с Эстонией разделяет их река Нарва )то есть можно легко и беспрепятственно пересечь границу на машине , и приобрести необходимый товар , а потом оформив необходимую документацию вернуть 15-20% добавочного налога (это я себе всё так в голове обрисовала, но и слова продавца укрепили мою веру в эту теорию )

5. Каждодневные истории в инстаграм с довольными покупателями , распаковывающими технику

6. Истории в инстаграм с якобы пересылкой товаров и демонстрацией чеков с трек-номерами

7. Многочисленные положительные отзывы (с липовыми комментаторами и отзовиками , создающие впечатление ажиотажа на их продукцию)

8. Плюс это не страница-однодневка, ведется аж с 2017( может тогда и работали честно)

9. Сказочка про возврат товара в течение 14 дней,если что-то не устроит и отсылки на законодательную базу ( якобы они придерживаются позиции "Клиент всегда прав")

10. На официальном сайте Isclad.ru ,на странице в вк и инстаграм указаны номера для обратной связи с клиентом ( я не позвонила с самого начала , но когда набрала их и причем с разных номеров в разное (рабочее!) время в РАЗНЫЕ дни, потому что мне перестали отвечать и везде заблокировали, я услышала: «К сожалению в настоящее время мы не можем ответить на ваш звонок ,пожалуйста оставьте голосовое сообщение после звукового сигнала или перезвоните позднее», но и позднее естественно никто и не собирался отвечать на звонки )

11. Множество вариантов для покупки (в рассрочку , по полной предоплате, наложенным платежем (но скидки в 15% вы не получаете - фактор человеческой жадности :D) и так далее)

12. И конечно же убедившим меня фактором стала ЦЕНА , но лучше б я переплатила 10 тыс и купила в официальном магазине (об этом ниже про cash refund)

ТО ЕСТЬ подытожив все вышеописанные моменты У МЕНЯ сложился образ честного магазина , открытого для связи с покупателем

Итак собственно счет на оплату предоставленный мне и квитанция со Сбербанк Онлайн с моей оплатой на счет некого Негуторова Андрея Викторовича , представляющего интересы господина Ткачева Андрея Владимировича ,на которого ,собственно , и оформлено данное ИП . Я решила купить по полной предоплате из-за опять же скидки в 15% на вышеупомянутую сумму 54590 рублей за IPhone 11 Purple 128 gb из-за уже довольно высокого уровня доверия к данному магазину .

СКРИНЫ :

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

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

Наступает пятница - день отправки товаров . В сторис инстаграм страницы Isclad.ru (так они там и записаны) молодой человек говорит , что сегодня день отправки ждите до 22:00 номера трек-номеров на электронную почту по мск , но трек-номер не пришел ни в этот день ни на следующий  . Далее следует беседа в вотсап( последнее сообщение написанное мной 19.01.21), из которой становится ясно , что никто мне ничего не пришлет . Мне перестали отвечать на сообщения , на звонки и заблокировали . Сегодня 21.01.21 деньги так и не поступили на карту

Естественно я эту ситуацию так не оставлю (дополню отзыв по мере продвижения в этом деле)

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

p.s. ЕСЛИ ВАС ВСЁ ЖЕ НЕ РАЗУБЕДИЛО ВСЁ ВЫШЕСКАЗАННОЕ ,а красивые картинки и видео с запаковкой товара в их инстаграме и вк кажутся вам убедительными , то смело покупайте

у меня это закончилось горьким опытом и потерей 46700 рублей ISCLAD.RU Ивангород Кингисеппское шоссе 9 , ТРЦ "Русь" 1 этаж

Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Про интернет-магазин Isclad.ru Ивангород . ОСТОРОЖНО МОШЕННИКИ !!!!!! Мошенничество, Интернет-мошенники, Интернет-магазин, Ивангород, Обман клиентов, Возврат денег, Возврат товара, Электроника, iPhone, iPad, Macbook, Tax-free, Instagram, ВКонтакте, Длиннопост, Негатив
Показать полностью 22
[моё] Мошенничество Интернет-мошенники Интернет-магазин Ивангород Обман клиентов Возврат денег Возврат товара Электроника iPhone iPad Macbook Tax-free Instagram ВКонтакте Длиннопост Негатив
28
662
okovochka
8 лет назад

Стена вконтакте⁠⁠

Профессиональный юмор электронщиков

Стена вконтакте Профессиональный юмор, Схема, Электроника, ВКонтакте, Длиннопост
Стена вконтакте Профессиональный юмор, Схема, Электроника, ВКонтакте, Длиннопост
Стена вконтакте Профессиональный юмор, Схема, Электроника, ВКонтакте, Длиннопост
Стена вконтакте Профессиональный юмор, Схема, Электроника, ВКонтакте, Длиннопост
Показать полностью 4
Профессиональный юмор Схема Электроника ВКонтакте Длиннопост
14
17
tCode255
tCode255
9 лет назад

Ну, Travolta, погоди!⁠⁠

Джон Траволта Яйца Электроника ВКонтакте Coub
0
6
EvgenGeller
EvgenGeller
11 лет назад

Начали готовиться... Экзамен через день...⁠⁠

Начали готовиться... Экзамен через день...
Экзамен Электроника ВКонтакте Переписка
9
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии