5 августа 2018 г.

Изменения поведений в Android P. Часть 2: от тегирования сокетов до ещё большего урезания Apache HTTP client (дважды!)

Последняя публичная бета
Дальше — релиз

     Эта статья является переводом второй половины вот этой: https://developer.android.com/preview/behavior-changes.html. Как всегда, я рекомендую читать оригинал.
    Перевод первой половины: https://myachinqa.blogspot.com/2018/04/android-p-1.html

   Теги сокетов

    До Android P, если сокет был затеган методом setThreadStatsTag(), то при использовании binder IPC с ParcelFileDescriptor контейнером для отправки сокета другому процессу, тег слетал.
    В Android P это поведение изменилось и теперь в этом сценарии тег сохраняется. Такое изменение может повлиять на оценки статистик сетевого трафика, если, например, получить их у метода queryDetailsForUidTag(). Чтобы вернуть старое поведение  вам нужно вызвать untagSocket() перед отправкой сокета другому процессу.

Сообщение о доступном объёме байтов в сокете

    Если вызвать метод available() после shutdownInput(), то будет возвращён 0.

Больше данных о сетях для VPN клиентов

    До версии платформы ниже Android P класс NetworkCapabilities сообщал ограниченный набор данных для VPN. Например, сообщал TRANSPORT_VPN, но не NET_CAPABILITY_NOT_VPN. Из-за этого разработчикам было трудно понимать, приведёт ли использование VPN к расходу средств пользователя. К примеру, проверка NET_CAPABILITY_NOT_METERED не определяла, поднят VPN на сети с оплатой трафика или же на безлимитной сети.
    Начиная с Android P, когда VPN вызывает метод setUnderlyingNetworks(), система просуммирует транспорты и свойства всех сетей, на которых запущено подключение и вернёт нормальную совокупность свойств этих сетей.


Файлы в директории xt_qtaguid больше недоступны приложениям

    Приложения больше не могут напрямую читать файлы в директории /proc/net/xt_qtaguid. Это сделано для того чтобы обеспечить единообразие поведений с устройствами, которые будут иметь Android P на старте, потому что у них этих файлов просто не будет.
    Публичные API, которые были завязаны на эти файлы — TrafficStats и NetworkStatsManager — продолжат работать как и ожидается. Однако не поддерживаемые функции cutils, к примеру qtaguid_tagSocket(), могут работать неправильно или же, в зависимости от устройств, не работать вовсе.

Заработало требование флага FLAG_ACTIVITY_NEW_TASK

    В Android P и выше вы не сможете запустить активити из не-активити контекста, если не передадите интент флаг FLAG_ACTIVITY_NEW_TASK. Попытка запустить активити без передачи флага ни к чему не приведёт, только сообщение в логе появится. 
Замечание: Требование флага всегда было запланированным поведением и работало до Android N. Однако в Android N был баг, из-за которого это требование отвалилось. Вот, починили.

Изменения, связанные с поворотом экрана

    Пользователи Android O могли переключаться между режимами автоповорот и портрет кнопкой в быстрых настройках или в настройках экрана. В Android P же для режима портрет сделано принципиальное изменение. Режим портрета переименован в зафиксировать ориентацию.
    В режиме фиксации ориентации пользователи могут сохранить поворот экрана в любом состоянии — портрет, ландшафт или обратные (прим. перев.: то есть обратный портрет — когда «низ» приходится на ту сторону, где обычно фронтальная камера — и обратный ландшафт) — если только этот режим поддерживается экраном приложения, находящегося на переднем плане. Таким образом, если пользователь взаимодействует с экранами приложений, каждый из которых поддерживает автоповорот, эти экраны будут автоматически повёрнуты в определённую пользователем ориентацию и не важно, как именно пользователь держит устройство в пространстве (кроме исключений, описанных ниже).
    Активити, которым требуется конкретная ориентация (например screenOrientation=landscape), игнорируют тот режим, на который пользователь установил лочку и сохраняют такое же поведение, каким оно было в Android O.

    Свойства ориентации для активити должны быть заданы в Android Manifest или программно, через setRequestedOrientation().
    Фиксация ориентации работает путём установки пользовательской настройки в свойствах, которая считывается WindowManager'ом и применяются им на ориентацию для активити. Пользовательская настройка ориентации перетирается в следующих сценариях (обычно на портретную):
  • Когда пользователь принимает предлагаемую приложением настройку ориентации, эта предлагаемая настройка перезаписывает пользовательскую. Прим. перев.: имеется в виду, что если экран приложения предполагает только одну конкретную ориентацию, то эта ориентация будет выставлена теперь как глобальная настройка и при выходе из приложения она сохранится, т.к. в момент принятия она и становится пользовательским предпочтением. Разумеется, если выход произойдёт на другой экран, где принудительная ориентация отличается от текущей, то уже эта настройка будет выставлена как пользовательское предпочтение
  • Когда пользователь принудительно включает портретный режим, общая настройка предпочтений изменяется на портрет.
    Следующая таблица описывает возможные поведения для типичных ориентаций экрана:
