Играем в APK-гольф. Уменьшение размера файлов Android APK на 99,9%

https://fractalwrench.co.uk/posts/playing-apk-golf-how-low-can-an-android-app-go/
  • Перевод
В гольфе выигрывает тот, у кого меньше очков.

Применим этот принцип в Android. Мы собираемся поиграть в APK-гольф и создать приложение минимально возможного размера, которое можно установить на Android 8.0 Oreo.

Базовый уровень


Начнём с дефолтного приложения, который генерирует Android Studio. Создадим хранилище ключей, подпишем приложение и измерим размер файла в байтах командой stat -f%z $filename.

Затем установим APK на смартфон Nexus 5x под Oreo, чтобы убедиться, что всё работает.



Прекрасно. Наш APK весит примерно полтора мегабайта.

APK Analyser


Полтора мегабайта кажутся слишком большим размером с учётом того, что делает наше приложение (а оно ничего не делает), так что давайте изучим проект и поищем, где по-быстрому сэкономить на объёме. Вот что сгенерировал Android Studio:

  • MainActivity, который расширяет AppCompatActivity.
  • Файл макета с ConstraintLayout для главного окна.
  • Файлы ресурсов с тремя цветами, одним строковым ресурсом и темой.
  • Библиотеки поддержки AppCompat и ConstraintLayout.
  • Один AndroidManifest.xml.
  • Файлы PNG для квадратной, круглой и фоновой иконок.

Пожалуй, проще всего разобраться с иконками, учитывая, что там в общей сложности 15 изображений и два XML-файла под mipmap-anydpi-v26. Давайте посчитаем всё это в APK Analyser из Android Studio.



Вопреки нашим первоначальным предположениям, похоже, что самый большой файл — Dex, а на ресурсы приходится всего 20% от размера APK.

Файл Размер
classes.dex 74%
res 20%
resources.arsc 4%
META-INF 2%
AndroidManifest.xml <1%

Исследуем по отдельности, что делает каждый файл.

Файл Dex


classes.dex — главный виновник раздутого APK, он занимает 73% всего объёма и поэтому станет первой целью оптимизации. Этот файл содержит весь наш скомпилированный код в формате Dex, а также список внешних методов во фреймворке Android и библиотеку поддержки.

В пакете android.support перечисляется более 13 000 методов, что кажется излишним для приложения типа "Hello World".

Ресурсы


В директории res находится большое количество файлов шаблонов, чертежей (drawables) и анимаций, которые сразу не видны в интерфейсе Android Studio. Опять же, они вытянуты из библиотеки поддержки и занимают около 20% размера APK.



Файл resources.arsc также содержит список всех этих ресурсов.

Подпись


В папке META-INF находятся файлы CERT.SF, MANIFEST.MF и CERT.RSA, которые нужны для подписи v1 APK. Если злоумышленник изменит код внутри APK, то подписи не совпадут, что защищает пользователя от запуска постороннего зловреда.

В MANIFEST.MF перечисляются файлы из APK, а CERT.SF содержит контрольные суммы манифеста и каждого отдельного файла. В CERT.RSA хранится открытый ключ, которым проверяется цельность CERT.SF.



Здесь нет очевидных целей для оптимизации.

AndroidManifest


AndroidManifest очень похож на наш оригинальный файл. Единственное отличие — вместо ресурсов вроде строк и drawables здесь указаны их целочисленные идентификаторы, начиная с 0x7F.

Включаем минификацию


