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

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

Android Oreo (версия Go)

Android Go – это инициатива, направленная на оптимизацию Android для миллиардов людей, которые впервые выходят в интернет. Начиная с Android 8.1, мы делаем Android отличной платформой для устройств начального уровня. В конфигурации Android Oreo (версия Go) доступны следующие функции:

  • Оптимизация памяти. Улучшено использование памяти на платформе, чтобы приложения могли эффективно работать на устройствах с ОЗУ объемом 1 ГБ или меньше.
  • Гибкие настройки таргетинга. Новые константы аппаратных функций, позволяющие настраивать распространение приложений через Google Play на устройства с обычным или небольшим объемом ОЗУ.
  • Google Play. Все приложения будут доступны на устройствах с Android Oreo (версия Go), но в Google Play будут показываться только те, которые оптимизированы разработчиками в соответствии с рекомендациями по созданию приложений для миллиардов пользователей.

Мы обновили рекомендации по созданию приложений для миллиардов пользователей, добавив в них информацию о том, как оптимизировать приложение для устройств с Android Oreo (версия Go). Большинству разработчиков лучше всего оптимизировать существующий APK-файл или использовать функцию нескольких APK Google Play, чтобы создать версию APK, предназначенную для устройств с небольшим объемом ОЗУ. Помните, что более легкое и эффективное приложение будет удобнее для всех пользователей, независимо от того, какое устройство они используют.

Neural Networks API

API нейронных сетей обеспечивает ускоренное выполнение вычислений и логических выводов для фреймворков машинного обучения на устройстве, таких как TensorFlow Lite – кроссплатформенная библиотека машинного обучения от Google для мобильных устройств, а также Caffe2 и других. Скачать TensorFlow Lite и ознакомиться с документацией можно в репозитории с открытым исходным кодом. TensorFlow Lite работает с Neural Networks API, чтобы эффективно запускать на мобильном устройстве такие модели, как MobileNets, Inception v3 и Smart Reply.

Обновления фреймворка автозаполнения

В Android 8.1 (уровень API 27) реализованы улучшения фреймворка автозаполнения, которые можно использовать в своих приложениях.

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

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

В Android 8.1 сервисы автозаполнения получили больше возможностей для настройки интерфейса сохранения данных благодаря поддержке CustomDescription and Validator в SaveInfo.

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

ValidatorОбъекты используются, чтобы не показывать интерфейс сохранения автозаполнения, когда условие валидатора не выполняется. Подробнее о классе Validator и его подклассах LuhnChecksumValidator и RegexValidator…

Уведомления

В Android 8.1 изменены уведомления.

  • Теперь приложения могут воспроизводить звуковые сигналы уведомлений не чаще одного раза в секунду. Звуки оповещений, которые превышают эту скорость, не ставятся в очередь и теряются. Это изменение не повлияет на другие аспекты работы уведомлений, и они будут по-прежнему отправляться.
  • NotificationListenerService и ConditionProviderService не поддерживаются на устройствах Android с малым объемом ОЗУ, которые возвращают true при вызове ActivityManager.isLowRamDevice().

Обновление EditText

Начиная с уровня API 27 метод EditText.getText() возвращает Editable. Ранее он возвращал CharSequence. Это изменение обратно совместимо, поскольку Editable реализует CharSequence.

Интерфейс Editable предоставляет дополнительные полезные функции. Например, поскольку Editable также реализует интерфейс Spannable, вы можете применить разметку к контенту в экземпляре EditText.

Действия Безопасного просмотра, выполняемые автоматически

Используя реализацию WebView API безопасного просмотра, ваше приложение может определять, когда экземпляр WebView пытается перейти на URL, который Google классифицировал как известную угрозу. По умолчанию WebView показывает межстраничное объявление с предупреждением о известной угрозе. На этом экране пользователь может выбрать, загружать ли URL или вернуться на безопасную предыдущую страницу.

В Android 8.1 можно программно определить, как приложение должно реагировать на известную угрозу:

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

Примечание. Чтобы обеспечить оптимальную защиту от известных угроз, инициализируйте Безопасный просмотр, прежде чем вызывать метод loadUrl() объекта WebView.

В приведенных ниже фрагментах кода показано, как настроить экземпляры WebView в приложении так, чтобы они всегда возвращались в безопасное состояние после обнаружения известной угрозы:

AndroidManifest.xml

<manifest>
    <application>
        ...
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="true" />
    </application>
</manifest>

MyWebActivity.java

Kotlin

private var superSafeWebView: WebView? = null
private var safeBrowsingIsInitialized: Boolean = false

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    superSafeWebView = WebView(this).apply {
        webViewClient = MyWebViewClient()
        safeBrowsingIsInitialized = false
        startSafeBrowsing(this@SafeBrowsingActivity, { success ->
            safeBrowsingIsInitialized = true
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!")
            }
        })
    }
}

Java

private WebView superSafeWebView;
private boolean safeBrowsingIsInitialized;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    superSafeWebView = new WebView(this);
    superSafeWebView.setWebViewClient(new MyWebViewClient());
    safeBrowsingIsInitialized = false;

    superSafeWebView.startSafeBrowsing(this, new ValueCallback<Boolean>() {
        @Override
        public void onReceiveValue(Boolean success) {
            safeBrowsingIsInitialized = true;
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
            }
        }
    });
}

MyWebViewClient.java

Kotlin

class MyWebViewClient : WebViewClient() {
    // Automatically go "back to safety" when attempting to load a website that
    // Safe Browsing has identified as a known threat. An instance of WebView
    // calls this method only after Safe Browsing is initialized, so there's no
    // conditional logic needed here.
    override fun onSafeBrowsingHit(
            view: WebView,
            request: WebResourceRequest,
            threatType: Int,
            callback: SafeBrowsingResponse
    ) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        callback.backToSafety(true)
        Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show()
    }
}

