Разработчик (Mobile Developer) и программист Алексей Гладков попытался независимо изучить компоненты мессенджера Max.

Android *
Пишем под самую популярную мобильную ОС
Почему разработчикам опенсорсных приложений для Android может не потребоваться подтверждать свою личность
Недавно Google анонсировала, что скоро смартфоны на базе Android будут работать только с приложениями, чьи разработчики подтвердили свою личность непосредственно Google. Но как это будут проверять? Напрашивается проверка по ключам подписи, но погодите-ка…
Если вы более-менее интересуетесь опенсорсом, наверняка вы слышали про “магазин” F-Droid. Что примечательно в нём — все приложения в его главном (единственном по умолчанию) репозитории собираются из исходников и подписываются одной сущностью — F-Droid. Эта особенность делает данный источник приложений уникальным в своём роде — в Google Play или RuStore каждый разработчик собирает и подписывает приложение сам.

Если Google не передумает и действительно введёт блокировку на “анонимных” разработчиков, вполне возможно, что F-Droid просто создаст единый аккаунт для своего ключа подписи, и продолжит спокойно предоставлять приложения даже на “сертифицированных” Android-девайсах.
Но наверняка вы скажете, что там распространяются приложения, неугодные Google, и будете правы. Однако они и так ломаются каждый месяц самой же корпорацией ввиду открытых исходников этих приложений и способов парсинга контента без официального API. Так что, думаю, обойдётся.
Что думаете?
🎲 Retrofit 3.0 — что изменилось?

