Android 8.1 の機能と API

Android 8.1(API レベル 27)では、ユーザーとデベロッパー向けのさまざまな新機能が導入されています。このドキュメントでは、デベロッパー向けの新機能について説明します。

Android Oreo(Go バージョン)

Android Go は、世界中でインターネットを利用する何十億人ものユーザーの Android エクスペリエンスを最適化する取り組みです。Android 8.1 以降、Android はエントリレベルのデバイスに適したプラットフォームとなっています。Android Oreo(Go バージョン)構成の機能は次のとおりです。

  • メモリの最適化。プラットフォーム全体のメモリ使用量を改善し、RAM が 1 GB 以下のデバイスでアプリを効率的に実行できるようにしました。
  • 柔軟なターゲット設定オプション。新しいハードウェア機能定数を使用すると、Google Play を通じて通常のデバイスまたは低 RAM デバイスにアプリを配布できます。
  • Google Play。すべてのアプリは Android Oreo(Go バージョン)を搭載したデバイスで利用できますが、Google Play では、何十億人ものユーザーに受け入れられるアプリの作成に関する ガイドラインに沿って、デベロッパーが特に最適化したアプリを公開します。

何十億人ものユーザー向けにビルドに関する ガイドラインを更新し、 Android Oreo(Go バージョン)デバイス向けにアプリを最適化する方法に関するガイダンスを追加しました。ほとんどのデベロッパーにとって、Android Oreo(Go バージョン)デバイスに備えるには、既存の APK を最適化するか、Google Play の 複数 APK 機能を使用して、APK の特定のバージョンを低 RAM デバイスをターゲットにすることをおすすめします。アプリの 軽量化と効率化は、デバイスに関係なく、すべてのユーザーにとってメリットとなることを忘れないでください。

ニューラル ネットワーク API

Neural Networks API は、TensorFlow Lite(Google のモバイル用クロス プラットフォーム ML ライブラリ)や Caffe2 などのデバイス上の機械学習フレームワークの計算と推論を高速化します。ダウンロードとドキュメントについては、TensorFlow Lite オープンソース リポジトリにアクセスしてください。TensorFlow Lite は Neural Networks API と連携して、モバイル デバイスで MobileNetsInception v3 スマート リプライなどのモデルを効率的に実行します。

自動入力フレームワークの更新

Android 8.1(API レベル 27)では、アプリに組み込むことができる自動入力フレームワークが改善されています。

BaseAdapter クラスに setAutofillOptions() メソッドが追加されました。これにより、アダプター内の値の文字列表現を提供できます。これは、アダプター内で値を動的に生成するスピナー コントロールで役立ちます。たとえば、setAutofillOptions() メソッドを使用して、ユーザーがクレジット カードの有効期限の一部として選択できる年リストの文字列表現を提供できます。自動入力サービスは、文字列表現を使用して、データを必要とするビューを適切に入力できます。

さらに、AutofillManager クラスには、仮想構造内のビューの表示に関する変更についてフレームワークに通知するために呼び出すことができる notifyViewVisibilityChanged(View, int, boolean) メソッドが含まれています。また、非仮想構造用のメソッドのオーバーロードもあります。ただし、非仮想構造の場合、このメソッドは通常、View クラスによってすでに呼び出されているため、フレームワークに明示的に通知する必要はありません。

また、Android 8.1 では、SaveInfo 内に CustomDescription and Validator のサポートを追加することで、自動入力サービスが保存 UI のアフォーダンスをカスタマイズできるようにしています。

カスタムの説明は、自動入力サービスが何を保存するかを明確にするのに役立ちます。たとえば、画面にクレジット カードが含まれている場合は、クレジット カード銀行のロゴ、クレジット カード番号の下 4 桁、有効期限番号を表示できます。詳細については、 CustomDescription クラスをご覧ください。

Validator オブジェクトは、Validator 条件が満たされていない場合に自動入力保存 UI が表示されないようにするために使用されます。詳しくは、 Validator クラスとそのサブクラス( LuhnChecksumValidator および RegexValidator)をご覧ください。

通知

Android 8.1 では、通知が次のように変更されています。

  • アプリでは、通知アラートを 1 秒に 1 回だけ音を鳴らすことができるようになりました。このレートを超えるアラート音はキューに追加されず、失われます。通知の動作の他の側面には影響せず、通知メッセージは引き続き想定どおりに送信されます。
  • NotificationListenerServiceConditionProviderService は、ActivityManager.isLowRamDevice() が呼び出されたときに true を返す低 RAM の Android 搭載デバイスではサポートされていません。

EditText の更新

API レベル 27 以降では、EditText.getText() メソッドは Editable を返します。以前は CharSequence を返していました。EditableCharSequence を実装するため、この変更には下位互換性があります。

Editable インターフェースには有用な追加機能が用意されています。たとえば、EditableSpannable インターフェースも実装しているため、EditText のインスタンス内のコンテンツにマークアップを適用できます。

