Android & Coffee с Васей
183 subscribers
74 photos
5 videos
50 links
Канал для разговоров за кофе о разработке. В основном Android, но вообще как получится
Download Telegram
🛠 Технические обновления

— Полностью переделали систему аналитики: добавлять события теперь супер просто, вся документация в одном месте, Android и iOS синхронизированы 📊

— Для отладки (только дев-версии) добавили:
 • Chucker
 • Flocon
 • Шеринг логов устройства прямо из приложения
 • для Flocon понадобилась модуляризация. Очень хотел это отложить, но не вышло. Сделал по аналогии с Now In Android — крупные утилитарные модули, крупные модули фич (пока без деления на апи/реализацию, но скоро тоже придётся делать) и app-модули

— Ещё раз прикрутили libphonenumber — расскажу отдельно ☎️

— Часть логики билда вынесли в Convention Plugins — стало проще поддерживать build.gradle и добавлять модули ⚙️

— В приложении много Bottom Sheet, поэтому сделали своё API поверх Material — получилось удобно, думаю рассказать 📱
👍5
Forwarded from 99developers (Alex Andronov)
С апдейтами для вас.

- включили международные переводы. С такими рейтами что хрен с нами кто поконкурирует. Пока не промоутим.
- запустили 1% кэшбека всем кто рефералил в вейтлисте. Им оставим все это на постоянке.
- 2,500 транзактящих пользователей. Конверсия от активного аккаунта в транзактящего пользователя больше 65%, неплохо.
- отладили ревью и комплаенс.
- кредиты растут так что к четвергу мы обычно перекрываем результат прошлой недели. Выплаты пока в норме, просрочки есть, но их оч мало.
- выключил вейтлист, получил леща от Миши, включил вейтлист обратно.
- встроили AI агента в чат в админке.
- начали делать SMM AI агента. Идея чтобы было дофига AI сотрудников живет и развивается.
🔥2
🚀 Firebase Real-Time Remote Config

С Firebase можно получать оповещения об изменении Remote Config.

Без real-time оставалось два варианта:
— ждать N часов для обновления
— дёргать fetch слишком часто и упираться в квоту 😵‍💫

Real-Time Remote Config позволяет запрашивать конфиг ровно тогда, когда он реально поменялся.

Как это устроено:
— клиент держит соединение с сервером Real-time Remote Config
— сервер шлёт сигнал об инвалидации
— клиент сам вызывает fetch (но не activate — важно)

Дальше решаете сами: применять сразу, вызвав activate, или, например, только при следующем старте.

⚙️ Чтобы включить real-time, нужно:
— в GCP включить Firebase Remote Config Realtime API (иначе listener молчит)
— добавить addOnConfigUpdateListener

Выглядит магически: меняешь флаг в консоли → приложение само узнаёт и реагирует.
👍1😢1
Подводные камни Firebase Real-Time Remote Config

Вот детали, о которых нужно помнить:

1️⃣ Нет гарантии доставки. Соединение с сервером может не установиться или разорваться. Вроде SDK обрабатывает это, но на практике обновления иногда «теряются»

2️⃣ Долгоживущее HTTP-соединение → дополнительный расход батареи и ресурсы

3️⃣ Нужно продумать активацию. Иначе рискуете: приложение стартовало в одном состоянии, а внезапно переключилось в другое

4️⃣ Конфиг может обновиться, пока приложение закрыто. Тогда апдейт дойдёт только через несколько секунд после старта. Если не вызвать activate сразу — изменения попадут лишь на следующем запуске. Иногда это ок, иногда критично
👍1
Во-первых, это красиво 😂
😁10🫡4
💁‍♂️ На техдолг можно забить
.
.
.
если любите запах горящего прода по утрам


Одно утро началось с "у нас жопка с Intercom" от CTO. Пользователи в поддержке видят чужие сообщения.
Нашли статью, собрались консилиумом. Я читаю — и понимаю: накосячил я.