При поддержке блога @dolgo_polo_dev
Вышел Retrofit 3.0. А точнее в один день вышло 2 версии — Retrofit 3.0 и 2.12
Библиотека важная, поэтому попробовал разобраться, что изменилось
Самое интересное случилось в 2.12 — добавили стриминговую сериализацию из Kotlin/Java-классов в Json/Protobuf
Зачем это нужно было?
➡ чтобы большие классы не сериализовывались целиком перед отправкой запроса, а начинали это делать во время передачи данных на бэк
Это позволит чутка снизить нагрузку на процессор и оперативку, если
передаете объемные данные в теле запроса (1 мегабайт+)
где-то вызываете
Retrofit.Call.enqueue()с главного потока — стриминг перенесет сериализацию с главного UI-потока в бэкграунд
Чтобы изменения заработали, нужно создавать конвертер с помощью функции withStreaming()
MoshiConverterFactory.create(moshi).withStreaming() // пример
В Retrofit 3.0 просто апнули версию OkHttp (3.14.9 -> 4.12.0). И немного поправили внутреннего кода, пару строк для совместимости с 4.12.0
Так что если обновите версию Retrofit, у вас транзитивно апнется OkHttp — будьте внимательны, берегите себя и своих тестировщиков
Из хороших новостей — Retrofit 3.0 формальный мажор, то есть бинарно совместим с предыдущими версиями (по словам разработчиков). Мажорное версию апнули для хайпа, чтобы подчеркнуть обновление OkHttp
Пруфы:
compare 3.0 with previous (https://github.com/square/retrofit/compare/2.12.0...3.0.0#diff-ee4546957dd484579c54b92114186cb4b3181a8906d98fbf94fbc526bf755943)(там много ченжей, но 90% из них — это обновление их website с документацией)
compare 2.12 with previous (https://github.com/square/retrofit/compare/2.11.0...2.12.0) (тут можно посмотреть, за счет чего сериализация стала асинхронной)
остальные посты про Android публикую в https://t.me/dolgo_polo_dev
Нужно было быстренько перехватить вызов нативной функции и посмотреть значение переменной в Android приложении. Как то давно использовал для этого замечательную утилиту Frida. Установил на планшет frida-server (root уже был) и клиент на PC, написал классический JS хук, но он не работал:
defineHandler({
onEnter(log, args, state) {
conslole.log('decoder_CRC_check()');
},
onLeave(log, retval, state) {
const libc = Module.findBaseAddress('libc.so');
console.log(hexdump(libc, {
/* address: ptr('0x1000'), -- to override the base address */
offset: 0,
length: 64,
header: true,
ansi: true
}));
}
});В консоли лишь получал TypeError: not a function at onEnter (D:\Distrib\Android TV\frida\hook.js:7)
Убил полдня в поисках "чего я делаю не так", при том что и официальная дока и нейронки твердят, что именно так и нужно получать базовый адрес модуля и, при необходимости, функций. Оказалось, во Frida 17 автор полностью удалил некоторые функции (а дока и нейронки еще не обновились):
Module.ensureInitialized()
Module.findBaseAddress()
Module.getBaseAddress()
Module.findExportByName()
Module.getExportByName()
Module.findSymbolByName()
Module.getSymbolByName()
Туда же статические функции Memory
И теперь надо писать цепочку вызовов:
const lib = Process.findModuleByName("libc.so");
console.log("[*] libc.so loaded at base: " + lib.base);
const funcAddr = lib.findExportByName("decoder_CRC_t_init");Итог получился такой универсальный скрипт:
Java.perform(function () {
const System = Java.use("java.lang.System");
const Runtime = Java.use('java.lang.Runtime');
const SystemLoadLibrary = System.loadLibrary.overload('java.lang.String');
const VMStack = Java.use('dalvik.system.VMStack');
// "ожидание"\перехват динамической загрузки нативных библиотек
SystemLoadLibrary.implementation = function(library) {
console.log("Loading dynamic library => " + library);
const loaded = Runtime.getRuntime().loadLibrary0(
VMStack.getCallingClassLoader(), library
);
if (library.includes("mylibname")) {
console.log("\n[+] Hooked mylibname");
// перехватываем только нужную нам
hookNativeFunc();
}
return loaded;
}
});
function hookNativeFunc() {
//тут имя полностью как называется сам файл в ресурсах
const lib = Process.findModuleByName("libmylibname.so");
console.log("[*] mylibname.so loaded at base: " + lib.base);
const funcAddr = lib.findExportByName("decoder_CRC_t_init");
if (!funcAddr) {
console.log("[-] Function not found!");
return;
}
console.log("[+] Found decoder_CRC_t_init at: " + funcAddr);
Interceptor.attach(funcAddr, {
onEnter: function (args) {
var result = args[0];
var inputPtr = args[1];
var len = args[2].toInt32();
console.log("\n[+] decoder_CRC_t_init called");
console.log(" result: " + result);
console.log(" inputPtr: " + inputPtr);
console.log(" len: " + len);
},
onLeave: function (retval) {
//нужный адрес массива, например из IDA PRO
const wordArrayOffset = 0x5B2C04;
const wordArray = lib.base.add(wordArrayOffset);
var ptr = new NativePointer(wordArray); // современный вариант чтения
console.log("[*] 5B2C04 contents:");
try {
console.log(hexdump(ptr, {
offset: 0,
length: 512,
header: true,
ansi: true
}));
} catch (e) {
console.log("[!] Error reading 5B2C04:", e);
}
console.log("Return value:", retval);
}
});
}
Запускается так frida -U -f com.android.app -l hook.js
Как ускорить Android-разработку и избавиться от мучительно долгих запусков эмуляторов ради простого теста?
Ответ — Robolectric — мощный инструмент для UI‑тестирования Android‑кода без эмулятора.
Позволяет запускать юнит-тесты Android-приложений прямо в JVM, без эмуляторов и физических устройств. Экономия на каждом тестовом прогоне, обратная связь почти мгновенная.
В Android‑комьюнити у Robolectric неоднозначная репутация из‑за трудностей совместимости с другими библиотеками. Но…его почти бесценные возможности пробудили любопытство и желание копнуть глубже и осмыслить этот инструмент.
Так и родилась статья «Мечтают ли андроиды о Robolectric? Разбираем фреймворк по косточкам» от Павла Нестеренко, нашего Android-разработчика.
Если вы устали ждать, пока эмулятор запустится, и хотите гонять юнит-тесты за секунды прямо в JVM, то рекомендуем статью к прочтению!

Save the date: 4 июля встречаемся на Android Meetup!
В программе доклады от спикеров Wildberries & Russ и Альфа-Банка, Q&A-сессия с розыгрышем мерча, нетворкинг и фуршет для классного завершения вечера.
Поговорим о том, как оживить виджеты, подружить Compose с Koin и навигацией, а заодно встроить одно Android-приложение в другое без боли...или с болью:
«Виджеты на Android: это просто?»
Александр Гирев, Android Team Lead продуктовой команды WB Partners
«Compose+Koin+JetpackNavigation: что мы поняли за 2 года»
Арсений Шпилевой, Android-разработчик кор-команды WB Partners
«Интеграция Android-приложений: подходы и лучшие практики»
Абакар Магомедов, главный техлид разработки в Альфа-Банке
Когда: 4 июля 18:00 (сбор гостей с 17:00)
Где: Москва, пространство Весна + онлайн-трансляция
Регистрация уже открыта — присоединяйтесь онлайн или офлайн!
Telegram запустил конкурс для разработчиков под Android. Призовой фонд: $50 000. Срок сдачи работ: 11 июля, 23:59 по дубайскому времени (UTC+4). Объявление итогов: июль 2025.
В дополнение к призовым, победитель конкурса сможет присоединиться к команде Telegram в Дубае и зарабатывать 1 миллион долларов в год после вычета налогов.
Задача: Внедрить обновлённый интерфейс профилей в приложение Telegram для Android в строгом соответствии с предоставленным дизайном.
Полные условия конкурсного задания, технические подробности и макеты представлены в отдельном канале платформы.
Вы - начинающий разработчик под Андроид или просто пишете "для себя" и решили отображать динамическую анимацию через SurfaceView. Например, взяв за основу вот этот код или похожий. Вы разместили SurfaceView или его наследника (у меня MySurfaceView) в activity layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activityMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<agalilov.doppler.MySurfaceView
android:id="@+id/dopplerView"
android:background="#040947"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="15dp"
app:layout_constraintBottom_toTopOf="@+id/btnStartStop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnStartStop"
android:layout_width="118dp"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:text="@string/start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dopplerView" />
</androidx.constraintlayout.widget.ConstraintLayout>Запускаете приложение и... ничего не работает: SurfaceView не меняется, картинки нет! Ошибок тоже нет, код рисования выполняется впустую.
Я провёл почти всю ночь, разбираясь в причине. Оказалось, для SurfaceView, который размещён внутри другого View, по-умолчанию используется z-order "позади" родительского View. Это поведение, документированное в разных источниках, оказалось для меня неожиданным.
Лечится просто: при инициализации (в конструкторе класса-наследника) SurfaceView устанавливаем setZOrderOnTop(true):
public MySurfaceView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setZOrderOnTop(true);
. . .
}Вот такая история :)
URLCheck: Полезная утилита для инспекции URL на Android
Хочу поделиться находкой, которая многим здесь придется по душе. Каждый из нас хоть раз с недоверием кликал по сокращенной или странной ссылке, присланной в мессенджере или почте. Сколько раз мы неосознанно переходили по ссылкам с кучей UTM-меток и прочего трекающего мусора?
Недавно я наткнулся на утилиту для Android, которая решает эту проблему - URLCheck.
Это не браузер, а приложение-посредник. Вы назначаете его для открытия ссылок по умолчанию, и когда вы кликаете на любую ссылку, вместо того чтобы сразу открыть его в браузере, URLCheck перехватывает его и показывает вам вот такое окно:

