29 декабря 2015 г.

В Android аду есть специальное место для Samsung

    Это перевод вот этой записи: http://verybadalloc.com/android/2015/12/19/special-place-for-samsung-in-android-hell/. Как всегда, рекомендую читать в оригинале, если есть такая возможность.
    Отказ от отвественности: если вы здесь только чтобы услышать, как кто-то поносит Samsung, проматывайте вниз. И да, вы пришли по назначению.
    Если вы используете библиотеку поддержки appcompat (конечно же используете), то могли видеть вот такой стек трейс  с Статистике падений от устройств Samsung под Android 4.2.2:
java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
at android.support.v7.app.ActionBarActivityDelegateBase.initializePanelMenu(ActionBarActivityDelegateBase.java:991)
at android.support.v7.app.ActionBarActivityDelegateBase.preparePanel(ActionBarActivityDelegateBase.java:1041)
at android.support.v7.app.ActionBarActivityDelegateBase.doInvalidatePanelMenu(ActionBarActivityDelegateBase.java:1259)
at android.support.v7.app.ActionBarActivityDelegateBase.access$100(ActionBarActivityDelegateBase.java:80)
at android.support.v7.app.ActionBarActivityDelegateBase$1.run(ActionBarActivityDelegateBase.java:116)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5299)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)


    А теперь слушайте очень внимательно, потому что эту историю вы будете рассказывать своим внукам.

  • Оказывается, что в некоторых устройствах (список здесь) в образе ROM встроена своя собственная версия поддержки MenuBuilder и она экспортируется в пути классов. Теперь, когда вы включаете нужную вам версию библиотеки поддержки (потому что она вам нужна) и используете поддержку ActionBar, приложение падает, потому что не может найти нужный ему класс.
  • Когда о проблеме было сообщено в проект Android'а, то первоначальным методом обхода ошибки было предложено скрытие имени класса MenuBuilder (итоговый путь не будет конфликтовать с Самсунговским), либо вернуться на версию 20 библиотеки поддержки. Обфускация была самым простым путём (серьёзно), это решение работало для библиотеки поддержки версий, начиная с 21.0.0, пока…
  • Год спустя, когда команда Google решила сделать что-то с этим (негодование в баг трекере было огромным) и они переименовали пакет, который содержит MenuBuilder, чтобы избежать конфликтов имён. Это изменение было сделано в версии 23.1.1, однако его было недостаточно, потому что…
  • Библиотека поддержки дизайна (Android Design Support Library) тоже использует MenuBuilder. Таким образом мы вернулись к исходной точке.
    И краши эти висят на первой же странице дневных краш репортов.
    Если вы просто ищете решение проблемы и попали сюда, пытаясь его нагуглить, то возьмите Proguard и добавьте следующие строки:

# Samsung ruining all nice things
-keep class !android.support.v7.view.menu.**,
 !android.support.design.internal.NavigationMenu,
 !android.support.design.internal.NavigationMenuPresenter,
 !android.support.design.internal.NavigationSubMenu, 
android.support.** {*;}
    Учтите, что это всё нужно написать одной строкой. И ещё замечание. Комментарий не обязателен для работы фикса, но настоятельно рекомендован для сохранности вашей психики.

Что отсюда можно вынести

    Сейчас я отойду ненадолго, возьму чашку кофе и вернусь, потому что пришло время поразглагольствовать.
    Если вы разработчик под Android, вы уже бесконечно ненавидите Samsung устройства. Ненавидите больше, чем средний пользователь, для которого Samsung - это синоним дурацкого Touchwiz и такого количества предустановленного ПО, что это уже за гранью разумного; вы презираете Samsung, потому что у вас нет выбора. Потому что из-за огромной доли Samsung вы просто не можете не поддерживать их устройства. И это самое обидное - вас лишают выбора!
    Не поймите меня неправильно, Samsung делает одни из лучших телефонов. Но все бы хотели, чтобы они прикладывали такие же усилия и к своему программному обеспечению. Общеизвестно, что Android разработчики практически не используют устройства от Samsung как личные телефоны.
    Конечно, эти проблемы есть не только у Samsung и горе затронуло все ROM'ы (кроме господской расы Nexus от Google). Но ёлки-палки, если вы стали абсолютным лидером по производству устройств под Android, то потрудитесь делать прошивки лучше, чем в среднем прошивки от любого другого производителя (как говорят в Нью-Йорке: огромная мощь несёт огромную ответственность).
    Основными причинами, почему iOS чуваки не принимают нас всерьёз: Android непонятный и нестабильный. Я понимаю, что фрагментация - это факт, но было бы здорово иметь возможность сказать, что стоимость сопровождения твоего приложения не включает отслеживание поведения на устройствах Wiko, которые, для начала, вообще не стоило называть Wiko (моё замечание: с суахили wiko переводится как "пение петуха". Видимо автор на это и намекает).
    Вместо того, чтобы позволять ненависти пройти сквозь тебя (обязательная отсылка к Звёздным войнам), было бы интересно посмотреть, смогло бы сообщество Android что-то сделать с этим. У HTML5 есть проект CanIUse, у iOS разработчиков есть SDK critic. Может мы создадим базу со всеми странными багами, которые накопились на всех основных устройствах? Одного Stackoverflow просто не хватает.
P.S.: Я знаю, я не предложил вам, что с этим делать, но вы всегда можете зафоловить меня в Twitter'е. (Моё замечание: да и меня тоже, чего уж там; или же здесь.)