4. インテントとインテントフィルタ


アプリケーションの 3 つのコアコンポーネントである、アクティビティ、サービス、ブロードキャストレシーバは、インテント と呼ばれるメッセージを介してアクティベートされます。インテントメッセージングは、同じまたは異なるアプリケーションにある複数のコンポーネント間の遅延ランタイムバインディングのための手段です。インテント自身、つまり Intent オブジェクトは、実行されるオペレーションの抽象的な記述、またときには、ブロードキャストの場合では発生済みおよび通知済みの記述、を保持する活動することのないデータの構造です。コンポーネントの各タイプに対応する配信のメカニズムは以下のように分類できます。

  • インテントオブジェクトを Context.startActivity() または Activity.startActivityForResult() に渡し、アクティビティを起動または、新たなことを実行する既存のアクティビティを取得します ( これは、startActivityForResult() を呼び出したアクティビティに対し情報を返す Activity.setResult() にも渡すことができます ) 。
  • インテントオブジェクトを Context.startService() に渡し、サービスを開始または新たな指示を継続中のサービスに配信します。同様に、インテントをContext.bindService() に渡し、呼び出しているコンポーネントとターゲットのサービスとの間の接続を確立します。サービスが実行されていないときにサービスを開始することもオプションで可能です。

  • 任意のブロードキャストメソッド ( Context.sendBroadcast()Context.sendOrderedBroadcast()Context.sendStickyBroadcast() などといった ) に渡されるインテントオブジェクトは、関与しているすべてのブロードキャストレシーバに配信されます。さまざまな種類のブロードキャストがシステムコード内で発生します。

いずれの場合も、Android システムは、インテント ( 必要であればそれをインスタンス化して ) に応答するために、適切なアクティビティ、サービス、ブロードキャストレシーバのセットを見つけます。それらのメッセージシステム内での重複はありません。つまり、ブロードキャストインテントは、ブロードキャストレシーバのみに配信され、アクティビティやサービスに配信されることはありません。startActivity() に渡されたインテントはアクティビティのみに配信され、サービスやブロードキャストレシーバに配信されることもありません。

このドキュメントはインテントオブジェクトの説明から入ります。その後、Android はインテントをコンポーネントにマップするために使用するルール、つまり、どのコンポーネントがインテントメッセージを受け取るべきなのかをいかにして解決するのかについて説明します。ターゲットとなるコンポーネントを明示的に指名していないインテントのために、潜在的なターゲットに関連のあるインテントフィルタ に対応するインテントオブジェクトをテストするプロセスもこれに含まれています。


インテントオブジェクト

ひとつの Intent オブジェクトは情報のバンドルです。ここには、インテントを受け取るコンポーネントに関与する情報 ( 受け付けるアクションや動作をかけるデータといった ) に加え、Android システムに関与する情報 ( ハンドリングすべきコンポーネントのカテゴリやターゲットアクティビティの起動方法の指示といった ) が含まれています。 主に以下を含めることができます。

コンポーネント名
インテントをハンドリングするコンポーネント名。このフィールドは ComponentName オブジェクトです。ターゲットコンポーネントのクラスの完全修飾名と ( 例えば、"com.example.project.app.FreneticActivity" ) とそのコンポーネントが置かれている場所にあるアプリケーションのマニフェストファイルに設定されたパッケージ名 ( 例えば、"com.example.project" ) の組み合わせです。コンポーネント名のパッケージの部分とマニフェストに設定されているパッケージ名とが必ずしも一致している必要はありません。

コンポーネント名はオプションです。これが設定されている場合は、指定したクラスのインスタンスにインテントオブジェクトが配信されます。これが設定されていない場合は、Android はインテントオブジェクトの他の情報を使用して適切なターゲットを見つけます。このドキュメントの後にある インテント解決 ドキュメントを参照してください。

コンポーネント名は setComponent()setClass()、 または setClassName() で設定し、getComponent() で読み込みます。

アクション
実行されるアクションの文字列名、または、ブロードキャストの場合、動作およびレポートされるアクション。インテントクラスではたくさんのアクション定数が定義されています。以下はその一部です。


コンスタント ターゲットコンポーネント アクション
ACTION_CALL アクティビティ 通話を開始する。
ACTION_EDIT アクティビティ ユーザ編集のデータを表示する。
ACTION_MAIN アクティビティ データ入力なしかつ出力の返却なしで、タスクの初期アクティビティとして開始する。
ACTION_SYNC アクティビティ モバイルデバイス上のデータを使ってサーバのデータを同期化する。
ACTION_BATTERY_LOW ブロードキャストレシーバ バッテリー残量が少ないときの警告。
ACTION_HEADSET_PLUG ブロードキャストレシーバ ヘッドセットがデバイスに取り付けられた、またはそこから取り外された。
ACTION_SCREEN_ON ブロードキャストレシーバ スクリーンが ON になった。
ACTION_TIMEZONE_CHANGED ブロードキャストレシーバ タイムゾーンの設定が変更された。

