У меня был такой же кейс, я его решил намного проще через StorageAccessFramework доступный вроде бы с 4.4 версии. Он даже разрешения на запись не требует и работает как обычный файлпикер в десктопах. Пользователь сам сможет выбрать папку и название файла.
288 картинок с почти нечитаемым текстом на 200 МБ трафика.
Даже просто выложить видео без текста было бы лучшим решением, потому что смотреть ваши скриншоты ровно тоже самое что и смотреть видео.
Для теста запустили приложение использующее exoPlayer для отображения потокового видео – все взлетело без проблем, работает. Так что «сишные» библиотеки не страшны
Но ExoPlayer по-умолчанию не имеет никаких нативных либ, только в экстеншонах, да и те доступны под х86 тоже, так что нужно еще и abi фильтр настроить правильно для эксперимента.
После всех этих действий, у меня перестал запускаться эмулятор и пока с этим не разобрался
Потому что для виртуализации используется Hyper-V, а эмуляторы из студии один из трех вариантов. Покапайте в эту сторону, возможно достаточно будет их пересоздать чтобы SDK вдуплил что теперь нужно использовать Hyper-V. (я не знаю деталей, не использую винду)
А есть примеры? А то пока нахожу только ограничения самой платформы (Android 9+), но не самого GP.
К тому же вендорские приложения, которые обновляются через GP, 100% их используют.
А почему iOS не на ReactNative? Мотивация взять ReactNative более менее понятна, но когда вы уже выбрали его набирать отдельную команду iOS разработки, чтобы делали все тоже самое что уже сделано на кроссплатформе выглядит не очень.
Думаю и правда проще. Но я пошел именно этим путём, чтобы показать удобную фишку с companion object : BiometricsUtils , благодаря которой можно опустить два последних шага и не добавлять BiometricsUtilsImpl вообще, оставив значение по-умолчанию в конструкторе.
Гугл будет дальше еще сильнее пушить Котлин через свои библиотеки. Компоуз работает только с Котлином, а новые АндроидХ либы уже имеют курутины как часть стандартного апи, а не в виде дополнительных Колин экстеншонов.
В релиз ноутах написано про compilation avoidance самих скриптов, а не про сброс кеша. Только что проверил на своем маленьком проекте. Менял minifyEnabled с false на true и собирал :app:assembleDebug. Если Котлин скрипты лежат в buildSrc, то при изменении все зависимости :app:assembleDebug выполняются заново. При использовании includeBuild все зависимости все UP-TO-DATE независимо от значения minifyEnabled как и должно быть.
У included build есть очень важное отличие от buildSrc – он не ломает Gradle cache. При любом изменении buildSrc cache слетает полностью, в то время как при использовании included build cache работает как положено.
Я несколько раз наталкивался на обсуждения, мол нужно ли использовать прям везде их или быть аккуратнее, поэтому решил замерить. Много ли выходит экономии или нет пусть каждый решает сам. Заключительная часть в таком случае больше подходит любителям экономить каждый байтик.
Даже если и обновят, то можно будет использовать только на последней версии Андроида. Можно самому собрать и поставлять вместе с приложением как например здесь.
С локалью все хорошо будет. Строковое значение резолвится на уровне UI через вызов asString, при смене конфигурации UI пересоздастся и вызовет опять asString.
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
Почему именно такие правила? Вам лень пройтись по всей библиотеке и выписать всю рефлексию? А еще R8 уже поддерживает упаковку правил прямо в jar, а не только в aar.
Вам нравится NavigationComponent (даже с учетом всех этих костылей)? Намного удобнее роутинга через какую-нибудь абстракцию с ручной работой с FragmentManager?
Еще рекомендую попробовать использовать Kotlin в Gradle скриптах. Вся Groovy магия резко пропадает оставляя Вас один на один с чистым Gradle API и небольшим количеством скодогенерированных расширений. Сначала будет очень больно, но со временем Вы разберетесь.
Почитать можно официальную документацию. Там будет очень много Java-специфичного и ничего Android-специфичного, но там вполне хорошо изложена база.
А если кратко по вашим вопросам:
Gradle работает с проектами (мы их обычно называем модулями), проект по сути ничего не умеет сам, он только предоставляет контекст. Плагины могут добавлять к проекту расширения (те самые блоки android { minSdk = 20 }) и задачи (например задачу сборки APK). Задачу еще можно объявить прямо внутри build.gradle без каких либо плагинов и сразу же добавить ее к текущему проекту. Переменную можно создать в области видимости конкретного скрипта (просто def myVar = 0 с нулевым отступом), блока в скрипте, или в проекте (текущем или корневом) через механизм Extra Properties (такие переменные можно будет вытащить из других скриптов). Почему конфигурация и добавление плагина разделены на два разных этапа я ответить не могу. Возможно было бы все и правда легче, если бы мы могли конфигурацию прокинуть как будто в конструктор плагина. Но тогда мы бы потеряли динамичность в настройке.
Когда я делал декораторы, у которых логика зависела от соседних ячеек, то все ломалось при использовании DiffUtils. Например, возьмем Ваш кейс с ячейками a. Теперь через DiffUtils удалим последнюю ячейку в блоке. Поскольку изменилась только одна ячейка (последняя), то для двух предыдущих перерисовка вызвана не будет, от чего вторая ячейка (которая стала последней в блоке) останется без скругленных краев. Нужно в таком случае на любые изменения в списке вызывать invalidateItemDecorations(). Есть ли какой то другой способ?
У меня был такой же кейс, я его решил намного проще через StorageAccessFramework доступный вроде бы с 4.4 версии. Он даже разрешения на запись не требует и работает как обычный файлпикер в десктопах. Пользователь сам сможет выбрать папку и название файла.
https://developer.android.com/training/data-storage/shared/documents-files#create-file
288 картинок с почти нечитаемым текстом на 200 МБ трафика.
Даже просто выложить видео без текста было бы лучшим решением, потому что смотреть ваши скриншоты ровно тоже самое что и смотреть видео.
Но ExoPlayer по-умолчанию не имеет никаких нативных либ, только в экстеншонах, да и те доступны под х86 тоже, так что нужно еще и abi фильтр настроить правильно для эксперимента.
Потому что для виртуализации используется Hyper-V, а эмуляторы из студии один из трех вариантов. Покапайте в эту сторону, возможно достаточно будет их пересоздать чтобы SDK вдуплил что теперь нужно использовать Hyper-V. (я не знаю деталей, не использую винду)
А есть примеры? А то пока нахожу только ограничения самой платформы (Android 9+), но не самого GP.
К тому же вендорские приложения, которые обновляются через GP, 100% их используют.
В стиме кучу игр (особенно старых) под 64-бита не пересобрали, так что их даже запустить на последних мак осях нельзя, а тут еще и м1.
А почему iOS не на ReactNative? Мотивация взять ReactNative более менее понятна, но когда вы уже выбрали его набирать отдельную команду iOS разработки, чтобы делали все тоже самое что уже сделано на кроссплатформе выглядит не очень.
Думаю и правда проще. Но я пошел именно этим путём, чтобы показать удобную фишку с
companion object : BiometricsUtils
, благодаря которой можно опустить два последних шага и не добавлятьBiometricsUtilsImpl
вообще, оставив значение по-умолчанию в конструкторе.Суд был про реализацию Java API, а не саму Java. Если бы проиграли, то Котлин бы не спас, т.к. он сам использует Java API.
Гугл будет дальше еще сильнее пушить Котлин через свои библиотеки. Компоуз работает только с Котлином, а новые АндроидХ либы уже имеют курутины как часть стандартного апи, а не в виде дополнительных Колин экстеншонов.
Зачем дата мапперам разделение на интерфейс и имплементацию? Вы их мокаете в тестах?
В релиз ноутах написано про compilation avoidance самих скриптов, а не про сброс кеша. Только что проверил на своем маленьком проекте. Менял
minifyEnabled
сfalse
наtrue
и собирал:app:assembleDebug
. Если Котлин скрипты лежат вbuildSrc
, то при изменении все зависимости:app:assembleDebug
выполняются заново. При использованииincludeBuild
все зависимости всеUP-TO-DATE
независимо от значенияminifyEnabled
как и должно быть.У included build есть очень важное отличие от buildSrc – он не ломает Gradle cache. При любом изменении buildSrc cache слетает полностью, в то время как при использовании included build cache работает как положено.
Тоже вполне себе валидный подход.
Я несколько раз наталкивался на обсуждения, мол нужно ли использовать прям везде их или быть аккуратнее, поэтому решил замерить. Много ли выходит экономии или нет пусть каждый решает сам. Заключительная часть в таком случае больше подходит любителям экономить каждый байтик.
Даже если и обновят, то можно будет использовать только на последней версии Андроида. Можно самому собрать и поставлять вместе с приложением как например здесь.
С локалью все хорошо будет. Строковое значение резолвится на уровне UI через вызов
asString
, при смене конфигурации UI пересоздастся и вызовет опятьasString
.Почему именно такие правила? Вам лень пройтись по всей библиотеке и выписать всю рефлексию? А еще R8 уже поддерживает упаковку правил прямо в jar, а не только в aar.
Вам нравится NavigationComponent (даже с учетом всех этих костылей)? Намного удобнее роутинга через какую-нибудь абстракцию с ручной работой с FragmentManager?
Еще рекомендую попробовать использовать Kotlin в Gradle скриптах. Вся Groovy магия резко пропадает оставляя Вас один на один с чистым Gradle API и небольшим количеством скодогенерированных расширений. Сначала будет очень больно, но со временем Вы разберетесь.
Очень рекомендую доклад с прошлогоднего Мобиуса Степан Гончаров — Gradle от A до Я.
Почитать можно официальную документацию. Там будет очень много Java-специфичного и ничего Android-специфичного, но там вполне хорошо изложена база.
А если кратко по вашим вопросам:
Gradle работает с проектами (мы их обычно называем модулями), проект по сути ничего не умеет сам, он только предоставляет контекст. Плагины могут добавлять к проекту расширения (те самые блоки
android { minSdk = 20 }
) и задачи (например задачу сборки APK). Задачу еще можно объявить прямо внутриbuild.gradle
без каких либо плагинов и сразу же добавить ее к текущему проекту. Переменную можно создать в области видимости конкретного скрипта (простоdef myVar = 0
с нулевым отступом), блока в скрипте, или в проекте (текущем или корневом) через механизм Extra Properties (такие переменные можно будет вытащить из других скриптов). Почему конфигурация и добавление плагина разделены на два разных этапа я ответить не могу. Возможно было бы все и правда легче, если бы мы могли конфигурацию прокинуть как будто в конструктор плагина. Но тогда мы бы потеряли динамичность в настройке.Когда я делал декораторы, у которых логика зависела от соседних ячеек, то все ломалось при использовании DiffUtils. Например, возьмем Ваш кейс с ячейками a. Теперь через DiffUtils удалим последнюю ячейку в блоке. Поскольку изменилась только одна ячейка (последняя), то для двух предыдущих перерисовка вызвана не будет, от чего вторая ячейка (которая стала последней в блоке) останется без скругленных краев. Нужно в таком случае на любые изменения в списке вызывать
invalidateItemDecorations()
. Есть ли какой то другой способ?