Android 4.2 API

API レベル: 17

Android 4.2(JELLY_BEAN_MR1)は Jelly Bean リリースのアップデートであり、ユーザーとアプリ デベロッパー向けに新機能を提供します。このドキュメントでは、デベロッパー向けの最も注目すべき有用な新しい API の概要を説明します。

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

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

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

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

重要な動作の変更点

以前に Android 向けアプリを公開したことがある場合は、アプリの動作に影響する可能性がある次の変更に注意してください。

  • コンテンツ プロバイダはデフォルトでエクスポートされなくなりました。つまり、android:exported 属性のデフォルト値は “false" です。他のアプリからコンテンツ プロバイダにアクセスできるようにする必要がある場合は、android:exported="true" を明示的に設定する必要があります。

    この変更は、android:targetSdkVersion または android:minSdkVersion を 17 以上に設定した場合にのみ有効になります。それ以外の場合、Android 4.2 以降で実行している場合でも、デフォルト値は “true" のままです。

  • 以前のバージョンの Android と比較すると、アプリが ACCESS_COARSE_LOCATION 権限をリクエストしても ACCESS_FINE_LOCATION 権限をリクエストしていない場合、ユーザーの位置情報の結果の精度が低下することがあります。

    ユーザーのプライバシー保護に応えるために、アプリが精度の高い位置情報ではなくおおよその位置情報の利用許可をリクエストする場合、都市ブロックより正確なユーザー位置情報の推定値は提供されません。

  • Settings.System で定義された一部のデバイス設定が読み取り専用になりました。Settings.System で定義された設定のうち、Settings.Global に移行されたものをアプリが書き込もうとすると、Android 4.2 以上での実行時に、書き込みオペレーションは通知なく失敗します。

    android:targetSdkVersionandroid:minSdkVersion の値が 17 未満であっても、Android 4.2 以降でのアプリの実行時に Settings.Global に移動した設定は変更できません。

  • アプリで WebView を使用している場合、Android 4.2 ではセキュリティ レイヤが追加され、より安全に JavaScript を Android コードにバインドできます。targetSdkVersion を 17 以上に設定する場合、JavaScript で使用できるようにするメソッドに @JavascriptInterface アノテーションを追加する必要があります(メソッドもパブリックである必要があります)。アノテーションを指定しないと、Android 4.2 以降で実行している WebView のウェブページからこのメソッドにアクセスできません。targetSdkVersion を 16 以下に設定する場合、アノテーションは不要ですが、ターゲット バージョンを更新してアノテーションを追加することにより、セキュリティを強化することをおすすめします。

    詳しくは、JavaScript コードを Android コードにバインドするをご覧ください。

Daydream

Daydream は、Android デバイス向けの新しいインタラクティブなスクリーンセーバー モードです。この機能は、デバイスをホルダーに挿入したときや、充電器に接続している状態でアイドル状態のまま(画面がオフになるのではなく)放置されているときに、自動的に有効になります。Daydream は、一度に 1 つの夢を表示します。これは、タッチすると消える純粋に視覚的なパッシブ ディスプレイの場合もあれば、すべての入力イベントにインタラクティブで応答性がある場合もあります。夢はアプリのプロセスで実行されます。Android UI ツールキット(ビュー、レイアウト、アニメーションなど)へのフルアクセスが可能なため、ライブ壁紙やアプリ ウィジェットよりも柔軟で強力になります。

Daydream の夢を作成するには、DreamService のサブクラスを実装します。DreamService API は、Activity の API と同様の設計になっています。目的に合った UI を指定するには、ウィンドウの取得後(onAttachedToWindow() コールバックなど)の任意の時点で、レイアウト リソース ID または ViewsetContentView() に渡します。

DreamService クラスは、基本の Service API に加えて、onDreamingStarted()onDreamingStopped()onDetachedFromWindow() などの重要なライフサイクル コールバック メソッドを提供します。DreamService は、システムによって自動的に起動されるため、アプリから開始することはできません。

Dream がインタラクティブな場合は、Dream からアクティビティを開始し、ユーザーをアプリのフル UI に誘導して、詳細やコントロールを行えるようにできます。finish() を使用して Dream を終了し、ユーザーが新しいアクティビティを表示できるようにします。

システムで daydream を利用できるようにするには、マニフェスト ファイルで <service> 要素を使用して DreamService を宣言します。次に、アクション "android.service.dreams.DreamService" を含むインテント フィルタを含める必要があります。次に例を示します。

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

