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 デバイスまたは低 RAM デバイスに設定できる新しいハードウェア機能定数。
  • Google Play。Android Oreo(Go エディション)を搭載したデバイスではすべてのアプリを利用できますが、Google Play では、数十億人向けのビルドの ガイドラインに沿って、数十億人のユーザーに優れたエクスペリエンスを提供するためにデベロッパーが特別に最適化したアプリが優先的に表示されます。

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

Neural Networks API

Neural Networks API は、TensorFlow Lite(モバイル向けの Google のクロス プラットフォーム ML ライブラリ)などのオンデバイスの機械学習フレームワークや、Caffe2 などの高速化された計算と推論を提供します。ダウンロードとドキュメントについては、TensorFlow Lite のオープンソース リポジトリをご覧ください。TensorFlow Lite は Neural Networks API と連携して、MobileNets、Inception 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 回のみになりました。このレートを超えるアラート音はキューに登録されず、失われます。この変更は、通知の動作の他の側面には影響しません。通知メッセージは引き続き期待どおりに投稿されます。
  • ActivityManager.isLowRamDevice() が呼び出されたときに true を返す低 RAM の Android 搭載デバイスでは、NotificationListenerService と ConditionProviderService はサポートされていません。

EditText の更新

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

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

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

Safe Browsing API の WebView 実装を使用すると、アプリは WebView のインスタンスが Google によって既知の脅威に分類された URL に移動しようとしたときに検出できます。デフォルトでは、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() メソッドを呼び出します。

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

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