Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

Android 8.1 の機能と API

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

Android Oreo(Go バージョン)

Android Go は、世界中からオンラインに接続している何十億という人々の Android 体験を最適化する取り組みです。Android 8.1 以降の Android は、エントリレベルのデバイスにとってすばらしいプラットフォームになります。Android Oreo(Go バージョン)には以下の機能が搭載されています。

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

何十億人ものユーザーに受け入れられるアプリを構築するためのガイドラインも改訂されており、Android Oreo(Go バージョン)デバイス向けにアプリを最適化する方法についての説明が追加されています。ほとんどの場合は、既存の APK を最適化するか、Google Play のマルチ APK 機能を使って、APK の特定のバージョンのターゲットを低 RAM デバイスに設定することによって Android Oreo(Go エディション)デバイスに対応するとよいでしょう。アプリの軽量化と効率化は、デバイスに関係なく、すべてのユーザーにとってメリットになることを覚えておきましょう。

Neural Networks API

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

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

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 クラスと、そのサブクラスの LuhnChecksumValidatorRegexValidator をご覧ください。

通知

Android 8.1 では、通知に関する以下の変更が行われています。

  • アプリで通知アラートを鳴らすことができる回数が 1 秒に 1 回だけになりました。この回数を超えるアラート音はキューに登録されず、失われます。この変更による通知動作の他の要素への影響はありません。通知メッセージは引き続き、期待どおりに表示されます。
  • ActivityManager.isLowRamDevice() が呼び出されたときに true を返す RAM の少ない Android デバイスにおいて、NotificationListenerServiceConditionProviderService がサポートされなくなりました。

EditText の更新

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

Editable インターフェースには有用な機能が追加されています。たとえば、Editable には Spannable インターフェースも実装されているため、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() は元の動画と同じ解像度のビットマップを返すため、メモリを浪費する可能性があることから、getScaledFrameAtTime() を使用することをおすすめします。たとえば、4K 動画のフレームのビットマップは 16 MB です。これは、サムネイル画像に必要な解像度をはるかに上回ります。

SharedMemory API

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

SharedMemory API は NDK の ASharedMemory ファシリティと相互運用されます。ASharedMemory を使用すると、読み取りと書き込みにマッピング可能なファイル記述子にアクセスできます。この方法は、アプリ間で、または 1 つのアプリ内の複数のプロセス間で、大量のデータを共有するのに適しています。

WallpaperColors API

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

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

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

壁紙から第 1、第 2、第 3 の色の詳細を取得するには、以下のメソッドを呼び出します。

ライブ壁紙における重要な色の変化をシステムに通知するには、notifyColorsChanged() メソッドを呼び出します。このメソッドは onComputeColors() ライフサイクル イベントをトリガーします。これにより、新しい WallpaperColors オブジェクトを提供する機会が得られます。

色の変化に対するリスナーを追加するには、addOnColorsChangedListener() メソッドを呼び出します。また、getWallpaperColors() メソッドを呼び出して、壁紙の第 1 の色を取得することもできます。

フィンガープリントの更新

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
  • GCM を使用するアルゴリズムで Cipher.getParameters().getParameterSpec(IvParameterSpec.class) を使用できなくなりました。代わりに、getParameterSpec(GCMParameterSpec.class) を使用してください。
  • TLS に関連付けられている多くの Conscrypt 内部クラスがリファクタリングされました。デベロッパーが反射的にこれらのクラスを使用することがあるため、以前の用法をサポートするために shim が残されていますが、詳細が一部変更されています。たとえば、ソケットのタイプは以前は OpenSSLSocketImpl でしたが、現在は、ConscryptFileDescriptorSocket または ConscryptEngineSocket になっています(どちらも OpenSSLSocketImpl を拡張したものです)。
  • SSLSession メソッドは、null 参照が渡されると IllegalArgumentException をスローしていましたが、現在は NullPointerException をスローします。
  • RSA KeyFactory では、エンコードされた鍵よりもサイズの大きいバイト配列から鍵を生成することができなくなりました。鍵構造がバッファ全体を満たさない KeySpec を提供する generatePrivate()generatePublic() を呼び出すと、InvalidKeySpecException が発生します。
  • 閉じているソケットによってソケットの読み取りが中断された場合、Conscrypt は読み取りから -1 を返していました。現在は、読み取りから SocketException がスローされます。
  • ルート CA 証明書のセットが変更され、古い証明書の多くが削除されました。さらに、WoSign と StartCom のルート証明書も削除されています。この決定について詳しくは、Google セキュリティ ブログの WoSign および StartCom が発行した証明書の完全無効化に関する投稿(英語)をご覧ください。