Java

public class MyWebViewClient extends WebViewClient {
    // Automatically go "back to safety" when attempting to load a website that
    // Safe Browsing has identified as a known threat. An instance of WebView
    // calls this method only after Safe Browsing is initialized, so there's no
    // conditional logic needed here.
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
            int threatType, SafeBrowsingResponse callback) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        callback.backToSafety(true);
        Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                Toast.LENGTH_LONG).show();
    }
}

Извлечение значков видео

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

Мы рекомендуем использовать этот метод вместо getFrameAtTime(), который может привести к неэффективному использованию памяти, поскольку возвращает битовую карту с тем же разрешением, что и исходное видео. Например, кадр из видео в формате 4K будет представлять собой растровое изображение размером 16 МБ, что намного больше, чем нужно для значка.

Shared Memory API

В Android 8.1 (уровень API 27) появился новый API SharedMemory. Этот класс позволяет создавать, сопоставлять и управлять анонимным экземпляром SharedMemory. Вы задаете защиту памяти для объекта SharedMemory для чтения и/или записи, и, поскольку объект SharedMemory является Parcelable, вы можете легко передать его другому процессу через AIDL.

API SharedMemory взаимодействует с функцией ASharedMemory в NDK. ASharedMemory предоставляет доступ к дескриптору файла, который затем можно сопоставить с операциями чтения и записи. Это отличный способ передавать большие объемы данных между приложениями или между несколькими процессами в одном приложении.

WallpaperColors API

В Android 8.1 (уровень API 27) живые обои могут передавать информацию о цвете в системный интерфейс. Для этого создайте объект WallpaperColors на основе битового изображения, объекта Drawable или трех выбранных вручную цветов. Вы также можете получить информацию о цвете.

Чтобы создать объект WallpaperColors, выполните одно из следующих действий:

  • Чтобы создать объект WallpaperColors, используя три цвета, создайте экземпляр класса WallpaperColors, передав основной, дополнительный и третичный цвета. Основной цвет не может быть нулевым.
  • Чтобы создать объект WallpaperColors из битовой карты, вызовите метод fromBitmap(), передав источник битовой карты в качестве параметра.
  • Чтобы создать объект WallpaperColors на основе объекта drawable, вызовите метод fromDrawable(), передав источник drawable в качестве параметра.

Чтобы получить сведения об основном, дополнительном или третьем цвете обоев, вызовите следующие методы:

  • getPrimaryColor() возвращает цвет, который лучше всего представляет обои.
  • getSecondaryColor() возвращает второй по значимости цвет обоев.
  • Метод getTertiaryColor() возвращает третий по значимости цвет обоев.

Чтобы уведомить систему о значительных изменениях цвета в живых обоях, вызовите метод notifyColorsChanged(). Этот метод запускает событие жизненного цикла onComputeColors(), в котором вы можете предоставить новый объект WallpaperColors.

Чтобы добавить прослушиватель изменений цвета, вызовите метод addOnColorsChangedListener(). Вы также можете вызвать метод getWallpaperColors(), чтобы получить основные цвета обоев.

Обновления отпечатков пальцев

В класс FingerprintManager добавлены следующие коды ошибок:

  • FINGERPRINT_ERROR_LOCKOUT_PERMANENT – пользователь слишком много раз пытался разблокировать устройство с помощью сканера отпечатков пальцев.
  • FINGERPRINT_ERROR_VENDOR – произошла ошибка сканера отпечатков пальцев, связанная с определенным поставщиком.

Обновления криптографии

В Android 8.1 внесены следующие изменения в криптографии:

  • В Conscrypt реализованы новые алгоритмы. Реализация Conscrypt используется вместо существующей реализации Bouncy Castle. Новые алгоритмы:
    • AlgorithmParameters:GCM
    • KeyGenerator:AES
    • KeyGenerator:DESEDE
    • KeyGenerator:HMACMD5
    • KeyGenerator:HMACSHA1
    • KeyGenerator:HMACSHA224
    • KeyGenerator:HMACSHA256
    • KeyGenerator:HMACSHA384
    • KeyGenerator:HMACSHA512
    • SecretKeyFactory:DESEDE
    • Signature:NONEWITHECDSA
  • Cipher.getParameters().getParameterSpec(IvParameterSpec.class) больше не работает с алгоритмами, использующими GCM. Вместо него используйте getParameterSpec(GCMParameterSpec.class).
  • Многие внутренние классы Conscrypt, связанные с TLS, были реорганизованы. Поскольку разработчики иногда получают доступ к этим полям с помощью рефлексии, мы оставили заглушки для поддержки предыдущего использования, но некоторые детали изменились. Например, раньше розетки относились к типу OpenSSLSocketImpl, а теперь – к типу ConscryptFileDescriptorSocket или ConscryptEngineSocket, которые являются расширениями типа OpenSSLSocketImpl.
  • SSLSessionметоды, которые вызывали исключение IllegalArgumentException при передаче нулевой ссылки, теперь вызывают исключение NullPointerException.
  • В RSA KeyFactory больше нельзя создавать ключи из байтовых массивов, размер которых превышает размер закодированного ключа. Вызовы функций generatePrivate() и generatePublic(), которые предоставляют KeySpec, где структура ключа не заполняет весь буфер, приведут к ошибке InvalidKeySpecException.
  • Если чтение сокета прерывается из-за его закрытия, Conscrypt возвращает значение -1. При чтении возникает ошибка SocketException.
  • Набор корневых сертификатов ЦС был изменен. В основном мы удалили большое количество устаревших сертификатов, а также корневые сертификаты для WoSign и StartCom. Подробнее об этом решении можно прочитать в блоге Google по вопросам безопасности.