定義済みの一般的アクション定数のリストは Intent クラスの説明を参照してください。Android API のさまざまな場所に他のアクションが定義されています。アプリケーションのコンポーネントをアクティベートするための独自のアクション文字列を定義することも可能です。 考案したものはアプリケーションのパッケージをプレフィックスに含める必要があります。例えば "com.example.project.SHOW_COLOR" のようにします。

アクションの役割はインテントの残りの部分 ( 特に データエクストラ フィールド ) の構造化の方法を決定するのが大部分で、メソッド名が引数と戻り値のセットを決定するのと同じくらい重要なことです。 この理由から、アクションにはできるだけ具体的を名前を使用し、インテントの他のフィールドとそれらをしっかりと連結しておくのがいいアイディアです。言い換えると、アクションを孤立させて定義するのではなく、ハンドリング可能なインテントオブジェクトに対する全体のプロトコルを定義します。

インテントオブジェクトにおけるアクションは setAction() メソッドで設定し、getAction() で読み込みます。

データ
活動対象データの URI およびデータの MIME タイプ。さまざままアクションがさまざまな種類のデータ使用と対になっています。例えば、アクションのフィールドが ACTION_EDIT  の場合、 データのフィールドはこれから編集される目的で表示されているドキュメントの URI になるでしょう。アクションのフィールドが ACTION_CALL の場合、データのフィールドは呼び出す電話番号が付加された tel: URI になるでしょう。同じように、アクションが ACTION_VIEW でデータのフィールドが http: URI の場合、受信するアクティビティは URI で参照されるデータをダウンロードし表示するという処理を担うことになるでしょう。

インテントとデータをハンドリングできるコンポーネントをマッチングさせているときに、URI に加えデータのタイプ ( その MIME タイプ ) を知っておくことが重要になる場合があります。例えば、イメージを表示できるコンポーネントがオーディオファイルを再生を担わされることなでないはずです。

多くの場合、データタイプは URI から推測されます。特に content: URI は、デバイス上に配置され、コンテントプロパイダにより制御されるデータであることを示しています ( コンテンツプロバイダ で詳解していますのでそれを参照してください ) 。 しかし、このタイプはインテントオブジェクトで明示的に設定することができます。 setData() メソッドは URI としてのみデータを特定し、 setType() は MIME タイプとしてのみデータを特定し、setDataAndType() は URI、 MIME タイプ両方で特定します。URI は getData() で、タイプは getType() で、読み込みます。


カテゴリ
インテントをハンドリングすべきコンポーネントの種類に関する付加的な情報を含んだ文字列。カテゴリ記述をインテントオブジェクトにいくつでも配置することができます。アクションでもそうだったように、インテントクラスはさまざまなカテゴリ定数を定義していて、以下はその一部です。

コンスタント 意味
CATEGORY_BROWSABLE リンクで参照されているデータを表示するためにブラウザにより安全に呼び出すことができるターゲットアクティビティ。例えば、イメージまたは e-mail メッセージ。
CATEGORY_GADGET ガジェットのホストになっている別のアクティビティを内部に組込み可能なアクティビティ。
CATEGORY_HOME ホームスクリーンを表示するアクティビティで、最初の画面が見えるのはデバイスがオンになったとき、または HOME キーが押されたとき。
CATEGORY_LAUNCHER タスクの初期アクティビティになれるまたはアプリケーションランチャーのトップレベルにリストされているアクティビティ。
CATEGORY_PREFERENCE プリファレンスパネルがターゲットのアクティビティ。

カテゴリのすべてのリストについては、Intent クラスの説明を参照してください。

addCategory() メソッドはインテントオブジェクトにカテゴリを格納し、removeCategory() は過去に追加されたカテゴリを削除し、 getCategories() はオブジェクトに現時点で設定されているすべてのカテゴリを取得します。

エクストラ
インテントをハンドリングするコンポーネントに配信されるべき追加情報のキーと値のペア。アクションでは、URI のデータの特定の種類でペアとなっているものもありますが、それと同じように、特定のエクストラでペアとなっているものがあります。例えば、 ACTION_TIMEZONE_CHANGED インテントは "time-zone" という新たなタイムゾーンを識別するエクストラを持っており、 ACTION_HEADSET_PLUG は "state"  というヘッドセットが差し込まれたか抜かれたか、また同様に "name" というヘッドセットのタイプを示すエクストラを持っています。もし SHOW_COLOR アクションを考案した場合は、色の値がエクストラのキーと値のペアで設定されるのではないでしょうか。