Вот несколько любопытных ключевых фич:
Очистка от трекеров: Автоматически вырезает из линка весь мусор вроде UTM-меток и параметров отслеживания, используя правила проекта ClearURLs.
Сканер VirusTotal: Позволяет в один клик отправить ссылку на проверку в VirusTotal и посмотреть отчет. (Нужен свой бесплатный API-ключ).
Раскрытие коротких ссылок: Показывает, куда на самом деле ведет укороченный линк типа
bit.ly- зачастую фишинговые ссылки скрываются за укороченными линками, чтобы усложнить блокировки.Проверка по хост-листам: Интегрируется со списками StevenBlack (adware, malware, fakenews и т.д.) и предупреждает, если домен находится в одном из них.
Pattern-checker: Для продвинутых - можно настроить свои правила на основе регулярных выражений. Например, автоматически заменять
httpнаhttpsилиtwitter.comнаnitter.net.Полный контроль над линком: Вы можете вручную отредактировать URL, посмотреть историю изменений или просто скопировать/поделиться ей.
И самое главное — приложение с открытым исходным кодом! Настоящий швейцарский нож для тех, кто заботится о своей безопасности и приватности в сети.
Где скачать:
GitHub (репка)
В общем, рекомендую попробовать. Для меня это стало одним из приложений категории "must-have".
Google опубликовала ролик в рамках своей юмористической рекламной кампании Best Phones Forever с «диалогом» между персонифицированными смартфонами Pixel и iPhone. Повествование разворачивается вокруг анонсированных Apple «прорывных» функций iOS 26, которые, по задумке Google, на самом деле уже давно доступны пользователям Pixel.
В видео iPhone перечисляет «новые» возможности операционной системы Apple: перевод сообщений и звонков в режиме реального времени, интеллектуальный отбор вызовов и умное удержание. Выясняется, что аналогичный функционал появился на устройствах Pixel еще пять лет назад, что ставит под сомнение новизну представленных Apple решений.
📜 M-V-подставь_свое
Model-View-*** - это шаблоны проектирования
Важное уточнение: это шаблоны проектирования только для presentation слоя, а не для целого приложения
💃 Model
- это как раз та часть приложения о которой мы ближайшее время говорить не будем
Чаще всего ее называют бизнес логикой, но это не совсем верно
Пока, лучше всего воспринимать ее как модель данных которую наше приложение хочет передать пользователю
Причем не важно будет это Ui или API, или что-то другое
MV шаблоны не про frontend, а про то как передать данные клиенту, кем бы он ни был
🖼 View
- это само представление данных пользователю. То, что он по итогу получит
В мире андройд это обычно Activity, Fragment, View или Compose
🪝***
- это какая-то прослойка между моделью данных и их представлением пользователю
Для чего все эти шаблоны вообще придумали?
Дело в том, что View это какой-то вариант отображения данных клиенту 🏐
И часто возникает ситуация, что нужно создать другой вариант отображения ⚽️
Это может быть как бизнес потребность в перекраске кнопок и проведении при этом ab-тестов, 🏀
или желании разработчиков заменить технологию отображения 🏈
Например, у вас было консольное приложение, а вы вдруг захотели сделать для него UI (GitBash|GitUi здравствуйте),
ну или решили заменить Android.View на Compose
Во всех этих случаях нам хочется чем-то разделить саму View и работу с Model, чтобы иметь возможность заменить только View, не трогая ничего другого
В Android, к этому еще добавляется проблема пересоздания View при изменении конфигурации. Когда вы переворачиваете экран (и не только), весь ваш UI просто уничтожается и создается полностью заново. Хотя с точки зрения пользователя это все тот же экран с теми же данными 🫠
Это создает дополнительную потребность отвязать View от остального приложения, чтобы можно было ее подменять прямо в рантайме
Основные шаблоны это MVC, MVP, MVVM и MVI
О них мы и поговорим в следующих постах...
ПС. Посты с большим опережением есть в тг канале из описания профиля
Магазину приложений RuStore исполнилось три года. Количество установок этого приложения на устройствах пользователей превысило 100 млн.

