Android 8.0: особенности и API

В Android 8.0 (уровень API 26) появилось множество новых функций и возможностей для пользователей и разработчиков. В этом документе рассказывается о том, что нового появилось для разработчиков.

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

Удобство для пользователей

Режим "Картинка в картинке"

Режим "Картинка в картинке" в Android 8.0.

В Android 8.0 (уровень API 26) действия можно запускать в режиме "картинка в картинке". Режим "Картинка в картинке" – это особый тип многооконного режима, который в основном используется для воспроизведения видео. Изначально режим "картинка в картинке" был доступен только на Android TV, но в Android 8.0 он появился и на других устройствах Android.

Когда действие находится в режиме PIP, оно приостановлено, но должно продолжать показывать контент. Поэтому убедитесь, что ваше приложение не приостанавливает воспроизведение в обработчике onPause(). Вместо этого приостановите видео в onStop() и возобновите воспроизведение в onStart(). Подробнее о жизненном цикле в многооконном режиме…

Чтобы указать, что в вашем действии можно использовать режим PIP, задайте для android:supportsPictureInPicture значение true в манифесте. Начиная с Android 8.0, для режима "Картинка в картинке" не требуется атрибут манифеста android:resizeableActivity. Однако если действие поддерживает другие многооконные режимы, для атрибута android:resizeableActivity нужно задать значение true.

В Android 8.0 (уровень API 26) появился новый объект PictureInPictureParams, который передается методам PIP и определяет поведение действия в этом режиме. Этот объект определяет такие свойства, как предпочтительное соотношение сторон для действия.

Существующие методы, описанные в статье Добавление режима "картинка в картинке", теперь можно использовать на всех устройствах Android, а не только на Android TV. Кроме того, в Android 8.0 есть следующие методы для поддержки режима "картинка в картинке":

  • Activity.enterPictureInPictureMode(PictureInPictureParams args) – переводит действие в режим "картинка в картинке". Соотношение сторон и другие настройки задаются с помощью args. Если какие-либо поля в args не заполнены, система использует значения, заданные при последнем вызове Activity.setPictureInPictureParams().

    Указанное действие помещается в угол экрана, а остальная часть экрана заполняется предыдущим действием, которое было на экране. Действие, переходящее в режим PIP, приостанавливается, но остается запущенным. Если пользователь нажмет на окно, система покажет меню, с которым можно взаимодействовать. События касания не доходят до окна, пока оно находится в режиме "картинка в картинке".

  • Activity.setPictureInPictureParams() – обновляет настройки конфигурации режима "Картинка в картинке" для действия. Если действие в данный момент находится в режиме PIP, настройки обновляются. Это полезно, если соотношение сторон действия меняется. Если объект activity не находится в режиме PIP, эти настройки конфигурации используются независимо от того, какой метод enterPictureInPictureMode() вы вызываете.

Уведомления

В Android 8.0 (уровень API 26) мы изменили дизайн уведомлений, чтобы упростить управление их поведением и настройками. включая следующие:

    Меню, которое появляется при долгом нажатии на уведомление в Android 8.0 (уровень API 26).

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

  • Каналы уведомлений. В Android 8.0 появились каналы уведомлений, которые позволяют создавать настраиваемые каналы для каждого типа уведомлений. В пользовательском интерфейсе каналы уведомлений называются категориями уведомлений. Подробнее о том, как настроить каналы уведомлений…
  • Точки уведомлений. В Android 8.0 появил��сь поддержка точек (значков) уведомлений на значках приложений. Они указывают на наличие уведомлений, которые пользователь ещё не отклонил или не открыл. Подробнее о том, как работать со значками уведомлений…
  • Откладывание. Пользователи могут отложить уведомления, чтобы они исчезли на некоторое время, а затем появились снова. Уведомления появляются снова с тем же уровнем важности, с которым они появились в первый раз. Приложения могут удалять или обновлять отложенные уведомления, но при обновлении они не появляются снова.
  • Тайм-ауты уведомлений. Вы можете задать тайм-аут при создании уведомления с помощью setTimeoutAfter(). Этот метод позволяет указать, через какое время уведомление должно быть отменено. При необходимости вы можете отмен��ть уведомление ��о ис��ече��ия указан��ого времени ожидания.
  • Настройки уведомлений. Вы можете вызвать setSettingsText(), чтобы задать текст, который будет показываться, когда вы создаете ссылку на настройки уведомлений в приложении из уведомления с помощью намерения Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES. Система может предоставить следующие дополнительные параметры с намерением отфильтровать настройки, которые ваше приложение должно показывать пользователям: EXTRA_CHANNEL_ID, NOTIFICATION_TAG и NOTIFICATION_ID.
  • Отклонение уведомлений. Пользователи могут отклонять уведомления самостоятельно, а приложения – программно. Вы можете определить, когда и почему уведомление было закрыто, реализовав метод onNotificationRemoved() из класса NotificationListenerService.
  • Цвет фона. Вы можете задать и включить цвет фона для уведомления. Используйте эту функцию только в уведомлениях о текущих задачах, которые пользователь должен видеть сразу. Например, можно задать цвет фона для уведомлений, связанных с маршрутами или текущим телефонным звонком. Вы также можете задать цвет фона с помощью поля setColor(). Это позволит вам использовать setColorized(), чтобы включить цвет фона для уведомления.
  • Стиль сообщений. В Android 8.0 уведомления, использующие класс MessagingStyle, в свернутом виде содержат больше контента. Для уведомлений, связанных с обменом сообщениями, следует использовать класс MessagingStyle. Вы также можете использовать метод addHistoricMessage(), чтобы добавить контекст в чат, добавив сообщения из истории в уведомления, связанные с обменом сообщениями.