インテントオブジェクトは、さまざまなタイプのエクストラデータを挿入するためにある put...() メソッドと、それと同様にデータを読み出すためにある get...() メソッドのシリーズです。これらのメソッドは Bundle オブジェクトのそれらに似ています。実際は、エクストラはひとつの Bundle として putExtras()getExtras() メソッドを使用してインストール可能で読み込まれるようになります。

フラグ
さまざまな種類のフラグ。Android システムに対し、アクティビティの起動方法 ( 例えば、アクティビティが属するべきアクティビティはどのタスクか ) 、起動後のその扱い ( 例えば、最近のアクティビティのリストにそれが属しているかどうか ) など多くの指示を出します。 これらすべてのフラグはインテントクラスで定義されます。

プラットフォームに搭載された Android システムとアプリケーションは、システムから発せられたブロードキャストを送出する、および、システムで定義済みのコンポーネントをアクティベートする、という両方の目的でインテントオブジェクトを採用します。 システムコンポーネントをアクティベートするためのインテントの構造化の方法について知るために、レファレンスの インテントのリスト を参考にしてください。


インテント解決

インテントはふたつのグループに分類されます。

  • 明示インテント は、ターゲットのコンポーネントをその名前 ( 最初の方で出てきた コンポーネント名 フィールドでセットする値 ) で指名します。一般的に コンポーネント名は他のアプリケーションの開発者には知らされないので、通常、明示インテントはアプリケーション内部でのメッセージとして使用されます。従属するサービスを開始したり、姉妹のアクティビティを起動するアクティビティのなどに使用します。
  • 暗黙インテント は、ターゲットの名前を指定しません ( コンポーネント名のフィールドは空です ) 。暗黙インテントは、他のアプリケーションをアクティベートする際に頻繁に使用されます。

Android は指定したターゲットクラスのインスタンスに明示インテントを届けます。どのコンポーネントがインテントを取得すべきかを決定する目的においては、インテントオブジェクト内には、コンポーネント名以外重要な情報はありません。

別の戦略として必要とされているのが暗黙インテントです。ターゲットの指定がない場合は、Android システムはインテントをハンドリングする最適なコンポーネント ( または複数のコンポーネント ) 見つける必要があります。要求されたアクションを実行する単一のアクティビティまたはサービス、または、ブロードキャストの告示に応答するブロードキャストレシーバのセットがそれに該当します。インテントオブジェクトのコンテンツと インテントフィルタ 、つまり潜在的にインテントを受信することができるコンポーネントに関連のある構造、とを比較することでそれを行います。フィルタは、コンポーネントの能力を公表し、ハンドリングできるインテントを制限します。それらにより公表されたタイプの暗黙インテントを受信する可能性のあるコンポーネントがオープンにされます。 コンポーネントがインテントフィルタを何も持っていない場合は、明示インテントのみしか受信しません。フィルタのあるコンポーネントは明示、暗黙両方のインテントを受信することができます。

インテントオブジェクトがインテントフィルタを通してテストされ、そのオブジェクトの調査が行われるのは以下の 3 つの局面のみです。

アクション
データ ( URI とデータタイプ共に )
カテゴリ

エクストラとフラグはインテントを受信するコンポーネントの解決には役立ちません。

インテントフィルタ

どの暗黙インテントがハンドリングできるのかということをシステムに知らせるため、アクティビティ、サービス、およびブロードキャストレシーバは、ひとつ以上のインテントフィルタを持つことができます。各フィルタは、コンポーネントの機能、そのコンポーネントが受信を希望するインテントのセットが記述されています。実際は、目的としているインテントをフィルタで取り込み、一方では望んでいないインテントをフィルタで除去しています。しかしその対象は望んでいない暗黙インテント( ターゲットクラスを指名していないもの ) だけです。明示インテントはそのコンテントが何であっても、常にそのターゲットに配信します。つまり、フィルタによる調査は行なわれません。しかし、暗黙インテントは、通過できるコンテントのフィルタがある場合のみ、コンポーネントに配信されます。

コンポーネントは実行可能な各ジョブ、ユーザに見せる各外観に対し、個別にフィルタを保持しています。例えば、サンプル Note Pad アプリケーションの NoteEditor アクティビティは 2 つのフィルタを持っています。ひとつはユーザが参照または編集可能な特定のノートを開始し、もうひとつはユーザが記入に保存可能な新しいブランクのノートを開始します。 ( Note Pad のフィルタの全てについては後半のセクションの Note Pad サンプル で説明されています ) 。

フィルタとセキュリティ

