en
Feedback
We Love Android

We Love Android

Open in Telegram

Новости из мира Android-разработки

Show more
655
Subscribers
No data24 hours
+17 days
+2430 days
Posts Archive
Насмотренность — важный навык в работе дизайнера. Это то что помогает быть в тренде, учиться на чужом опыте, черпать вдохновение, отличать хороший дизайн от плохого, критически оценивать свою работу и так далее. Нет вы не ошиблись каналом, просто я считаю, что насмотренность важна и разработчикам. Чем больше чужого кода смотришь — тем лучше пишешь свой. Просто потому что больше новых приёмов и концепций узнаёшь, улучшаешь свой скилл владения языком. С хэштегом #насмотренность буду писать про всё интересное на что наткнулся при просмотре open-source проектов. Это первый пост :) 👀 Companion object Чаще всего companion object используется просто как замена статическим методам и полям из Java. А ведь companion object это в первую очередь object и как у любого другого объекта у него может быть имя и он может реализовывать интерфейсы и наследоваться от других классов. Сегодня будет два примера таких companion object'ов. ☝️ Json в kotlinx.serialization Это класс, но мы можем использовать его как-будто он object:
val result = Json.decodeFromString("42")

Всё потому что companion object у Json реализует класс Json:
companion object Default : Json(JsonConfiguration(), EmptySerializersModule())

Зачем так сложно, если можно было бы просто объявить object Json? Потому что тогда не было бы возможности создать свой инстанс, а когда Json это класс, такая возможность остаётся. ✌️CoroutineContext.Key в kotlinx.coroutines CoroutineContext вообще интересная штука. По сути это что-то между Map и Set. Каждый элемент контекста хранится в CoroutineContext по ключу и получить элементы контекста можно через оператор get. Каждый ключ должен быть singleton'ом и ключ должен быть у каждого элемента контекста (Job, CoroutineDispatcher и т.д.). Идеальная задача для companion object! У каждого элемента контекста companion object это реализация CoroutineContext.Key и смотрите какая красота получается в совокупности с оператором get у CoroutineContext:
val job = coroutineContext[Job]
val dispatcher = coroutineContext[CoroutineDispatcher]

Выглядит как-будто получаем элемент контекста по типу. На самом деле используется companion object c типом Key, объявленный в этих классах. Например, в Job он выглядит так:
companion object Key : CoroutineContext.Key<Job>

Repost from Dev Easy Notes
Два друга @JvmWildcard и @JvmSuppressWildcards. В комментах накинули вопрос про @JvmSuppressWildcards. Тоже довольно неочевидная штука, но порой приходится разбираться. Суть в чем, Java и Kotlin полностью совместимы, что означает что из Java можно вызывать Kotlin, и наоборот. На стыке этих двух языков начинаются приколы, например в Kotlin все типы делятся на Nullable и NotNullable, а в Java такого разделения нет.  Работа дженериков тоже немного отличается. Буквально в предыдущем посте я описывал, что ковариантность и контравариантность в Kotlin может работать на уровне классов, а не ссылок. И вот пример: class Box<out T>(val value: T) fun box(value: Integer): Box< Integer> = Box(value) fun unbox(box: Box<Number>): Number = box.value Как видите в Box дженерик помечен как out, что означает ковариантность на уровне всех объектов. Только это работает на уровне Kotlin. Если попытаемся вызвать метод box из Java, то он вернет Box без дженерика. Это как бы немного нарушает логику ковариантности которую обещает Kotlin. При этом в методе unbox автоматически появится wildcard. В итоге в Java получим вот это: Box box(Integer value) Number unbox(Box<? extend Number>) В целом все не так страшно, однако иногда охото подкрутить это поведение. Например, мы не хотим, чтобы в методе unbox автоматически проставлялся wildcard. Или же напротив проставлялся в результатах функции, в методе box. И вот для этого, нужны наши волшебные аннотации. Кафк всегда, лучше на примере. Делаем в Kotlin:   fun box(value: Integer): Box<@JvmWildcard Integer> = Box(value) Получаем в Java: Box<? extend Integer> box(Integer value) Делаем в Kotlin:   fun unbox(box: Box<@JvmSuppressWildcards Number>): Number = box.value Получаем в Java: Number unbox(Box<Number> box) Сравните эти две полученные функции с дефектным поведением и суть станет ясна. Где это нужно на практике? У меня такое было только при работе с Dagger. Фишка в чем, в том что Dagger работает на базе Kapt. Если вдруг не знали, то kapt работает в два приседания. Сперва он перегоняет весь код в Java Stub и только потом генерит нужный код. Поэтому он такой долгий и по этой причине иногда нужно делать подсказки компилятору, когда пишем модули на Kotlin. В противном случае кодогенератор начинает чудить и падать.

