Android 4.3 API

API レベル: 18

Android 4.3(JELLY_BEAN_MR2)は Jelly Bean リリースのアップデートであり、ユーザーとアプリ デベロッパー向けに新機能を提供します。このドキュメントでは、特に注目すべき新しい API を紹介します。

アプリ デベロッパーは、Android 4.3 のシステム イメージと SDK プラットフォームを、できるだけ早く SDK Manager からダウンロードする必要があります。アプリをテストするために Android 4.3 を搭載したデバイスがない場合は、Android 4.3 システム イメージを使用して、Android Emulator でアプリをテストします。次に、Android 4.3 プラットフォーム向けにアプリをビルドして、最新の API の使用を開始します。

対象 API レベルを更新する

Android 4.3 搭載デバイス向けにアプリを最適化するには、targetSdkVersion"18" に設定し、Android 4.3 システム イメージにインストールしてテストし、この変更を含むアップデートを公開します。

Android 4.3 で API を使用しながら古いバージョンもサポートするには、minSdkVersion でサポートされていない API を実行する前に、システム API レベルをチェックする条件をコードに追加します。下位互換性の維持については、異なるプラットフォーム バージョンのサポートをご覧ください。

Android サポート ライブラリでは、古いバージョンのプラットフォームに新機能を実装するためのさまざまな API も提供されています。

API レベルの仕組みの詳細については、API レベルとはをご覧ください。

重要な動作の変更点

以前に Android 向けのアプリを公開したことがある場合は、Android 4.3 での変更によってアプリが影響を受ける可能性があることに留意してください。

アプリが暗黙的インテントを使用する場合

お客様のアプリは、制限付きプロファイル環境で正しく動作しない場合があります。

制限付きプロファイル環境のユーザーは、一部の標準的な Android アプリを使用できない場合があります。たとえば、制限付きプロファイルでウェブブラウザとカメラアプリが無効になっている場合があります。そのため、どのアプリが使用できるかについてアプリで推測しないでください。アプリが Intent を処理できるかどうかを確認せずに startActivity() を呼び出すと、制限付きプロファイルでアプリがクラッシュする可能性があります。

暗黙的インテントを使用する場合は、必ず、resolveActivity() または queryIntentActivities() を呼び出して、アプリがインテントを処理できることを確認する必要があります。次に例を示します。

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

アプリがアカウントに依存している場合

お客様のアプリは、制限付きプロファイル環境で正しく動作しない場合があります。

制限付きプロファイルの環境内のユーザーは、デフォルトではユーザー アカウントにアクセスできません。アプリが Account に依存している場合、制限付きプロファイルで使用すると、アプリがクラッシュまたは予期しない動作をする可能性があります。

アプリが機密性の高いアカウント情報に依存しているため、制限付きプロファイルでアプリが完全に使用されないようにするには、マニフェストの <application> 要素で android:requiredAccountType 属性を指定します。

制限付きプロファイルが独自のアカウントを作成できなくてもアプリを使用し続けることができるようにするには、アカウントを必要とするアプリ機能を無効にするか、プライマリ ユーザーが作成したアカウントへのアクセスを制限付きプロファイルに許可してください。詳しくは、以下の制限付きプロファイルでのサポート アカウントをご覧ください。

アプリで VideoView を使用する場合

Android 4.3 では、動画が小さく表示される場合があります。

以前のバージョンの Android では、VideoView ウィジェットでは layout_heightlayout_width"wrap_content" 値が "match_parent" と同じであると誤って計算されていました。そのため、以前に高さまたは幅に "wrap_content" を使用して目的の動画レイアウトを提供していた場合でも、Android 4.3 以降では動画のサイズが大幅に小さくなる可能性があります。この問題を解決するには、"wrap_content""match_parent" に置き換え、動画が Android 4.3 とそれ以前のバージョンで想定どおりに表示されることを確認します。

制限付きプロファイル

Android タブレットで、ユーザーはプライマリ ユーザーに基づいて制限付きプロファイルを作成できるようになりました。 ユーザーは制限付きプロファイルを作成する際に、そのプロファイルで利用できるアプリなどの制限を有効にできます。Android 4.3 の新しい API セットでは、開発するアプリに対してきめ細かい制限設定を構築することもできます。たとえば、新しい API を使用すると、制限付きプロファイルの環境で実行しているときに、アプリ内で使用できるコンテンツのタイプを制御できるようになります。

作成した制限をユーザーが制御するための UI は、システムの設定アプリによって管理されます。アプリの制限設定をユーザーに表示するには、ACTION_GET_RESTRICTION_ENTRIES インテントを受け取る BroadcastReceiver を作成して、アプリが提供する制限を宣言する必要があります。システムはこのインテントを呼び出して、利用可能な制限をすべてのアプリに照会し、プライマリ ユーザーが各制限付きプロファイルの制限を管理できるように UI を作成します。

BroadcastReceiveronReceive() メソッドで、アプリが提供する制限ごとに RestrictionEntry を作成する必要があります。各 RestrictionEntry では、制限のタイトル、説明、次のいずれかのデータ型を定義します。

  • TYPE_BOOLEAN: 制限(true または false)を指定します。
  • 相互に排他的な複数の選択肢(ラジオボタンの選択肢)がある制限の場合は、TYPE_CHOICE
  • TYPE_MULTI_SELECT: 相互に排他的でない複数の選択肢(チェックボックスの選択肢)がある制限の場合は、