インテントフィルタはセキュリティに頼ることができません。インテントフィルタが、確かな種類の暗黙インテントのみを受信するコンポーネントをオープンにしている間は、ターゲットのコンポーネントから明示インテントを妨げるものは何もありません。フィルタがインテントを制限していたとしても、コンポーネントは明確なアクションとデータソースをハンドリングするよう求め、誰かが別のアクションとデータソースを使用して、明示インテントを常に組み立て、コンポーネントをターゲットに指名できるようになります。

インテントフィルタは IntentFilter クラスのインスタンスです。しかしながら、Android システムは、コンポーネントの機能についてそのコンポーネントを起動する前に知っている必要があることから、通常インテントフィルタは Java コードではなく、アプリケーションのマニフェストファイル ( AndroidManifest.xml ) の <intent-filter> 要素で設定します。( 例外としては Context.registerReceiver() を呼び出すことにより動的に登録されたブロードキャストレシーバがひとつあります。それらは IntentFilter で直接作成されます) 。

フィルタには、インテントのフィールドと同じく、アクション、データ、およびカテゴリのフィールドがあります。暗黙インテントは 3 つのエリアでフィルタに接触し、テストが行われます。フィルタを持つコンポーネントに配信するために、3 つのテストをパスする必要があります。そのうちのひとつでも失敗した場合、Andorid システムはそのインテントをコンポーネントに配信しません。そうなるとコンポーネントはそのフィルタに基づいていないことは確かです。しかしながら、コンポーネントは複数のインテントフィルタを保持できることから、コンポーネントのフィルタのうちのひとつも通過しないインテントは、別のコンポーネントでもすり抜ける可能性があります。 少なくともそのフィルタに該当していないことになります。しかしながら、ひとつのコンポーネントで複数のフィルタを持てることから、インテントがそのコンポーネントにあるフィルタのひとつを通らなかったとしても、別のフィルタに適合する可能性があります。

以下に、各 3 つのテストの詳細を説明します。

アクション テスト
マニフェストファイルの <intent-filter> 要素に、サブ要素としてアクションを <action> で列挙します。以下はそのサンプルです。
<intent-filter . . . >
<action android:name="com.example.project.SHOW_CURRENT" />
<action android:name="com.example.project.SHOW_RECENT" />
<action android:name="com.example.project.SHOW_PENDING" />
. . .
</intent-filter>

サンプルにあるように、インテントオブジェクトの場合はひとつのアクションだけしか指名できませんでしたが、ひとつのフィルタに複数列挙することができます。このリストを空にすることはできません。フィルタは少なくともひとつの <action> 要素を含める必要がありますが、何も指定しない場合はすべてのインテントがブロックされます。

このテストにパスするために、インテントオブジェクトで特定されたアクションは、フィルタで列挙されたアクションのひとつに合致している必要があります。フィルタにこのオブジェクトが特定されていないまたはアクションが特定されていない場合、結果は以下のようになります。

  • フィルタがアクションをリストする時点で失敗した場合、適合するインテントがないため、すべてのインテントのテストが失敗します。フィルタを通過できるインテントはありません。
  • 他方では、アクションを特定できないインテントオブジェクトは自動的にテストにパスします。但しフィルタに最低でもひとつのアクションが含まれでいる限りにおいてです。

カテゴリ テスト
同様に、 <intent-filter> 要素にサブ要素とカテゴリを列挙します。以下はサンプルです。
<intent-filter . . . >
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
. . .
</intent-filter>

前半で説明したアクションとカテゴリの定数は、マニフェストファイルでは使用されないという点に注意してください。その代わりすべて文字列の値になります。例えば、上のサンプルの文字列 "android.intent.category.BROWSABLE" は、このドキュメントの前半で述べたCATEGORY_BROWSABLE 定数に対応しています。 同じように、文字列 "android.intent.action.EDIT" は ACTION_EDIT 定数に対応しています。

カテゴリテストにパスするインテントに対しては、インテントオブジェクトのすべてのカテゴリは、フィルタのカテゴリと一致している必要があります。フィルタに追加のカテゴリを列挙することができますが、インテントにあるカテゴリを削除することはできません。

原則にしたがって、カテゴリを持たないインテントオブジェクトは、フィルタの内容とは無関係に、常にテストにパスしなければなりません。 これはほとんど正しいのですが、ひとつだけ例外があり、Android は、 startActivity() で渡されたすべての暗黙インテントを少なくともひとつのカテゴリ、"android.intent.category.DEFAULT" (  CATEGORY_DEFAULT 定数 ) を含んでいるかのように扱います。したがって、暗黙インテントの受信を望んでいるアクティビティは、インテントフィルタに "android.intent.category.DEFAULT" を含める必要があります ("android.intent.action.MAIN" と "android.intent.category.LAUNCHER" をフィルタに設定した場合はその例外になります。この設定により、新たなタスクを開始し、起動スクリーンを表示するような印がアクティビティに付けられます。 "android.intent.category.DEFAULT" をカテゴリのリストに含めることができますが必須ではありません ) 。この後の インテントマッチングの使用 でこれらのフィルタについてもう少し説明します。