Хронология фиаско:
— очень давно завёл Account с id "на будущее", оставил TODO (на скрине). Тогда бэк еще не присылал id, поэтому оставил так;
— позже добавил чтение id из JWT, но не для Account;
— когда понадобилось использовать id, в одном месте взял его из JWT, а в другом — из Account.

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

Вывод: техдолг обычно не взрывается сразу. Он копится и стреляет в самый неожиданный момент. Не копите техдолг.
👍6😱1
🪛 Архитектура Android-приложений

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

Это любопытно: несмотря на официальные рекомендации Google, сообщество продолжает искать свои решения.

Почему?

Гайдлайны от Google (как и любые другие) дают каркас, но в реальных проектах остаётся много открытых вопросов. Их сложно закрыть одним рецептом: разные ожидания от продукта, окружение, требования по безопасности и UX часто конфликтуют — отсюда новые компромиссные подходы.

Если сказать кратко, любое «плохое» решение в проекте можно оправдать его эволюцией 😆

Пара интересных статей последних месяцев:
Compose + Koin + Jetpack Navigation: что мы поняли за 2 года
Демоприложения: как жить, когда у вас 90+ application-модулей
Разбираем чистую архитектуру в Android: от а до я
Функциональное программирование в Android. Побочные эффекты и ELM-архитектура
Архитектура Android. Понятно и подробно
👍4
🤦‍♂️ Обрадовался, что вышла новая Android Studio Canary, пошел обновляться.

Обновился — пропала возможность выбрать Build Type. И по умолчанию собирает Release (с минификацией, естественно). А я уже пост в линку написал 😂

Помогло классическое Invalidate Caches.... Сейчас всё работает четко
Нашел очень интересную статью по тому, как лучше реализовать загрузку данных во вью модели.

Прочитал и закрыл. Снова открыл и снова прочитал. Короче, никак не отпускало. Под её влиянием написал предыдущий пост про статьи по архитектуре.

Поскольку статья была на английском, решил перевести и адаптировать её для Хабра.

Забирайте, может пригодиться в ваших приложениях!

https://habr.com/ru/articles/950494/
7🔥4🌚1
🚀 Kotlin 2.2.0: context-sensitive resolution (preview)

В новой версии kotlin можно опускать префиксы типов!

Было:


when (payment) {
Payment.Card -> println("💳")
Payment.Cash -> println("💵")
}


Стало:


when (payment) {
Card -> println("💳")
Cash -> println("💵")
}


Теперь компилятор понимает из контекста:
— subject в when
— явный return type
— тип переменной
— is / as проверки
— sealed иерархии
— тип параметра

🟢 Как включить:

1️⃣ Добавляем аргумент компилятора

freeCompilerArgs += "-Xcontext-sensitive-resolution"


2️⃣ Скачиваем Android Studio 2025.2+. Иначе конструкция будет подсвечиваться как ошибка в IDE

----

🧪 Пока preview, может поменяться. Зато код становится заметно чище.
👍6
https://neal.fun/not-a-robot/

Ну и докажи теперь, что ты не робот! 😂
👾3
This media is not supported in your browser
VIEW IN TELEGRAM
👨‍🎨 Тени в Jetpack Compose

В Compose 1.9 добавили новые тени: модификаторы dropShadow и innerShadow. До этого уже был shadow. В чем разница?

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

Чем ближе объект к источнику света, тем тень больше "уходит" под объект. Внизу экрана тень вытягивается вниз.

На видео видно как тень меняется при скролле. Чтобы было еще заметнее, сделал её красной
👀2
💁️️️️️️ Тень от shadow — часто не та, что ожидает дизайнер.

Это решили добавлением новых модификаторов dropShadow и innerShadow.

Теперь тень можно настраивать по нескольким параметрам:
- radius — размытие по краям, “мягкость” тени
- spread — расширение или сужение тени относительно границ объекта
- offset — смещение тени по осям X и Y