次に、すべての RestrictionEntry オブジェクトを ArrayList に格納し、それをブロードキャスト レシーバの結果に EXTRA_RESTRICTIONS_LIST エクストラの値として挿入します。

システムは、設定アプリにアプリの制限の UI を作成し、各制限を RestrictionEntry オブジェクトごとに指定した一意のキーで保存します。ユーザーがアプリを開いたときに、getApplicationRestrictions() を呼び出して、現在の制限を照会できます。これにより、RestrictionEntry オブジェクトで定義した各制限の Key-Value ペアを含む Bundle が返されます。

ブール値、単一選択、複数選択の値では処理できない具体的な制限を提供する場合は、ユーザーが制限を指定し、ユーザーが制限設定からそのアクティビティを開くことを許可するアクティビティを作成できます。ブロードキャスト レシーバで、結果の BundleEXTRA_RESTRICTIONS_INTENT エクストラを含めます。このエクストラでは、起動する Activity クラスを示す Intent を指定する必要があります(putParcelable() メソッドを使用して、インテントで EXTRA_RESTRICTIONS_INTENT を渡します)。プライマリ ユーザーがアクティビティに入り、カスタム制限を設定したら、EXTRA_RESTRICTIONS_LIST または EXTRA_RESTRICTIONS_BUNDLE キーを使用して、エクストラの制限値を含む結果を返す必要があります。この結果は、RestrictionEntry オブジェクトと Key-Value ペアのどちらを指定するかによって異なります。

制限付きプロファイルでサポートされるアカウント