データ テスト
アクション、カテゴリと同じように、インテントフィルタに対するデータ仕様がサブ要素に含まれます。かつ、このケースでは、サブ要素は複数指定可能、または、何も指定しないことも可能です。以下はサンプルです。
<intent-filter . . . >
<data android:mimeType="video/mpeg" android:scheme="http" . . . />
<data android:mimeType="audio/mpeg" android:scheme="http" . . . />
. . .
</intent-filter>

<data> 要素には、URI およびデータタイプ ( MIME メディアタイプ ) を特定できます。個別の属性、schemehostport、および path があり、以下のように URI の部分に対応しています。

scheme://host:port/path

例えば、以下の URI であれば、

content://com.example.project:200/folder/subfolder/etc

 scheme は "content"、 host は "com.example.project"、 port は "200"、そして path は "folder/subfolder/etc" です。ホストとポートを合わせて URI の 情報源 を構成し、ホストが特定されていない場合、ポートは無視されます。

各属性はオプションですが、それぞれ独立していません。情報源に意味を持たせるためには、scheme も指定されていなければなりません。 path に意味を持たせるためには、scheme、authority がともに特定されていなければなりません。

インテントオブジェクトの URIと、フィルタの URI の指定との比較が行われているときには、実際のフィルタで記述されている URI の部分のみが比較されています。例えば、フィルタに scheme だけが特定されていれば、その scheme と同じすべての URI とそのフィルタが合致します。フィルタが scheme と 情報源が特定され、 path が特定されていない場合は、インテントの path とは無関係に、その scheme と 情報源のが同じすべての URI と合致します。 フィルタが scheme、情報源、および path を特定した場合は、scheme、情報源、および path が同じ URI のみと合致します。しかしながら、フィルタにおける path の特定では、ワイルドカードが使用でき、path の部分一致の照合が要求できます。

<data> 要素の type 属性でデータの MIME タイプ を特定します。これはフィルタの URI とくらべるとごく普通です。インテントオブジェクトとフィルタの両方に "*" ワイルドカードをサブタイプフィールドに使用できます。例えば、"text/*" や "audio/*" で何らかのサブタイプの一致を意味します。

データのテストでは、インテントオブジェクトの URI とデータタイプ両方と、フィルタの URI とデータタイプを比較します。そのルールは以下のようになります。

  1. URI と データタイプが共に含まれていないインテントオブジェクトは、フィルタも同じように URI または データタイプが特定されていない場合に限り、テストにパスします。
  2. URI が含まれ、データタイプが含まれていない ( および URI からタイプが推測されない ) インテントオブジェクトは、その URI とフィルタの URI が合致し、フィルタも同じようにタイプが特定されていない場合に限り、テストにパスします。これは、 mailto:tel: のように実際のデータを参照しない URI のケースになります。

  3. URI が含まれず、データタイプが含まれるインテントオブジェクトは、フィルタに同じデータタイプが列挙され、URI には同じように特定されていない場合に限り、テストにパスします。

  4. URI と データタイプが共に含まれている ( または URI からタイプが推測される) インテントオブジェクトは、タイプがフィルタに列挙されているタイプに一致する場合に限り、タイプ 部のテストにパスします。 URI と フィルタの URI に適合した場合、または、content: または file: URI を持ち、かつフィルタが URI を特定しない場合のいずれかの場合にURI 部のテストにパスします。言い換えるなら、フィルタにデータタイプのみが列挙されている場合、コンポーネントは、 content:file: データをサポートするとみなされます。

インテントがひとつ以上のアクティビティまたはサービスのフィルタを通過できる場合、ユーザにどのコンポーネントをアクティベートするのかを尋ねられる場合があります。ターゲットが見つからない場合は、例外が発生します。

一般的なケース

上記のデータテスト、ルールでの最後のルールは、コンポーネントはファイルまたはコンテンツプロバイダからローカルデータを取得できるということを期待していることを示しています。したがって、フィルタは、ただデータタイプに合うものを列挙し、明示的に scheme に content:file: は指名する必要はありません。これが一般的なケースです。例えば、以下の <data> 要素のようにすることで、コンポーネントはコンテンツプロバイダからイメージデータを取得し、それを表示できることを Android に伝えます。

<data android:mimeType="image/*" />

利用可能なデータはほとんどコンテンツプロバイダにより投入されることから、データタイプが指定されていて URI 指定されていないデータが最も一般的です。

