Функции и API Android 8.1

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

Android Oreo (версия Go)

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

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

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

API нейронных сетей

API нейронных сетей обеспечивает ускоренные вычисления и выводы для инфраструктур машинного обучения на устройствах, таких как TensorFlow Lite — кроссплатформенная библиотека машинного обучения Google для мобильных устройств, а также Caffe2 и других. Посетите репозиторий с открытым исходным кодом TensorFlow Lite для загрузки и документации. TensorFlow Lite работает с 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

Котлин

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!")
            }
        })
    }
}

Джава

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

Котлин

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()
    }
}

Джава

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 МБ, что намного больше, чем вам нужно для миниатюрного изображения.

API общей памяти

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

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

API цветов обоев

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

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

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

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

  • 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 .
  • Набор корневых сертификатов CA был изменен, в основном удалено большое количество устаревших сертификатов, а также удалены корневые сертификаты для WoSign и StartCom. Дополнительную информацию об этом решении можно найти в публикации в блоге безопасности Google « Окончательное удаление доверия к сертификатам WoSign и StartCom» .