KMM Utilities - набор различных утилит для Kotlin 👉 ApiResult - монада для оборачивания результата операции. Схоже с kotlin.Result, но больше возможностей. 👉 Common - Дополнения к Kotlin stdlib 👉 Datetime - Все чего не хватает и kotlinx.datetime, Java Calendar и DateTime API. 👉 Coroutines: Расширения для Coroutines & Flows API. Расширения для Android.

Обычно мы на всех проектах добавляем тип сборки QA. Это такая сборка, которая максимально близка к релизной, но может включат
Обычно мы на всех проектах добавляем тип сборки QA. Это такая сборка, которая максимально близка к релизной, но может включать в себя дебаг-панель и позволяет подключиться к приложению через дебаггер. И вот недавно оказалось, что схема не работает. QA сборки не обфусцируются, а значит не сильно отличаются от дебажных. Причём не понятно в какой момент отвалилась обфускация и из-за чего это произошло. Расследование привело к багтреккеру гугла: "AGP 7.2.0 onwards does not obfuscate our built app" и issue закрыто как Won't fix (Intended behavior) 🙂 Дело в том, что флаг isDebuggable = true теперь отключает обфускацию и по задумке инженеров гугла так должно было работать всегда. Ведь вы не сможете бегать по коду дебаггером, если он отличается от исходников, какой же это тогда получается debuggable? То что раньше была возможна обфускация с isDebuggable = true это изначально ошибочное поведение и AGP никогда не должен был так работать. Видимо ошибка показалась настолько очевидной, что фикс даже не упомянули в release notes, а как известно every change breaks someones workflow, что и случилось. Решение подсказали там же в issue. Новый API, добавленный в AGP 7.0 4.2 позволяет вклиниться в процесс подготовки артефактов сборки. Можно подменять, добавлять и изменять промежуточные файлы, например: манифест, APK и даже использовать совсем чёрную магию — модифицировать уже скомпилированные классы. Хотелось когда-нибудь модифицировать один класс в библиотеке, чтобы не ждать исправления бага? Но сейчас не об этом. Нам интересен манифест. С помощью этого API мы можем дописать любой текст в смердженный манифест, в частности и флаг debuggable. 👨‍🦽 Результат можно увидеть в фиксе для gradle-infrastructure или в отдельном сниппете. P.S. Помимо флага в манифесте приходится ещё руками менять значение BuildConfig.DEBUG ведь он тоже зависит от isDebuggable. #agp #snippet

Repost from Android Guards
Даже если на устройстве есть root доступ, команды adb push/pull все равно будут работать в пользовательском режиме. Это значи
Даже если на устройстве есть root доступ, команды adb push/pull все равно будут работать в пользовательском режиме. Это значит, что не выйдет скачать или отправить файлы в директории доступные только суперпользователю. Но выход есть. Вместо adb push будет cat file.txt | adb shell su -c "dd of=/data/file.txt", а для замены adb pull - adb shell su -c "dd if=/data/file.txt" >> file.txt. В целом, так можно выполнить любую команду с правами root - adb shell su -c "<command>". #aht

SuperImage - это Android-приложение для улучшения качества изображений на основе нейронной сети, созданное с использованием ф
SuperImage - это Android-приложение для улучшения качества изображений на основе нейронной сети, созданное с использованием фреймворка глубокого обучения MNN и Real-ESRGAN. Входное изображение обрабатывается тайлами на графическом процессоре устройства с использованием предварительно обученной модели Real-ESRGAN. Затем плитки объединяются в окончательное изображение с высоким разрешением. Это приложение требует поддержки Vulkan или OpenCL и Android 7 или выше. SuperImage на GitHub: https://github.com/Lucchetto/SuperImage Платформа: Android ⭐️: 486

Repost from Android Broadcast
Вышла вторая Dev Preview Android 14, которую можно ознаменовать как "еще больше ограничений для разработчиков" и радость для
Вышла вторая Dev Preview Android 14, которую можно ознаменовать как "еще больше ограничений для разработчиков" и радость для магазинов приложений! 👉 Выдача доступа приложения к отдельным фото и видео, вместо всех (аналогично на iOS) 👉 Credential Manager - единая точка работы с sign-in. Через Jetpack это API уже портировано на Android 4.4+ 👉 Дополнительные ограничения по запуску Activity из фона 👉 Больше ограничений на фоновую работу 👉 Новое API в PackageInstaller позволит каждый раз не запрашивать установку приложений, а сделать это один раз для приложений. Альтернативным магазинам станет жить проще 👉 Региональные настройки для всей системы и для каждого приложения 👉 Разработчики смогут определить когда делаются скриншоты Все изменения я разберу в отдельных постах @android_broadcast #android14

Repost from Mobile Compose
#Article #Medium #Compose [Eng] How to Handle Automatic Content Resizing when keyboard is visible in Jetpack Compose Неплохая статья с разбором того, как можно адаптировать контент приложения под открытие/закрытие клавиатуры на Compose.

Repost from Android Broadcast
Обновили официальную документацию по обработке изменения конфигурации (поворот экрана, смена языка и пр.). Добавили советы по использованию Jetpack API, как работать с этим из Compose и лучшие практик