25 мая 2022 года VK при поддержке Минцифры запустила открытое бета‑тестирование отечественного магазина мобильных приложений для Android под названием RuStore.
В начале февраля 2023 года RuStore объявил о завершении этапа бета‑тестирования магазина приложений. Также создатели платформы перевели интерфейс консоли разработчика на английский язык для удобства иностранных издателей и партнёров.
В декабре 2024 года месячная аудитория магазина приложений RuStore составила 50 млн пользователей старше 12 лет по всей России, согласно исследованию Mediascope. Аудитория Xiaomi Mi Store составила 19 млн, Samsung Galaxy Store — 14 млн, HUAWEI AppGallery — 10 млн, рассказали Хабру в пресс‑службе RuStore. А в Минцифры заявили, что RuStore от VK обошёл по числу пользователей в России App Store от Apple.
В VK добавили, что в каталоге RuStore уже более 50 тысяч приложений, доступных на ОС Android, Harmony OS и «Аврора», от разработчиков из 40 стран мира. Также вышли версии RuStore для электронных книг и умных телевизоров, для проекторов, Hi‑Fi‑аудиоплееров, игровых консолей, кассовых терминалов, умных часов.
Google I/O 2025: два вечера главных анонсов вместе с Surf

20 и 21 мая — подключайся к нашим стримам по Google I/O. Будем вместе следить за анонсами новинок, делиться первыми впечатлениями и обсуждать всё самое интересное из мира технологий и разработки в прямом эфире.
Смотрим и комментируем:
20 мая (вторник)
→ 20:00 — Google Keynote: все главные анонсы и будущее технологий от Google.21 мая (среда)
→ 20:00 — What’s new in Android development tools: новинки для Android-разработчиков.
→ 21:00 — What’s new in Flutter: свежие обновления для Flutter-сообщества.
Время указано по Москве. Позже добавим сюда наших спикеров и персональные ссылки на трансляции.
Залетай на эфиры в нашу группу ВКонтакте, чтобы обсудить новинки и пообщаться с разработчиками. Запись сохраним.
Ближайшие события
Android-приложение «Контакты»: работает — не трогай