Фреймворк автозаполнения

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

В Android 8.0 (уровень API 26) появился фреймворк автозаполнения, который упрощает заполнение форм, например для входа в аккаунт или ввода данных банковской карты. Существующие и новые приложения работают с фреймворком автозаполнения после того, как пользователь включит автозаполнение.

Вы можете оптимизировать работу приложения с фреймворком. Подробнее о фреймворке автозаполнения…

Скачиваемые шрифты

В Android 8.0 (уровень API 26) и библиотеке поддержки Android 26 можно запрашивать шрифты из приложения-поставщика, а не включать их в APK-файл или скачивать с его помощью. Эта функция уменьшает размер APK-файла, увеличивает долю успешных установок приложения и позволяет нескольким приложениям использовать один и тот же шрифт.

Подробнее о доступных для скачивания шрифтах…

Шрифты в XML

В Android 8.0 (уровень API 26) появилась новая функция – шрифты в XML, которая позволяет использовать шрифты в качестве ресурсов. Это значит, что вам не нужно упаковывать шрифты как объекты. Шрифты компилируются в файле R и автоматически становятся доступны в системе как ресурс. Затем вы можете получить доступ к этим шрифтам с помощью нового типа ресурса font.

Support Library 26 обеспечивает полную поддержку этой функции на устройствах с API версии 14 и выше.

Подробнее о том, как использовать шрифты в качестве ресурсов и получать системные шрифты, читайте в статье Шрифты в XML.

Автоматическое изменение размера TextView

В Android 8.0 (уровень API 26) можно настроить автоматическое изменение размера текста в зависимости от размера TextView. Это означает, что намного проще оптимизировать размер текста на разных экранах или с динамическим контентом. Подробнее об автоматическом изменении размера TextView в Android 8.0…

Адаптивные значки

В Android 8.0 (уровень API 26) появились адаптивные значки приложений. Адаптивные значки поддерживают визуальные эффекты и могут принимать разные формы на разных моделях устройств. Подробнее о том, как создавать адаптивные значки…

Управление цветом

Разработчики Android-приложений для работы с изображениями теперь могут использовать преимущества новых устройств с дисплеями, поддерживающими широкую цветовую гамму. Чтобы показывать изображения с широкой цветовой гаммой, приложениям нужно будет включить флаг в манифесте (для каждого действия) и загрузить растровые изображения со встроенным широким цветовым профилем (AdobeRGB, Pro Photo RGB, DCI-P3 и т. д.).

WebView API

В Android 8.0 есть несколько API, которые помогают управлять объектами WebView, показывающими веб-контент в приложении. Эти API повышают стабильность и безопасность приложения. К ним относятся:

  • Version API
  • Google SafeBrowsing API
  • Termination Handle API
  • Renderer Importance API

Подробнее о том, как использовать эти API, рассказывается в статье Управление компонентами WebView.

В класс WebView добавлен Safe Browsing API, который повышает безопасность просмотра веб-страниц. Подробную информацию вы найдете в статье API Google для безопасного просмотра веб-страниц.

Закрепление ярлыков и виджетов

В Android 8.0 (уровень API 26) появилась возможность закреплять ярлыки и виджеты в приложении. В приложении можно создавать закрепленные ярлыки и виджеты для поддерживаемых программ запуска, если пользователь предоставил разрешение.

Подробную информацию вы найдете в ��у��овод��т��е по закреплению ярлыков и виджетов.

Максимальное соотношение сторон экрана

В Android 8.0 (уровень API 26) изменился способ настройки максимального соотношения сторон приложения.

Во-первых, в Android 8.0 появился атрибут maxAspectRatio, с помощью которого можно задать максимальное соотношение сторон для приложения. Кроме того, в Android 8.0 и более поздних версиях максимальное соотношение сторон приложения по умолчанию соответствует соотношению сторон устройства, на котором оно запущено.

Подробнее о том, как объявить максимальное соотношение сторон, читайте в статье Поддержка нескольких экранов.

Поддержка показа на нескольких экранах

Начиная с Android 8.0 (уровень API 26), платформа предлагает расширенную поддержку нескольких дисплеев. Если действие поддерживает многооконный режим и выполняется на устройстве с несколькими экранами, пользователи могут перемещать действие с одного экрана на другой. При запуске действия приложение может указать, на каком экране оно должно выполняться.

Примечание. Если операция поддерживает многооконный режим, Android 8.0 автоматически включает для нее поддержку нескольких экранов. Протестируйте приложение, чтобы убедиться, что оно корректно работает в среде с несколькими экранами.