DreamService には他にも注意すべき便利なメソッドがいくつかあります。

  • setInteractive(boolean) は、Dream が入力イベントを受け取るか、ユーザー入力直後に終了するかを制御します。dream がインタラクティブの場合、ユーザーは [戻る] ボタンまたは [ホーム] ボタンを使用して dream を終了できます。また、finish() を呼び出して dream を停止することもできます。
  • 完全に没入できるディスプレイが必要な場合は、setFullscreen() を呼び出してステータスバーを非表示にできます。
  • Daydream が開始する前に、ディスプレイが暗くなり、アイドル タイムアウトが近づいていることをユーザーに知らせます。setScreenBright(true) を呼び出すと、ディスプレイを通常の明るさに設定できます。

詳細については、DreamService のドキュメントをご覧ください。

セカンダリ ディスプレイ

Android では、有線接続または Wi-Fi でユーザーのデバイスに接続されている追加画面に、アプリで独自のコンテンツを表示できるようになりました。セカンダリ ディスプレイ用に独自のコンテンツを作成するには、Presentation クラスを拡張して onCreate() コールバックを実装します。onCreate() 内で、setContentView() を呼び出してセカンダリ ディスプレイの UI を指定します。Dialog クラスの拡張として、Presentation クラスは、アプリがセカンダリ ディスプレイに一意の UI を表示できる領域を提供します。

Presentation を表示できるセカンダリ ディスプレイを検出するには、DisplayManager API または MediaRouter API を使用します。DisplayManager API を使用すると、一度に接続される複数のディスプレイを列挙できますが、通常は MediaRouter を使用して、システムのプレゼンテーションのデフォルト ディスプレイにすばやくアクセスする必要があります。

プレゼンテーションのデフォルト表示を取得するには、MediaRouter.getSelectedRoute() を呼び出して ROUTE_TYPE_LIVE_VIDEO を渡します。これにより、システムで現在選択されている動画プレゼンテーションのルートを表す MediaRouter.RouteInfo オブジェクトが返されます。MediaRouter.RouteInfo が null でない場合、getPresentationDisplay() を呼び出して、接続されたディスプレイを表す Display を取得します。

次に、Display オブジェクトを Presentation クラスのコンストラクタに渡して、プレゼンテーションを表示できます。プレゼンテーションがセカンダリ ディスプレイに表示されます。

実行時に新しいディスプレイが接続されたことを検出するには、MediaRouter.SimpleCallback のインスタンスを作成し、その中で onRoutePresentationDisplayChanged() コールバック メソッドを実装します。このメソッドは、新しいプレゼンテーション ディスプレイが接続されたときにシステムによって呼び出されます。次に、ROUTE_TYPE_LIVE_VIDEO ルートタイプとともに MediaRouter.addCallback() に渡して、MediaRouter.SimpleCallback を登録します。onRoutePresentationDisplayChanged() への呼び出しを受け取った場合は、上記のように MediaRouter.getSelectedRoute() を呼び出します。

セカンダリ画面の Presentation の UI をさらに最適化するには、アプリまたはアクティビティに適用した <style>android:presentationTheme 属性を指定して、別のテーマを適用します。

ユーザーのデバイスに接続されている画面は、画面サイズのほうが大きく、画面密度も異なる傾向があることに留意してください。画面の特性は異なる場合があるため、そのような大きなディスプレイ向けに最適化されたリソースを用意する必要があります。Presentation から追加のリソースをリクエストする必要がある場合は、getContext().getResources() を呼び出して、ディスプレイに対応する Resources オブジェクトを取得します。これにより、セカンダリ ディスプレイの画面サイズと密度に最適な、アプリからの適切なリソースが提供されます。

詳細とコードサンプルについては、Presentation クラスのドキュメントをご覧ください。

ロック画面ウィジェット

Android では、ユーザーがアプリ ウィジェットをロック画面に追加できるようになりました。アプリ ウィジェットをロック画面で使用できるようにするには、AppWidgetProviderInfo を指定する XML ファイルに android:widgetCategory 属性を追加します。この属性は、home_screenkeyguard の 2 つの値をサポートします。この属性はデフォルトで home_screen に設定されているため、ユーザーはアプリ ウィジェットをホーム画面に追加できます。アプリ ウィジェットをロック画面でも利用できるようにする場合は、keyguard の値を追加します。

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

また、ロック画面でアプリ ウィジェットの初期レイアウトを android:initialKeyguardLayout 属性で指定する必要があります。これは、アプリ ウィジェットが初期化されてレイアウトを更新できるまですぐに表示できるレイアウトを提供するという点で、android:initialLayout と同じように機能します。

ロック画面でアプリ ウィジェットを作成する方法など、ロック画面用のアプリ ウィジェットの作成について詳しくは、アプリ ウィジェットのガイドをご覧ください。

複数ユーザー

