Dolgo.polo Dev | Денис Долгополов – Telegram
Dolgo.polo Dev | Денис Долгополов
2.27K subscribers
87 photos
2 videos
120 links
Разбираемся в мобильной разработке (Android/iOS) и пытаемся выяснить, зачем оно так устроено

Статистика/цены: @dolgo_polo_dev_stats

По вопросам/рекламе: @dolgopolovdenis
Download Telegram
Channel name was changed to «Dolgo.polo Dev | Денис Долгополов»
произошел ребрендинг

p.s. 10 лайков и начинаю копить на экспресс-дизайн от Николая Иронова
46👍7
Во что упороться, если надоел обычный Android

Этот мир абсолютно понятен и захотелось челленджа?

Тогда можно попробовать:


VR / AI


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

сейчас все работает из коробки, есть бесплатные SDK


AndroidTV


уровень входа низкий. отличий от обычного андроида крайне мало:

• UI управляется только перемещением фокуса с пульта

• железо телека часто слабее ноунейм телефона за 4к рублей

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

первые шаги можно сделать на эмуляторе (прямо в Android Studio), а потом прикупить приставку за 5к+ рублей и запускать в гостиной свое приложение

дешевые приставки не берите (я брал)


Оптимизации


Это вечное

Можно поускорять запуск приложения, замерить количество fps в UI, поразгонять сетевые запросы, снизить прожорливость RAM и расход батареи....


Мультиплатформ + iOS


Переписать свой проект, чтоб он скомпилировался под iOS)

Изучить аналоги android-библиотек, вдохновиться их подходами, добавить в резюме фулл-стек-разработчик...


WearOS / Android Auto


тут не знаю, не играл. если есть кто работал с этим, поделитесь, сильно от мобилки отличается?

....

что еще интересное бывает?
🎄17166👍4🍓3🔥1
Кастомные операторы

Наткнулся на либу для построения графов

Насколько она хороша не знаю, но меня зацепило, как они грациозно позволяют задать граф:


LabeledGraph { A - "C" - E }


• A и E — объекты вершин, возможно уже с какими-то связями

• "C" — название для новой вершины, для которой автоматически создастся объект

и вместе они соединяются в направленный граф с помощью минуса


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


operator fun minus(new: Any) = Vertex(incoming = this, current = new)


....

есть еще ситуации, когда кастомный operator реально упрощает жизнь?

operator fun minus(b: Int) = this + b 👍
💊17👍11🌭5
Новая рубрика — #cross_post

в ней мы сравним iOS и Android технологии

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

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

и возможно приблизим кросс-платформу. или точно поймем, что оно нам не надо


p.s. в некоторых темах будут участвовать приглашенные эксперты и просто заслуженные мэтры iOS/Android-разработки
🔥13👍3🌭1
Coroutine и Async/Await


Общее

• позволяют писать асинхронный код последовательно
• позволяют асинхронным функциям возвращать результат синхронно, без явных callback-ов (Android) / completion-ов (iOS)
• раньше многопоточный код писался с помощью очередей/реактивных потоков


Coroutine

• асинхронные функции помечаются ключевым словом suspend

CoroutineScope — "область", для которой задаются параметры и внутри которой выполняются suspend-функции

• пул-потоков задается через Dispatcher

• можно отменить выполнение отдельной suspend`-функции или всего `CoroutineScopecancel()

• есть два основных билдера — launch (запускает корутину) и async/await (создает корутину и возвращает результат)


CoroutineScope(Dispatcher.Main).launch {
val result = doSomething()
}

suspend fun doSomething(): String {
...
}




Async/await

• асинхронная функция помечается ключевым словом async, место вызова функции помечает как await

Task — это контекст, позволяющий запустить асинхронный код, относительно точки вызова. Может быть вызван, как из синхронной, так и асинхронной функции

• пул потоков задается через Actor

• можно отменить выполнение async-фукнции или всего Taskcancel()

async-функции можно вызывать внутри Task и других async-функций