もうひとつ一般的な設定としては、scheme と データタイプでのフィルタがあります。例えば、以下の <data> 要素のようにすることで、コンポーネントはネットワークからビデオデータを取得し、それを再生できることを Android に伝えます。

<data android:scheme="http" android:type="video/*" />

例えば、ユーザがウェブページ上のリンクを追いかけたときのブラウザアプリケーションの動作を考えてみてください。まず始めにデータ表示( リンクがHTML ページなら可能なはずだということで ) を試みます。データを表示できない場合、scheme と データタイプを持つ暗黙インテントを組み立て、そのジョブを実行できるアクティビティを開始します。それを受け付けるものが何もない場合は、ダウンロードマネージャにデータをダウンロードするよう要求します。これをコンテンツプロバイダのコントロール下に置くことで、潜在的に大きな ( フィルタにデータタイプを指名しているだけの ) アクティビティのプールが応答することができます。

アプリケーションのほとんどは、なんらかの特定のデータを参照することなく、きれいな状態で開始する方法を持ち合わせています。アプリケーションを初期化できるアクティビティは、アクションとして"android.intent.action.MAIN" が特定されたフィルタをもっています。そのフィルタにアプリケーションランチャーを表示させることにするなら、 "android.intent.category.LAUNCHER" カテゴリも特定します。

<intent-filter . . . >
<action android:name="code android.intent.action.MAIN" />
<category android:name="code android.intent.category.LAUNCHER" />
</intent-filter>

インテントマッチングの使用

インテントフィルタに接触し、インテントのマッチングが行われる目的として、アクティベートするターゲットを発見するということだけでなく、デバイス上のコンポーネントのセットに関連する何かを発見するというのがあります。例えば、 "android.intent.action.MAIN" アクションと"android.intent.category.LAUNCHER" カテゴリが使用されているインテントフィルタを見つけることで (前のセクションで詳解しているように )、Android システムはアプリケーションランチャーを投入し、ユーザがアプリケーションを起動できることをトップレベルのスクリーンで表示します。  その後、ランチャーでそれらのアクティビティのアイコンとラベルが表示します。同じように、システムはそのフィルタに "android.intent.category.HOME" を持つアクティビティを探し、ホームスクリーンを発見します。

作成したアプリケーションでも同じ方法でインテントのマッチングを使用することができます。PackageManagerquery...() メソッドのセットを持っていて、それらのメソッドは特定のインテントを受け付けるすべてのコンポーネントを返却し、同じように resolve...() メソッドで、インテントに最も適合するコンポーネントを決定します。例えば、 queryIntentActivities() は引数で与えられたインテントを実行可能なすべてのアクティビティのリストを返却し、 queryIntentServices() は同じようにサービスのリストを返却します。2つのメソッドは共にコンポーネントをアクティベートすることはありません。つまり、応答できるもののリストなだけです。ブロードキャストレシーバにも同じような queryBroadcastReceivers() メソッドがあります。


Note Pad サンプル

Note Pad サンプルアプリケーションにより、ユーザはノートのリストを閲覧し、リストの個別アイテムの詳細を参照し、そのアイテムを編集し、新たなアイテムをリストに追加することができます。このセクションでは、マニフェストファイルで宣言されているインテントフィルタに注目します ( SDK をオフラインで動かしている場合は、このサンプルのアプリケーションのマニフェストファイルを含むすべてのソースファイルが <sdk>/samples/NotePad/index.html にあります。オンラインでドキュメントを参照する場合は、ここの セクションの チュートリアルとサンプルコード にソースファイルがあります ) 。

Note Pad アプリケーションは、このマニフェストファイルで3 つのアクティビティを宣言しており、それぞれ少なくともひとつのインテントフィルタがあります。またここには、ノートのデータを管理するコンテンツプロバイダも宣言しています。これはまったくそのままのマニフェストファイルです。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.notepad">
<application android:icon="@drawable/app_notes"
android:label="@string/app_name" >

<provider android:name="NotePadProvider"
android:authorities="com.google.provider.NotePad" />

<activity android:name="NotesList" android:label="@string/title_notes_list">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
</activity>

<activity android:name="NoteEditor"
android:theme="@android:style/Theme.Light"
android:label="@string/title_note" >
<intent-filter android:label="@string/resolve_edit">
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="com.android.notepad.action.EDIT_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>
</activity>

<activity android:name="TitleEditor"
android:label="@string/title_edit_title"
android:theme="@android:style/Theme.Dialog">
<intent-filter android:label="@string/resolve_title">
<action android:name="com.android.notepad.action.EDIT_TITLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>
</activity>

</application>
</manifest>