Только одно действие может быть возобновлено, даже если у приложения несколько экранов. Активность, на которой находится фокус, возобновляется, а все остальные видимые активности приостанавливаются, но не останавливаются. Дополнительную информацию о жизненном цикле объекта activity, когда видно несколько объектов activity, вы можете найти в разделе Жизненный цикл в многооконном режиме.

Когда пользователь перемещает действие с одного экрана на другой, система изменяет размер действия и при необходимости вносит изменения во время выполнения. Ваше действие может самостоятельно обработать изменение конф��гурации или позволить системе уничтожить процесс, содержащий ваше действие, и воссоздать его с новыми размерами. Подробнее об обработке изменений конфигурации…

В ActivityOptions есть два новых метода для поддержки нескольких экранов:

setLaunchDisplayId()
Указывает, на каком экране должно отображаться действие при запуске.
getLaunchDisplayId()
Возвращает текущий экран запуска действия.

Оболочка adb расширена для поддержки нескольких дисплеев. Теперь с помощью команды shell start можно запустить действие и указать для него целевой экран:

adb shell start <activity_name> --display <display_id>

Единые поля и отступы в макете

В Android 8.0 (уровень API 26) стало проще указывать ситуации, когда противоположные стороны элемента View используют одинаковые поля или отступы. В частности, теперь в XML-файлах макетов можно использовать следующие атрибуты:

Примечание. Если вы настраиваете логику приложения для поддержки разных языков и культур, включая направление текста, помните, что эти атрибуты не влияют на значения layout_marginStart, layout_marginEnd, paddingStart и paddingEnd. Вы можете задать эти значения самостоятельно, в дополнение к новым атрибутам вертикального и горизонтального макета, чтобы создать поведение макета, зависящее от направления текста.

Захват указателя

Некоторым приложениям, например играм, клиентам удаленного рабоче��о стола и виртуализации, требуется управление указателем мыши. Захват указателя – это новая функция в Android 8.0 (уровень API 26), которая обеспечивает такой контроль, доставляя все события мыши в сфокусированное представление в вашем приложении.

Начиная с Android 8.0, View в вашем приложении может запрашивать захват указателя и определять прослушиватель для обработки событий захваченного указателя. В этом режиме указатель мыши скрыт. Представление может отменить захват указателя, когда информация о мыши больше не нужна. Система также может освободить захват указателя, когда представление теряет фокус, например, когда пользователь открывает другое приложение.

Подробнее о том, как использовать эту функцию в приложении…

Категории приложений

В Android 8.0 (уровень API 26) каждое приложение может объявить категорию, к которой оно относится. Эти категории используются для группировки приложений со схожими целями или функциями при их представлении пользователям, например в разделах "Использование данных", "Использование батареи" или "Использование хранилища". Вы можете определить категорию для своего приложения, задав атрибут android:appCategory в теге манифеста <application>.

Android TV Launcher

В Android 8.0 (уровень API 26) появился новый главный экран Android TV, ориентированный на контент. Он доступен в эмуляторе Android TV и образе устройства Nexus Player для Android 8.0. На новом главном экране видеоконтент упорядочен по строкам, соответствующим каналам, каждый из которых заполнен программами из приложения в системе. Приложения могут публиковать несколько каналов, а пользователи могут выбирать, какие каналы они хотят видеть на главном экране. На главном экране Android TV также есть строка "Смотреть дальше", в которой показываются программы из приложений, подобранные на основе предпочтений пользователя. Приложения также могут предоставлять видео для предварительного просмотра, которые автоматически воспроизводятся, когда пользователь выбирает программу. API для заполнения каналов и программ входят в состав TvProvider API, которые р��спространяются как модуль библиотеки поддержки Android в Android 8.0.

AnimatorSet

Начиная с Android 8.0 (уровень API 26) API AnimatorSet поддерживает поиск и воспроизведение в обратном порядке. Перемотка позволяет установить позицию набора анимации на определенный момент времени. Воспроизведение в обратном порядке полезно, если в приложении есть анимация для действий, которые можно отменить. Вместо того, чтобы определять два отдельных набора анимации, вы можете воспроизвести один и тот же в обратном порядке.

Ввод и навигация

Кластеры навигации с помощью клавиатуры

Если в вашем приложении используется сложная иерархия View, как на рисунке 2, рекомендуем объединить элементы интерфейса в кластеры, чтобы упростить навигацию с помощью клавиатуры. Чтобы переключаться между кластерами, пользователи могут нажимать клавиши Meta + Tab или Поиск + Tab ��а ��стройствах Chromebook. Хорошими примерами кластеров являются боковые панели, панели навигации, области основного контента и элементы, которые могут содержать много дочерних элементов.

Пример действия, включающего пять кластеров навигации, по которым пользователь может перемещаться с помощью сочетания клавиш для кластера навигации. Кластеры расположены в следующем порядке: верхняя панель, левая боковая панель, область основного контента, нижняя панель и плавающая кнопка действия.
Рисунок 2. Activity, содержащий 5 кластеров навигации

Чтобы сделать элемент View или ViewGroup кластером, задайте для атрибута android:keyboardNavigationCluster значение true в XML-файле макета элемента или передайте true в setKeyboardNavigationCluster() в логике интерфейса приложения.

Примечание. Кластеры не могут быть вложенными, хотя невложенные кластеры могут находиться на разных уровнях иерархии. Если вы попытаетесь вложить кластеры друг в друга, фреймворк будет считать кластером только верхний элемент ViewGroup.