Ключевые слова in и out. А так же что такое ковариантность и контрвариантность (12 мин) Погружение в вариативность Generic типов в Kotlin. Тема непростая, но может раскрыть вам новые грани гибкости вашего кода и его строго типизации

Building an Android System Design Architecture for Efficient Image Uploads with Clean Architecture Пример проектирования архи
Building an Android System Design Architecture for Efficient Image Uploads with Clean Architecture Пример проектирования архитектуры для приложения, которое могло бы позволить загружать большое количество картинок на сервер без блокировки UI и с доп. кейсами. Без примера кода, но с разбивкой на слои и детальным описанием связей и работы каждого слоя. Читать (En)

Repost from Android Guards
Попалась мне тут совершенно замечательная ссылка, которой не имею сил не поделиться - https://github.com/krizzsk/HackersCave4StaticAndroidSec. Там куча ссылок на туториалы, утилиты и исследования по уязвимостями в Android. Звучит скучно да? Верно. Это был бы еще один всратый "awesome list" если бы не одно "но" - там много ссылок на нативные китайские блоги и статьи. И там действительно полезная инфа, которую просто так не загулишь, если не ищешь специально на китайском. Я давно хотел найти что-то подобное и вот оно пришло. Из полезного лично для себя, я нашел там разбор форматов различных файлов (AndroidManifest.xml, resources.arsc и т.п.) и материалы по статическому анализу. Всем 你好 ;)

Mastering Execution Time Measurement in Kotlin Статья с примерами того, как можно измерять время выполнение ваших функций в K
Mastering Execution Time Measurement in Kotlin Статья с примерами того, как можно измерять время выполнение ваших функций в Kotlin, с помощью👇 • measureNanoTime() • measureTimeMillis() • measureTimeMicros() • measureTime() Читать (En)

Repost from Android Broadcast
В Chrome появится поддержка Partial Custom Tabs, которая частично перекрывает контент вашего приложения и позволяет взаимодействовать с вашим приложениям и Web контентом. Эта возможность уже доступна в Jetpack Browser 1.5.0 @android_broadcast #chrome #jetpack

Про нейминг в коде Арсений Мельников выпустил отличную статью про нейминг. Арсений занимается нашим публиным API у Dodo IS, круто что у него в этом такой системный подход. https://habr.com/ru/company/dododev/blog/714512/

Repost from Mobile Compose
#Featured #AndroidDevelopers #MADSkills #YouTube [Eng] Constraints and modifier order Очередной видеоролик про базовые практики в Compose из серии MAD Skills, в котором на этот раз разбирается как работает цепочка модификаторов (Modifiers) в Compose, а также почему так важен порядок их применения.

Repost from Android Good Reads
Как Reddit переезжали на Anvil Дано: приложение на 500 модулей, активно использующее Dagger 2 и кастомный kapt процессор для борьбы с циклическими зависимостями. Команде не нравилось, что их DI сетап слишком сложный, онбордить новых людей в него трудно, а использование kapt существенно замедляет сборку. Чтобы решить эти проблемы, проект перевели на работу с Anvil. В статье – история миграции, результаты и советы тем, кто решит повторить их путь.

Read You - открытый RSS-ридер для Android на Jetpack Compose и с Material You. Read You на GitHub: https://github.com/Ashinch
Read You - открытый RSS-ридер для Android на Jetpack Compose и с Material You. Read You на GitHub: https://github.com/Ashinch/ReadYou Платформа: Android ⭐️: 1.8K

Repost from Mobile Compose
#Article #Blog #OpenSource Maps Compose Library Tutorial for Android: Getting Started В феврале 2022 года Google выпустила библиотеку Maps Compose (набор composable функций с открытым исходным кодом для упрощения интеграции с Google Maps, а также различных типов данных, связанных с Maps SDK). О том, как работать с этой библиотекой на примере приложения GeoMarker — в сегодняшней статье.

Дамп и расшифровка трафика без использования Proxy Все мы так или иначе сталкивались с необходимостью посмотреть трафик приложения и поисследовать его. Но всегда мешают всякие нехорошие безопасники, которые заставляют делать разработчиков SSL Pinning в приложении. И наиболее частый вопрос - как открутить пиннинг в приложении. Как правило, это использование frida или аналогов, чтобы подмениить и отключить проверку сертификата в приложении. Но сделать это удается далеко не всегда и не со всеми приложениями. Есть альтернативный вариант данному методу - это логировать SSL-ключи, которые используются для шифрования внутри канала связи, снимать дамп трафика и потом его расшифровывать этими ключами. Спасибо огромное @vadim_a_yegorov за универсальный скрипт для Android и iOS (12/13/14/15), который помогает снимать и сохранять ключи! Вот тут можно найти полный Frida-код этого прекрасного скрипта. Спасибо, это очень круто! #sslpinning #ssl #keys #dump