Task(priority: .medium) {
let result = await doSomething()
}


func doSomething() async throws -> [String] {
...
}



#cross_post
@dolgo_polo_dev

за помощью в подготовке материала спасибо:
• iOS
@alextar04
• Android
@dmitry_tsyvtsyn (aka @android_under_the_hood)
🏆13👍12🍓2🔥1
Открыл для себя мир кастомных эмоджи в тг 🙂 🤡

апрувните, пожалуйста, канал, появится возможность настроить красивые реакции)

t.me/dolgo_polo_dev?boost

пока тестил их, нашел баг — если добавлять кастомный эмоджи в пост после двух блоков кода (например swift + kotlin), то после публикации поста эмоджи распадается на два — базовый и кастомный

🧠 --> 🧠🧠
Please open Telegram to view this post
VIEW IN TELEGRAM
👾98🐳2
Swift / Kotlin


Они оказывается жуть как похожи

И речь не о том, что они оба ООП + статически типизированы + автоматически выводят типы + не требует точки с запятой в конце строки...


Радует больше совпадение по сахарным фичам, которые есть в обоих языках:

🔵extension — расширение классов

🔵именованные аргументы у функций

🔵модификатор internal для ограчения видимости по модулю

🔵null-safety

🔵lateinit var (Android) / lazy var (iOS)

💎 в документации по интеропу есть целая таблица сопоставления ключевых слов kotlin <-> swift


extension Double {
var km: Double { return self * 1_000.0 }
}
let result = 25.4.km

var x: Bool? = getXorNull()
print(x ?? false)



fun Double.km() = this * 1_000.0
val result = 25.4.km()

var x: Boolean? = getXorNull()
print(x ?: false)


#cross_post
@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍188🦄3👎21❤‍🔥1
Реверс-инжиниринг чужого приложения

Dolgo.polo Dev x Coffee&Code
#cross_post

💎 iOS

во что собирается приложение?

в .ipa-файл, а в нем код в формате unix executable file (бинарь, скомпилированный код)


можно ли декомпилировать чужое приложение?

да, если у вас есть доступ до .ipa файла (как его получить), можно с легкостью дойти до ассемблерного кода (используя Hopper, можно получить даже псевдо код)

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


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

да, например тулза sideloadly позволяет пересобрать .ipa файл с дополнительным фреймворком (который мы можем написать сами)

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


что защищает от хакнутых приложений?

🔵источник приложений только один — AppStore (уже нет)
🔵подпись .ipa-файла, связанная с аккаунтом разработчика
🔵DeviceCheck — фича, позволяющая сгенерировать токен оригинальность приложения и проверить его на бэкенде


можно ли посмотреть исходники любой библиотеки?

только если она в публичном доступе

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

еще есть возможность изучить библиотеку прямо в рантайме, если она написана на Objective-C, используя инструменты дебага

например можно:
🔵запринтить все методы объекта (подробнее)
🔵переопределить любой (да да, любой, даже приватный) метод
🔵подменить класс в рантайме, создать класс в рантайме
🔵вызывать любой метод (даже не объявленный)
🔵подключить любую библиотеку (даже системные фреймворки Apple) и много чего еще




💎 Android

во что собирается приложение?

в .apk-файл, в котором лежит java-байткод (Java/Kotlin-код компилируется в java-байткод на этапе сборки .apk)


можно ли декомпилировать чужое приложение?

да

получить .apk-файл можно из любого приложения, установленного на устройстве

дальше достаточно использовать любую программу, умеющую превращать байткод обратно в Java-код

единственная защита от этого — обфускация кода. но она лишь усложняет читаемость кода, а не защищает от считывания


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

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


что защищает от хакнутых приложений?

🔵подпись приложения

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

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

🔵Play integrity API — фича, позволяющая сгенерировать токен оригинальность приложения и проверить его на бэкенде


можно ли посмотреть исходники любой библиотеки?

да, у нас есть доступ к исходникам любой либы, написанной на Java/Kotlin (в том числе системных/гугловских) прямо из Android Studio