На устройствах с сенсорными экранами можно задать для элемента android:touchscreenBlocksFocus объекта ViewGroup, назначенного кластеру, значение true, чтобы разрешить навигацию только в пределах этого кластера. Если вы примените эту конфигурацию к кластеру, пользователи не смогут использовать клавишу Tab или клавиши со стрелками для перехода в кластер или из него. Вместо этого им нужно будет нажать комбинацию клавиш для навигации по кластеру.

Посмотреть фокус по умолчанию

В Android 8.0 (уровень API 26) можно назначить элемент View, который должен получить фокус после возобновления созданного или воссозданного действия и нажатия пользователем клавиши навигации, например Tab. Чтобы применить настройку "фокус по умолчанию", задайте для атрибута android:focusedByDefault элемента View значение true в XML-файле макета, содержащем элемент интерфейса, или передайте true в setFocusedByDefault() в логике интерфейса приложения.

Голосовой вывод

Экземпляры TextToSpeech могут использоваться в действиях и сервисах для диктовки и произнесения контента. Начиная с Android 8.0 (уровень API 26) приложение может получать более точную информацию о том, когда система синтеза речи начинает произносить отдельные слова, если эта система предоставляет такие данные. Вы можете использовать эту функцию, чтобы привлечь внимание к определенным словам, когда их произносит система синтеза речи.

Чтобы использовать эти улучшения механизма преобразования текста в речь в своем приложении, зарегистрируйте экземпляр UtteranceProgressListener. В процессе регистрации добавьте обработчик для метода onRangeStart().

Система синтеза речи вызывает rangeStart(), чтобы записать момент времени, в который должно начаться воспроизведение аудио для определенного диапазона текста. Когда начинается воспроизведение аудио для этого диапазона текста, выполняется метод onRangeStart() вашего приложения. Приложение может реагировать на этот обратный вызов, например выделять диапазон текста, связанный с высказыванием.

Дополнительную информацию об отслеживании воспроизведения в системе синтеза речи можно найти в справочной документации по классу UtteranceProgressListener.

Система

Новые детекторы StrictMode

В Android 8.0 (уровень API 26) добавлены три новых детектора StrictMode, которые помогают выявлять потенциальные ошибки в приложении:

  • detectUnbufferedIo() обнаружит, когда ваше приложение считывает или записывает данные без буферизации, что может значительно повлиять на производительность.
  • detectContentUriWithoutPermission() обнаруживает, когда ваше приложение случайно забывает предоставить разрешения другому приложению при запуске объекта Activity за пределами вашего приложения.
  • detectUntaggedSockets() будет определять, когда ваше приложение вы��олняет сетевой трафик без использования setThreadStatsTag(int) для пометки вашего трафика в целях отладки.

Данные кеша

В Android 8.0 (уровень API 26) улучшены рекомендации и поведение в отношении кешированных данных. Теперь каждому приложению выделяется квота на место на диске для кешированных данных, возвращаемая методом getCacheQuotaBytes(UUID).

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

Также есть два новых поведения, которые можно включить для каждого каталога, чтобы контролировать, как система освобождает кешированные данные:

  • StorageManager.setCacheBehaviorAtomic() можно использовать, чтобы указать, что каталог и все его содержимое должны быть удалены как единый атомарный блок.
  • setCacheBehaviorTombstone(File, boolean) можно использовать, чтобы указать, что вместо удаления файлов в каталоге их размер должен быть усечен до 0 байт, а пустой файл должен остаться нетронутым.

Наконец, если вам нужно выделить место на диске для больших файлов, используйте новый API allocateBytes(FileDescriptor, long), который при необходимости автоматически удаляет кешированные файлы других приложений. Чтобы определить, достаточно ли на устройстве места на диске для новых данных, вызовите getAllocatableBytes(UUID) вместо getUsableSpace(). Первый метод учитывает кешированные данные, которые система может удалить от вашего имени.

Разбиение на страницы у поставщика контента

Мы обновили поставщиков контента, чтобы они поддерживали загрузку больших наборов данных по од��ой странице за раз. Например, приложение для работы с фотографиями, в котором хранятся тысячи изображений, может запрашивать подмножество данных для показа на странице. Каждая страница результатов, возвращаемая поставщиком контента, представлена одним объектом Cursor. Чтобы использовать эту функцию, и клиент, и поставщик должны реализовать разбиение на страницы.

Подробную информацию об изменениях, связанных с поставщиками контента, можно найти в статьях ContentProvider и ContentProviderClient.

Запросы на обновление контента

В классы ContentProvider и ContentResolver добавлен метод refresh(), который позволяет клиентам легко узнавать, актуальна ли запрашиваемая ими информация.

Вы можете добавить собственную логику обновления контента, расширив ContentProvider. Переопределите метод refresh(), чтобы он возвращал значение true. Это будет указывать клиентам поставщика, что вы пытались обновить данные самостоятельно.

Клиентское приложение может явно запросить обновленный контент, вызвав другой метод, который также называется refresh(). При вызове этого метода передайте URI данных, которые нужно обновить.