Android では、タブレットなどの共有可能なデバイスで複数のユーザー スペースを利用できるようになりました。デバイス上の各ユーザーには、独自のアカウント、アプリ、システム設定、ファイル、その他のユーザー関連データのセットがあります。

アプリ デベロッパーは、1 つのデバイスで複数のユーザーを対象としてアプリを正しく動作させるために、何か特別なことをする必要はありません。デバイスに存在するユーザー数に関係なく、アプリが特定のユーザーについて保存するデータは、アプリが他のユーザーのために保存するデータとは区別して保存されます。システムは、アプリが実行されているユーザー プロセスに属するユーザーデータを追跡し、アプリがそのユーザーのデータにのみアクセスできるようにし、他のユーザーのデータにはアクセスできないようにします。

マルチユーザー環境でのデータの保存

アプリがユーザー設定を保存したり、データベースを作成したり、ユーザーの内部または外部ストレージにファイルを書き込むと、そのデータにアクセスできるのは、そのユーザーとして実行されているときのみです。

マルチユーザー環境でアプリが適切に動作するように、ハードコードされたパスを使用して内部アプリ ディレクトリや外部ストレージの場所を参照せず、常に適切な API を使用してください。

特定のユーザーのデータを保存するためにどの API を使用しても、別のユーザーとして実行している間はデータにアクセスできません。アプリの観点からは、各ユーザーはまったく異なるデバイスで実行されています。

マルチユーザー環境でのユーザーの特定

分析情報を収集したり、他のアカウントの関連付けを作成したりするなどして、アプリでユニーク ユーザーを識別する場合は、一意のインストールを識別するための推奨方法に従う必要があります。アプリの初回起動時に新しい UUID を作成することで、1 台のデバイスにアプリをインストールしたユーザーの数に関係なく、各ユーザーをトラッキングするための一意の ID を確実に取得できます。または、サーバーから取得したローカル トークンを保存するか、Google Cloud Messaging が提供する登録 ID を使用できます。

アプリがハードウェア デバイス識別子(Wi-Fi MAC アドレスや SERIAL 番号など)のいずれかをリクエストする場合、これらの識別子はユーザーではなくハードウェアに関連付けられているため、どのユーザーも同じ値を提供します。言うまでもなく、これらの識別子が原因で発生するその他の問題については、アプリのインストールを特定するブログ投稿をご覧ください。

新しい全般設定

Settings.Global の追加により、複数のユーザーをサポートするようにシステム設定が更新されました。この一連の設定は読み取り専用であるため、Settings.Secure 設定と似ていますが、デバイス上のすべてのユーザー空間にグローバルに適用されます。

いくつかの既存の設定が、Settings.System または Settings.Secure からここに移動しました。以前 Settings.System で定義した設定(AIRPLANE_MODE_ON など)をアプリが現在変更している場合、Android 4.2 以降を搭載しているデバイスでは、これらの設定を Settings.Global に移行すると、この変更が機能しなくなります。Settings.Global にある設定は引き続き読み取ることができますが、この設定はアプリを変更しても安全とはみなされなくなったため、変更しようとすると通知なく失敗し、Android 4.2 以降でアプリを実行すると、システムログに警告が書き込まれます。

RTL レイアウトのサポート

Android では、レイアウトの向きを適切に変換するユーザー インターフェースを作成できる API がいくつか提供され、右から左(RTL)UI を使用する言語や、アラビア語やヘブライ語などの読み上げ方向を使用する言語をサポートできるようになりました。

アプリで RTL レイアウトのサポートを開始するには、マニフェスト ファイルの <application> 要素に android:supportsRtl 属性を設定し、“true" に設定します。有効にすると、さまざまな RTL API が有効になり、アプリを RTL レイアウトで表示できるようになります。たとえば、アクションバーの右側にはアイコンとタイトル、左側にアクション ボタンが表示されます。フレームワークが提供する View クラスで作成したレイアウトも逆になります。

RTL レイアウトで表示したときのアプリの外観をさらに最適化する必要がある場合は、次の 2 つの基本的なレベルで最適化を行います。

  1. 左向きと右向きのレイアウト プロパティを、開始向きと終了向きのレイアウト プロパティに変換します。

    たとえば、android:layout_marginLeft の代わりに android:layout_marginStart を、android:layout_marginRight の代わりに android:layout_marginEnd を使用します。

    RelativeLayout クラスには、左右の位置を置き換える対応するレイアウト属性も用意されています。たとえば、android:layout_toLeftOf の代わりに android:layout_alignParentLeftandroid:layout_toStartOf を置き換える android:layout_alignParentStart などです。

  2. RTL レイアウトを完全に最適化するには、ldrtl リソース修飾子(ldrtl は layout-direction-right-to-left} の略)を使用して、完全に個別のレイアウト ファイルを指定します。たとえば、デフォルトのレイアウト ファイルは res/layout/ に保存し、RTL に最適化されたレイアウトは res/layout-ldrtl/ に保存できます。

    ldrtl 修飾子はドローアブル リソースに適しています。そのため、読み取り方向に対応する向きのグラフィックを提供できます。