💎 Выводы

все секреты, попавшие в .apk/.ipa-файл (токены/алгоритмы шифрования/пароли/протоколы...), могут быть вытащены и подменены с помощью реверс-инжиниринга на обоих платформах

на iOS изучить/подменить чужое приложение сложнее, но тоже реально

так что все что попало в .apk/.ipa-файл — считай open-source


спасибо Coffee&Code и в частности @gronzeisl за экспертизу по iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍9👏9🎉22
🧬 Чистка Google Play

Тут Play Market пообещал вычистить мусорные приложения, которые не имеют полезного функционала

А я вспомнил историю, рассказываю

Наверное, все слышали от стримеров/блогеров, насколько казики платят выше рынка за рекламу

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

Лет 5 назад, когда только начинал заниматься фрилансом и постоянных заказчиков не было, часто натыкался на объявления:

Сделать приложение, которое открывает википедию в WebView. А если потрясти телефон и покричать в микрофон, открывается однорукий бандит. Оплата 10к


А 10к за приложение, которое пишется за несколько часов по шаблону — это много

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

Не брал такие заказы, и вам не советую

Кстати единственные, кто платили столько же — владельцы приложений для установки модов/скинов на майнкрафт

Есть миллион приложений, которые zip-архивы со скинами/модами кидают через Intent и ContentResolver в приложение Minecraft, тем самым устанавливая моды. Парочка из них мои)


@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
😁188👍411🤩1👾1
🧬 Все каналы по мобильной разработке

Собрал тут кажется самую большую коллекцию:


🌸Android — авторский контент об Android

🌸iOS — авторский контент об iOS

🌸Компании — bigtech-компании и организации

🌸Подборки/новости/библиотеки


@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥385🆒22
🧬 Кросс-платформа

Пошла волна 🌊 хейта в сторону кросс-платформы (раз, два), а у меня на эту тему давно черновик лежит)

Давайте так:

Все последнее время топят за кросс-платформу

А какие в ней плюсы для разработчиков?

Вы куда воюете?

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


А для простых работяг:

🔵уменьшение рабочих мест

🔵нужно ботать новые технологии

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

🔵x2 времени на сборку проекта, x3 проблем с кэшами студии, x4 сломанных джоб на CI

🔵более универсальное — всегда более ограниченное. привет урезанные API и библиотеки с минимальным конфигом, чтоб SDK не развалилось на повороте

🤡🤡💩

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍50💅6🤡3
🧬 Локаль

Наткнулся тут на интересный стандарт хранения выбранного в системе языка:

🔵 BCP 47 — оригинал документа
🔵 обзор на понятном языке

Казалось бы, достаточно сохранить код языка (ru, en, fr...). И возможно зарезервировать место для диалекта и бульку для "слева-направо или справо-налево"

А на самом деле может быть так:

he-IL-u-ca-hebrew-tz-jeruslm

что означает

Hebrew as spoken in Israel, using the traditional Hebrew calendar, and in the "Asia/Jerusalem" time zone as identified in the tz database


а теперь представьте, сколько там еще интересного, если прочитать все 83 страницы BCP 47

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
12🦄6😁3🤔2👍1
🧬 Загадка на логику

Представьте, запускается приложение

В каком порядке будете инициализровать эти 4 библиотеки?

1️⃣ Sentry SDK — логирует ошибки, краши и ANR-ы

2️⃣ Auth SDK — хранит данные о юзере

3️⃣ UserTracker SDK — логирует действия юзера, в том числе события запуска

4️⃣ FeatureFlags SDK — стягивает фича флаги для А/Б

победителю — пятикратное ура 👍

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
110🦄4🤯2
🧬 Ваше устройство украли — мы его заблокировали

Гугл в начале мая анонсировал фичу Android Theft Protection


Если вор выхватит у вас телефон из рук и начнет с ним убегать, то экран автоматически заблокируется