Примечание. Поскольку вы можете запрашивать данные по сети, вызывайте refresh() на стороне клиента, только если есть веские основания полагать, что контент устарел. Чаще всего обновление контента выполняется в ответ на жест пролистывания для обновления, который явно запрашивает отображение актуального контента в текущем пользовательском интерфейсе.

Улучшения JobScheduler

В Android 8.0 (уровень API 26) появилось несколько улучшений для JobScheduler. Благодаря этим улучшениям вашему приложению будет проще соответствовать новым ограничениям на фоновое выполнение, поскольку вы можете использовать запланированные задания вместо фоновых служб или неявных широковещательных приемников, которы�� теперь ограничены.

Изменения в JobScheduler:

  • Теперь вы можете связать очередь работ с запланированным заданием. Чтобы добавить рабочий элемент в очередь задания, вызовите JobScheduler.enqueue(). Когда задание выполняется, оно может брать ожидающие задачи из очереди и обрабатывать их. Эта функция позволяет решать многие задачи, для которых ранее требовался запуск фоновой службы, в частности службы, реализующей IntentService.
  • В библиотеке поддержки Android 26.0.0 появился новый класс JobIntentService, который предоставляет те же функции, что и IntentService, но использует задания вместо сервисов при работе на устройствах с Android 8.0 (уровень API 26) или более поздней версии.
  • Теперь вы можете вызвать JobInfo.Builder.setClipData(), чтобы связать ClipData с заданием. Этот параметр позволяет связать разрешения URI с заданием, аналогично тому, как эти разрешения могут быть переданы в Context.startService(). Вы также можете использовать разрешения URI с намерениями в рабочих очередях.
  • Для запланированных заданий теперь поддерживается несколько новых ограничений:
    JobInfo.isRequireStorageNotLow()
    Задача не выполняется, если на устройстве недостаточно свободного места.
    JobInfo.isRequireBatteryNotLow()
    Задача не выполняется, если уровень заряда батареи достиг критического порога или опустился ниже него. При этом на устройстве появляется системное диалоговое окно Батарея разряжена.
    NETWORK_TYPE_METERED
    Для выполнения задачи требуется подключение к сети с тарификаци��й тр��фика, ��а��ример к мобильному интернету.

Специальное хранилище данных

В Android 8.0 (уровень API 26) можно использовать собственное хранилище данных для настроек. Это удобно, если приложение хранит настройки в облаке или локальной базе данных или если настройки зависят от устройства. Подробнее о реализации хранилища данных…

Улучшение медиаконтента

VolumeShaper

Доступен новый класс VolumeShaper. Используйте его для выполнения коротких автоматических переходов громкости, таких как постепенное появление, затухание и перекрестное затухание. Подробнее об управлении амплитудой с помощью VolumeShaper…

Улучшения аудиофокуса

Аудиоприложения совместно используют аудиовыход на устройстве, запрашивая и отменяя фокус звука. Приложение обрабатывает изменения фокуса, запуская или останавливая воспроизведение или уменьшая громкость. Доступен новый класс AudioFocusRequest. Используя этот класс в качестве параметра requestAudioFocus(), приложения получают новые возможности при обработке изменений в аудиофокусе: автоматическое приглушение и отложенное получение фокуса.

Показатели медиаконтента

Новый метод getMetrics() возвращает объект PersistableBundle, содержащий информацию о конфигурации и производительности, представленную в виде карты атрибутов и значений. Метод getMetrics() определен для следующих классов медиаконтента:

Показатели собираются отдельно для каждого экземпляра и сохраняются в течение всего времени его существования. Если показатели недоступны, метод возвращает значение null. Возвращаемые показатели зависят от класса.

MediaPlayer

Начиная с Android 8.0 (уровень API 26) MediaPlayer может воспроизводить защищенный DRM контент и медиафайлы, зашифрованные на уровне образца HLS.

В Android 8.0 добавлена новая перегруженная команда seekTo(), которая обеспечивает точный контроль при поиске кадра. Он включает второй параметр, который указывает режим поиска:

  • SEEK_PREVIOUS_SYNC перемещает позицию медиафайла в синхронизированный (или ключевой) кадр, связанный с источником данных, который находится непосредственно перед заданным временем или в этот момент.
  • SEEK_NEXT_SYNC перемещает позицию воспроизведения на синхронизированный (или ключевой) кадр, связанный с источником данных, который находится сразу после указанного времени или в этот момент.
  • SEEK_CLOSEST_SYNC перемещает позицию медиафайла к кадру синхронизации (или ключевому кадру), связанному с источником данных, который находится ближе всего к указанному времени или в указанное время.
  • SEEK_CLOSEST перемещает позицию медиафайла к кадру (не обязательно кадру синхронизации или ключевому кадру), связанному с источником данных, который находится ближе всего к указанному времени или в указанное время.

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

MediaRecorder

  • MediaRecorder теперь поддерживает формат MPEG2_TS, который полезен для потоковой передачи.

    Kotlin

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)

    Java

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);

    Посмотреть MediaRecorder.OutputFormat

  • Теперь MediaMuxer может обрабатывать любое количество аудио- и видеопотоков. Теперь вы не ограничены одной аудио- и/или одной видеодорожкой. Используйте addTrack(), чтобы микшировать сколько угодно треков.
  • В MediaMuxer также можно добавить одну или несколько дорожек метаданных, содержащих заданную пользователем информацию о кадрах. Формат метаданных определяется вашим приложением. Дорожка метаданных поддерживается только для контейнеров MP4.