最初のアクティビティである NotesList は、単一のノートというよりは複数のノートのディレクトリ ( ノートのリスト ) を操作するという事実により、他のアクティビティと区別されます。これは通常はアプリケーションに初期のユーザインターフェースを供給するものです。3 つのインテントフィルタにより記述されていることにより、以下の 3 つのことが実現できます。

  1. <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    このフィルタは、 Note Pad アプリケーションのメインのエントリポイントを宣言しています。標準の MAIN アクションはインテントに他のどんな情報も要求しないエントリポイントであり ( たとえば、データ未指定 ) 、 LAUNCHER カテゴリはこのエントリポイントがアプリケーションランチャーにリストされている必要があることを述べています。

  2. <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.PICK" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
    </intent-filter>

    このフィルタはノートのディレクトリ上でアクティビティができることを宣言しています。これによりユーザはディレクトリを ( VIEWEDIT アクションを介して ) 参照または編集したり、ディレクトリから個別のノートを ( PICK アクションを介して ) 拾い上げることができるようになります。

    <data> 要素の mimeType 属性はそれらのアクションが動作するデータの種類を特定します。Note Pad のデータ ( vnd.google.note ) を保持しているコンテンツプロバイダからカーソルのゼロ位置やアイテム (vnd.android.cursor.dir) を取得することができるアクティビティを意味します。アクティビティを起動するインテントオブジェクトは、アクティビティがオープンすべきタイプの的確なデータを特定する content: URI を含んでいます。

    このフィルタで DEFAULT カテゴリが提供されている点にも注目してください。ここにあるのは、Context.startActivity()Activity.startActivityForResult() メソッドがすべてのインテントを DEFAULT カテゴリを含んでいるかのように振る舞うことがその理由です。但し、以下の例外がふたつだけあります。

    • 明示的にターゲットアクティビティを指名するインテント
    • MAIN アクションと LAUNCHER カテゴリで構成されたインテント

    したがって、DEFAULT カテゴリはMAIN アクションと LAUNCHER カテゴリを含めたフィルタを除くすべてのフィルタで 必須 です ( インテントフィルタは明示インテントでは調査されません ) 。

  3. <intent-filter>
    <action android:name="android.intent.action.GET_CONTENT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
    </intent-filter>

    このフィルタには、ユーザが選択するディレクトリの特定を求めることなくユーザにより選択されたノートが返される能力がこのアクティビティにはある、というということが記述されています。GET_CONTENT アクションは PICK アクションと似ています。どちらのケースでも、アクティビティが返却するのは、ユーザにより選択されたノートの URI です ( どのケースでも、startActivityForResult() を呼び出してNoteList アクティビティを開始したアクティビティに返されます ) 。しかしながら、ここでは、呼び出し元はユーザが取り出す先として、データのディレクトリではなく目的のデータのタイプを特定しています。

    データタイプの vnd.android.cursor.item/vnd.google.note は、アクティビティが返却可能なデータのタイプを示しています。この場合は、個別のノートのURIになります。返されたURI を元に、呼び出し元は、正確に 1 件のアイテムに対するカーソルを、Note Pad データ ( vnd.google.note ) を保持しているコンテンツプロバイダから取得できます。

    言い換えると、前のフィルタにある PICK アクションに対しては、このデータタイプは、アクティビティがユーザに表示可能であるデータのタイプを示し、GET_CONTENT フィルタに対しては、アクティビティが呼び出し元に返却可能なデータのタイプであることを示しています。

これらの機能を与えられ、以下のインテントが NotesList アクティビティを解決します。

アクション: android.intent.action.MAIN
データを特定せずにアクティビティを起動します。
アクション: android.intent.action.MAIN
カテゴリ: android.intent.category.LAUNCHER
データ選択の特定せずにアクティビティを起動します。これはトップレベルのリストを投入するランチャーにより使用される実際のインテントです。このアクションをカテゴリに合致するフィルタを使うすべてのアクティビティがリストに追加されます。
アクション: android.intent.action.VIEW
データ: content://com.google.provider.NotePad/notes
content://com.google.provider.NotePad/notes の下のすべてのノートのリストを表示するアクティビティを要求します。これによりユーザはリストを閲覧しそこにあるアイテムの情報を取得できます。
アクション: android.intent.action.PICK
データ: content://com.google.provider.NotePad/notes
content://com.google.provider.NotePad/notes の下のノートのリストからノートを選択するアクティビティを要求します。これによりユーザはリストからノートを抜き取り、アクティビティはこのアイテムに対する URI を NoteList アクティビティを開始したアクティビティに返します。
アクション: android.intent.action.GET_CONTENT
データタイプ: vnd.android.cursor.item/vnd.google.note
個別のNote Padデータのアイテムを提供するアクティビティを要求します。