RTL レイアウトをサポートする他のさまざまな API がフレームワーク全体で利用可能です。たとえば、View クラスではカスタムビューに適切な動作を実装でき、Configuration では現在のレイアウト方向をクエリできます。

注: SQlite を使用していて、「数値のみ」のテーブル名または列名がある場合は、注意が必要です。デバイスがアラビア語ロケールに設定されている場合に、String.format(String, Object...) を使用すると、対応する数字がアラビア語に変換されてエラーが発生する可能性があります。数値が ASCII として保持されるようにするには、String.format(Locale,String,Object...) を使用する必要があります。また、数値の書式設定には String.valueOf(int) ではなく String.format("%d", int) を使用します。

Fragment のネスト

フラグメントをフラグメント内に埋め込むことができるようになりました。これは、動的で再利用可能な UI コンポーネントを、それ自体が動的で再利用可能な UI コンポーネントに配置する、さまざまな状況で役立ちます。たとえば、ViewPager を使用して左右にスワイプして画面スペースの大部分を消費するフラグメントを作成する場合、各フラグメント ページにフラグメントを挿入できるようになりました。

フラグメントをネストするには、フラグメントを追加する FragmentgetChildFragmentManager() を呼び出します。これにより FragmentManager が返されます。これをトップレベル アクティビティから通常どおり使用してフラグメント トランザクションを作成できます。たとえば、既存の Fragment クラス内からフラグメントを追加するコードは次のようになります。

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

ネストされたフラグメント内から、getParentFragment() を呼び出すことで、親フラグメントへの参照を取得できます。

Android サポート ライブラリでは、ネストされたフラグメントもサポートされるようになりました。これにより、Android 1.6 以降では、ネストされたフラグメントの設計を実装できます。

注: レイアウトに <fragment> が含まれている場合、レイアウトをフラグメントにインフレートすることはできません。ネストされたフラグメントは、フラグメントに動的に追加される場合にのみサポートされます。

Renderscript

RenderScript の計算機能が拡張され、次の機能が追加されました。

スクリプト組み込み関数

次のような一般的なオペレーションを実装する、Renderscript の組み込みスクリプト組み込みを使用できます。

スクリプト組み込みを使用するには、各組み込み関数の静的 create() メソッドを呼び出して、スクリプトのインスタンスを作成します。次に、組み込みスクリプトごとに使用可能な set() メソッドを呼び出して、必要な入力とオプションを設定します。最後に、forEach() メソッドを呼び出してスクリプトを実行します。

スクリプト グループ

ScriptGroup を使用すると、関連する RenderScript スクリプトを連結し、1 回の呼び出しで実行できます。

ScriptGroup.Builder を使用し、addKernel() を呼び出してすべてのスクリプトをグループに追加します。すべてのスクリプトを追加したら、addConnection() を呼び出してスクリプト間の接続を作成します。接続の追加が完了したら、create() を呼び出してスクリプト グループを作成します。スクリプト グループを実行する前に、入力 AllocationsetInput(Script.KernelID, Allocation) メソッドで実行する初期スクリプトを指定し、結果が書き込まれる出力 Allocation と、setOutput() で実行する最終的なスクリプトを指定します。最後に、execute() を呼び出してスクリプト グループを実行します。

FilterScript

Filterscript は既存の Renderscript API に制約を定義します。これにより、生成されるコードをさまざまなプロセッサ(CPU、GPU、DSP)で実行できるようになります。Filterscript ファイルを作成するには、.rs ファイルではなく .fs ファイルを作成し、#pragma rs_fp_relaxed を指定して、スクリプトが厳格な IEEE 754-2008 浮動小数点精度を必要としないことを Renderscript ランタイムに伝えます。この精度により、denorms のゼロへのフラッシュとゼロへの丸めが可能になります。また、Filterscript スクリプトでは 32 ビットの組み込み型を使用せず、__attribute__((kernel)) 属性を使用してカスタムルート関数を指定する必要があります。これは、root() 関数のデフォルトのシグネチャで定義されているポインタが Filterscript でサポートされていないためです。

注: Filterscript のサポートはプラットフォームに存在しますが、デベロッパー サポートは SDK Tools リリース 21.0.1 で利用できるようになります。

Android 4.2 におけるすべての API の変更点について詳しくは、API 差分レポートをご覧ください。