Метаданные могут быть полезны для офлайн-обработки. Например, сигналы гироскопа от датчика могут использоваться для стабилизации видео.

При добавлении дорожки метаданных ее MIME-формат должен начинаться с префи��са application/. Запись метаданных выполняется так же, как и запись видео- и аудиоданных, за исключением того, что данные не поступают из MediaCodec. Вместо этого приложение передает методу writeSampleData() объект ByteBuffer со связанной временной меткой. Временная метка должна быть в той же временной базе, что и видео- и аудиодорожки.

Сгенерированный файл MP4 использует TextMetaDataSampleEntry, определенный в разделе 12.3.3.2 спецификации ISOBMFF, чтобы указать MIME-формат метаданных. При использовании MediaExtractor для извлечения файла с дорожкой метаданных MIME-формат метаданных будет извлечен в MediaFormat.

Улучшенный доступ к медиафайлам

Storage Access Framework (SAF) позволяет приложениям предоставлять собственный класс DocumentsProvider, который может открывать другим приложениям доступ к файлам в источнике данных. Поставщик документов может даже предоставлять доступ к файлам, которые находятся в сетевом хранилище или используют протокол, например Media Transfer Protocol (MTP).

Однако доступ к большим медиафайлам из удаленного источника данных создает некоторые проблемы:

  • Медиапроигрывателям требуется доступ к файлу от поставщика документов с возможностью перемотки. Если большой медиафайл находится в удаленном источнике данных, поставщик документов должен заранее получить все данные и создать дескриптор файла моментального снимка. Проигрыватель не может воспроизвести файл без дескриптора, поэтому воспроизведение не начнется, пока поставщик документов не завершит скачивание файла.
  • Менеджерам медиаколлекций, например приложениям для работы с фотографиями, необходимо пройти через ряд URI доступа, чтобы добраться до медиафайлов, хранящихся на внешней SD-карте, через папки с ограниченным доступом. Из-за этого массовые операции с медиафайлами, такие как перемещение, копирование и удаление, выполняются довольно медленно.
  • Менеджеры медиаколлекций не могут определить местоположение документа по его URI. Из-за этого пользователям таких приложений сложно выбрать, где сохранить медиафайл.

В Android 8.0 эти проблемы решены за счет улучшения Storage Access Framework.

Пользовательские поставщики документов

Начиная с Android 8.0, Storage Access Framework позволяет пользовательским поставщикам документов создавать дескрипторы файлов с возможностью поиска для файлов, находящихся в удаленном источнике данных. SAF может открыть файл, чтобы получить нативный дескриптор файла с возможностью поиска. Затем SAF передает поставщику документов запросы на отдельные байты. Эта функция позволяет поставщику документов возвращать точный диапазон байтов, запрошенный приложением медиапроигрывателя, вместо предварительного кеширования всего файла.

Чтобы использовать эту функцию, необходимо вызвать новый метод StorageManager.openProxyFileDescriptor(). Метод openProxyFileDescriptor() принимает объект ProxyFileDescriptorCallback в качестве обратного вызова. SAF вызывает обратный вызов каждый раз, когда клиентское приложение выполняет операции с файлом в дескрипторе файла, возвращенном поставщиком документов.

Прямой доступ к документам

Начиная с Android 8.0 (уровень API 26), вы можете использовать метод getDocumentUri(), чтобы получить URI, который ссылается на тот же документ, что и заданный mediaUri. Однако, поскольку возвращенный URI поддерживается DocumentsProvider, менеджеры коллекций медиафайлов могут получить доступ к документу напрямую, без необходимости обхода деревьев каталогов с ограниченной областью действия. В результате менеджеры по работе с медиаконтентом могут выполнять операции с файлами в документе значительно быстрее.

Внимание! Метод getDocumentUri() только находит медиафайлы, но не предоставляет приложениям разрешение на доступ к ним. Чтобы узнать больше о том, как получить разрешение на доступ к медиафайлам, ознакомьтесь со справочной документацией.

Пути к документам

При использовании Storage Access Framework в Android 8.0 (уровень API 26) вы можете использовать метод findDocumentPath(), доступный в классах DocumentsContract и DocumentsProvider, чтобы определить путь от корня файловой системы по идентификатору документа. Метод возвращает этот путь в объекте DocumentsContract.Path. Если в файловой системе есть несколько путей к одному и тому же документу, метод возвращает путь, который используется чаще всего для доступа к документу с указанным идентификатором.

Эта функция особенно полезна в следующих случаях:

  • В вашем приложении есть диалоговое окно "Сохранить как", в котором показывается местоположение определенного документа.
  • В результатах поиска в приложении показываются папки. Если пользователь выбирает одну из них, должны загружаться дочерние документы, которые в ней находятся.

Примечание. Если у приложения есть доступ только к некоторым документам по указанному пути, возвращаемое значение findDocumentPath() будет включать только папки и документы, к которым у приложения есть доступ.

Отслеживание воспроизведения аудио