Мы ещё не пробовали включить опцию минификации и сжатия ресурсов в файле build.gradle для нашего приложения. Сделаем это.

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile(
              'proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

-keep class com.fractalwrench.** { *; }

Если установить minifyEnabled в значение true, то активируется Proguard, который очищает приложение от ненужного кода. А также обфусцирует имена символов, затрудняя обратную разработку приложения.

shrinkResources удалит из APK любые ресурсы, на которые нет прямой ссылки. Могут возникнуть проблемы, если вы получаете доступ к ресурсам не напрямую, но к нашему приложению это не относится.

786 КБ (уменьшение на 50%)


Мы наполовину уменьшили размер APK без видимого изменения в работе программы.



Если вы ещё не включили minifyEnabled и shrinkResources в своём приложении, это самая главная вещь, которую следует вынести из этой статьи. Можно легко сэкономить несколько мегабайт, потратив всего парочку часов на конфигурацию и тестирование.

Прощай, AppCompat, мы едва тебя узнали


classes.dex теперь занимает 57% всего APK. Основная часть списка методов из файла Dex принадлежит пакету android.support, так что мы собираемся удалить библиотеку поддержки. Для этого нужно сделать следующее:

  • Полностью удалить блок зависимостей из build.gradle.

    dependencies {
        implementation 'com.android.support:appcompat-v7:26.1.0'
        implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    }
  • Обновить MainActivity для расширения класса android.app.Activity.

    public class MainActivity extends Activity
  • Обновить наш шаблон для использования единого TextView.

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Hello World!" />
  • Удалить styles.xml и аттрибут android:theme из элемента <application> в AndroidManifest.
  • Удалить colors.xml.
  • Сделать 50 отжиманий, пока Gradle синхронизируется.

108 КБ (уменьшение на 87%)


Матерь божья, файл уменьшился почти в десять раз: с 786 КБ до 108 КБ. Единственным заметным изменением стало только изменение цвета тулбара, который окрасился в дефолтную тему ОС.



На директорию res теперь приходится 95% размера APK из-за всех этих иконок лаунчера. Если бы эти иконки делал наш дизайнер, мы бы попытались конвертировать их в WebP, более эффективный формат, который поддерживается в API 15 и более поздних версиях.

К счастью, Google уже оптимизировала наши drawables, хотя в противном случае мы бы и сами могли оптимизировать их и удалить из PNG ненужные метаданные с помощью ImageOptim.

Давайте поступим нешаблонно — и заменим все наши иконки запуска единственной однопиксельной чёрной точкой в папке res/drawable. Эта картинка весит 67 байт.

6808 байт (уменьшение на 94%)


Мы избавились почти от всех ресурсов, так что неудивительно, что размер APK уменьшился примерно на 95%. В файле resources.arsc по-прежнему упоминаются следующие ресурсы:

  • 1 файл шаблона
  • 1 строковый ресурс
  • 1 иконка лаунчера

Пойдём сверху вниз.

Файл шаблона (6262 байта, сокращение на 9%)


Фреймворк Android раздувает наш файл XML и автоматически создаёт объект TextView, который используется как contentView для Activity.

Попробуем обойтись без этого посредника, удалив файл XML и программно задав contentView. Объём ресурсов уменьшится, потому что исчезнет файл XML, но увеличится размер файла Dex, поскольку мы упоминаем там дополнительные методы TextView.

TextView textView = new TextView(this);
textView.setText("Hello World!");
setContentView(textView);

Выглядит как неплохой обмен.

Имя приложения (6034 байта, сокращение на 4%)


Давайте удалим strings.xml и заменим android:label в манифесте AndroidManifest буквой "A". Это кажется маленьким изменением, но удаление записи из resources.arsc уменьшает количество символов в манифесте и удаляет файл из директории res. Каждая мелочь идёт на пользу — мы только что сэкономили 228 байт.

Иконка лаунчера (5300 байт, сокращение на 13%)


Документация для resources.arsc в репозитории Android Platform объясняет, что каждый ресурс APK упоминается в resources.arsc с целочисленным идентификатором. У этих ID два пространства имён:

0x01: системные ресурсы (предустановленные в framework-res.apk)

0x7f: ресурсы приложения (в файле .apk приложения)

Так что произойдёт с нашим APK, если мы поставил ссылку на ресурс в пространстве имён 0x01? По идее, мы получим более красивую иконку и одновременно уменьшим размер своего файла.

android:icon="@android:drawable/btn_star"



Само собой, вам никогда не следует доверять системным ресурсам вроде иконок в реальном рабочем приложении. Такой метод провалит валидацию в Google Play, а некоторые производители ещё и по-своему определяют белый цвет, так что действуйте осторожно.

Манифест (5252 байта, сокращение на 1%)


Мы ещё не трогали манифест.

android:allowBackup="true"
android:supportsRtl="true"

Удаление этих аттрибутов экономит 48 байт.

Хак Proguard (4984 байта, сокращение на 5%)


Похоже, что классы BuildConfig и R ещё остались в файле Dex.

-keep class com.fractalwrench.MainActivity { *; }

Уточнение правила Proguard удалит ненужные классы.

Обфускация (4936 байт, сокращение на 1%)


Обфусцируем имя для класса Activity. Для обычных классов Proguard автоматически делает это, но поскольку имя класса Activity вызывается через Intents, его не обфусцировали по умолчанию.

MainActivity -> c.java

com.fractalwrench.apkgolf -> c.c

META-INF (3307 байт, сокращение на 33%)


В данный момент мы подписываем приложение одновременно подписями v1 и v2. Это кажется лишней тратой ресурсов, потому что v2 обеспечивает превосходную защиту и производительность, хешируя весь APK целиком.

Подпись v2 не видна из APK Analyser, поскольку включена в бинарный блок в самом файле APK. Подпись v1 видна, в виде файлов CERT.RSA и CERT.SF.

Давайте уберём галочку для подписи v1 в интерфейсе Android Studio и сгенерируем подписанный APK. Попробуем сделать и наоборот.

Подпись Размер
v1 3511
v2 3307

Похоже, теперь мы будем использовать v2.

Куда мы идём — там не нужны IDE


Пришло время редактировать APK вручную. Используем следующие команды:

# 1. Создать неподписанный apk
./gradlew assembleRelease

# 2. Разархивировать архив
unzip app-release-unsigned.apk -d app

# Сделать необходимые правки

# 3. Заархивировать архив
zip -r app app.zip

# 4. Запустить zipalign
zipalign -v -p 4 app-release-unsigned.apk app-release-aligned.apk

# 5. Запустить apksigner с подписью v2
apksigner sign --v1-signing-enabled false --ks $HOME/fake.jks --out signed-release.apk app-release-unsigned.apk

# 6. Проверить подпись
apksigner verify signed-release.apk

Детальный обзор процесса подписи APK см. здесь. В общем, Gradle генерирует неподписанный архив, zipalign делает выравнивание по границе байта для несжатых ресурсов, чтобы оптимизировать потребление RAM после загрузки APK, и в конце запускается криптографическая процедура подписи APK.

Неподписанный и невыровненный APK весит 1902 байт, то есть процедура добавляет примерно 1 килобайт.

Несоответствие размеров файлов (2608 байт, сжатие на 21%)


Странно! Если разархивировать невыровненный APK и подписать его вручную, то пропадает файл META-INF/MANIFEST.MF, что экономит 543 байта. Если кто-то знает, почему так происходит, то дайте знать!

Теперь у нас в подписанном APK осталось три файла. Но ведь мы можем ещё избавиться от файла resources.arsc, потому что не устанавливаем никаких ресурсов!

После этого остаётся только манифест и файл classes.dex, оба примерно одинакового размера.

Хаки со сжатием (2599 байт, сокращение на 0,5%)


Теперь изменим все оставшиеся строки на ‘c’, обновив версии до 26, а затем сгенерируем подписанный APK.

compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "c.c"
        minSdkVersion 26
        targetSdkVersion 26
        versionCode 26
        versionName "26"
    }

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="c.c">

    <application
        android:icon="@android:drawable/btn_star"
        android:label="c"
        >
        <activity android:name="c.c.c">

Это уменьшает размер ещё на 9 байт.

Хотя количество символов в файле не изменилось, но дело в том, что увеличилась частотность символа ‘c’. В результате алгоритм сжатия сработал более эффективно.

Привет, ADB (2462 байт, сокращение на 5%)


Можно ещё сильнее оптимизировать манифест, удалив фильтр намерения Launch для класса Activity. С этого момента будем запускать приложение следующей командой:

adb shell am start -a android.intent.action.MAIN -n c.c/.c

Вот новый манифест:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="c.c">

    <application>
        <activity
            android:name="c"
            android:exported="true" />
    </application>
</manifest>

Мы также избавились от иконки лаунчера.

Очистка от ссылок на методы (2179 байт, сокращение на 12%)


По изначальным условиям, мы должны подготовить APK, который способен установиться на устройство.

Наше приложение перечисляет методы в классах TextView, Bundle и Activity. Можно уменьшить размер файла Dex, удалив эти ссылки и заменив их новым классом Application. Таким образом, файл Dex теперь будет ссылаться на единственный метод — конструктор класса Application.

Исходные файлы теперь выглядят следующим образом:

package c.c;
import android.app.Application;
public class c extends Application {}

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="c.c">
    <application android:name=".c" />
</manifest>

Используем adb для проверки, что APK успешно установился, это можно также проверить через «Настройки».



Оптимизация Dex (1961 байт, сокращение на 10%)


Я потратил несколько часов, изучая формат файла Dex ради этой оптимизации, поскольку разные механизмы вроде контрольных сумм и смещений затрудняют ручное редактирование.

Если вкратце, в итоге выяснилось, что единственным требованием для установки APK является факт существования файла classes.dex. Поэтому мы просто удалим оригинальный файл, запустим touch classes.dex в консоли и сэкономим 10% от размера, используя пустой файл.

Иногда глупейшее решение — самое лучшее.

Понимание манифеста (1961 байт, сокращение на 0%)


Манифест неподписанного APK — это файл в бинарном формате XML, который вроде бы официально не документирован. Можно изменить содержимое файла с помощью редактора HexFiend.

В заголовке файла угадываются некоторые интересные элементы — первые четыре байта кодируют 38, что совпадает с номером версии файла Dex. Следующие два байта кодируют 660, что совпадает с размером файла.

Попробуем удалить один байт, установив targetSdkVersion на 1, и изменив размер файла в заголовке на 659. К сожалению, система Android отвергает новый файл как неправильный APK. Похоже, тут всё устроено как-то посложнее…

Непонимание манифеста (1777 байт, сокращение на 9%)


А попробуем набросать случайных символов по всему файлу, а затем установить APK, не изменяя указанный размер файла. Так мы проверим, осуществляется ли проверка контрольной суммы, и как наши изменения повлияют на смещения в заголовке файла.

Удивительно, но такой манифест воспринят как валидный APK на Nexus 5X под Oreo:



Мне кажется, я только что услышал, как разработчик фреймворка Android, ответственный за поддержку BinaryXMLParser.java, очень громко закричал в подушку.

Для максимальной выгоды нужно заменить все эти глупые символы нулевыми байтами. Это поможет распознать важные части файла в HexFiend, а также сократит несколько байт благодаря хаку сжатия, упомянутому выше.

Манифест UTF-8


Вот важные компоненты Manifest, без которых APK не установится.



Некоторые вещи очевидны, такие как теги манифеста и пакета. В пуле строк видны versionCode и название пакета.

Шестнадцатиричный манифест




Просмотр файла в шестнадцатиричном виде показывает значения в заголовке файла, которые описывают пул строк и другие значения, вроде размера файла 0x9402. Строки тоже интересно закодированы — если они больше 8 байт, то общая длина указывается в двух предыдущих байтах.

Но вряд ли здесь можно найти другие варианты для оптимизации.

Готово? (1757 байт, сокращение 1%)


Изучим окончательный APK.



В течение всего этого имени в APK было указано моё имя в подписи v2. Создадим новое хранилище ключей, в котором используется хак для сжатия.



Мы сэкономили 20 байт.

Шаг 5: Признание


1757 байт — это очень мало, чёрт возьми. И насколько я знаю, это самый маленький существующий APK.

Однако я разумно полагаю, что кто-нибудь из Android-сообщества способен выполнить дальнейшие оптимизации и ещё улучшить результат. Если вы умудритесь уменьшить файл с нынешних 1757 байт, присылайте пулл-реквест в репозиторий, где хостится самый маленький APK, или сообщайте в твиттере. (С момента публикации статьи файл уже уменьшили до 820 байт — прим. пер.)
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 49
  • 0
    The current size of the APK is 820 bytes.
    • +6
      Там ещё PR до 678 висит. Ещё чуть-чуть, и можно остановится на 666.
    • +1
      Ах, здорово. Вот что называется настоящий гольф.
      А то, помню, на stackoverflow был какой-то странный гольф, где можно было использовать всевозможные «читерские» ухищрения, вроде использования специализированных языков для гольфа, и даже — своих собственных!

      Конечно, дело ещё не дошло до файла состоящего из двух символов, но всё же, сжатие кода под громоздкий C куда более интересный труд, чем использования других языков.
      • +3
        Использование DSA Keystore, уменьшение размера манифеста (1295 байт, сокращение на 26%)
        Манифест дополнительно оптимизирован с использованием скомпилированного XML-файла, и использования DSA Keystore меньше по размеру, чем его создаёт Android Studio.

        Сплошное сжатие zopfli (1180 байт, сокращение на 9%)
        Улучшение сжатия APK.

        Использование сигнатуры эллиптической кривой (922 байта, сокращение на 16%)
        Подписи эллиптической кривой еще меньше чем DSA, и поддерживаются в подписи APK v2.

        Удаление classes.dex (824 байта, уменьшение на 11%)
        Если в манифесте отсутствует элементы кода, для PackageParser не требуется файл classes.dex.

        Дальнейшая ручная настройка манифеста (820 байт, сокращение на 0,5%),
        Дальнейшая оптимизация байтового уровня манифеста.
        • 0
          Что происходит с отображением самого apk файла? Он запускается, или после всех ухищрений остаётся только сам факт валидности APK?
          • 0
            Второе. Он устанавливается и всё :)
            • 0
              Тогда позвольте-с спросить в чем суть всего действа? Можно и до 300 байт ужать, только мне казалось, что за любым действием должна стоять практическая ценность.
              • 0
                Можно и до 300 байт ужать

                Репозиторий ждёт вашего решения!
                только мне казалось, что за любым действием должна стоять практическая ценность.

                Огромное разнообразие деятельности человечества не несёт под собой никакой практической ценности, а если продолжить, то и сама жизнь не имеет под собой никакой ценности, Вселенной на нас плевать, всё тлен, пора ложиться и умирать.
                Ну а я так не думаю, и буду ужимать проги, играть в игры и вообще развлекаться.
                • 0
                  Нет-нет, Вы не поняли. Для меня действительно эта проблема крайне актуальна. Актуальна настолько, что я не останавливаюсь ни перед чем для уменьшения размера своих приложений, недавно полностью переписал (точнее написал. Это тот вариант, когда легче снести и построить заново, чем реставрировать) библиотеку для работы с Гуглодиском (ибо она банально шлет запросы на их API, поэтому кто мешает просто слать их дефолтной явовской HTTPRequest?). Нужно выложить на Гитхаб, да, просто все руки не доходят. На очереди ЯДиск и Дропбокс, ибо вынужден иметь эти библиотеки одновременно, ибо юзеры из разных стран. Дак вот весь замес сей мозговой работы заключается в том, что приложение на выходе полностью работает и имеет задуманный функционал при уменьшении его размера на 30 и более процентов. Тут хороший вопрос задали, работает ли все это, сам хотел спросить. Ибо если не работает, тогда зачем все это? Увы, но ни о каких 99% и даже 70% и речи быть не может, когда от приложения ожидается, что оно работает (кто бы мог подумать). А пустышки собирать, которые только компилятся… как-то не знаю… Не, понятно, интересно в плане задачек, но хотелось бы все-таки, чтобы приложения выполняли свою основную цель: работали)
                  • 0
                    Нет-нет, Вы не поняли.

                    Извиняюсь, бывает.
                    • 0
                      И правда бывает) Вообще частенько сталкиваюсь на Хабре с такой тенденцией, хорошо если при это ничьи чувства не задеваются (хотя бывает всякое). Пока еще не определил точно с чем это может быть связано, но скорее всего с большой загрузкой здешней аудиторией в плане специфики ее работы, и как следствие — сложностями фильтрации поступающей информации.
                • 0
                  Зарядка для ума :) Лет десять назад так же издевались над PE-файлами после статей Мыщъха.
                  • 0
                    Ага-ага, и не говори, работало бы еще это все — цены бы не было)
            • +15

              Скиньте статью разработчикам из фейсбука кто-нибудь

              • +2
                Простите, но это прекрасно!
                • +2
                  Теперь сделайте тоже самое с APK, собираемым QtCreator
                  • 0
                    Да вроде приемлемого размера получается.
                    • 0
                      Да там же кутишные библиотеки вшиваются, министро или как их там. Вообще, меня это нисколько не смущает.
                      • 0

                        министро- это отдельный apk, но да же без него у меня на простых приложениях получалось в районе 9 Mb.

                        • 0
                          Кто-то из нас двоих что-то путает. Насколько помню, при сборке можно выбрать встраивать библиотеки qt или нет. Вот с ними получается ~9мб, без них значительно меньше, но без них у меня и с установленным министро никогда ничего не запускалось, даже hello world.
                  • +3
                    круто. разбалованы железом мы.
                    • 0
                      Однако 1,5 Мб для Hello world это очень и очень!
                    • +1
                      Почитать интересно, но в реальной жизни большинство не пригодится…
                      Как минимум как уже обойтись без support library? Не говоря уже о сокращении манифест файла, смене иконки, и тем более о keystore.
                      • +1
                        Некоторые могут быть не в курсе про proguard, как он работает и настраивается. Кто-то не следит за тем, какие именно файлы попадают в apk. Да даже support library можно подключить не целиком, а только -core-ui, если не требуются все возможности библиотеки одновременно. Причём, несмотря на использование proguard для удаления неиспользуемого кода, подключение лишь части библиотеки вместо полной версии даёт ощутимую разницу в размере релизного приложения.
                      • 0
                        Был у меня проект (с конфигами по-умолчанию) на Eclipse без Gradle, который по умолчанию собирал apk до размера 200Кб. Перенос в Android Studio увеличил файл до 1Мб.
                        • 0
                          Смена системы сборки ничего не добавляет сама по себе. Возможно, автоматически подключились библиотеки совместимости (support library), от которых в статье избавлялись на втором шаге.
                        • +1
                          Покупал как-то чайник Redmond, который с управлением через Bluetooth, поставил программу на смартфон для удалённого управления чайником. 47 Мб…
                          • 0

                            Эту штуку делают Ready for Sky, раньше пилили приложение на C++/Qt, но похоже перешли на Java

                            • +1
                              Интересно, что такой высокотехнологичный чайник я сдал через два месяца использования по гарантии, так как у него просто-напросто лопнуло крепление крышки. Я подозреваю, что из-за несоответствия прочности пластика и силы удерживающей его пружины.
                              • 0
                                Интересно, хоть один заявит, что нет корреляции между качеством чайника и качеством приложения, уровнем инженерной проработки решения девайса и инженерной проработки софта? )
                                • +3
                                  Я бы лучше спросил, нафига там с самого начала блютуз (понятно, что с ним все становится круче), если он все равно до кухни не добивает? %)
                                  • +2

                                    Чтобы можно было гордо отвечать статусом 418 I'm a teapot в ближайшем IOT-окружении.

                                    • 0
                                      Ухаха, точно! С другой стороны, и в чайнике уже без веба не обошлось… %)
                                    • 0
                                      В этих чайниках нет самого очевидного — нельзя удаленно узнать, сколько в нем воды. Можно вкл/выкл и цвет подсветки менять. А зачем его включать, если в нем кончилась вода?..
                                      • +1
                                        Неужели ни в одном нет?! Тогда это вообще жесть какая-то. Буквально. %)
                                      • +1
                                        Недавно тоже купил такой. Не особо полезно, но юзкейсы всё же есть — подогреть чайник, чтобы налить вторую кружку чая, например. В этом случае вода в нём остаётся, но после первой кружки могло пройти достаточно времени. Так вот, теперь включаю его, не вставая из-за компьютера.
                                        но
                                        (на самом деле всё это не важно и не нужно, я просто поиграться его купил, потому что это клево, и оправдываюсь теперь)
                                        • 0

                                          Там есть цифровая регуляция температуры чайника — вот это реально нужная мегафича ) Запарить дрожжи — греем чайник до 40, горячая не обжигающая вода — 60… вообщем до 100 градусов чайник греем редко. И через синийзуб можно выставлять температуру с точностью до градуса ))

                                • +2
                                  Представил себе чайник-криптоферму… :)
                                • 0
                                  создать приложение минимально возможного размера, которое можно установить на Android 8.0 Oreo

                                  Почему нельзя было бы установить на android 8?

                                  • 0
                                    Статья как нельзя кстати рассказывает почему не смотря на рост производительности устройств и выходов новых версий ОС устройства в среднем все равно работают медленно)
                                    Существует такая игрушка .kkrieger 96кб с графикой уровня Q3 но никому не нужна такая оптимизация, нужно чтобы заводы штамповали девайсы а кодеры писали тонны кода под который были бы нужны все более емкие хранители, а потом это все потребляет больше энегрии и так далее… :)
                                    • 0
                                      Ну, ради честности — что пример из статьи (после определенного момента, когда пример уже не мог запускаться), что та игрушка, это не совсем оптимизация, это уже, скорее, выжимание всех соков, экстрим. :)
                                      • 0
                                        Оптимизация требует времени программиста (а также тестировщика и менеджера), а следовательно большего бюджета. Все хотят оптимизированные программы, но мало кто захочет переплачивать вдвое/втрое за оптимизацию.
                                        • +1
                                          При этом ВСЕ переплачивают за НЕоптимизацию. :) Новым железом, электричеством, временем…
                                      • 0
                                        Все равно основная оптимизация приложений под Андроид — разрешение на установку на сменный носитель. Таким приложениям памяти хватает.
                                        • 0
                                          Не во всех устройствах есть этот сменный накопитель. И начиная с какой-то версии Android API значение этого параметра сменилось с дефолтного (перенос разрешён пользователем) на отключённое, нужно явно разрешать в манифесте. Из-за этого многие программы потеряли возможность переноса, даже если раньше её имели.
                                          • 0
                                            Не во всех, но почему не прописать один параметр, облегчая пользователям жизнь?
                                            Есть какое-то логическое обоснование отключения переноса во умолчанию?
                                            • 0
                                              Есть какое-то логическое обоснование отключения переноса во умолчанию?

                                              Как всегда: загнать всех пользователей на устройства без флешек.
                                              • 0
                                                Затягивание гаек. Возможно, ради безопасности и уменьшения количества ошибок непредвиденного поведения. Чтобы каждый разработчик сначала сам проверил перенос приложения, и только потом включал эту опцию для всех.
                                                • 0
                                                  Можно было перенести в настройки возможность перенести вручную, для тех кто туда забрался и понимает что делает

                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.