Manual DI
DI-фреймворки продолжают появляться как грибы после дождя. Теперь рекомендуют использовать Metro, но всё чаще можно услышать, что люди принципиально отказываются от каких-либо библиотек для реализации DI. Так как в моей команде мы в основном делаем переиспользуемые общие модули, мы тоже давно отказались от DI-фреймворков. И знаете что? Мы вообще не испытываем из-за этого каких-либо проблем.
Тут я вспомнил про свой KMP-сэмпл и решил, что будет круто показать всё это на примере и заменить Koin в проекте. Но хорошо, что я не начал делать это раньше времени: буквально на докладе про сравнение DI-фреймворков с Podlodka Android Crew я узнал, что Александр Власюк уже всё сделал раньше и даже заслал pull request🌐
Примечательно, что Manual DI не только даёт compile-time safety по сравнению с Koin (без всяких плагинов), но даже количество строк кода в проекте сократилось😲
Понятно, что это всего лишь пример. Если использовать Koin глобально, то кода с Manual DI придётся писать больше. Однако я придерживаюсь подхода, при котором DI должен быть изолирован внутри модуля, а зависимости должны быть объявлены явно, чтобы можно было легко переиспользовать этот модуль где угодно.
А вы что думаете, стоят ли DI-фреймворки, чтобы их изучать и постоянно мигрировать проект на все более новые решения❓
#DI #Kotlin #KMP
DI-фреймворки продолжают появляться как грибы после дождя. Теперь рекомендуют использовать Metro, но всё чаще можно услышать, что люди принципиально отказываются от каких-либо библиотек для реализации DI. Так как в моей команде мы в основном делаем переиспользуемые общие модули, мы тоже давно отказались от DI-фреймворков. И знаете что? Мы вообще не испытываем из-за этого каких-либо проблем.
Тут я вспомнил про свой KMP-сэмпл и решил, что будет круто показать всё это на примере и заменить Koin в проекте. Но хорошо, что я не начал делать это раньше времени: буквально на докладе про сравнение DI-фреймворков с Podlodka Android Crew я узнал, что Александр Власюк уже всё сделал раньше и даже заслал pull request
Примечательно, что Manual DI не только даёт compile-time safety по сравнению с Koin (без всяких плагинов), но даже количество строк кода в проекте сократилось
Понятно, что это всего лишь пример. Если использовать Koin глобально, то кода с Manual DI придётся писать больше. Однако я придерживаюсь подхода, при котором DI должен быть изолирован внутри модуля, а зависимости должны быть объявлены явно, чтобы можно было легко переиспользовать этот модуль где угодно.
А вы что думаете, стоят ли DI-фреймворки, чтобы их изучать и постоянно мигрировать проект на все более новые решения
#DI #Kotlin #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍21🔥6🗿3
Изменение конфигурации в прошлом
Еще пару лет назад я заметил, что если в AndroidManifest явно прописать все варианты изменения конфигурации в configChanges, то Compose сможет самостоятельно подхватить подавляющее большинство изменений без какого-либо дополнительного кода. Но тогда я был непонят сообществом, и никто это всерьез не воспринял😨
Теперь же об этом заговорили инженеры из Google, рекомендую посмотреть доклад с Droidcon🟥 . Начиная с compileSdk 36, можно одной строчкой игнорировать все текущие и будущие причины пересоздания Activity из-за изменения конфигурации.
Это позволит нам полностью избавиться от андроидовской ViewModel и инкапсулировать нашу логику в обычных классах. При этом это не значит, что Activity никогда не будет пересоздаваться, изменение конфигурации лишь одна из причин. Но в таких случаях состояние можно сохранить только с помощью SavedInstanceState, ViewModel здесь бы не помогла.
А вы что думаете, готовы ли вы забыть об изменении конфигурации в Android и о ViewModel в частности?
#Android #Compose
Еще пару лет назад я заметил, что если в AndroidManifest явно прописать все варианты изменения конфигурации в configChanges, то Compose сможет самостоятельно подхватить подавляющее большинство изменений без какого-либо дополнительного кода. Но тогда я был непонят сообществом, и никто это всерьез не воспринял
Теперь же об этом заговорили инженеры из Google, рекомендую посмотреть доклад с Droidcon
Это позволит нам полностью избавиться от андроидовской ViewModel и инкапсулировать нашу логику в обычных классах. При этом это не значит, что Activity никогда не будет пересоздаваться, изменение конфигурации лишь одна из причин. Но в таких случаях состояние можно сохранить только с помощью SavedInstanceState, ViewModel здесь бы не помогла.
А вы что думаете, готовы ли вы забыть об изменении конфигурации в Android и о ViewModel в частности?
#Android #Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29👎6✍4🔥4😎3😁1
Проблема KSP
Kotlin Symbol Processing — современная технология для генерации кода, но насколько безопасно использовать библиотеки с KSP в проекте?
При обновлении зависимостей мы попали в следующую ловушку: не все библиотеки, которые мы используем, поддержали KSP2, и при этом новая версия Room крашится, если явно отключить поддержку KSP2 в gradle.properties. Сейчас ещё можно обойти проблему, понизив версии, но начиная с AGP 9 и Kotlin 2.3.0 KSP1 перестанет работать.
Что с этим делать?
🔘 Можно включить режим ждуна и мониторить, когда авторы сторонних библиотек добавят поддержку, но не факт, что это произойдёт.
🔘 Форкнуть библиотеку и реализовать поддержку самостоятельно, что может оказаться нетривиальной задачей, если раньше с KSP вы не работали.
🔘 Избавиться от зависимости на такую библиотеку. Если она не глубоко интегрирована в проект, то проще выбрать этот путь, тогда при очередном обновлении зависимостей проблем не возникнет.
А используете ли вы в своих проектах библиотеки с KSP, кроме Room и Dagger?
#KSP #Android
Kotlin Symbol Processing — современная технология для генерации кода, но насколько безопасно использовать библиотеки с KSP в проекте?
При обновлении зависимостей мы попали в следующую ловушку: не все библиотеки, которые мы используем, поддержали KSP2, и при этом новая версия Room крашится, если явно отключить поддержку KSP2 в gradle.properties. Сейчас ещё можно обойти проблему, понизив версии, но начиная с AGP 9 и Kotlin 2.3.0 KSP1 перестанет работать.
Что с этим делать?
А используете ли вы в своих проектах библиотеки с KSP, кроме Room и Dagger?
#KSP #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21❤1🤔1
Советы по работе с AI-агентами для начинающих
На днях посмотрел отличный доклад от Евгения Сатурова на Podlodka AI Crew о страхах разработчиков и типичных ошибках при работе с AI-агентами.
Я делал точно такие же ошибки, поэтому поделюсь советами с вами:
🔘 Выбирайте лучшую доступную модель на сегодня, не используйте auto-режим в Cursor и подобных инструментах.
🔘 Не пишите задачи напрямую. Формулируйте мета-промпт с описанием задачи для модели, чтобы она составила вам подробный таск-промпт.
🔘 В мета-промпте пишите, что вы хотите сделать, а не как, избегайте чрезмерной специфики.
🔘 Прикладывайте весь необходимый контекст. Плохо, когда модель начинает делать семантический поиск по проекту.
🔘 Не дробите задачу слишком сильно — это неэффективно. Современные модели могут достаточно долго работать автономно, главное не вылезти за контекст. По возможности используйте сабагентов.
🔘 Не вступайте в споры с моделью и не правьте код руками. Просто откажитесь от сгенерированного кода, обновите таск-промпт, правила проекта и попробуйте снова.
💬 Делитесь в комментариях своими лучшими практиками по работе с AI-агентами.
#AI
На днях посмотрел отличный доклад от Евгения Сатурова на Podlodka AI Crew о страхах разработчиков и типичных ошибках при работе с AI-агентами.
Я делал точно такие же ошибки, поэтому поделюсь советами с вами:
#AI
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍19🤡18😡2❤1🥴1
Мы в команде создаём переиспользуемые общие модули между приложениями, и общая логика ключевых модулей шарится между Android и iOS. Это, безусловно, несёт в себе много плюсов, но и добавляет много сложностей.
Например, так сложилось, что в Android все модули находятся в монорепозитории, а в iOS каждый отдельный модуль — это отдельный репозиторий из-за особенностей менеджера пакетов Swift (SPM).
Поэтому мы предоставляем общий фреймворк через SPM, который iOS-разработчики могут подключить как отдельную зависимость.
И если вы шарите код только одной библиотеки, всё достаточно просто. Но когда появляется вторая и третья библиотека, начинаются проблемы. В KMP рекомендуется использовать так называемый umbrella-модуль, чтобы не тащить рантайм KMP в каждый отдельный фреймворк.
Но это несёт в себе одну большую проблему: всё, что мы экспортируем, попадает в одно пространство имён. Соответственно, одинаково названные классы при интеропе в Objective-C будут переименованы: к одному из классов добавится нижнее подчёркивание. И изменения в одном модуле легко могут сломать другой🙃
Мы пока полноценно не решили эту проблему, но выработали правило: обязательно указывать имя модуля для всех публичных сущностей, которые экспортируются в Objective-C. Но с приходом Swift Export проблема должна отпасть, так как там можно будет указывать отдельный импорт для каждой библиотеки.
Это далеко не единственная проблема, с которой мы столкнулись. Если тема интересна — ставьте реакции, и я напишу ещё посты по теме.
#KMP #iOS
Например, так сложилось, что в Android все модули находятся в монорепозитории, а в iOS каждый отдельный модуль — это отдельный репозиторий из-за особенностей менеджера пакетов Swift (SPM).
Поэтому мы предоставляем общий фреймворк через SPM, который iOS-разработчики могут подключить как отдельную зависимость.
И если вы шарите код только одной библиотеки, всё достаточно просто. Но когда появляется вторая и третья библиотека, начинаются проблемы. В KMP рекомендуется использовать так называемый umbrella-модуль, чтобы не тащить рантайм KMP в каждый отдельный фреймворк.
Но это несёт в себе одну большую проблему: всё, что мы экспортируем, попадает в одно пространство имён. Соответственно, одинаково названные классы при интеропе в Objective-C будут переименованы: к одному из классов добавится нижнее подчёркивание. И изменения в одном модуле легко могут сломать другой
Мы пока полноценно не решили эту проблему, но выработали правило: обязательно указывать имя модуля для всех публичных сущностей, которые экспортируются в Objective-C. Но с приходом Swift Export проблема должна отпасть, так как там можно будет указывать отдельный импорт для каждой библиотеки.
Это далеко не единственная проблема, с которой мы столкнулись. Если тема интересна — ставьте реакции, и я напишу ещё посты по теме.
#KMP #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍77❤5🔥3🤡3😎2👏1
Forwarded from Android Broadcast
Алексей Панов @kotlin_adept , опытный мобильный разработчик, реализующий приложения с применением KMP, проведет собеседование на позицию Kotlin Multiplatform разработчика в прямом эфире на YouTube канале "Android Broadcast" (время и дата будут объявлены позже)
Требования к кандидату:
👉 Опыт в мобильной разработки
👉 Опыт с Kotlin
👉 Понимание как происходит разработка приложений с KMP
Будет теория и практика. Это ваш шанс проявить себя и заявить на большую аудиторию о своих возможностях!
Если решили принять участие - заполняйте анкету!
#AndroidBroadcast
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👎2
Проблема версионирования
Продолжаем тему KMP, и прежде чем перейти к следующей проблеме, хочется поговорить о том, как мы делим наши библиотеки для предоставления общего кода в iOS.
Мы разбиваем библиотеку на две части: core и compose. В core-модуле, соответственно, лежит вся логика, а в compose — только вёрстка. При этом каждый модуль мы делим на пакеты api/internal и с помощью правила detekt запрещаем использовать публичные сущности из пакета internal.
Также мы стараемся избегать использования сторонних библиотек, кроме ключевых, таких, как Ktor, SQLDelight, но в качестве исключения мы приняли решение использовать Decompose. Это позволяет значительно упростить интеграцию с общим кодом в iOS, ведь всё, что нужно сделать — это смаппить жизненный цикл. А дальше, в зависимости от текущего состояния навигации, показываем тот или иной экран и отправляем события в компонент. Это позволяет скрыть все детали реализации и меньше страдать из-за проблем с интеропом.
Однако то, что хорошо работает на iOS, создаёт проблемы на Android, так как в публичном интерфейсе core-модуля приходится раскрывать все интерфейсы компонентов, чтобы иметь возможность обращаться к ним из ui-модуля. Хотя для интеграции модуля в Android достаточно передать верхнеуровневый компонент из core-модуля в экран, никто не мешает разработчикам обращаться к другим публичным сущностям.
Одним из решений здесь видится использование специальных аннотаций, например
В такой парадигме поддерживать обратную совместимость API, а тем более ABI, почти нереально. Поэтому, поскольку это внутренние библиотеки, мы приняли решение поднимать мажорную версию только в том случае, если реально ломаем точки интеграции API. Для iOS мы просто создаём задачи на доработку, где указываем, что поменялось в этом релизе и что требует обновления.
Процесс получился далёким от идеала, но пока что это работает🙃
#KMP #iOS
Продолжаем тему KMP, и прежде чем перейти к следующей проблеме, хочется поговорить о том, как мы делим наши библиотеки для предоставления общего кода в iOS.
Мы разбиваем библиотеку на две части: core и compose. В core-модуле, соответственно, лежит вся логика, а в compose — только вёрстка. При этом каждый модуль мы делим на пакеты api/internal и с помощью правила detekt запрещаем использовать публичные сущности из пакета internal.
Также мы стараемся избегать использования сторонних библиотек, кроме ключевых, таких, как Ktor, SQLDelight, но в качестве исключения мы приняли решение использовать Decompose. Это позволяет значительно упростить интеграцию с общим кодом в iOS, ведь всё, что нужно сделать — это смаппить жизненный цикл. А дальше, в зависимости от текущего состояния навигации, показываем тот или иной экран и отправляем события в компонент. Это позволяет скрыть все детали реализации и меньше страдать из-за проблем с интеропом.
Однако то, что хорошо работает на iOS, создаёт проблемы на Android, так как в публичном интерфейсе core-модуля приходится раскрывать все интерфейсы компонентов, чтобы иметь возможность обращаться к ним из ui-модуля. Хотя для интеграции модуля в Android достаточно передать верхнеуровневый компонент из core-модуля в экран, никто не мешает разработчикам обращаться к другим публичным сущностям.
Одним из решений здесь видится использование специальных аннотаций, например
@InternalVisibilityAPI, которые будут предупреждать пользователя о том, что это внутренний API библиотеки.В такой парадигме поддерживать обратную совместимость API, а тем более ABI, почти нереально. Поэтому, поскольку это внутренние библиотеки, мы приняли решение поднимать мажорную версию только в том случае, если реально ломаем точки интеграции API. Для iOS мы просто создаём задачи на доработку, где указываем, что поменялось в этом релизе и что требует обновления.
Процесс получился далёким от идеала, но пока что это работает
#KMP #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28❤2
Это уже мое четвертое публичное собеседование, в котором я стараюсь раскрыть основные аспекты работы с современными технологиями:
Сегодня на собеседовании будет задачка на ревью проекта с плохим кодом, но с упором на KMP. И по ходу эфира обсудим все нюансы интеграции общего кода с iOS.
Если вам интересна эта тема, обязательно приходите на прямой эфир, будет интересно! А в конце я смогу ответить на все ваши вопросы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥48❤3🤡3
Материалы для углублённого изучения KMP
По мотивам вчерашнего собеса хочу посоветовать классные доклады, которые помогут вам глубже разобраться в принципах работы Kotlin Multiplatform и Kotlin Native, а также лучше понять нюансы интеропа со Swift-кодом.
На английском:
🔘 ЖЦ объектов в Kotlin/Native
🔘 Процесс компиляции в Kotlin/Native, отличия статических и динамических фреймворков
🔘 Проблемы текущего интеропа и возможные пути улучшения
🔘 Разница между Kotlin и Swift concurrency
🔘 Принцип работы Swift Export
На русском:
🔘 Совместная работа Kotlin/Native GC и ARC в Swift
🔘 iOS Memory Management
#KMP
По мотивам вчерашнего собеса хочу посоветовать классные доклады, которые помогут вам глубже разобраться в принципах работы Kotlin Multiplatform и Kotlin Native, а также лучше понять нюансы интеропа со Swift-кодом.
На английском:
На русском:
#KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
👍30🔥14😁1
Стоит ли переходить с Room на SQLDelight?
На данный момент обе библиотеки поддерживают KMP. Если раньше особого выбора не было, то теперь многие могут задаться вопросом: стоит ли вообще переходить с Room?
Я считаю, что нет, не стоит. Конечно, у каждой библиотеки есть свои преимущества и недостатки, но, на мой взгляд, у SQLDelight их заметно больше:
🔘 Нельзя задать разные имена для таблицы в БД и сгенерированного класса. Если вы придерживаетесь общепринятого синтаксиса именования таблиц, то имена сгенерированных классов будут выглядеть просто ужасно.
🔘 Видимость сгенерированных файлов также нельзя регулировать — все они будут public.
🔘 Нет поддержки suspend-функций, приходится явно менять диспетчер для каждого запроса. (оказывается есть, в настройках плагина есть свойство generateAsync)
🔘 Нельзя сразу сгенерировать класс с отношением many-to-many или другими связями, например, чтобы получить фильм со списком актёров, придётся делать дополнительный маппинг на стороне Kotlin.
🔘 Нет автоматических миграций, как в Room (но в целом это зло).
🔘 Очень скудная документация.
Из плюсов я бы выделил следующее:
🟢 Небольшие таблицы можно сразу смаппить в доменные типы с помощью Type Projections.
🟢 Нет магии аннотаций, все запросы пишутся явно.
🟢 Нет зависимости на KSP и плагины компилятора.
🟢 Поддерживается больше таргетов, чем в Room.
🟢 Может работать не только с SQLite.
В общем, я пришёл к выводу, что Room для меня выигрывает у SQLDelight, и мигрировать с него я бы не стал. Но и возвращаться обратно, если вы уже перешли, особого смысла тоже не вижу.
А что думаете вы, какая из библиотек вам ближе❓
#Room #SQLDelight #KMP
На данный момент обе библиотеки поддерживают KMP. Если раньше особого выбора не было, то теперь многие могут задаться вопросом: стоит ли вообще переходить с Room?
Я считаю, что нет, не стоит. Конечно, у каждой библиотеки есть свои преимущества и недостатки, но, на мой взгляд, у SQLDelight их заметно больше:
Из плюсов я бы выделил следующее:
В общем, я пришёл к выводу, что Room для меня выигрывает у SQLDelight, и мигрировать с него я бы не стал. Но и возвращаться обратно, если вы уже перешли, особого смысла тоже не вижу.
А что думаете вы, какая из библиотек вам ближе
#Room #SQLDelight #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
❤25👍12❤🔥3
10 кругов ада, или как вручную перенести все фотки из-за аккаунта разработчика
Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку🤑
Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.
Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика🤨
Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.
Пишу в техподдержку, чтобы аккаунт удалили окончательно и я смог поменять платёжный профиль. На что получаю ответ: сделать это нельзя, если на аккаунте нет активных приложений😵
Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.
Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.
Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...
Вот такой вот квест получился. А если бы аккаунта разработчика не было, все бы решилось проще, так что думайте😏
#Offtop
Так вышло, что фотографирую я не очень часто, и только сейчас у меня закончилось место на Google Диске. Теперь в каждом своём приложении Google показывает страшные баннеры и вынуждает купить подписку
Что ж, убедили, идём покупать. Но с русским платёжным профилем ничего не купить. Зачем тогда предлагали? Ну да ладно.
Пытаемся поменять платёжный профиль, но этого сделать нельзя из-за активного аккаунта разработчика
Аккаунт я давно забросил и все приложения там удалил, но Google заодно «удалил» и мой аккаунт, так как я не подтвердил личность.
Пишу в техподдержку, чтобы аккаунт удалили окончательно и я смог поменять платёжный профиль. На что получаю ответ: сделать это нельзя, если на аккаунте нет активных приложений
Тут я понял, что ситуация патовая и надо что-то делать. Одним из вариантов было создать новый аккаунт для фоток и заодно перенести все фото на Яндекс Диск.
Окей, качаем через Google Takeout архив со всеми фотками. Метаданные EXIF лежат там в отдельном JSON-файле, соответственно, ни данных о дате, ни геолокации в фотке нет, и нужно это как-то восстанавливать.
Я нашёл скрипт на Python, который это делает, и пришлось ещё немного подвайбкодить, чтобы всё заработало...
Вот такой вот квест получился. А если бы аккаунта разработчика не было, все бы решилось проще, так что думайте
#Offtop
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤯22😁8❤4👍1😨1
Зоопарк кроссплатформенных фреймворков
Думаю, вы все слышали про такие фреймворки, как Flutter и Expo (React Native) для разработки кроссплатформенных мобильных приложений и не только. Но, разумеется, таких фреймворков существует значительно больше, и по сей день появляются новые решения.
Давайте рассмотрим некоторые из них:
Valdi — фреймворк от Snapchat, где UI пишется на TypeScript DSL, который напрямую компилируется в нативные вьюшки. Разработчики обещают производительность, сопоставимую с нативными приложениями, так как фреймворк не использует ни WebView, ни JavaScript Bridge. Поддерживает Android, iOS и macOS.
ArkUI-X — проект, расширяющий декларативный UI-фреймворк для разработки приложений под HarmonyOS NEXT и позволяющий добавить поддержку компиляции под Android и iOS. Это ещё один фреймворк, использующий TypeScript, а точнее его надмножество ArkTS.
Skip — единственный платный для корпоративного использования фреймворк, который изначально представлял собой транспилятор из Swift в Kotlin и позволял переводить нативные iOS-приложения на SwiftUI в Android-приложения с Jetpack Compose. Но в новом режиме Fuse Skip начал использовать недавно вышедший Swift SDK для Android, что позволит уйти от прямой транспиляции кода по крайней мере для бизнес-логики.
Если честно, я не верю в широкое распространение этих фреймворков, но будет интересно посмотреть, к чему всё это приведёт. А что думаете вы? Попробовали бы один из этих фреймворков для разработки мобильных приложений?
#Crossplatform #Frameworks
Думаю, вы все слышали про такие фреймворки, как Flutter и Expo (React Native) для разработки кроссплатформенных мобильных приложений и не только. Но, разумеется, таких фреймворков существует значительно больше, и по сей день появляются новые решения.
Давайте рассмотрим некоторые из них:
Valdi — фреймворк от Snapchat, где UI пишется на TypeScript DSL, который напрямую компилируется в нативные вьюшки. Разработчики обещают производительность, сопоставимую с нативными приложениями, так как фреймворк не использует ни WebView, ни JavaScript Bridge. Поддерживает Android, iOS и macOS.
ArkUI-X — проект, расширяющий декларативный UI-фреймворк для разработки приложений под HarmonyOS NEXT и позволяющий добавить поддержку компиляции под Android и iOS. Это ещё один фреймворк, использующий TypeScript, а точнее его надмножество ArkTS.
Skip — единственный платный для корпоративного использования фреймворк, который изначально представлял собой транспилятор из Swift в Kotlin и позволял переводить нативные iOS-приложения на SwiftUI в Android-приложения с Jetpack Compose. Но в новом режиме Fuse Skip начал использовать недавно вышедший Swift SDK для Android, что позволит уйти от прямой транспиляции кода по крайней мере для бизнес-логики.
Если честно, я не верю в широкое распространение этих фреймворков, но будет интересно посмотреть, к чему всё это приведёт. А что думаете вы? Попробовали бы один из этих фреймворков для разработки мобильных приложений?
#Crossplatform #Frameworks
👍12😐7
Как улучшить дальность сканирования кодов маркировки
Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.
Как можно улучшить ситуацию?
🟢 Как ни странно, можно попробовать уменьшить разрешение камеры, двух мегапикселей более чем достаточно для распознавания.
🟢 Увеличить параметр zoomRatio в камере по-умолчанию, например, установить 1.5f вместо 1f.
🟢 Реализовать автоматический зум к потенциальным кодам. Для этого в ML Kit появились настройки enableAllPotentialBarcodes и ZoomSuggestionOptions.
🟢 Ограничить размер зоны сканирования.
Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?
P.S. Обучение собственной модели не предлагать🙂
#Camera #BarcodeReader
Библиотеки вроде Google ML Kit, ZXing или его аналога на C++ со стандартными настройками камеры имеют довольно посредственную дальность сканирования, приходится подносить камеру очень близко, чтобы хоть что-то отсканировать. Особенно это касается акцизных марок нового образца. При этом, если взглянуть на коммерческие решения, они работают на голову выше.
Как можно улучшить ситуацию?
Наверняка можно придумать что-то ещё. Хотелось бы спросить совета у тех, кто уже сталкивался с подобной задачей, есть идеи, что еще можно сделать?
P.S. Обучение собственной модели не предлагать
#Camera #BarcodeReader
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍5❤🔥3😈1
Посмотрите на код на изображении. Эта composable-функция используется на экране с камерой, чтобы сделать полупрозрачную рамку по периметру. Как думаете, в чем тут проблема?
Вместо прозрачного выреза на некоторых старых устройствах будет чёрный прямоугольник.
Я уже когда-то сталкивался с этой проблемой, когда Compose еще не было и в помине. При работе с Android Canvas проблема заключалась в использовании PorterDuff.Mode.CLEAR.
В прошлый раз эту проблему в AndroidView удалось пофиксить, переведя отрисовку на hardware-accelerated layer:
Но как сделать то же самое в Compose? Если просто получить текущий View через LocalView, то, вероятно, мы не получим нужного поведения, так как изменим layerType для верхнеуровневой вьюшки.
Мне ничего лучше не пришло в голову, чем сделать composable-функцию враппер, в которой контент будет прокидываться в AbstractComposeView, где уже и будет происходить изменение layerType.
Таким образом, чтобы пофиксить проблему, достаточно будет обернуть код на изображении в этот враппер. Если нужен код враппера, напишите в комментариях.
P.S. Как думаете, когда люди уже перестанут использовать семилетние смартфоны Xiaomi?
#Android #Canvas #Compose
Я уже когда-то сталкивался с этой проблемой, когда Compose еще не было и в помине. При работе с Android Canvas проблема заключалась в использовании PorterDuff.Mode.CLEAR.
В прошлый раз эту проблему в AndroidView удалось пофиксить, переведя отрисовку на hardware-accelerated layer:
setLayerType(LAYER_TYPE_HARDWARE, null)
Но как сделать то же самое в Compose? Если просто получить текущий View через LocalView, то, вероятно, мы не получим нужного поведения, так как изменим layerType для верхнеуровневой вьюшки.
Мне ничего лучше не пришло в голову, чем сделать composable-функцию враппер, в которой контент будет прокидываться в AbstractComposeView, где уже и будет происходить изменение layerType.
Таким образом, чтобы пофиксить проблему, достаточно будет обернуть код на изображении в этот враппер. Если нужен код враппера, напишите в комментариях.
P.S. Как думаете, когда люди уже перестанут использовать семилетние смартфоны Xiaomi?
#Android #Canvas #Compose
🤯22🔥4😭3👍2
Android Gradle Library Plugin
Если вы вдруг пропустили, то для KMP-проектов появился отдельный Android-плагин для library-модулей, который значительно уменьшает количество Gradle-тасок и ускоряет как конфигурацию проекта, так и сборку.
Особенности плагина:
🔘 В нём убрали поддержку flavor и build type.
🔘 Отключена Java-компиляция по умолчанию.
🔘 Отключены по умолчанию unit и инструментальные тесты (не забудьте про них, а то будет как в этом посте).
Мы уже подключили его в пару наших проектов, и результаты действительно впечатляющие🔥
🟢 Количество тасок при прогоне unit-тестов уменьшилось более чем в 4 раза, и во столько же раз удалось ускорить их выполнение.
🟢 С Android Lint похожая история: там количество запускаемых тасок сократилось в 2 раза, и в 1,5 раза удалось получить прирост скорости.
В общем, миграция определённо того стоит, но посмотрите внимательно на текущие ограничения в документации, возможно, вам пока этот плагин не подойдёт.
#Android #KMP #Gradle
Если вы вдруг пропустили, то для KMP-проектов появился отдельный Android-плагин для library-модулей, который значительно уменьшает количество Gradle-тасок и ускоряет как конфигурацию проекта, так и сборку.
Особенности плагина:
Мы уже подключили его в пару наших проектов, и результаты действительно впечатляющие
В общем, миграция определённо того стоит, но посмотрите внимательно на текущие ограничения в документации, возможно, вам пока этот плагин не подойдёт.
#Android #KMP #Gradle
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26😱2
Jetpack Navigation 3
Только сейчас дошли руки более пристально взглянуть на новую Jetpack Navigation 3.
Помню, многие жаловались, что Decompose весь такой сложный, а навигация от Google простая. Но что мы видим в новой версии:
NavBackStack, NavEntry, NavDisplay, NavEntryDecorator, SceneStrategy и так далее🫠
При этом, несмотря на то что вышла стабильная версия, много кода всё равно придётся писать дополнительно:
Хочешь навигацию по табам? Пиши код для управления бэкстеком.
Нужен BottomSheet? Пиши декоратор.
Необходимо привязать ЖЦ ViewModel к экрану? Подключай отдельную библиотеку.
Нужна вложенная навигация? Разбирайся с кастомными сценами.
В общем, вы поняли. Довольно много бойлерплейта придётся копировать из примеров на GitHub, чтобы всё завести. Если хотите, чтобы я сделал подробное сравнение с Decompose, вы знаете, что надо сделать👍
Ну и напишите, планируете ли вы миграцию с любой другой библиотеки на Navigation 3? Интересно будет узнать ваше мнение.
#Compose #Navigation
Только сейчас дошли руки более пристально взглянуть на новую Jetpack Navigation 3.
Помню, многие жаловались, что Decompose весь такой сложный, а навигация от Google простая. Но что мы видим в новой версии:
NavBackStack, NavEntry, NavDisplay, NavEntryDecorator, SceneStrategy и так далее
При этом, несмотря на то что вышла стабильная версия, много кода всё равно придётся писать дополнительно:
Хочешь навигацию по табам? Пиши код для управления бэкстеком.
Нужен BottomSheet? Пиши декоратор.
Необходимо привязать ЖЦ ViewModel к экрану? Подключай отдельную библиотеку.
Нужна вложенная навигация? Разбирайся с кастомными сценами.
В общем, вы поняли. Довольно много бойлерплейта придётся копировать из примеров на GitHub, чтобы всё завести. Если хотите, чтобы я сделал подробное сравнение с Decompose, вы знаете, что надо сделать
Ну и напишите, планируете ли вы миграцию с любой другой библиотеки на Navigation 3? Интересно будет узнать ваше мнение.
#Compose #Navigation
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍103🔥15❤7🤯4
Представьте ситуацию: вы скачали какое-то приложение из Google Play и отложили телефон, а тем временем кто-то получает полный удаленный доступ к вашему устройству, разблокирует его и может зайти в любое приложение даже без вашего разрешения на шаринг экрана 😨
Звучит жутко. Но такой вирус точно не пропустят в сторы, да ведь?
На самом деле еще как пропустят, потому что именно так работают приложения для удаленного доступа. Мой коллега Андрей Жуков поделился особенностями технической реализации такого приложения.
Ключевым элементом для удаленного управления является Accessibility Service и справедливости ради, пользователю все-таки придется выдать одно разрешение на его использование, поэтому просто скачать приложение недостаточно.
Теперь оператор сможет удаленно управлять устройством. Однако без доступа к шарингу экрана ничего видно не будет. Но как выдать разрешение без ведома пользователя? Очень просто: находим нужную кнопку подтверждения трансляции экрана и автоматически нажимаем на нее через тот же Accessibility Service 💀
Дальше встает вопрос: а как приложение может вообще работать до разблокировки экрана пользователем? Для этого в Android есть специальный режим Direct Boot mode. Его особенность в том, что у приложения есть доступ только к специальному зашифрованному хранилищу устройства, и для работы в этом режиме как минимум придется произвести миграцию SharedPreferences.
Остается решить вопрос со стабильностью. Например, можно перезапускать сервисы после перезагрузки устройства, реализовать механизм хелсчеков, детектить, что система пересоздала sticky-сервис, или прибегнуть к советам из этого поста.
В общем, лично для меня тема показалась очень интересной, но в формате одного поста раскрыть ее полноценно не получится. Если вы хотели бы узнать подробности, то ставьте реакции, и я мотивирую ребят написать подробную статью или сделать доклад по теме.🔥
#Android #AccessibilityService #RemoteControll
Звучит жутко. Но такой вирус точно не пропустят в сторы, да ведь?
На самом деле еще как пропустят, потому что именно так работают приложения для удаленного доступа. Мой коллега Андрей Жуков поделился особенностями технической реализации такого приложения.
Ключевым элементом для удаленного управления является Accessibility Service и справедливости ради, пользователю все-таки придется выдать одно разрешение на его использование, поэтому просто скачать приложение недостаточно.
Теперь оператор сможет удаленно управлять устройством. Однако без доступа к шарингу экрана ничего видно не будет. Но как выдать разрешение без ведома пользователя? Очень просто: находим нужную кнопку подтверждения трансляции экрана и автоматически нажимаем на нее через тот же Accessibility Service 💀
Дальше встает вопрос: а как приложение может вообще работать до разблокировки экрана пользователем? Для этого в Android есть специальный режим Direct Boot mode. Его особенность в том, что у приложения есть доступ только к специальному зашифрованному хранилищу устройства, и для работы в этом режиме как минимум придется произвести миграцию SharedPreferences.
Остается решить вопрос со стабильностью. Например, можно перезапускать сервисы после перезагрузки устройства, реализовать механизм хелсчеков, детектить, что система пересоздала sticky-сервис, или прибегнуть к советам из этого поста.
В общем, лично для меня тема показалась очень интересной, но в формате одного поста раскрыть ее полноценно не получится. Если вы хотели бы узнать подробности, то ставьте реакции, и я мотивирую ребят написать подробную статью или сделать доклад по теме.
#Android #AccessibilityService #RemoteControll
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥106❤9👍7
Итоги 2025 года
Как и у многих, у меня выдался не самый простой конец года, и в целом этот год для индустрии вышел нелёгким: какие-то проекты закрылись, кого-то сократили, и в целом чувствуется упадок интереса к сфере мобильной разработки и не только😕
Тем не менее хочется верить в лучшее, что турбулентность пройдёт, компании адаптируются к новым условиям и снова начнут вкладывать деньги в инвестиционную деятельность🤑
Несмотря на всё это, канал значительно вырос за этот год. Спасибо всем старым и новым подписчикам за поддержку, лайки, репосты и комментарии. Всё это мотивирует и дальше продолжать вести канал и как-то развивать наше сообщество❤️
Всех с наступающим и отличных вам новогодних каникул🏡
Как и у многих, у меня выдался не самый простой конец года, и в целом этот год для индустрии вышел нелёгким: какие-то проекты закрылись, кого-то сократили, и в целом чувствуется упадок интереса к сфере мобильной разработки и не только
Тем не менее хочется верить в лучшее, что турбулентность пройдёт, компании адаптируются к новым условиям и снова начнут вкладывать деньги в инвестиционную деятельность
Несмотря на всё это, канал значительно вырос за этот год. Спасибо всем старым и новым подписчикам за поддержку, лайки, репосты и комментарии. Всё это мотивирует и дальше продолжать вести канал и как-то развивать наше сообщество
Всех с наступающим и отличных вам новогодних каникул
Please open Telegram to view this post
VIEW IN TELEGRAM
❤48
Pixnapping attack
На днях узнал об одной интересной уязвимости, которая, по сути, без каких-либо разрешений и без root-доступа позволяет украсть изображение с любого приложения на устройстве будь то браузер или нативное приложение, например TOTP-код из Google Authenticator😱
Как это работает?
🔘 Атакующее приложение через intent открывает приложение-жертву и тут же возвращает свою Activity в foreground, что делает атаку почти незаметной для пользователя.
🔘 Затем поверх атакуемого приложения накладывается стек полупрозрачных Activity, где всё заливается белым цветом за исключением одного прозрачного пикселя, через который просвечивает UI атакуемого приложения.
🔘 Используя blur и особенности SurfaceFlinger, можно растянуть этот пиксель и получить либо однородный шаблон, если пиксель белый, либо шумный, если пиксель другого цвета.
🔘 Далее нужно определить цвет пикселя. Это делается за счёт особенностей графического сжатия в GPU: однородные изображения рендерятся быстрее, а шумные медленнее. Измерить это время можно с помощью VSync callback.
🔘 Таким образом, повторяя этот процесс для разных пикселей, можно полностью восстановить изображение атакуемого приложения 👍
Насколько это опасно?
На текущий момент нет гарантированной защиты от этой атаки, хотя Google и предприняла попытку ограничить количество Activity, которые могут использовать blur. Однако, как можно понять, такой сложный pipeline требует времени: полное восстановление изображения может занимать порядка 24 часов😁
Поэтому для сценариев кражи TOTP-кодов используются более оптимизированные варианты атаки.
На мой взгляд, уязвимость очень интересная, но из-за её сложности маловероятно, что она будет массово эксплуатироваться в реальных условиях.
А вам в целом откликается тема безопасности? Было бы вам интересно узнать больше про подобного рода уязвимости?
#Security #Android
На днях узнал об одной интересной уязвимости, которая, по сути, без каких-либо разрешений и без root-доступа позволяет украсть изображение с любого приложения на устройстве будь то браузер или нативное приложение, например TOTP-код из Google Authenticator
Как это работает?
Насколько это опасно?
На текущий момент нет гарантированной защиты от этой атаки, хотя Google и предприняла попытку ограничить количество Activity, которые могут использовать blur. Однако, как можно понять, такой сложный pipeline требует времени: полное восстановление изображения может занимать порядка 24 часов
Поэтому для сценариев кражи TOTP-кодов используются более оптимизированные варианты атаки.
На мой взгляд, уязвимость очень интересная, но из-за её сложности маловероятно, что она будет массово эксплуатироваться в реальных условиях.
А вам в целом откликается тема безопасности? Было бы вам интересно узнать больше про подобного рода уязвимости?
#Security #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53🤯22🔥5❤2🤔1
Хотите заняться своим английским в 2026, чтобы выйти на международный рынок? 🚀 💵
С этим помогут в онлайн-школе разговорного английского Authentic Pigeon
Ребята соберут кастомную программу с разговорной практикой и органично впишут занятия в ваше расписание, чтобы изучение языка было в удовольствие, а не обязаловку.
Абсолютно кайфую от подхода ребят. Занятия тут это не потогонка, а крутой дружеский разговор.
Студент школы — Иван
⚡️ Узнать подробнее и записаться на бесплатный демо-урок
Реклама. Моисеева Анастасия Андреевна, ИНН 270393875959. Erid: 2VtzqvCfEFU
С этим помогут в онлайн-школе разговорного английского Authentic Pigeon
Ребята соберут кастомную программу с разговорной практикой и органично впишут занятия в ваше расписание, чтобы изучение языка было в удовольствие, а не обязаловку.
Абсолютно кайфую от подхода ребят. Занятия тут это не потогонка, а крутой дружеский разговор.
Студент школы — Иван
⚡️ Узнать подробнее и записаться на бесплатный демо-урок
Реклама. Моисеева Анастасия Андреевна, ИНН 270393875959. Erid: 2VtzqvCfEFU
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
PRO английский ⚡️ Authentic Pigeon
Бот онлайн-школы разговорного английского для профессионалов с карьерными целями. Наш канал — @authenticpigeon
👍6