プライマリ ユーザーに追加されたアカウントは制限付きプロファイルで使用できますが、デフォルトでは AccountManager API からアクセスできません。制限付きプロファイルで AccountManager を使用してアカウントを追加しようとすると、エラーが発生します。こうした制限があるため、次の 3 つのオプションがあります。

  • 制限付きプロフィールからオーナーのアカウントへのアクセスを許可します。

    制限付きプロファイルからアカウントにアクセスするには、android:restrictedAccountType 属性を <application> タグに追加する必要があります。

    <application ...
        android:restrictedAccountType="com.example.account.type" >
    

    注意: この属性を有効にすると、アプリは制限付きプロファイルからプライマリ ユーザーのアカウントにアクセスできるようになります。そのため、アプリに表示される情報から機密情報とみなされる個人を特定できる情報(PII)が明らかにならない場合にのみ、これを許可してください。システム設定は、アプリが制限付きプロファイルをアカウントに付与していることをプライマリ ユーザーに通知します。したがって、アプリの機能にとってアカウントへのアクセスが重要であることをユーザーに明確にする必要があります。可能であれば、プライマリ ユーザーに対する適切な制限機能を提供して、アプリで許可されるアカウント アクセス量を定義する必要もあります。

  • アカウントを変更できない場合に特定の機能を無効にします。

    アカウントを使用したいが、アプリの主要な機能にアカウントが必要ない場合は、アカウントの可用性を確認し、機能を使用できない場合は機能を無効にできます。まず、利用可能な既存のアカウントがあるかどうかを確認する必要があります。存在しない場合は、getUserRestrictions() を呼び出して新しいアカウントを作成できるかどうかをクエリし、結果の DISALLOW_MODIFY_ACCOUNTS エクストラを確認します。true の場合は、アカウントへのアクセスを必要とするアプリの機能をすべて無効にする必要があります。次に例を示します。

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    注: この場合、マニフェスト ファイルで新しい属性を宣言しないでください。

  • 個人用アカウントにアクセスできない場合はアプリを無効にする。

    アプリがアカウント内の機密性の高い個人情報に依存しているため(また、制限付きプロファイルでは新しいアカウントを追加できないため)、制限付きプロファイルではそのアプリを利用できないことが重要である場合は、android:requiredAccountType 属性を <application> タグに追加します。

    <application ...
        android:requiredAccountType="com.example.account.type" >
    

    たとえば、Gmail アプリはこの属性を使用して、制限付きプロファイルに対してアプリ自体を無効にします。これは、制限付きプロファイルではオーナーの個人用メールアドレスを使用できないためです。

  • ワイヤレスと接続

    Bluetooth Low Energy(Smart Ready)

    Android は、android.bluetooth の新しい API で Bluetooth Low Energy(LE)をサポートするようになりました。新しい API を使用すると、心拍数モニターや歩数計などの Bluetooth Low Energy の周辺機器と通信する Android アプリを構築できます。

    Bluetooth LE は、一部の Android 搭載デバイスでは利用できないハードウェア機能であるため、マニフェスト ファイルで "android.hardware.bluetooth_le"<uses-feature> 要素を宣言する必要があります。

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
    

    Android の Classic Bluetooth API を使い慣れている方は、Bluetooth LE API の使用にはいくつかの違いがあります。最も重要なことは、BluetoothAdapter の取得、接続済みデバイスのリストの取得、デバイスの状態の確認などの高レベルのオペレーションに使用する必要がある BluetoothManager クラスが追加されたことです。たとえば、BluetoothAdapter を取得する方法は以下のとおりです。

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter
    

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
    

    Bluetooth LE 周辺機器を検出するには、BluetoothAdapterstartLeScan() を呼び出して、BluetoothAdapter.LeScanCallback インターフェースの実装を渡します。Bluetooth アダプターが Bluetooth LE 周辺機器を検出すると、BluetoothAdapter.LeScanCallback の実装は onLeScan() メソッドの呼び出しを受け取ります。このメソッドは、検出されたデバイスを表す BluetoothDevice オブジェクト、デバイスの RSSI 値、デバイスのアドバタイズ レコードを含むバイト配列を提供します。

    特定の種類の周辺機器のみをスキャンする場合は、代わりに startLeScan() を呼び出し、アプリがサポートする GATT サービスを指定する UUID オブジェクトの配列を含めます。

    注: Bluetooth LE デバイスのスキャン、または、以前の API を使用したクラシック Bluetooth デバイスのスキャンのみ行うことができます。LE とクラシック Bluetooth デバイスの両方を一度にスキャンすることはできません。

    Bluetooth LE 周辺機器に接続するには、対応する BluetoothDevice オブジェクトで connectGatt() を呼び出し、BluetoothGattCallback の実装を渡します。BluetoothGattCallback の実装は、デバイスとの接続状態やその他のイベントに関するコールバックを受け取ります。メソッドが新しい状態として STATE_CONNECTED を渡すと、onConnectionStateChange() コールバック中にデバイスとの通信を開始できます。

    デバイスで Bluetooth 機能にアクセスするには、アプリが特定の Bluetooth ユーザー権限をリクエストすることも必要です。詳しくは、Bluetooth Low Energy API ガイドをご覧ください。

    Wi-Fi スキャン専用モード

    Android は、ユーザーの現在地を特定する際に、Wi-Fi を使用して付近のアクセス ポイントをスキャンして現在地を特定します。しかし、ユーザーはバッテリーを節約するために Wi-Fi をオフにしておくことが多いため、位置情報の精度は低下します。Android にはスキャン専用モードが追加されました。このモードではデバイスの Wi-Fi がアクセス ポイントをスキャンして位置情報を取得し、アクセス ポイントに接続することなく位置情報を取得できます。これにより、バッテリー使用量を大幅に削減できます。

    ユーザーの位置情報を取得する必要があるが、現在 Wi-Fi がオフになっている場合は、アクション ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE を使用して startActivity() を呼び出すことで、ユーザーに Wi-Fi スキャン専用モードを有効にするようリクエストできます。

    Wi-Fi 設定

    新しい WifiEnterpriseConfig API を使用すると、エンタープライズ向けサービスで管理対象デバイスの Wi-Fi 構成を自動化できます。

    着信へのすばやい対応

    Android 4.0 以降では、「クイック レスポンス」という機能により、電話に出たりデバイスのロックを解除したりしなくても、着信に応答してすぐにテキスト メッセージで応答できます。これまでは、これらのクイック メッセージは常にデフォルトのメッセージ アプリで処理されていました。今後は、ACTION_RESPOND_VIA_MESSAGE のインテント フィルタで Service を作成することで、どのアプリでもメッセージを処理する機能を宣言できます。

    ユーザーが着信にクイック レスポンスで応答すると、電話アプリは ACTION_RESPOND_VIA_MESSAGE インテントに、受信者(発信者)を表す URI と、ユーザーが送信したいメッセージを含む EXTRA_TEXT エクストラを送信します。サービスはインテントを受け取ると、メッセージを配信し、すぐに自身を停止する必要があります(アプリにアクティビティを表示することはできません)。

    このインテントを受け取るには、SEND_RESPOND_VIA_MESSAGE 権限を宣言する必要があります。

    マルチメディア

    MediaExtractor と MediaCodec の強化

    Android では、MediaCodecMediaExtractor の既存の API を使用して、ISO/IEC 23009-1 規格に従い、独自の Dynamic Adaptive Streaming over HTTP(DASH)プレーヤーを簡単に記述できるようになりました。これらの API の基盤となるフレームワークは、断片化された MP4 ファイルの解析をサポートするように更新されましたが、MPD メタデータを解析し、個々のストリームを MediaExtractor に渡すことについてはアプリが引き続き行う必要があります。

    暗号化されたコンテンツで DASH を使用する場合、getSampleCryptoInfo() メソッドは、暗号化された各メディア サンプルの構造を記述した MediaCodec.CryptoInfo メタデータを返します。また、getPsshInfo() メソッドが MediaExtractor に追加され、DASH メディアの PSSH メタデータにアクセスできるようになりました。このメソッドは、UUID オブジェクトのバイトへのマップを返します。UUID は暗号方式を指定し、バイトはその方式に固有のデータです。

    メディア DRM

    新しい MediaDrm クラスは、DRM の問題をメディア再生から分離することで、メディア コンテンツでのデジタル著作権管理(DRM)のモジュラー ソリューションを提供します。たとえば、この API の分離により、Widevine メディア形式を使用することなく、Widevine で暗号化されたコンテンツを再生できます。この DRM ソリューションは DASH 共通暗号化もサポートしているため、ストリーミング コンテンツでさまざまな DRM スキームを使用できます。

    MediaDrm を使用すると、ライセンスの取得とプロビジョニングのために、不透明なキー リクエスト メッセージを取得し、サーバーからキーレスポンス メッセージを処理できます。アプリ側ではサーバーとのネットワーク通信を処理します。MediaDrm クラスは、メッセージを生成して処理する機能のみを提供します。

    MediaDrm API は、Android 4.1(API レベル 16)で導入された MediaCodec API と組み合わせて使用することを意図しています。これには、コンテンツのエンコードとデコードに使用する MediaCodec、暗号化されたコンテンツを処理するための MediaCrypto、コンテンツの抽出とデマルチプレクスを行うための MediaExtractor が含まれます。

    まず、MediaExtractor オブジェクトと MediaCodec オブジェクトを作成する必要があります。次に、DRM スキームを識別する UUID に(通常はコンテンツ内のメタデータから)アクセスし、それを使用して MediaDrm オブジェクトのインスタンスをコンストラクタとともに構築します。

    Surface からの動画のエンコード

    Android 4.1(API レベル 16)では、メディア コンテンツの低レベルのエンコードとデコード用に MediaCodec クラスが追加されました。Android 4.1 では、動画をエンコードする際、メディアに ByteBuffer 配列を提供することが必要でしたが、Android 4.3 では、エンコーダへの入力として Surface を使用できるようになりました。たとえば、既存の動画ファイルからの入力をエンコードしたり、OpenGL ES から生成されたフレームを使用したりできます。

    エンコーダへの入力として Surface を使用するには、まず MediaCodecconfigure() を呼び出します。次に、createInputSurface() を呼び出して、メディアをストリーミングできる Surface を受け取ります。

    たとえば、指定された SurfaceeglCreateWindowSurface() に渡すことで、OpenGL コンテキストのウィンドウとして使用できます。次に、サーフェスのレンダリング中に、eglSwapBuffers() を呼び出してフレームを MediaCodec に渡します。

    エンコードを開始するには、MediaCodecstart() を呼び出します。終了したら、signalEndOfInputStream() を呼び出してエンコードを終了し、Surfacerelease() を呼び出します。

    メディア多重化

    新しい MediaMuxer クラスを使用すると、1 つの音声ストリームと 1 つの動画ストリームを多重化できます。これらの API は、Android 4.2 でメディアを逆多重化(demuxing)するための MediaExtractor クラスに相当するものです。

    サポートされている出力形式は MediaMuxer.OutputFormat で定義されています。現時点でサポートされている出力形式は MP4 のみです。MediaMuxer では現在、一度に 1 つの音声ストリームまたは 1 つの動画ストリームのみがサポートされています。

    MediaMuxer は主に MediaCodec と連携するように設計されているため、MediaCodec で動画処理を実行してから、MediaMuxer で出力を MP4 ファイルに保存できます。MediaMuxerMediaExtractor と組み合わせて使用すると、エンコードまたはデコードすることなくメディア編集を実行できます。

    RemoteControlClient の再生進捗状況とスクラブ

    Android 4.0(API レベル 14)では RemoteControlClient が追加され、リモコン クライアントからのメディア再生コントロール(ロック画面で使用可能なコントロールなど)が可能になりました。Android 4.3 では、このようなコントローラで再生位置を表示し、再生のスクラビングのコントロールを行えるようになりました。RemoteControlClient API を使用してメディアアプリのリモート コントロールを有効にしている場合は、2 つの新しいインターフェースを実装することで、再生スクラブを許可できます。

    まず、FLAG_KEY_MEDIA_POSITION_UPDATE フラグを setTransportControlsFlags() に渡して有効にします。

    次に、次の 2 つの新しいインターフェースを実装します。

    RemoteControlClient.OnGetPlaybackPositionListener
    これにはコールバック onGetPlaybackPosition() が含まれます。これは、リモコンが UI で進行状況を更新する必要がある場合にメディアの現在の位置をリクエストします。
    RemoteControlClient.OnPlaybackPositionUpdateListener
    これにはコールバック onPlaybackPositionUpdate() が含まれます。ユーザーがリモコン UI で再生をスクラブしたときに、メディアの新しいタイムコードをアプリに通知します。

    再生を新しい位置に更新したら、setPlaybackState() を呼び出して、新しい再生状態、位置、速度を指定します。

    これらのインターフェースを定義したら、setOnGetPlaybackPositionListener()setPlaybackPositionUpdateListener() をそれぞれ呼び出すことで、RemoteControlClient に対して設定できます。

    グラフィック

    OpenGL ES 3.0 のサポート

    Android 4.3 では、OpenGL ES 3.0 の Java インターフェースとネイティブ サポートが追加されています。OpenGL ES 3.0 の主な新機能は次のとおりです。

    • 高度な視覚効果の加速
    • 高品質の ETC2/EAC テクスチャ圧縮を標準機能として搭載
    • GLSL ES シェーディング言語の新しいバージョン(整数と 32 ビット浮動小数点をサポート)
    • 高度なテクスチャ レンダリング
    • テクスチャ サイズとレンダリング バッファ形式の広範な標準化

    Android の OpenGL ES 3.0 用の Java インターフェースは、GLES30 で提供されます。OpenGL ES 3.0 を使用する場合は、必ずマニフェスト ファイルで <uses-feature> タグと android:glEsVersion 属性を使用して宣言してください。次に例を示します。

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>
    

    また、必ず setEGLContextClientVersion() を呼び出して OpenGL ES コンテキストを指定し、バージョンとして 3 を渡します。

    デバイスでサポートされている OpenGL ES バージョンを実行時にチェックする方法など、OpenGL ES の使用について詳しくは、OpenGL ES API ガイドをご覧ください。

    ドローアブルの mipmap

    mipmap をビットマップまたはドローアブルのソースとして使用すると、高品質の画像を提供し、さまざまな画像スケールを簡単に提供できます。これは、アニメーション中に画像の拡大縮小が想定される場合に特に便利です。

    Android 4.2(API レベル 17)では、Bitmap クラスの mipmap のサポートが追加されました。mipmap ソースを提供して setHasMipMap() を有効にしている場合、Android は Bitmap の mip 画像を入れ替えます。Android 4.3 では、BitmapDrawable オブジェクトでも mipmap を有効にできるようになりました。それには、mipmap アセットを用意して、ビットマップ リソース ファイルで android:mipMap 属性を設定するか、hasMipMap() を呼び出します。

    ユーザー インターフェース

    オーバーレイの表示

    新しい ViewOverlay クラスは、View の上に透明なレイヤを提供します。このレイヤにビジュアル コンテンツを追加できます。このレイヤはレイアウト階層に影響しません。任意の ViewViewOverlay を取得するには、getOverlay() を呼び出します。オーバーレイは、ホストビュー(作成元のビュー)と常に同じサイズと位置になるため、ホストビューの前に表示されるコンテンツを追加できます。ただし、ホストビューの境界を拡張することはできません。

    ViewOverlay は、ビュー階層に影響を与えることなくコンテナの外部でビューをスライドしたり、画面内でアイテムを移動したりするなどのアニメーションを作成する場合に特に便利です。ただし、オーバーレイの使用可能領域はホストビューと同じ領域に制限されるため、レイアウト内の位置の外に移動するビューをアニメーション化する場合は、目的のレイアウト境界を持つ親ビューのオーバーレイを使用する必要があります。

    ウィジェット ビュー(Button など)にオーバーレイを作成する場合、add(Drawable) を呼び出して Drawable オブジェクトをオーバーレイに追加できます。RelativeLayout などのレイアウト ビューに対して getOverlay() を呼び出すと、ViewGroupOverlay が返されます。ViewGroupOverlay クラスは ViewOverlay のサブクラスであり、add(View) を呼び出して View オブジェクトを追加することもできます。

    注: オーバーレイに追加するドローアブルとビューはすべてビジュアルのみです。フォーカス イベントや入力イベントを受け取ることはできません。

    たとえば次のコードは、親ビューのオーバーレイにビューを配置して、そのビューで変換アニメーションを実行することで、ビューを右側にスライドするアニメーションを作成します。

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }
    

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();
    

    光学境界レイアウト

    9-patch 背景画像を含むビューの場合、ビューの「クリップ」境界ではなく、背景画像の「光学的」境界に基づいて隣接するビューに合わせるように指定できるようになりました。

    たとえば、図 1 と図 2 はそれぞれ同じレイアウトを示していますが、図 1 のバージョンはクリップ境界を使用して(デフォルトの動作)、図 2 は光学境界を使用しています。ボタンとフォトフレームに使用される 9-patch 画像は、縁の周囲にパディングがあるため、クリップ境界を使用すると、9-patch 画像同士やテキストとの整合が見られません。

    注: 図 1 と図 2 のスクリーンショットでは、デベロッパー設定 [レイアウト境界を表示] が有効になっています。各ビューの赤い線は光学境界、青い線はクリップの境界、ピンクの線はマージンを示します。

    図 1. クリップ境界を使用するレイアウト(デフォルト)。

    図 2. 光学境界を使用したレイアウト。

    光学境界に基づいてビューを調整するには、親レイアウトのいずれかで android:layoutMode 属性を "opticalBounds" に設定します。次に例を示します。

    <LinearLayout android:layoutMode="opticalBounds" ... >
    

    図 3. 光学境界のある Holo ボタン 9-patch のズームビュー。

    これを行うには、ビューの背景に適用する 9-patch 画像で、9-patch ファイルの下部と右側に沿った赤色の線を使用して光学境界を指定する必要があります(図 3 を参照)。赤い線は、クリップの境界から差し引く必要がある領域を示し、画像の光学境界を残しています。

    レイアウトで ViewGroup の光学境界を有効にすると、android:layoutMode"clipBounds" に設定してグループに対してオーバーライドしない限り、すべての子孫ビューは光学境界レイアウト モードを継承します。また、すべてのレイアウト要素は子ビューの光学境界を尊重し、子ビューの光学境界に基づいて独自の境界を調整します。ただし、現在のところレイアウト要素(ViewGroup のサブクラス)は、それ自体の背景に適用される 9-patch 画像の光学的境界をサポートしていません。

    ViewViewGroup、またはそれらのサブクラスをサブクラス化してカスタムビューを作成すると、ビューはこれらの光学的境界動作を継承します。

    注: Holo テーマでサポートされているすべてのウィジェットは、ButtonSpinnerEditText などの光学境界で更新されています。そのため、アプリに Holo テーマ(Theme.HoloTheme.Holo.Light など)を適用する場合は、android:layoutMode 属性を "opticalBounds" に設定することですぐにメリットが得られます。

    Draw 9-patch ツールを使用して独自の 9-patch 画像の光学境界を指定するには、Ctrl キーを押しながら境界ピクセルをクリックします。

    Rect 値のアニメーション

    新しい RectEvaluator を使用して、2 つの Rect 値の間でアニメーション化できるようになりました。この新しいクラスは、ValueAnimator.setEvaluator() に渡すことができる TypeEvaluator の実装です。

    ウィンドウのアタッチとフォーカス リスナー

    以前は、ビューがウィンドウにアタッチまたはデタッチされたとき、またはフォーカスが変更されたときをリッスンするには、View クラスをオーバーライドして、それぞれ onAttachedToWindow()onDetachedFromWindow()、または onWindowFocusChanged() を実装する必要がありました。

    アタッチ イベントとデタッチ イベントを受信するには、代わりに ViewTreeObserver.OnWindowAttachListener を実装し、addOnWindowAttachListener() を使用してビューに設定します。また、フォーカス イベントを受信するには、ViewTreeObserver.OnWindowFocusChangeListener を実装し、addOnWindowFocusChangeListener() を使用してビューに設定します。

    テレビのオーバースキャンのサポート

    アプリがすべてのテレビの画面全体に表示されるようにするには、アプリ レイアウトでオーバースキャンを有効にします。オーバースキャン モードは FLAG_LAYOUT_IN_OVERSCAN フラグによって決まります。このフラグは、Theme_DeviceDefault_NoActionBar_Overscan などのプラットフォーム テーマで有効にするか、カスタムテーマで windowOverscan スタイルを有効にすることで有効にできます。

    画面の向き

    <activity> タグの screenOrientation 属性で、自動回転に関するユーザー設定を尊重するための追加の値がサポートされるようになりました。

    "userLandscape"
    "sensorLandscape" と同じように動作しますが、ユーザーが自動回転を無効にすると、通常の横向きにロックされ、切り替えられません。
    "userPortrait"
    動作は "sensorPortrait" と同じですが、ユーザーが自動回転を無効にすると通常の縦向きにロックされ、反転できなくなります。
    "fullUser"
    "fullSensor" と同様に動作し、4 方向すべてへの回転を許可します。ただし、ユーザーが自動回転を無効にした場合は、ユーザーの希望する向きにロックされます。

    さらに、"locked" を宣言して、アプリの向きを画面の現在の向きにロックできるようになりました。

    回転アニメーション

    WindowManager の新しい rotationAnimation フィールドを使用すると、システムが画面の向きを切り替えたときに使用する 3 つのアニメーションから 1 つを選択できます。アニメーションには次の 3 つがあります。

    注: これらのアニメーションは、「全画面」モードを使用するようにアクティビティを設定した場合にのみ使用できます。全画面モードは、Theme.Holo.NoActionBar.Fullscreen などのテーマで有効にできます。

    たとえば、「クロスフェード」アニメーションを有効にする方法は次のとおりです。

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }
    

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }
    

    ユーザー入力

    新しいセンサータイプ

    新しい TYPE_GAME_ROTATION_VECTOR センサーにより、磁気干渉を心配せずにデバイスの回転を検出できます。TYPE_ROTATION_VECTOR センサーとは異なり、TYPE_GAME_ROTATION_VECTOR は磁北に基づいたものではありません。

    新しい TYPE_GYROSCOPE_UNCALIBRATED センサーと TYPE_MAGNETIC_FIELD_UNCALIBRATED センサーは、バイアスの推定を考慮せずに未加工のセンサーデータを提供します。つまり、既存の TYPE_GYROSCOPE センサーと TYPE_MAGNETIC_FIELD センサーは、それぞれデバイス内のジャイロドリフトとハードアイアンから推定されるバイアスを考慮したセンサーデータを提供します。一方、これらのセンサーの新しい「未調整」バージョンでは、未加工のセンサーデータが提供され、推定バイアス値が個別に提供されます。これらのセンサーを使用すると、推定バイアスを外部データで強化することで、センサーデータに対して独自のカスタム キャリブレーションを行うことができます。

    通知リスナー

    Android 4.3 では、新しいサービスクラス NotificationListenerService が追加されています。これにより、システムからの新しい通知が掲載されたときに、その通知に関する情報をアプリで受け取ることができます。

    現在、アプリでユーザー補助サービス API を使用してシステム通知にアクセスしている場合は、ユーザー補助 API を使用するようにアプリを更新する必要があります。

    連絡先プロバイダ

    「contactables」のクエリ

    新しい連絡先プロバイダのクエリ Contactables.CONTENT_URI を使用すると、指定したクエリに一致するすべての連絡先に属するすべてのメールアドレスと電話番号を含む 1 つの Cursor を効率的に取得できます。

    連絡先の差分のクエリ

    連絡先プロバイダに新しい API が追加され、連絡先データに対する最近の変更を効率的にクエリできるようになりました。以前は、連絡先データが変更されるとアプリに通知が届くことはありましたが、変更内容が正確にはわかっていなかったため、すべての連絡先を取得してから、繰り返して変更を見つける必要がありました。

    挿入と更新に対する変更を追跡するために、CONTACT_LAST_UPDATED_TIMESTAMP パラメータを選択に含めて、前回のプロバイダに対するクエリ以降に変更された連絡先のみをクエリできるようになりました。

    削除された連絡先を追跡するために、新しいテーブル ContactsContract.DeletedContacts では、削除された連絡先のログが提供されます(ただし、削除された各連絡先はこのテーブルに一定期間保持されます)。CONTACT_LAST_UPDATED_TIMESTAMP と同様に、新しい選択パラメータ CONTACT_DELETED_TIMESTAMP を使用して、前回のプロバイダへのクエリ後に削除された連絡先を確認できます。このテーブルには、ログを保持する日数(ミリ秒単位)を含む定数 DAYS_KEPT_MILLISECONDS も含まれます。

    また、ユーザーがシステム設定メニューで連絡先ストレージを消去すると、連絡先プロバイダが CONTACTS_DATABASE_CREATED アクションをブロードキャストするようになりました。これにより、連絡先プロバイダのデータベースが実質的に再作成されるようになりました。これは、保存した連絡先情報をすべて破棄し、新しいクエリで再読み込みする必要があることをアプリに通知するためのものです。

    これらの API を使用して連絡先の変更をチェックするサンプルコードについては、SDK サンプルのダウンロードにある ApiDemos サンプルをご覧ください。

    ローカライズ

    双方向テキストのサポートの改善

    以前のバージョンの Android は、RTL(右から左)言語とレイアウトをサポートしていますが、方向が混在するテキストが正しく処理されないことがあります。そのため、Android 4.3 では BidiFormatter API が追加され、逆方向のコンテンツでテキストの一部が不明瞭にならずに、適切に書式設定できるようになりました。

    たとえば、「15 Bay Street, Laurel, CA」のような文字列変数を含む文を作成する場合は、通常、ローカライズされた文字列リソースと変数を String.format() に渡します。

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
    

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);
    

    ただし、ロケールがヘブライ語の場合、書式設定された文字列は次のようになります。

    ?Bay Street, Laurel, CAהאם התכוונת ל 15

    「ベイストリート」の「15」は残っていないため、不正解です。この問題を解決するには、BidiFormatter とその unicodeWrap() メソッドを使用します。たとえば、上記のコードは次のようになります。

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )
    

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));
    

    デフォルトでは、unicodeWrap() は 1 番目が強い方向性の推定ヒューリスティックを使用します。テキスト方向の最初の信号がコンテンツ全体の適切な方向を表していない場合、間違っている可能性があります。必要に応じて、TextDirectionHeuristics から unicodeWrap()TextDirectionHeuristic 定数のいずれかを渡すことで、別のヒューリスティックを指定できます。

    注: これらの新しい API は、以前のバージョンの Android でも、Android サポート ライブラリから利用でき、BidiFormatter クラスと関連 API が用意されています。

    ユーザー補助サービス

    キーイベントを処理する

    AccessibilityService は、onKeyEvent() コールバック メソッドでキー入力イベントのコールバックを受信できるようになりました。これにより、ユーザー補助サービスは、キーボードなどのキーベースの入力デバイスでの入力を処理し、それらのイベントを、以前はタップ入力またはデバイスの十字キーでのみ可能だった特別なアクションに変換できます。

    テキストを選択してコピーして貼り付ける

    AccessibilityNodeInfo で、AccessibilityService でノード内のテキストの選択、切り取り、コピー、貼り付けを行える API が提供されるようになりました。

    切り取りまたはコピーするテキストの選択を指定するには、ユーザー補助サービスで新しいアクション ACTION_SET_SELECTION を使用し、ACTION_ARGUMENT_SELECTION_START_INTACTION_ARGUMENT_SELECTION_END_INT を使用して選択の開始位置と終了位置を渡します。または、既存のアクション ACTION_NEXT_AT_MOVEMENT_GRANULARITY(以前はカーソル位置の移動のみ)でカーソル位置を操作し、引数 ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN を追加することで、テキストを選択することもできます。

    次に、ACTION_CUTACTION_COPY を使用して切り取りまたはコピーしてから、ACTION_PASTE を使用して貼り付けることができます。

    注: これらの新しい API は、以前のバージョンの Android でも、Android サポート ライブラリAccessibilityNodeInfoCompat クラスを介して利用できます。

    ユーザー補助機能を宣言する

    Android 4.3 以降、ユーザー補助サービスで特定のユーザー補助機能を使用するには、メタデータ ファイルでユーザー補助機能を宣言する必要があります。機能がメタデータ ファイルでリクエストされていない場合、その機能は何も実行されません。サービスのユーザー補助機能を宣言するには、AccessibilityServiceInfo クラスのさまざまな「機能」定数に対応する XML 属性を使用する必要があります。

    たとえば、サービスは flagRequestFilterKeyEvents 機能をリクエストしない場合、キーイベントを受け取りません。

    テストとデバッグ

    自動 UI テスト

    新しい UiAutomation クラスには、テスト自動化のためのユーザー操作をシミュレートできる API が用意されています。UiAutomation API では、プラットフォームの AccessibilityService API を使用して、画面コンテンツを検査し、任意のキーボード イベントやタッチイベントを挿入できます。

    UiAutomation のインスタンスを取得するには、Instrumentation.getUiAutomation() を呼び出します。これを行うには、adb shell から InstrumentationTestCase を実行するときに、instrument コマンドで -w オプションを指定する必要があります。

    UiAutomation インスタンスを使用して任意のイベントを実行し、executeAndWaitForEvent() を呼び出し、実行する Runnable、オペレーションのタイムアウト時間、UiAutomation.AccessibilityEventFilter インターフェースの実装を渡します。目的のイベントをフィルタして特定のテストケースの成功または失敗を判断できる呼び出しを受け取るのは、UiAutomation.AccessibilityEventFilter 実装内で行います。

    テスト中にすべてのイベントをモニタリングするには、UiAutomation.OnAccessibilityEventListener の実装を作成し、それを setOnAccessibilityEventListener() に渡します。リスナー インターフェースは、イベントが発生するたびに onAccessibilityEvent() への呼び出しを受け取り、イベントを記述する AccessibilityEvent オブジェクトを受け取ります。

    UiAutomation API には、uiautomator などの UI テストツールの開発を促進するために、非常に低レベルで公開されているさまざまなオペレーションがあります。たとえば、UiAutomation は次のことも可能です。

    • 入力イベントを挿入する
    • 画面の向きを変更する
    • スクリーンショットを撮る

    また、UI テストツールで最も重要なことは、Instrumentation とは異なり、UiAutomation API はアプリの境界を越えて動作する点です。

    アプリの Systrace イベント

    Android 4.3 では、beginSection()endSection() の 2 つの静的メソッドを持つ Trace クラスが追加され、systrace レポートに含めるコードブロックを定義できます。追跡可能なコードのセクションをアプリに作成すると、Systrace ログでは、アプリ内の速度低下の発生箇所を、より詳細に分析できます。

    Systrace ツールの使用方法については、Systrace を使用した表示とパフォーマンスの分析をご覧ください。

    セキュリティ

    アプリの秘密鍵用の Android キーストア

    Android は、KeyStore 機能で Android Key Store というカスタム Java セキュリティ プロバイダを提供するようになりました。これにより、自分のアプリでのみ表示、使用できる秘密鍵を生成、保存できます。Android キーストアを読み込むには、"AndroidKeyStore"KeyStore.getInstance() に渡します。

    Android Key Store でアプリの秘密認証情報を管理するには、KeyPairGeneratorSpecKeyPairGenerator を使用して新しい鍵を生成します。まず、getInstance() を呼び出して KeyPairGenerator のインスタンスを取得します。次に、initialize() を呼び出して KeyPairGeneratorSpec のインスタンスを渡します。これは KeyPairGeneratorSpec.Builder を使用して取得できます。 最後に、generateKeyPair() を呼び出して KeyPair を取得します。

    ハードウェア認証情報ストレージ

    Android では、KeyChain 認証情報用にハードウェア格納型ストレージもサポートされるようになりました。これにより、鍵を抽出できないようにすることで、セキュリティを強化できます。つまり、ハードウェア格納型キーストア(セキュア エレメント、TPM、TrustZone)に格納された鍵を暗号オペレーションに使用することはできますが、秘密鍵マテリアルをエクスポートすることはできません。OS カーネルでさえ、この鍵マテリアルにアクセスできません。すべての Android 搭載デバイスがハードウェアのストレージをサポートしているわけではありませんが、KeyChain.IsBoundKeyAlgorithm() を呼び出すことで、ハードウェア格納型ストレージが使用可能かどうかを実行時に確認できます。

    マニフェストの宣言

    宣言可能な必須機能

    <uses-feature> 要素で以下の値がサポートされるようになりました。これにより、アプリに必要な機能を提供するデバイスにのみアプリをインストールできます。

    FEATURE_APP_WIDGETS
    アプリがアプリ ウィジェットを提供し、ユーザーがアプリ ウィジェットを埋め込むことができるホーム画面または類似の場所を備えたデバイスにのみインストールする必要があることを宣言します。以下に例を示します。
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    
    FEATURE_HOME_SCREEN
    アプリがホーム画面の代替機能として動作し、サードパーティのホーム画面アプリをサポートするデバイスにのみインストールされることを宣言します。以下に例を示します。
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    
    FEATURE_INPUT_METHODS
    アプリがカスタム入力方法(InputMethodService でビルドされたキーボード)を提供し、サードパーティの入力方法をサポートするデバイスにのみインストールする必要があることを宣言します。以下に例を示します。
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    
    FEATURE_BLUETOOTH_LE
    アプリが Bluetooth Low Energy API を使用すること、および Bluetooth Low Energy を介して他のデバイスと通信できるデバイスにのみインストールすることを宣言します。例:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />
    

    ユーザー権限

    アプリが特定の API にアクセスするために必要な権限を宣言するために、<uses-permission> で以下の値がサポートされるようになりました。

    BIND_NOTIFICATION_LISTENER_SERVICE
    新しい NotificationListenerService API を使用するために必要です。
    SEND_RESPOND_VIA_MESSAGE
    ACTION_RESPOND_VIA_MESSAGE インテントを受け取るために必要です。

    Android 4.3 で行われた API の変更点について詳しくは、API の違いレポートをご覧ください。