API レベル: 18
Android 4.3(JELLY_BEAN_MR2
)は Jelly Bean リリースのアップデートであり、ユーザーとアプリ デベロッパー向けに新機能を提供します。このドキュメントでは、最も注目すべき新しい API の概要について説明します。
アプリ デベロッパーは、できるだけ早く SDK Manager から Android 4.3 のシステム イメージと SDK プラットフォームをダウンロードする必要があります。アプリをテストするための 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_height
と layout_width
の "wrap_content"
の値を "match_parent"
と同じ値に誤って計算していました。そのため、Android 4.3 以降では、高さまたは幅に "wrap_content"
を使用して目的の動画レイアウトを提供していたかもしれませんが、それにより、動画のサイズが大幅に小さくなることがあります。この問題を解決するには、"wrap_content"
を "match_parent"
に置き換え、Android 4.3 と以前のバージョンで動画が想定どおりに表示されることを確認します。
制限付きプロフィール
Android タブレットでは、ユーザーがプライマリ ユーザーに基づいて制限付きプロファイルを作成できるようになりました。 ユーザーは、制限付きプロファイルを作成するときに、そのプロファイルで利用できるアプリなどの制限を有効にできます。Android 4.3 の新しい API セットを使用すると、開発するアプリ向けのきめ細かい制限設定を構築することもできます。たとえば、新しい API を使用すると、制限付きプロファイル環境での実行時に、アプリ内で使用できるコンテンツの種類をユーザーが制御できるようになります。
作成した制限をユーザーが制御するための UI は、システムの設定アプリによって管理されます。アプリの制限設定をユーザーに表示するには、ACTION_GET_RESTRICTION_ENTRIES
インテントを受け取る BroadcastReceiver
を作成して、アプリが提供する制限を宣言する必要があります。システムはこのインテントを呼び出して、すべてのアプリに適用可能な制限を照会し、プライマリ ユーザーが各制限付きプロファイルの制限を管理できる UI を作成します。
BroadcastReceiver
の onReceive()
メソッドで、アプリが提供する制限ごとに RestrictionEntry
を作成する必要があります。各 RestrictionEntry
では、制限のタイトル、説明、および次のいずれかのデータ型を定義します。
TYPE_BOOLEAN
: 制限(true または false)TYPE_CHOICE
: 相互に排他的な複数の選択肢(ラジオボタンの選択肢)がある制限。TYPE_MULTI_SELECT
: 相互に排他的でない複数の選択肢(チェックボックスの選択肢)がある制限用。
次に、すべての RestrictionEntry
オブジェクトを ArrayList
に格納し、EXTRA_RESTRICTIONS_LIST
エクストラの値としてブロードキャスト レシーバの結果に挿入します。
設定アプリでアプリの制限の UI が作成され、RestrictionEntry
オブジェクトごとに指定した一意のキーで各制限が保存されます。ユーザーがアプリを開いたときに、getApplicationRestrictions()
を呼び出すことで、現在の制限を照会できます。RestrictionEntry
オブジェクトで定義した制限ごとに Key-Value ペアを含む Bundle
が返されます。
ブール値、単一選択、複数選択の値では処理できない具体的な制限を提供する場合は、ユーザーが制限を指定し、ユーザーが制限設定からそのアクティビティを開けるアクティビティを作成できます。ブロードキャスト レシーバでは、結果の Bundle
に EXTRA_RESTRICTIONS_INTENT
エクストラを含めます。このエクストラでは、起動する Activity
クラスを示す Intent
を指定する必要があります(putParcelable()
メソッドを使用して、インテントで EXTRA_RESTRICTIONS_INTENT
を渡します)。プライマリ ユーザーがアクティビティに入り、カスタム制限を設定する場合、アクティビティは、RestrictionEntry
オブジェクトと Key-Value ペアのどちらを指定するかに応じて、EXTRA_RESTRICTIONS_LIST
キーまたは EXTRA_RESTRICTIONS_BUNDLE
キーを使用して、エクストラに制限値を含む結果を返す必要があります。
制限付きプロファイルでのアカウントのサポート
プライマリ ユーザーに追加されたすべてのアカウントは制限付きプロファイルで使用できますが、デフォルトでは 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 周辺機器を検出するには、BluetoothAdapter
で startLeScan()
を呼び出して、BluetoothAdapter.LeScanCallback
インターフェースの実装を渡します。Bluetooth アダプターが Bluetooth LE 周辺機器を検出すると、BluetoothAdapter.LeScanCallback
の実装は onLeScan()
メソッドの呼び出しを受け取ります。このメソッドは、検出されたデバイスを表す BluetoothDevice
オブジェクト、デバイスの RSSI 値、デバイスのアドバタイズ レコードを含むバイト配列を提供します。
特定の種類の周辺機器のみをスキャンする場合は、代わりに startLeScan()
を呼び出して、アプリがサポートする GATT サービスを指定する UUID
オブジェクトの配列を含めることができます。
注: Bluetooth LE デバイスのスキャンまたは以前の API を使用したクラシック Bluetooth デバイスのスキャンのみが可能です。LE と Classic 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 では、MediaCodec
と MediaExtractor
の既存の 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
オブジェクトのインスタンスをコンストラクタで構築できます。
サーフェスからの動画のエンコード
Android 4.1(API レベル 16)では、メディア コンテンツの低レベルのエンコードとデコード用に MediaCodec
クラスが追加されました。動画をエンコードする際、Android 4.1 ではメディアに ByteBuffer
配列を指定する必要がありましたが、Android 4.3 ではエンコーダへの入力として Surface
を使用できるようになりました。たとえば、既存の動画ファイルからの入力をエンコードしたり、OpenGL ES から生成されたフレームを使用したりできます。
エンコーダへの入力として Surface
を使用するには、まず MediaCodec
に対して configure()
を呼び出します。次に、createInputSurface()
を呼び出して、メディアをストリーミングできる Surface
を受け取ります。
たとえば、指定された Surface
を eglCreateWindowSurface()
に渡すことで、OpenGL コンテキストのウィンドウとして使用できます。次に、サーフェスのレンダリング中に、eglSwapBuffers()
を呼び出してフレームを MediaCodec
に渡します。
エンコードを開始するには、MediaCodec
に対して start()
を呼び出します。完了したら、signalEndOfInputStream()
を呼び出してエンコードを終了し、Surface
に対して release()
を呼び出します。
メディア多重化
新しい MediaMuxer
クラスを使用すると、1 つの音声ストリームと 1 つの動画ストリームを多重化できます。これらの API は、メディアを逆多重化(非多重化)するために Android 4.2 で追加された MediaExtractor
クラスに対応するものです。
サポートされている出力形式は MediaMuxer.OutputFormat
で定義されています。現時点でサポートされている出力形式は MP4 のみです。MediaMuxer
は現在、一度に 1 つの音声ストリームや 1 つの動画ストリームのみをサポートしています。
MediaMuxer
は主に MediaCodec
と連携するように設計されているため、MediaCodec
を使用して動画処理を行い、MediaMuxer
を使用して出力を MP4 ファイルに保存できます。MediaMuxer
を MediaExtractor
と組み合わせて使用すると、エンコードまたはデコードすることなくメディア編集を実行できます。
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 では、Java インターフェースと OpenGL ES 3.0 のネイティブ サポートが追加されています。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
の上に透明なレイヤを提供します。このレイヤにビジュアル コンテンツを追加できます。このレイヤはレイアウト階層には影響しません。任意の View
の ViewOverlay
を取得するには、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 画像は、縁の周囲にパディングがあるため、クリップ境界を使用すると、画像同士やテキストとの位置が合っていないように見えます。
注: 図 1 と図 2 のスクリーンショットでは、[レイアウト境界を表示] デベロッパー向け設定が有効になっています。各ビューの赤い線は光学的境界、青色の線はクリップの境界、ピンクの線はマージンを示します。
![](https://developer.android.google.cn/static/images/tools/clipbounds_2x.png?authuser=9&hl=ja)
図 1. クリップ境界を使用したレイアウト(デフォルト)。
![](https://developer.android.google.cn/static/images/tools/opticalbounds_2x.png?authuser=9&hl=ja)
図 2. 光学境界を使用したレイアウト。
光学境界に基づいてビューを配置するには、親レイアウトのいずれかで android:layoutMode
属性を "opticalBounds"
に設定します。次に例を示します。
<LinearLayout android:layoutMode="opticalBounds" ... >
![](https://developer.android.google.cn/static/images/tools/ninepatch_opticalbounds_2x.png?authuser=9&hl=ja)
図 3. 光学境界のある Holo ボタンの 9-patch の拡大表示。
これを行うには、ビューの背景に適用する 9-patch 画像で、9-patch ファイルの下部と右側に沿った赤い線を使用して光学境界を指定する必要があります(図 3 を参照)。赤い線は、クリップ境界から差し引かれる領域を示しており、画像の光学的境界が残っています。
レイアウトで ViewGroup
の光学境界を有効にすると、android:layoutMode
を "clipBounds"
に設定してグループに対してオーバーライドしない限り、すべての子孫ビューは光学境界レイアウト モードを継承します。また、すべてのレイアウト要素は子ビューの光学的境界を尊重し、子ビューの光学的境界に基づいて独自の境界を調整します。ただし、レイアウト要素(ViewGroup
のサブクラス)は現在、それ自体の背景に適用される 9-patch 画像の光学的境界をサポートしていません。
View
、ViewGroup
、またはそれらのサブクラスをサブクラス化してカスタムビューを作成すると、ビューはこれらの光学バインドされた動作を継承します。
注: Holo テーマでサポートされているすべてのウィジェットは、Button
、Spinner
、EditText
などの光学境界で更新されています。そのため、アプリが Holo テーマ(Theme.Holo
、Theme.Holo.Light
など)を適用する場合は、android:layoutMode
属性を "opticalBounds"
に設定すると、すぐにメリットが得られます。
Draw 9-patch ツールを使用して、9-patch 画像の光学境界を指定するには、Ctrl キーを押しながら境界ピクセルをクリックします。
Rect 値のアニメーション
新しい RectEvaluator
を使用して、2 つの Rect
値の間でアニメーション化できるようになりました。この新しいクラスは TypeEvaluator
の実装で、ValueAnimator.setEvaluator()
に渡すことができます。
ウィンドウのアタッチとフォーカス リスナー
以前は、ビューがウィンドウにアタッチまたはデタッチされるタイミング、またはそのフォーカスが変更されたときにリッスンするには、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.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
「Bay Street」の左側に「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 次強方向推定ヒューリスティックを使用します。テキスト方向の最初のシグナルがコンテンツ全体の適切な方向を表していない場合、正しい方向に進めないことがあります。必要に応じて、TextDirectionHeuristic
定数のいずれかを TextDirectionHeuristics
から unicodeWrap()
に渡すことで、別のヒューリスティックを指定できます。
注: これらの新しい API は、以前のバージョンの Android でも、Android サポート ライブラリから BidiFormatter
クラスと関連 API とともに利用できます。
ユーザー補助サービス
キーイベントを処理する
AccessibilityService
は、onKeyEvent()
コールバック メソッドでキー入力イベントのコールバックを受信できるようになりました。これにより、ユーザー補助サービスはキーボードなどのキーベースの入力デバイスの入力を処理し、そのイベントを、以前はタップ入力やデバイスの十字キーでのみ可能だった特殊なアクションに変換できます。
テキストを選択してコピーして貼り付ける
AccessibilityNodeInfo
に、AccessibilityService
でノード内のテキストを選択、切り取り、コピー、貼り付けできる API が提供されるようになりました。
切り取りまたはコピーするテキストの選択を指定するには、ユーザー補助サービスで新しいアクション ACTION_SET_SELECTION
を使用し、ACTION_ARGUMENT_SELECTION_START_INT
と ACTION_ARGUMENT_SELECTION_END_INT
を使用して選択の開始位置と終了位置を渡します。または、既存のアクション ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(以前はカーソル位置の移動のみ用)を使用してカーソル位置を操作し、引数 ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
を追加してテキストを選択することもできます。
その後、ACTION_CUT
、ACTION_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
オブジェクトを受け取ります。
uiautomator などの UI テストツールの開発を促進するために、UiAutomation
API が非常に低レベルで公開しているさまざまなオペレーションが他にもあります。たとえば、UiAutomation
は次のことも可能です。
- 入力イベントを挿入する
- 画面の向きを変更する
- スクリーンショットを撮る
UI テストツールで最も重要な点は、Instrumentation
とは異なり、UiAutomation
API はアプリの境界を越えて機能します。
アプリの Systrace イベント
Android 4.3 では、beginSection()
と endSection()
という 2 つの静的メソッドを持つ Trace
クラスが追加されています。これにより、systrace レポートに含めるコードブロックを定義できます。追跡可能なコードのセクションをアプリに作成することで、Systrace ログでは、アプリ内の速度低下が発生している場所について、より詳しい分析結果が得られます。
Systrace ツールの使用方法については、Systrace を使用した表示とパフォーマンスの分析をご覧ください。
セキュリティ
アプリ秘密鍵用の Android キーストア
Android では、Android Key Store と呼ばれるカスタム Java セキュリティ プロバイダが KeyStore
ファシリティで提供されるようになりました。これにより、アプリのみが表示および使用できる秘密鍵を生成して保存できます。Android Key Store を読み込むには、"AndroidKeyStore"
を KeyStore.getInstance()
に渡します。
Android Key Store でアプリの秘密認証情報を管理するには、KeyPairGeneratorSpec
で KeyPairGenerator
を使用して新しい鍵を生成します。まず、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 差分レポートをご覧ください。