Системный сервис AudioManager поддерживает список активных объектов AudioPlaybackConfiguration, каждый из которых содержит информацию об определенном сеансе воспроизведения аудио. Чтобы получить набор активных конфигураций, вызовите метод getActivePlaybackConfigurations().

Начиная с Android 8.0 (уровень API 26), вы можете зарегистрировать обратный вызов, который будет уведомлять ваше приложение об изменении одного или нескольких объектов AudioPlaybackConfiguration. Для этого вызовите registerAudioPlaybackCallback(), передав экземпляр AudioManager.AudioPlaybackCallback. Класс AudioManager.AudioPlaybackCallback содержит метод onPlaybackConfigChanged(), который система вызывает при изменении конфигурации воспроизведения аудио.

Функции связи

Wi-Fi Aware

В Android 8.0 (уровень API 26) доба��лена ��о��держ��а Wi-Fi Aware на основе спецификации Neighbor Awareness Networking (NAN). На устройствах с поддержкой Wi-Fi Aware приложения и устройства поблизости могут обнаруживать друг друга и обмениваться данными по Wi-Fi без точки доступа к интернету. Мы работаем с партнерами по оборудованию, чтобы как можно скорее внедрить технологию Wi-Fi Aware в устройства. Подробнее о том, как интегрировать Wi-Fi Aware в приложение…

Bluetooth

В Android 8.0 (уровень API 26) поддержка Bluetooth расширена за счет следующих функций:

  • Поддержка стандарта AVRCP 1.4, который позволяет просматривать фонотеку.
  • Поддержка стандарта Bluetooth Low-Energy (BLE) 5.0.
  • Интеграция кодека Sony LDAC в стек Bluetooth.

Подключение дополнительных устройств

В Android 8.0 (уровень API 26) есть API, которые позволяют настраивать диалоговое окно запроса на подключение с дополнительными устройствами по Bluetooth, BLE и Wi-Fi. Подробнее о подключении дополнительных устройств…

Дополнительную информацию об использовании Bluetooth на устройствах Android можно найти в руководстве по Bluetooth. Изменения в работе Bluetooth, относящиеся к Android 8.0 (уровень API 26), описаны в разделе Bluetooth на странице Изменения в поведении Android 8.0.

Совместный доступ

Умный доступ

Android 8.0 (API уровня 26) запоминает, какими приложениями пользователь предпочитает делиться контентом, и предлагает их в первую очередь. Например, если пользователь сфотографирует чек, Android 8.0 может предложить приложение для учета расходов, а если сделает селфи – приложение социальной сети. Android 8.0 автоматически изучает все эти шаблоны в соответствии с персональными предпочтениями пользователей.

Умный обмен работает не только с image, но и с другими типами контента, например audio, video, text, URL и т. д.

Чтобы включить умную отправку, добавьте в намерение, которое отправляет контент, ArrayList, содержащий до трех строковых аннотаций. Аннотации должны описывать основные компоненты или темы контента. В примере кода ниже показано, как добавить аннотации к намерению.

Kotlin

val annotations: ArrayList<String> = arrayListOf(
        "topic1",
        "topic2",
        "topic3"
)

intent.putStringArrayListExtra(
        Intent.EXTRA_CONTENT_ANNOTATIONS,
        annotations
)

Java

ArrayList<String> annotations = new ArrayList<>();

annotations.add("topic1");
annotations.add("topic2");
annotations.add("topic3");

intent.putStringArrayListExtra(
    Intent.EXTRA_CONTENT_ANNOTATIONS,
    annotations
);

Подробную информацию об аннотациях умного обмена можно найти в статье EXTRA_CONTENT_ANNOTATIONS.

Классификатор текста

На совместимых устройствах приложения могут использовать новый классификатор текста, чтобы проверять, соответствует ли строка известному типу объекта классификатора, и получать предлагаемые альтернативные варианты выбора. Система распознает адреса, URL, номера телефонов и адреса электронной почты. Дополнительную информацию можно найти по адресу TextClassifier.

Специальные возможности

В Android 8.0 (уровень API 26) поддерживается несколько новых специальных возможностей для разработчиков, которые создают собственные сервисы специальных возможностей:

Подробнее о том, как сделать приложение более доступным, см. Специальные возможности.

Безопасность и конфиденциальность

Разрешения

В Android 8.0 (уровень API 26) появилось несколько новых разрешений, связанных с телефонией:

  • Разрешение ANSWER_PHONE_CALLS позволяет приложению отвечать на входящие звонки программно. Чтобы обработать входящий вызов в приложении, используйте метод acceptRingingCall().
  • Разрешение READ_PHONE_NUMBERS предоставляет приложению доступ к телефонным номерам, сохраненным на устройстве.

Оба разрешения классифицируются как опасные и входят в группу разрешений PHONE.

Новые API для доступа к аккаунту и обнаружения

В Android 8.0 (уровень API 26) улучшен доступ приложений к аккаунтам пользователей. Для управляемых аккаунтов аутентификаторы могут использовать собственные правила, чтобы решать, скрывать ли аккаунты от приложения или показывать их ему. Система Android отслеживает приложения, у которых есть доступ к определенному аккаунту.