Ориентация экрана Поведение
unspecified, user В режимах автоповорота и лочки ориентации Активити может быть отрисована в портретной, ландшафтной или обратных ориентациях. От приложения ожидается поддержка обоих внешних видов
userLandscape В автоповороте и в лочке Активити может быть отрисована только в ландшафтной или обратной ландшафтной ориентации. Ожидается поддержка только ландшафтного внешнего вида
userPortrait В автоповороте и в лочке Активити может быть отрисована в портретной или обратной портретной ориентации. Ожидается поддержка только портретного внешнего вида
fullUser В режимах автоповорота и лочки ориентации Активити может быть отрисована в портретной, ландшафтной или обратных ориентациях. От приложения ожидается поддержка обоих внешних видов. При этом пользователи могут залочить конкретно обратную портретную ориентацию и запрещать разворот на 180 градусов
sensor, fullSensor, sensorPortrait, sensorLandscape Лочка ориентации игнорируется и включается полностью автоматический поворот. Используйте это с большой осторожностью, т.к. это поведение ломает UX


Помеченный устаревшим Apache HTTP client станет недоступен приложениям с не стандартным ClassLoader

    В Android 6.0 мы сняли Apache HTTP client с поддержки. Это не затронуло большинство приложений, использующих таргет ниже Android P. Однако теперь, если приложение использует не стандартную структуру ClassLoader, клиент будет ему недоступен, даже если таргет останется ниже P.
    Затронуты будут те приложения, которые, которые используют не стандартный ClassLoader, который явно использует ClassLoader системы. Дело в том, что системный КлассЛоадер больше не сможет найти классы в org.apache.http.*. и бросит исключение NoClassDefFoundError. Так что вам нужно искать их в вашем собственном КлассЛоадере, а не передавать эту задачу на системный.

Перебор камер

    На Android P каждую из существующих камер можно найти вызовом getCameraIdList(). Категорически не стоит в приложениях писать код так, будто на устройстве может быть только одна фронтальная и/или задняя камера.
    К примеру, если в вашем приложении есть кнопка переключения между передней и задней камерами, нужно будет понимать, что каждой из них может быть более чем одна. Вам нужно будет каждый раз получать список доступных камер и смотреть на их характеристики. По этим характеристикам вы будете решать, какую из камер лучше использовать в данный момент.

Приложения с target Android P

    Описанные ниже изменения поведений затрагивают те приложения, которые указали таргет на P и выше.

Сервисы переднего плана

    Приложения с таргетом на Android P и выше и использующие foreground services обязаны запросить разрешение FOREGROUND_SERVICE. Это обычный пермишен, так что система автоматически предоставит его всем приложениям, которые его запросят. Если же разрешение не запросить, то при попытке создания сервиса переднего плана система бросит SecurityException.

Изменения, связанные с приватностью

    Если ваше приложение указывает поддержку Android P, вам нужно будет помнить об изменениях, перечисленных ниже.

Устаревший Build serial number

    Объявленное устаревшим ещё в Android 8.0 (API level 26) поле Build.SERIAL, в Android P всегда начнёт возвращать "UNKNOWN". Если вашему приложению совершенно необходимо получить аппаратный идентификатор, вам придётся запросить разрешение READ_PHONE_STATE, а затем вызвать getSerial().

Защита DNS

    Приложения в Android P должны проверять, что если в системе используется DNS-over-TLS, то их собственные встроенные DNS клиенты  также должны шифровать DNS при обращениях к тем же хостам, к которым обращалась система. Либо приложение должно отключить свой резолвер и использовать только системный.

Изменения безопасности во Framework

    Если в приложении задан таргет Android P, система принудительно будет использовать строгие сетевые и файловые правила безопасности. Чтобы узнать больше, прочтите старину Security Behavior Changes.