У многих полей контакта есть типы. Например, у номеров телефонов или адресов электронной почты по умолчанию есть типы «рабочий» и «домашний». Аналитики сказали, что нужно реализовать дополнительные типы и дать пользователю возможность создавать свои. Звучит легко, но на деле оказалось совсем непросто.
Чтобы заменить стандартные типы полей, нужно добавить новую базу данных с доступными типами полей, а также реализовать отображение и возможность выбора поля. Для этого пришлось во многом переписать код редактирования полей контакта, где и без этого логика была непростой. Теперь стало совсем сложно: при добавлении или обновлении поля в contentProvider нужно указывать тип поля, так что мы начали указывать «custom».
После добавления кастомных типов приложение потеряло стабильность, появились кейсы, в которых кастомные типы работали неправильно. Один из них приводил к крашу: база данных не успевала создаваться при открытии интента на редактирование контакта.
Изначальный путь пользователя — это открыть приложение и увидеть список контактов с аватаркой, именем и номером телефона. Пока этот список подгружался на экране, база данных обычно успевала создаться. Но мы не учли, что при открытии интента на редактирование контакта из другого приложения сразу появляется экран редактирования — в этом случае база данных не успевала инициализироваться.
Создание схемы БД и инициализация стандартными значениями происходила в отдельном потоке, так что у нас получилась небольшая гонка потоков. UI готов отобразить экран и идет в БД за данными, но БД не успевает инициализироваться, так что запрос приводил к критической ошибке. Баг воспроизводился при попытке обратиться к БД только при первом холодном запуске на устройстве или после очистки данных, так как здесь приложению приходится заново создавать схему базы данных.
Пришлось опять добавлять костыль: в отдельной корутине ожидать инициализации БД и только потом начинать рисовать экран...
Дмитрий Бражник, старший инженер-программист в департаменте разработки мобильных приложений YADRO, рассказал в статье, как его команда пыталась допилить стандартное AOSP-приложение «Контакты» и к чему они в итоге пришли.
Хардкодить допоздна? А может, лучше нет, ворк?