В предыдущих версиях Android приложениям, которые отслеживали список аккаунтов пользователя, приходилось получать обновления обо всех аккаунтах, включая аккаунты несвязанных типов. В Android 8.0 добавлен метод addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]), который позволяет приложениям указывать список типов аккаунтов, для которых должны приниматься изменения.

Изменения в API

В AccountManager добавлено шесть новых методов, которые помогают аутентификаторам управлять тем, какие приложения могут видеть аккаунт:

В Android 8.0 (уровень API 26) появились два специальных значения названия пакета, которые позволяют задавать уровни видимости для приложений, не настроенных с помощью метода setAccountVisibility(android.accounts.Account, java.lang.String, int). Значение видимости PACKAGE_NAME_KEY_LEGACY_VISIBLE применяется к приложениям, у которых есть разрешение GET_ACCOUNTS и которые предназначены для версий Android ниже 8.0, или к приложениям, чьи подписи соответствуют аутентификатору, предназначенному для любой версии Android. PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE – значение видимости по умолчанию для приложений, для которых оно не было задано ранее и к которым не применяется PACKAGE_NAME_KEY_LEGACY_VISIBLE.

Дополнительную информацию о новых API для доступа к аккаунту и обнаружения можно найти в справочных материалах по AccountManager и OnAccountsUpdateListener.

Тестирование

Инструментальное тестирование

В Android 8.0 (уровень API 26) предусмотрена дополнительная поддержка инструментальных тестов.

Запуск для процессов приложений, не используемых по умолчанию

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

Чтобы определить нестандартные инструменты процесса, перейдите к файлу манифеста, а затем к нужному элементу <instrumentation>. Добавьте атрибут android:targetProcess и задайте для него одно из следующих значений:

  • Название определенного процесса.
  • Список названий процессов, разделенных запятыми.
  • Подстановочный знак ("*"), который позволяет запускать инструментарий для любого запущенного процесса, выполняющего код в пакете, указанном в атрибуте android:targetPackage.

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

Как посмотреть результаты во время тестирования

Теперь вы можете получать результаты во время выполнения инструментального теста, а не после него, вызвав addResults().

Имитация намерений для тестирования

Чтобы упростить создание изолированных независимых тестов пользовательского интерфейса для действий приложения, в Android 8.0 (уровень API 26) добавлен метод onStartActivity(). Вы переопределяете этот метод в пользовательском подклассе класса Instrumentation.ActivityMonitor, чтобы обрабатывать определенное намерение, которое вызывает ваш тестовый класс.

Когда тестовый класс вызывает намерение, метод возвращает объект-заглушку Instrumentation.ActivityResult вместо выполнения самого намерения. Используя эту логику макета намерения в своих тестах, вы можете сосредоточиться на том, как ваше действие подготавливает и обрабатывает намерение, которое вы передаете другому действию или совершенно другому приложению.

Среда выполнения и инструменты

Оптимизация платформы

В Android 8.0 (уровень API 26) оптимизирована среда выполнения и другие компоненты платформы, что позволило повысить производительность. В частности, в ней реализована сборка мусора с параллельным уплотнением, более эффективное использование памяти и локальность кода.

Это позволяет ус��ор��ть ��а��ру��ку �� ��овысить производительность как ОС, так и приложений.

Обновленная поддержка языка Java

В Android 8.0 (уровень API 26) добавлена поддержка нескольких дополнительных API OpenJDK Java:

Подробную информацию о классах и методах в этих новых пакетах можно найти в справочной документации по API.

Если вы хотите использовать функции языка Java 8 в Android Studio, скачайте последнюю предварительную версию.

Обновленные API ICU4J Android Framework

В Android 8.0 (уровень API 26) расширены API ICU4J Android Framework, которые представляют собой подмножество API ICU4J. Разработчики приложений могут использовать их в пакете android.icu. Эти API используют данные локализации, хранящиеся на устройстве, поэтому вы можете уменьшить размер APK-файла, не компилируя в него библиотеки ICU4J.

Таблица 1. Версии ICU, CLDR и Unicode, используемые в Android.

Уровень Android API Версия ICU Версия CLDR Версия Unicode
Android 7.0 (уровень API 24), Android 7.1 (уровень API 25) 56 28 8.0
Android 8.0 (API уровня 26) 58,2 30.0.3 9.0

Дополнительную информацию об интернационализации в Android, включая поддержку ICU4J, можно найти в статье Интернационализация в Android.

Android Enterprise

Для устройств с Android 8.0 (уровень API 26) были добавлены новые корпоративные функции и API. Вот основные преимущества:

  • Рабочие профили на полностью управляемых устройствах позволяют компаниям разделять рабочие и личные данные, управляя и теми, и другими.
  • Делегирование API позволяет владельцам устройств и профилей назначать управление приложениями другим приложениям.
  • Улучшения в процессе инициализации (включая новые параметры настройки) сокращают время настройки.
  • Новые элементы управления Bluetooth, Wi-Fi, резервным копированием и безопасностью позволяют предприятиям управлять большим количеством устройств. Журнал сетевой активности помогает компаниям выявлять проблемы.

Чтобы узнать больше об этих и других новых API и функциях Android Enterprise, ознакомьтесь со статьей Android в корпоративной среде.