Счётчик сетевых данных и одновременные подключения

    Приложениям с таргетом Android P система считает сетевой трафик даже в тех сетях, которые не являются текущими сетями. Например для мобильных подключений при активных Wi-Fi (прим. перев.: так бывает, к примеру, в метро, когда активен Wi-Fi, но данные гонятся через мобильную связь). Методы для запроса данных о таком трафике находятся в классе NetworkStatsManager.
    В частности метод getMultipathPreference() вернёт значение по сетевому трафику для вышеописанного сценария. Новое поведение таково, что при запросе будет возвращаться true для мобильных данных, но только до достижения определённого порога за день. После этого будет возвращаться false. Приложениям, работающим на Android P, нужно вызывать этот метод и менять своё поведение, исходя из полученного результата. Прим. перев.: трафик для многих всё ещё очень дорог. Если вам сказали, что лимиты суточные исчерпаны — учитывайте это и снижайте аппетиты.
    Класс ConnectivityManager.NetworkCallback сообщает приложениям информацию о VPN. Теперь приложениям будет проще слушать сетевые события: не нужно использовать синхронные и асинхронные вызовы и обращаться к ограниченным API. Кроме того это означает, что передача информации работает корректно в том числе когда устройство подключено сразу к нескольким сетям одновременно.

Фокус у View

    Вьюхи с нулевым размером (т.е. с высотой или шириной равной 0) больше не получают фокус. Кроме того, в активити не будет никакой стартовой позиции фокуса. Но если нужно, вы сами можете задать стартовую позицию фокуса на нужном элементе.

Задание hex значения CSS RGBA

    В Android P для приложений включена поддержка черновой редакции CSS Color Module Level 4, что позволяет задавать цвета в CSS в виде 4 или 8 hex цифр.
    Поддержка CSS Color Module Level 4 была добавлена в Chrome начиная с 52 версии, однако WebView отключает эту фичу. Дело в том, что мы обнаружили Android приложения с цветами в 32 битном hex в Android представлении (ARGB). Для них использование этой фичи может привести к ошибкам отображения цветов.
    Например, если приложение имеет таргет ниже Android P, цвет #80ff8080 WebView отрисует как #ff8080 — первые две цифры, кодирующие прозрачность, будут проигнорированы. Для приложений с таргетом P и выше, цвет будет интерпретироваться как светлозелёный с 50% прозрачностью (#80ff80).

Элементы при прокрутке документов

    До Android P позиция прокрутки устанавливалась для элемента body, а значение скрола для  элемент root было нулевым. Android P использует стандарт поведения, при котором root и есть прокручиваемый элемент.
    Кроме того, прямой доступ к document.body.scrollTop, document.body.scrollLeft, document.documentElement.scrollTop или document.documentElement.scrollLeft будет иметь разное поведение, в зависимости от целевого SDK. Чтобы узнать значение прокрутки для порта просмотра (прим. перев.: https://ru.wikipedia.org/wiki/Порт_просмотра), по возможности нужно использовать document.scrollingElement.

Оптимизация DEX ahead-of-time компиляции

    На устройствах с Android P, Android runtime (ART) будет использовать новый ahead-of-time компилятор, который оптимизирует сжатые DEX файлы. Он конвертирует DEX из пакетов приложений (APK) в более компактый машинный код. Благодаря этому ваши приложения будут запускаться быстрее, также занимать меньше места на диске и в оперативной памяти. В особенности это улучшение будет выгодна для устройств нижнего ценового сегмента с низкой скоростью I/O хранилищ.

Уведомления от остановленных приложений

    До Android P уведомления от приостановленных приложений отменялись. В Android P их уведомления будут просто скрыты до тех пор, пока работа приложения не будет возобновлена. Прим. перев.: на момент написания этих строк я не понимаю, идёт ли речь лишь о Doze/App Standby или более глобально — о приложениях, остановленных через Force Stop.

Устаревший Apache HTTP клиент

    В Android 6 мы сняли Apache HTTP клиент с поддержки. Начиная с Android P эта библиотека удалена из bootclasspath и по умолчанию недоступна приложениям.
    Чтобы использовать Apache HTTP в приложениях с таргетом Android P и выше, в AndroidManifest.xml нужно добавить
<uses-library android:name="org.apache.http.legacy" android:required="false"/>

    Замечание: Атрибут android:required="false" нужно использовать в тех приложениях, минимальный SDK у которых 23 или ниже. Потому что на устройствах с уровнем API ниже чем 24 библиотеки org.apache.http.legacy попросту нет (т.е. классы Apache HTTP и так доступны в bootclasspath).

    В качестве альтернативы, дабы библиотека Apache была доступна в рантайме, вы можете встроить org.apache.http в сам APK. Если решите это сделать, вам нужно будет перепаковать библиотеку (утилитой типа Jar Jar), чтобы избежать проблем совместимости классов во время работы.

Комментариев нет:

Отправить комментарий