Работает это на основе Google AI, который вероятно анализирует датчики акселерометра, gps и, возможно, камеры/микрофона (это уже мои догадки)


Вопросов эта фича вызывает больше чем ответов:

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

🔵начнут ли воры красть телефоны странно и нестандартно двигаясь, чтобы запутать ИИ

🔵сработает ли эта фича, когда девушка выхватывает телефон, чтобы прочитать твои переписки

🔵неужели уже можно дешево в фоне постоянно гонять ИИ, анализирующий датчики, не переживая за CPU/батарею?

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
9🤯14😁12👍54
🧬 Фоновые процессы теперь более заметны

Обратил внимание, что после обновления на Android 14 в списке запущуенных приложений начали отображаться запущенные процессы

"1 активный фоновый элемент"

Подозреваю, что туда попадают запущенные Service и, возможно, воркеры WorkManager-а

так что теперь у юзеров появляется дополнительная более явная возможность остановить фоновую работу

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍14🦄64🤔1
This media is not supported in the widget
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
3216👍3🦄2👎1🔥1👏1
🧬 Жизнь это сложно

Но еще сложнее следить за жизненным циклом

Одна из самых сложных штук в мобилке, хотя казалось бы

Во-первых, ЖЦ отличается у:
🔵Application
🔵Activity
🔵Fragment
🔵View
🔵не говоря уже о процессах, сервисах и тасках

Добавим влияние диалогов/шторок, частично перекрывающих экран

Дальше умножаем это на сложные экраны современных девайсов — раскладушки, двойные экраны, режимы окна к окне...

Складываем с рекомпозицией от Compose, если используете AndroidView внутри Compose или наоборот

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

Готово, стало сложно 🧠

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
22🗿8😁6🌭6🤣2💔2🦄2
🧬 Как OkHttp-клиент выполняет сетевой запрос

Выступал тут на DevFest, у меня оттуда остался один полезный слайд про OkHttp-клиент

Коротко:

OkHttp-клиент — самый популярный сетевой клиент на Android, поверх которого часто используют Retrofit

Главное — он умеет много всего из коробки


🔵записывать/читать кэш, управлять им с помощью хэдера cache-control
🔵управлять cookie и разруливать их атрибуты
🔵устанавливать соединение по http1 и http2 (а по http3 нет, завидуем iOS-разработчикам)
🔵выбирать сеть, по которой будет выполнен запрос
🔵работать с DNS и направлять трафик через Proxy
🔵выполнять сам запрос, то есть как раз передавать байты по интернету. при этом "движок", выполняющий запрос, можно подменить

А возможно это все благодаря Interceptor-ам — цепочке колбеков, позволяющих прочитать/изменить запрос и ответ

Вы можете написать кастомные Interceptor-ы и добавить их в список appInterceptor-ов или networkInterceptor-ов

Или можете залезть в исходники OkHttp и посмотреть на его стандартные Interceptor-ы, в которых как раз и реализована вся вышеперечисленная магия

На картинке:
🔵отличия между appInterceptor-ами или networkInterceptor-ами
🔵стандартные OkHttp Interceptor-ы и их роль

full hd картинка в комментариях

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍31🔥1533
🔗 Какая Activity открыта

Нашел для себя еще одну крутую комманду adb:

adb shell dumpsys window windows | grep 'mActivityRecord'
// в Windows grep можно заменить на find

Она показывает имя открытой Activity


сделал для нее alias:

adbAStack = "adb shell dumpsys window windows | grep 'mActivityRecord"


Например, с помощью нее вычислил название активити со списком свернутых приложений в системном лаунчере:

com.sec.android.app.launcher/com.android.quickstep.RecentsActivity

Теперь могу открыть это меню прямо через adb (зачем?) или сделать в приложении кнопку "открыть список свернутых приложений" (зачем??)


А если серьезно команда имба, так как по внешнему виду UI не всегда понятно, с какой Activity работаешь

еще про adb:
🔵как тапать хомяка через adb
🔵(habr) прикладное adb для зумеров

@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍328