![image](https://habrastorage.org/getpro/habr/post_images/8bb/9c6/18d/8bb9c618d894a14b42da38c4a0e643b5.jpg)
Вчера в блоге Android была опубликована запись, в которой разработчики рассказывают о своей работе над уменьшением размера обновлений. Как отмечается в тексте, ежедневно миллионы пользователей обновляют свою систему и приложения, и многие из них внимательно следят за тем, сколько мобильного трафика на это уходит.
Для того, чтобы уменьшить размер обновлений, разработчики Android еще в июне 2016 года стали применять алгоритм bsdiff за авторством Колина Персиваля для патча бинарных файлов. Тогда это помогло снизить размер приложений и обновлений к ним, в среднем, на 47% относительно полного APK.
Теперь же команда Android хочет поделиться новым решением, которое позволяет снизить объем обновлений на, в среднем, 65% от первоначального размера. Речь идет о File-by-file patching.
Подход достаточно прост. Вместо того, чтобы скачивать полный APK и переустанавливать все файлы приложения, система обновления производит сверку пользовательских файлов и скачанных. Это позволяет загружать только те файлы, которые претерпели какие-либо изменения в ходе разработки.
По словам разработчиков Android этот простой, но эффективный подход позволяет сократить трафик обновлений на 6 петабайт ежедневно.
Но есть и некоторые подводные камни. Сжатие APK-файлов происходит почти так же, как и ZIP, с использованием Deflate. Это позволяет значительно уменьшить размер, но в тоже время затрудняет определение того, в какие именно файлы были внесены изменения:
![image](https://habrastorage.org/getpro/habr/post_images/829/ddc/fbe/829ddcfbe2ce6133a3f5fc9642042f58.gif)
Демонстрация работы Deflate
Как видно по изображению выше, внесение даже одного символа полностью изменяет структуру пережатого файла. Следовательно, file-by-file patching основывается на сравнении несжатых файлов между собой. В процессе обновления происходит сверка распакованных файлов, как старых, так и новых. На этом этапе все еще используется bsdiff. Затем, при применении патча выявляются файлы, требующие замены и скачиваются именно они. После этого APK опять пересобирается уже на стороне устройства. В качестве доказательств разработчики приводят сводную таблицу по ряду наиболее популярных приложений для Android:
![image](https://habrastorage.org/getpro/habr/post_images/968/3a6/9e1/9683a69e158f3ec4db26a56e4564e997.png)
Эти приложения уже используют систему обновления file-by-file.
У данного подхода есть несколько минусов. Первое — конечный APK должен полностью совпадать с исходным, байт в байт. На этот параметр влияет сборка Deflate (чаще всего используется собранная на основе Zlib) и ее настройки.
Как оказалось в ходе анализа, все разработчики используют только два параметра сжатия при помощи Deflate: либо по умолчанию (6), либо максимальный (9). Каких-либо других параметров разработчики Android не обнаружили.
Другой минус подхода — требования к вычислительным мощностям на конечном устройстве, конкретно, к процессору. Процессы распаковки, сверки и обратной сборки в APK требуют значительных мощностей от устройства пользователя, и не все существующие девайсы смогут справиться с этой процедурой в равной степени успешно. Это приводит к более длительному применению патча на старых и маломощных устройствах. Кроме того, время обработки увеличивается пропорционально, исходя из размеров обновления.
Комментарии (38)
Zapped
07.12.2016 17:21+1После этого APK опять пересобирается уже на стороне устройства.
и кто, интересно, его (APK) подписывает? ))foxin
07.12.2016 17:27а в чем проблема, что будет собранный на самом девайсе APK подписан самим же девайсом?
Zapped
07.12.2016 17:30в целом, наверное, это не проблема
непонятно только будет от кого апдейт прилетел (если эта информация вообще кому-нибудь нужна)foxin
07.12.2016 17:36Апдейт будет прилетать от гугла и, как я понимаю, будет на лету подписываться гуглом же. Пришел апк — проверили что подписан гуглом — все ок.
Zapped
07.12.2016 17:42+2неее
я понял почему
конечный APK должен полностью совпадать с исходным, байт в байт
в оригинале есть примечание:
(see APK Signature Schema v2 for why).
Схема подписи APK v2 — введена в Android 7.0. Встраивается в саму APK (ZIP-архив), в отличие от APK для Android 6.0 и ниже, где используется JAR-подпись (подробности по вышеприведённой ссылке)SadOcean
08.12.2016 10:53+1Магазин будет присылать дельту и подпись (для полного файла).
Дельта обновит распакованные ресурсы, их соберут в архив и проверят подпись.
Точно так же в обычном случае присылают архив и подпись, проверяют подпись и ставят архив.
Заморочки с сертификацией и доверием к открытому ключу разработчика в этом случае этой схемы не касаются, но там и так все решено.
Namolem
09.12.2016 17:26а нельзя просто прикрепить новую подпись (ведь файлы то идентичны)?
Zapped
09.12.2016 18:06да новую-то можно
только тут вопрос, который я озвучил: «кто подписал?», и соответственно, степени доверия к подписавшему )
тут ведь вопрос в чём:
подпись — это зашифрованный закрытым ключом подписавшего (в оригинале — разработчика) хэш содержимого
если содержимое — изменилось хоть на байт — всё, подпись невалидна
если подписал кто-то другой, то это «кто-то другой». нельзя удостоверить, что содержимое финального APK то же, что подписывал оригинальный разработчик
c JAR-подписью такое могло бы сработать, т.к. там подписывается СОДЕРЖИМОЕ APK (который есть ZIP-архив)
тут же речь о подписывании самого бинарного APK (APK Signature Schema v2). вот поэтому
конечный APK должен полностью совпадать с исходным, байт в байт
Zapped
09.12.2016 18:20а не, не выйдет
в Android нельзя поставить обновления, подписанные другим ключом, нежели обновляемое приложение. Можно только снести предыдущую версию и ставить «обновление» с нуля.
Lucky_spirit
07.12.2016 19:34Лично мне кажется, что появится новый вирус на Android, который заразит утилиту, занимающуюся сборкой APK файла на устройстве. Этот вирус будет просто потом инжектить вредоносный код в каждый собранный APK.
zagayevskiy
07.12.2016 20:05Если всё так просто, то ничего не изменилось. Просто ваш мифический вирус уже сейчас заражает утилиту, занимающуюся установкой апк на устройстве.
qw1
08.12.2016 15:49Какой смысл заражать APK, собранные под конкретное устройство, если они с этого устройства никуда не уходят?
Если хочется закрепиться в системе и, раз уж доступ на запись получен (обычно /system монтируется как read only при инициализации ядра), проще дописаться куда-нибудь к системным бинарникам.
Например, во framework.jar, чтобы инжектиться автоматически в каждое приложение.
rPman
08.12.2016 00:18+1Такое ощущение что все комментаторы выше не хабравчане, а какие то левые
Люди, ау! если каждое приложение будет таскать с собой полную копию используемого фреймворка, вместо того чтобы добавить его в зависимость, как это сделано в нормальных linux-системах, то тогда каждый фонарик будет весить 5-35мб вместо 10кб.
Ради интереса, посмотрите, сколько приложений таскают с собой код webkit для просмотра html.
впору уже аппаратную дедупликацию запускать, а во время установки, принудительно распаковывать все сжатые файлы, которые могут в принципе хранить дублируемый код, так как сделать все правильно никому уже не придет в голову…
p.s. оперативная память например засирается именно этим.develop7
08.12.2016 00:40-1Ради интереса, посмотрите, сколько приложений таскают с собой код webkit для просмотра html.
Ух ты, как интересно. И сколько же?
Areso
08.12.2016 08:43К примеру, каждое приложение, написанное мной. На моем устройстве их больше одного)
Они, правда, еще и ворох JS библиотек тащат, но по сравнению с webkit'ом — капля в море. 200 килобайт против 20 мегабайт.develop7
08.12.2016 09:34И на Lollipop+ тоже?
Areso
08.12.2016 17:10У меня два устройства (4.4 и 4.2), не было возможности проверить 5 и новее. К тому же, я всегда старался включать как можно более старое API в проекте.
develop7
08.12.2016 17:37Ясно. Crosswalk пользуетесь?
Я не просто так спросил про Lollipop, на 5+ поставляется обновляемый так же часто, как Google Chrome, Android System WebView, к-рый делает вот буквально то, что вы сказали. Как Crosswalk в shared mode, только всё официально и искаропки.
qw1
08.12.2016 16:03Что я вижу в apk, так это всякие SDK, как гугловские
com.google.ads
,
com.google.android.gms
com.google.market
которые нужны для in-app purchase,
так и sdk от десятка социальных кнопок и рекламных сетей
com.facebook.*
com.flurry.*
com.twitter.*
com.yandex.metrica
com.yandex.mobile.ads
Ещё частый гость — библиотеки поддержки определённых визуальных стилей (разного рода action-bar-ы и контролы), которые с определённых версий есть в Android. Но нам же надо запуститься на как можно большем количестве платформ, и чтобы вёрстка не поплыла, поэтому системными не пользуемся.
HTC-шные приложения содержат контролы типа com.htc.lib1.cc.view.viewpager, которые есть во framework, но для удобства, чтобы под каждое устройство не собирать свой пакет почтового клиента или календаря/будильника, их включают в обновления, скачиваемые из маркета. Поэтому будильник весит 5.5MB.zagayevskiy
10.12.2016 13:47Android Support Library забыли упомянуть. Там с некоторых пор стали появляться вещи, которых во системе вообще нет (например, RecyclerView), а так же вещи, которые из системы использовать неудобно (например, фрагменты).
DrGluck
09.12.2016 10:01-1Это всё конечно благородно, но можно, вместо этого, будут выходить обновления на не самых старых телефонах, а? Например Galaxy Note 3/4, спасибо, пожалуйста.
mekegi
09.12.2016 10:34+1Товарищи из статьи отвечают за ядро андроида. Ваша претензия ни о чем, ибо обновления на ваш конкретный телефон зависят только от производителя этого вашего телефона.
DrGluck
09.12.2016 11:51Я понимаю, что это вопрос не к ним, это просто крик души. Каждый раз вижу в ленте новость об обновлении Андроида и каждый раз понимаю «мммкей, это не для тебя, жалкий неудачник».
qw1
09.12.2016 20:08Проще сказать себе «У меня нет на это времени».
А так, при желании, можно себе любую версию залепить на любой девайс. А если не будет хватать памяти или ещё чего (например, нет поддержки определённых команд видеоускорения) — повод помозгоштурмить и сделать компромисное решение )))
На HTC HD2, который выходил в 2009 на Windows Mobile 6.5, до сих пор то Windown Phone, то Android 7 выпустят. Даже отсутствие каких-то исходников этих людей не останавливает.
Kenya-West
Лечение всегда легче, чем профилактика, вот и придумывают костыли при обновлении, когда можно спроектировать ОС так, чтобы приложения на выходе получались с изначально небольшим размером. Почему нельзя разработать приложение весом в 3 МБ вместо 300 МБ? Ответ: сама ОС такая.
Например, на Windows 10 приложения — это тупо набор скриптов, причём без преувеличения говорю. Даже обратная совместимость определяется двумя строчками в манифесте, все ресурсы хранит система, знай себе юзай ссылки на ресурсы, вызывай системные API и не пиши хуки, всё сделано за тебя, разрабатывай как хочешь. Итог: приложение на Android/iOS занимает 150 МБ, а на Windows — 1 МБ, и то это округление в большую сторону от 150 КБ.
Вывод: 400 000 000+ юзеров на Windows 10 экономят трафика столько, сколько Android и не снилось!
foxin
Положим, что каждый юзер WinPhone получает 1 обновление в день (в среднем) и чистая экономия — 1 МБ. 4*10^8 юзеров * 10^6 Байт = 4*10^14 Байт = 400 ТБ.
В то же время
.
6 ПБ / 400 ТБ = 15 раз. Так что нет. Самая непопулярная платформа если даже и экономит трафик, то в 15 раз меньше, чем самая популярная. Так себе достижение, если честно.
develop7
Арифметика, бессердечная ты сука.
ChiefPilot
Может мобильная Windows всё-таки «взлетит» когда-нибудь? Просто народ пока не просёк (причём и программисты и пользователи).
jehy
Пишу под мобильную Windows и под Android. Пока что вся экосистема UWP просто враждебна разработчику. Если интересно — могу написать об этом целый отдельный пост боли и страданий.
HUMAN1TY
Конечно пишите, надо ведь поделиться опытом с теми, кто думает начать писать под эту платформу.
ad1Dima
Ну, боль и страдания есть на всех платформах. Причём чаще всего боль и страдания возникают тогда, когда принципы одной платформы пытаются перенести на другую.
ChiefPilot
Конечно интересно! Напишите, пожалуйста. И если так, то тогда понятно, почему так не популярна платформа. Жаль, конечно… Потому, что мне — как пользователю — почему-то очень нравится и интерфейс и то, что на 1 Гб ОЗУ всё бегает не хуже (а то и лучше), чем на двух-трёх на Андроиде.
ad1Dima
непопулярна она по 2 причинам: низкая доля WP. Неясные преимущества на ПК, перед традиционными средствами.
Посмотрим, сможет ли Xbox и HoloLens стимулировать разработчиков.
IgeNiaI
Сильно сомневаюсь, что разработчики мобильной ОС думали о размере обновлений меньше, чем разработчики настольной ОС.
В iOS и Android тоже используется принцип, когда все ресурсы и весь код совместимости старых приложений с новой системой есть в самой системе. Другой вопрос, когда новое приложение хотят запустить на старой системе, где нет нужного кода. Тогда приходится этот код встраивать в само приложение, и на Windows абсолютно такая же ситуация.
Откуда тогда такой размер в приложениях? Это потому, что разработчики не хотят пользоваться стандартными ресурсами, и рисуют свои. Опять же, на Windows абсолютно такая же ситуация.
lgorSL
Можно. На андроиде код занимает очень малую часть от приложения. Если повыкидывать из приложения звуки, кастомные кнопочки, сплеш-скрин и прочие красивости, оно будет весить очень мало. Только пользователи будут недовольны, потому что им красивостей хочется, а размер +- 10 мб не важен.
Например, когда я писал небольшую игру на libgdx+scala, apk файл весил 3мб.
Внутри лежит classes.dex на 1.7 мб (большая часть — scala library), ещё 4.6 мб занимают библиотечки от libgdx, всё это с остальными ресурсами ужимается в апк размером в 3мб. (единственный косяк — библиотечки лежат сразу для пяти платформ, "x86", "x86_64", "armeabi", "armeabi-v7a", "arm64-v8a")
Ага, попробуйте поставить Windows Visual Studio. Даже если отключить все опции, она займёт 5 гб на диске. Для сравнения, образ линукса занимает около одного гигабайта. А в линуксе уже установлены gcc и прочие штуки для разработки.
knotri
(единственный косяк — библиотечки лежат сразу для пяти платформ, "x86", "x86_64", "armeabi", "armeabi-v7a", "arm64-v8a")
Это можно пофиксить настойками в gradle, будут генерироваться отдельные apk для каждой платформы — плей маркет такое поддерживает — и сам разрулит какому пользователю что отдавать.