2 番目のアクティビティである NoteEditor は、ユーザに個別のノートへの項目を示し、その編集をユーザに許可します。2 つのインテントフィルタにより記述されていることにより以下のふたつのことができます。

  1. <intent-filter android:label="@string/resolve_edit">
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />
    <action android:name="com.android.notepad.action.EDIT_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
    </intent-filter>

    最初は、ユーザに個別のノートで相互作用させる、つまり参照 ( VIEW ) または 編集 ( EDIT ) させることを可能にすることが、このアクティビティの最も重要な目的です (EDIT_NOTE カテゴリは、EDIT と同じ意味です) 。このインテントは MIME タイプの vnd.android.cursor.item/vnd.google.note に合致するデータの URI を含みます。これは、個別の特定されたノートの URI になります。これは、一般的に  NoteList アクティビティの PICK または GET_CONTENT アクションにより返却される URI になります。

    前にもあったように、このフィルタに列挙されている DEFAULT カテゴリにより、明示的に NoteEditor クラスを特定していないインテントでもアクティビティが起動できるようになります。

  2. <intent-filter>
    <action android:name="android.intent.action.INSERT" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
    </intent-filter>

    ユーザに新たなノートを作成させることを可能にすることが、このアクティビティの次に重要な目的で、このアクティビティは既存のノートディレクトリにノートを挿入( INSERT ) します。このインテントは MIME タイプの vnd.android.cursor.dir/vnd.google.note に合致するデータの URI を含みます。これは、ノートが配置される場所のディレクトリに対する URI です。

これらの機能を与えられ、以下のインテントが NotesEditor アクティビティを解決します。

アクション: android.intent.action.VIEW
データ: content://com.google.provider.NotePad/notes/ID
ID で識別されたノートの内容を表示するアクティビティを要求します (  content: URI がグループの個別のメンバーを特定する詳しい方法については、コンテンツプロバイダ を参照してください ) 。
アクション: android.intent.action.EDIT
データ: content://com.google.provider.NotePad/notes/ID
ID で識別されたノートの内容を表示し、ユーザがそれを編集できるアクティビティを要求します。ユーザが変更を保存した場合、アクティビティはコンテンツプロバイダのノートデータを更新します。
アクション: android.intent.action.INSERT
データ: content://com.google.provider.NotePad/notes
新しいノートを作成し、 content://com.google.provider.NotePad/notes にあるノートリストに新しい空のノートを作成し、ユーザがそれを編集できるアクティビティを要求します。ユーザがそのノートを変更した場合はその URI が呼び出し元に返却されます。

最後のアクティビティである TitleEditor によりユーザはノートのタイトルを編集できます。これはインテントフィルタは使わず 、アクティビティを直接呼び出す ( 明示的にそのコンポーネントをインテントに指名する ) ことにより実装できます。しかし、いい機会ですので、既存のデータでを別の動作を公開する以下のやり方を紹介します。

<intent-filter android:label="@string/resolve_title">
<action android:name="com.android.notepad.action.EDIT_TITLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter>

このアクティビティに対するインテントフィルタは、 "com.android.notepad.action.EDIT_TITLE" というカスタムのアクションを使用します。これは、前の VIEWEDIT アクションのように、特定のノート ( データタイプが vnd.android.cursor.item/vnd.google.note ) に呼び出される必要があります。しかしながら、ここでのアクティビティはノートデータに含まれるタイトルを表示し、ノートの内容そのものを表示するものではありません。

通常の DEFAULT カテゴリのサポートに加え、タイトルエディタは、 ALTERNATIVESELECTED_ALTERNATIVE のふたつの標準カテゴリをサポートします。これらのカテゴリはメニューのオプションでユーザに提供することのできるアクティビティを識別します ( LAUNCHER カテゴリもまったく同じで、アプリケーションランチャーでユーザに提供されるアクティビティを識別します ) 。フィルタもまた明示的なラベルを (  android:label="@string/resolve_title" を使って ) 提供している点に注目してください。これは、ユーザが現在参照しているデータに対する代替のアクションとしてこのアクティビティがいつ提示されるのかということをユーザが分かるようより良くコントロールするためです( それらのカテゴリとオプションメニューの構築についてのさらに詳しい情報は、 PackageManager.queryIntentActivityOptions()Menu.addIntentOptions() メソッドを参照してください ) 。

これらの機能を与えられ、以下のインテントが TitleEditor アクティビティを解決します。

アクション: com.android.notepad.action.EDIT_TITLE
データ: content://com.google.provider.NotePad/notes/ID
ノート ID に関連のあるタイトルを表示するアクティビティを要求し、ユーザのタイトル編集を可能にします。