23 апреля в 20:00 приглашаем воронежских разработчиков на неформальный митап. Для тех, кто не сможет прийти офлайн, будет трансляция.
Никаких скриншотов кода на слайдах. Никакого душного обсуждения документации. Поговорим о том, что окружает нас вне работы. Прокачаем софт-скиллы и нетворкинг.
В программе митапа три доклада:
Лёша, Android-разработчик Surf — «Дедлайн "вчера": как работать с приоритетами».
Как рассеивается внимание? Как ставить приоритеты в работе с командой? Когда нужно выносить переписку в звонок, а когда можно обойтись текстом? Ответим на эти и многие другие вопросы про приоритеты в работе и жизни.Дима, Flutter-разработчик Surf — «Тимлид — друг или враг? Или так»?
Расскажу о роли тимлида, но со стороны нижестоящего сотрудника. Что мне нравится/что не нравится в лиде, что для меня кажется полезным, а смысл чего я не понимаю.Кирилл, iOS-разработчик, наш друг и гость из Una Financial — «Work-life health для IT-шника среднего возраста».
Поделюсь жизненными проблемами разработчиков и способами их решения. Внимательный слушатель вообще сможет их избежать! Обсудим, как сделать жизнь лучше, повысить её качество. Максимально продлим трудоспособный возраст.
Митап пройдет 23 апреля, в 20:00, в воронежском пространстве «Eventuki»: ул. Фридриха Энгельса, 52.
Участие в митапе бесплатное, чтобы прийти или получить ссылку на трансляцию, нужно зарегистрироваться 👈
Запись трансляции обязательно сохраним, но если вы из Воронежа, мы очень ждём понетворкать вживую. До встречи 😉
Вышло видеоруководство по переводу смартфонов Pixel на GrapheneOS с упором на конфиденциальность, включая настройку ключевых параметров и установку приложений, а также способы работать с сервисами Google Play с отключением трекеров.
Добавлен Room! :)
Ранее я уже делился статьей про Delight SQL Viewer — библиотеку, позволяющую отлаживать SQLDelight-базу данных напрямую внутри вашего Kotlin Multiplatform-приложения. Однако в одном из наших внутренних проектов используется Room Multiplatform и хотелось иметь возможность отладки БД и в нем. Так и появилась вторая версия библиотеки, которая теперь поддерживает и Room, и SQLDelight.
Что делает библиотека?
Позволяет просматривать, добавлять, редактировать и удалять записи в базе через удобный UI прямо в приложении.
Автоматически добавляет иконку-ярлык для быстрого запуска (Android и iOS).
На Desktop ярлыки не поддерживаются. Для запуска интерфейса используйте обычную кнопку или меню в вашем UI.
Легко отключается в продакшен-сборках — можно либо не вызывать init, либо подключать stub-модуль вместо основной библиотеки.
Как использовать?
Зависимости (shared/build.gradle.kts)
val isRelease = /* Ваша логика определения релизной сборки */
dependencies {
if (isRelease) {
// В релизе – stub, чтобы не вшивать весь отладочный UI.
api("ru.bartwell.delightsqlviewer:stub:2.0.0")
} else {
// В debug – полная функциональность.
api("ru.bartwell.delightsqlviewer:runtime:2.0.0")
api("ru.bartwell.delightsqlviewer:core:2.0.0")
// Выберите, что используете:
api("ru.bartwell.delightsqlviewer:sqldelight-adapter:2.0.0")
// или
// api("ru.bartwell.delightsqlviewer:room-adapter:2.0.0")
}
}Инициализация
SQLDelight (Android):
DelightSqlViewer.init( object : SqlDelightEnvironmentProvider() { override fun getDriver() = sqlDelightDriver override fun getContext() = context } )Room (Android):
DelightSqlViewer.init( object : RoomEnvironmentProvider() { override fun getDriver() = roomDatabase override fun getContext() = context } )iOS (пример для SQLDelight):
let provider = SqlDelightEnvironmentProvider(driver: sqlDriver) DelightSqlViewer.shared.doInit(provider: provider, isShortcutEnabled: true)Аналогично и для RoomEnvironmentProvider.
Также, чтобы ярлык корректно работал на iOS, в вашем AppDelegate нужно переопределить методы обработки ярлыков, например:
class AppDelegate: NSObject, UIApplicationDelegate { func application( _ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions ) -> UISceneConfiguration { return ShortcutActionHandler.shared.getConfiguration(session: connectingSceneSession) } }Или вызовите DelightSqlViewer.shared.launch() в обработчике вашего Shortcut.
Desktop:
DelightSqlViewer.init( object : SqlDelightEnvironmentProvider() { override fun getDriver() = sqlDelightDriver } )
Аналогично и для RoomEnvironmentProvider.
Запуск
После инициализации вызов DelightSqlViewer.launch() откроет интерфейс просмотра и редактирования (на Android/iOS можно также запустить через ярлык при долгом тапе на иконку приложения).
Button(onClick = { DelightSqlViewer.launch() }) {
Text("Open DB Viewer")
}Итог
Теперь Delight SQL Viewer покрывает оба основных способа хранения данных в мультиплатформенных проектах — SQLDelight и Room Multiplatform. Если нужно быстро проверить содержимое вашей БД или вручную поправить что-то прямо во время тестирования, эта библиотека может сэкономить кучу времени. Ну и, конечно, легко «прячется» в релизе, чтобы никакого отладочного UI не оставалось.
Ссылка на репозиторий: https://github.com/bartwell/delight-sql-viewer
Буду рад фидбэку и вопросам!
Как устроена мобильная архитектура Авито?
Гость нового выпуска подкаста «Android Broadcast» — Александр Бильчук, руководитель юнита мобильной архитектуры Авито. В беседе с Кириллом Розовым Саша делится особенностями работы отдела мобильной архитектуры:
как ставятся задачи и требования к их выполнению?
как оценить пользу архитектурных решений?
как влияют Jetpack Compose, SwiftUI, AI на архитектуру?
как вообще прийти к роли мобильного архитектора?
Ответы на эти и другие вопросы вы найдете в видео.
Подписывайтесь на канал AvitoTech в Telegram, там мы рассказываем больше о профессиональном опыте наших инженеров, проектах и работе в Авито, а также анонсируем митапы и статьи.
Сегодня мое приложение "Печать чека НПД" стало "кирпичом". Что случилось ? Налоговая сделала метод апи требующим авторизацию.
https://lknpd.nalog.ru/api/v1/receipt/nomer_inn/id_cheka/json
Вы спросите, так как какая проблема добавить к запросу авторизацию ?
1) Документации на апи нет
2) Проблемы пройти модерацию Google Play после такой доделки
а) Что отвечать на вопрос об афилированности с госорганами. В обоих вариантах чувствую тот еще гиморой
б) Секция персональных данных. Угу. Попробуй ИИ объяснить зачем тебе логин/пароль от чужого сайта