プログラマティックなセーフ ブラウジング アクション

Safe Browsing API の WebView 実装を使用すると、Google が既知の脅威として分類した URL に WebView のインスタンスが移動しようとした場合に、それをアプリで検出できます。デフォルトでは、既知の脅威についてユーザーに警告するインタースティシャルが WebView に表示されます。この画面では、このまま URL を読み込むか、安全な前のページに戻るかを選択できます。

Android 8.1 では、既知の脅威に対するアプリの対応方法をプログラムで定義できます。

  • アプリからセーフ ブラウジングに既知の脅威を報告するかどうかは、ユーザーが管理できます。
  • セーフ ブラウジングで既知の脅威に分類された URL に遭遇するたびに、安全なページに戻るなどの特定のアクションをアプリに自動的に実行させることができます。

注: 既知の脅威に対する保護を最適化するには、セーフ ブラウジングを初期化してから WebView オブジェクトの loadUrl() メソッドを呼び出してください。

次のコード スニペットは、既知の脅威に遭遇した後に常に安全な状態に戻るようにアプリの 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 MB のビットマップで、サムネイル画像に必要なサイズよりもはるかに大きくなります。

SharedMemory API

Android 8.1(API レベル 27)では、新しい SharedMemory API が導入されています。このクラスを使用すると、匿名の SharedMemory インスタンスを作成、マッピング、管理できます。読み取りと書き込みの SharedMemory オブジェクトにメモリ保護を設定できます。また、SharedMemory オブジェクトは Parcelable であるため、AIDL を介して別のプロセスに簡単に渡すことができます。

SharedMemory API は、NDK の ASharedMemory 機能と相互運用します。ASharedMemory は、読み取りと書き込みにマッピングできるファイル記述子へのアクセスを許可します。アプリ間や単一アプリ内の複数のプロセス間で大量のデータを共有する場合に適しています。

WallpaperColors API

Android 8.1(API レベル 27)では、ライブ壁紙からシステム UI に色情報を提供できます。そのためには、ビットマップやドローアブルから WallpaperColors オブジェクトを作成するか、手動で選択した 3 つの色を使用します。この色の情報も取得できます。

WallpaperColors オブジェクトを作成するには、次のいずれかを行います。

  • 3 色を使用して WallpaperColors オブジェクトを作成するには、プライマリ カラー、セカンダリ カラー、ターシャリ カラーを渡して、WallpaperColors クラスのインスタンスを作成します。プライマリ カラーを null にすることはできません。
  • ビットマップから WallpaperColors オブジェクトを作成するには、ビットマップ ソースをパラメータとして渡して fromBitmap() メソッドを呼び出します。
  • ドローアブルから WallpaperColors オブジェクトを作成するには、ドローアブル ソースをパラメータとして渡して fromDrawable() メソッドを呼び出します。

壁紙からプライマリ カラー、セカンダリ カラー、ターシャリ カラーの詳細を取得するには、次のメソッドを呼び出します。

  • getPrimaryColor() は、壁紙の中で最も視覚的に表現できる色を返します。
  • getSecondaryColor() は、壁紙の中で 2 番目に目立つ色を返します。
  • getTertiaryColor() メソッドは、壁紙の中で 3 番目に目立つ色を返します。

ライブ壁紙の色の大幅な変化についてシステムに通知するには、notifyColorsChanged() メソッドを呼び出します。このメソッドは、新しい WallpaperColors オブジェクトを提供できる onComputeColors() ライフサイクル イベントをトリガーします。

色の変化に対するリスナーを追加するには、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) を使用してください。
  • TLS に関連付けられている多くの Conscrypt 内部クラスがリファクタリングされました。デベロッパーがリフレクティブにアクセスする場合があるため、以前の使用をサポートするために shim が残されていますが、詳細の一部は変更されています。たとえば、以前は OpenSSLSocketImpl 型でしたが、現在は ConscryptFileDescriptorSocket 型または ConscryptEngineSocket 型になりました。どちらも OpenSSLSocketImpl を拡張します。
  • null 参照が渡されたときに IllegalArgumentException をスローするために使用されていた SSLSession メソッドが、NullPointerException をスローするようになりました。
  • RSA KeyFactory では、エンコードされた鍵より大きいバイト配列から鍵を生成できなくなりました。鍵構造がバッファ全体を満たさない KeySpec を提供する generatePrivate()generatePublic() を呼び出すと、InvalidKeySpecException になります。
  • ソケットが閉じられることでソケットの読み取りが中断された場合、Conscrypt は読み取りから -1 を返すために使用されます。読み取りは SocketException をスローするようになりました。
  • ルート CA 証明書のセットが変更されました。多くの古い証明書が削除されましたが、WoSign と StartCom のルート証明書も削除されました。この決定について詳しくは、Google セキュリティ ブログの WoSign 証明書と StartCom 証明書の信頼の最終削除をご覧ください。