Эти параметры позволяют как бы задать индивидуальный источник света для каждого объекта. Кроме того, значения dropShadow и innerShadow теперь близки к тем, что используются в Figma — поэтому повторить дизайн из макета стало проще.

Можете сами увидеть разницу shadow и dropShadow
👍2
В анонсе Compose 1.9, как мне кажется, уделили незаслуженно мало внимания новым теням. Поэтому держите годную статью по новому апи и его возможностям:

The Art of Shadows in Jetpack Compose
11
🔪 Material Icons — всё

В релизе Compose от 24 сентября убрали зависимость от библиотеки material-icons-core. Этот артефакт больше не поддерживается и не рекомендуется к использованию, поскольку он:

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


Это означает, что при обновлении Compose ваш проект скорее всего перестанет собираться, если вы используете пакет androidx.compose.material.icons (например, часто используется Icons)

Новый рекомендуемый способ — Material Symbols. Нужно просто качать иконки с сайта Google Fonts

Обходной путь — добавить зависимость на material-icons-core вручную. Подойдёт в качестве временного решения, если миграция слишком долгая или вам действительно нужны те самые иконки.
🐳2😢1
Переписка с поддержкой Google 🤩

— REJECT: У вас неправильно заполнена финансовая декларация
— Я бы хотел подать апелляцию. Помогите понять, что не так?
— Ваша апелляция рассмотрена. У вас неправильно заполнена финансовая декларация. Хорошего дня

😹

Справедливости ради, ответили за день, относительно быстро
👏5👍1🎉1
🧯 Обычный апдейт Compose. Минус регистрация. Минус прод. Минус утро.

Всё началось с утреннего “регистрация не работает” от саппорта. Сначала подумал, что какой-то очень специфический случай, но количество обращений очень быстро росло. Запустил приложение у себя и не смог ничего нажать на экране. Я в ступоре, потому что просто нет идей, почему это может не работать.

Всё оказалось довольно интересно и превратилось в небольшое расследование.

Предыстория:
У нас есть KYC Safety шторка (на скрине). Она показывается блокирующе перед KYC.
Мы договорились, что закрыть её можно только по кнопке:
— нет крестика
— не работает системный Back ⬅️
— нельзя свайпнуть вниз 👇
Как выглядит код Bottom Sheet для бодрого утра:


JazariModalBottomSheet(
onDismissed = onDismissed,
sheetState = rememberModalBottomSheetState(confirmValueChange = { false }),
properties = ModalBottomSheetProperties(shouldDismissOnBackPress = false),
) {
KycSafetyInternal(onButtonClick = { dismiss() })
}



Вот эта строка блокирует свайп:


confirmValueChange = { false }


А вот эта — закрытие по Back:


shouldDismissOnBackPress = false


И раньше всё это работало. Но после обновления Compose до BOM 2025.10.00 (а с ним — и Material3 до версии 1.4.0) всё сломалось.
В changelog видно, что Bottom Sheet сильно переработали — улучшили, но, видимо, поменяли логику открытия.

📉 Что изменилось:
Раньше шторка сразу открывалась, а confirmValueChange вызывался только при изменении состояния (например, при свайпе).
Теперь же он вызывается сразу при открытии.
А поскольку я возвращаю false, шторка не может показаться из Hidden состояния.

Результат:
Шторка не видна, но Window диалога уже оказывается поверх UI и перехватывает все клики 🤯

В итоге экран как будто блокируется, и выйти из этого состояния невозможно 🙃

Про это изменение в changelog — ни слова. Но по описанию апдейта легко представить, где зацепили.

🧯 Починилось так:


sheetState = rememberModalBottomSheetState { it != SheetValue.Hidden }


Уже на ревью в сторе. Это было бодрое утро!
🔥10
Откопал в коде экран одной из итераций защиты от фрода.

Жаль, что в таком виде это не пошло в продакшн 🤡
🔥51