謎めいたインテント
前回の画面遷移のところで出てきた、インテントについて調べてみたが、結構奥が深くまだまだ謎の部分が多い。
とりあえず、わかる範囲でまとめてみる。
画面遷移の復習
まず、画面遷移の復習として、 前回の画面遷移プログラム2と 画面遷移プログラム3 を合体して、遷移先アクティビティと遷移先アクティビティで相互にデータをやりとりするプログラムの例を示します。
ここでは、ただ単に2つのプログラムを合体するだけでは面白くないので、遷移元アクティビティと遷移先アクティビティ を異なるパッケージに実装する事にします。
画面遷移プログラム4(1)-遷移元アクティビティ(ActivityTarget.java)
画面遷移プログラム4(2)-遷移先アクティビティ(OtherActivity.java)
前回同様、マニフェストファイル(AndroidManifest.xml)には、遷移先のアクティビティの登録が必要です。
画面遷移プログラム2と画面遷移プログラム3を合体しただけなので、 特にプログラムの説明は必要無いと思います。
コンポーネント
本題のインテントに入る前に、もうちょっと寄り道してアンドロイドのコンポーネントについて簡単にまとめてみます。
コンポーネントという言葉は、アクティビティのウィジェットを指す時にも使われますが、 ここでいうコンポーネントとは、それとは別のアプリケーションの構成要素としてのコンポーネントです。
アプリケーションのコンポーネントとは、システムの要求に応じて呼び出す事ができるアプリケーションの構成要素です。
そのアプリケーションが許可していれば、インテントを利用してアプリケーションより、他のアプリケーションを呼び出す事ができます。
アプリケーションは、コンポーネント単位で呼び出す事ができます。
今まで、アンドロイドのアプリケーションのコンポーネントとして、アクティビティクラスを作成してきました。
コンポーネントにはアクティビティの他にも、サービス, ブロードキャストレシーバ,コンテンツ プロバイダと呼ばれるコンポーネントが存在していて、 必要に応じて呼び出す事ができます。
- アクティビティ
コンポーネントでは唯一GUIを持ち、フォアグランドでユーザと対話する事ができるコンポーネントです。
Activityクラスを継承したクラスとして実装されます。
画面遷移の例でみてきたように、startActivityメソッドやstartActivityForResultメソッドを使って起動されます。
画面遷移の例では自アプリケーション内のアクティビティを呼び出していましたが、これらのメソッドを使って他のアプリケーションのアクティビティを呼び出す事もできます。 - サービス
バックグラウンドで動作し、アプリケーションの要求に応じて、いろいろなサービスを提供するコンポーネントです。
よくとりあげられるmp3などの音楽ファイルの演奏の例をあげると、アクティビティを起動して、GUIにより音楽ファイルを選択してサービスに渡すと、 音楽ファイルの演奏にもうGUIは必要無いので、別のアプリケーションを使うためアクティビティを終了させる事があります。
アクティビティが終了しても、音楽ファイルの演奏をし続けます。
これは、起動したアクティビティが終了しても、サービスはまだ生き続ける事ができるためです。
サービスはServiceクラスを継承したクラスとして実装されます。
startServiceメソッドでサービスを起動して、 stopServiceメソッドを使って停止する事ができます。
また、bindServiceメソッドで接続を確立して、unbindServiceメソッドで接続を解除する事もできます。
サービスのプログラムの例については「サービスとNotification」を参照して下さい。 - ブロードキャストレシーバ
ブロードキャスト レシーバは、ブロードキャストの連絡を受信して、それに対処する処理を受け持つコンポーネントです。
たとえばタイム ゾーンが変更されり、電池の残量が少なくなった事を検知するなど、何らかの状態が変化した時に、 これをアプリケーションに知らせるためにブロードキャストが送信されます。
アプリケーションでは、これをブロードキャストレシーバで受診して、何らかの処理をおこなう事になります。
ブロードキャストレシーバはBroadcastReceiverクラスを継承したクラスとして実装します。
ブロードキャストによる配信が必要なった場合は、sendBroadcast等のメソッドを使って配信をおこないます。
ブロードキャストレシーバのプログラムの例については「ブロードキャストレシーバ」を参照して下さい。 - コンテンツ プロバイダ
コンテンツ プロバイダは、データを管理していて、 アプリケーションからデータに対する要求があった場合に、データの処理をおこないます。
ContentProviderクラスを継承したクラスとして実装されます。
コンテンツ プロバイダのプログラムの例については「コンテンツ プロバイダ」を参照して下さい。
アプリケーションがコンポーネントを認識するためには、 マニフェストファイル(AndroidManifest.xml )へのコンポーネントの登録が必要です。
インテントの要素とインテントフィルタ
アプリケーションから、コンテンツ プロバイダ以外のコンポーネントを呼び出す場合には、 インテントにコンポーネントの呼び出し情報をセットして渡してやる必要があります。
コンテンツ プロバイダでは、ContentResolverを使ってデータのやりとりをおこないます。
インテントとは意図とか目的という意味ですが、 この場合の意図とは、アプリケーションをどのように呼び出すかという呼び出し側の意図を、意味しているものと思われます。
インテントの要素
インテントを使ってコンポーネントを呼び出す場合には、以下のようなインテントオブジェクトの要素に呼び出し情報を指定します。
- コンポーネント名
インテントにコンポーネント名を指定して、コンポーネントを呼び出す事ができます。
これを、「明示的」なコンポーネントの呼び出しといいます。
コンポーネント名の指定は、Classオブジェクトを引数に指定してsetClassメソッドを使って指定する事ができます。
また、コンポーネント名をsetComponentメソッド,setClassNameメソッド を使って、 パッケージ名とコンポーネントのクラス名で指定する事もできます。
パッケージ名は、アンドロイドプロジェクトを作成する時に指定したパッケージ名 (すなわちマニュフェストファイルのmanifestタグのpackage属性の値)を指定します。
クラス名はコンポーネントのクラス名を、クラスの完全修飾名で指定します。 - アクション
アクション名を使って、コンポーネントを「暗黙的」に呼び出す事もできます。 - データ
データにはURIとデータタイプを指定します。 URIはscheme,host,port,pathで構成されていて、「scheme://host:port/path」の形式で指定します。 データタイプはデータの MIMEタイプを、例えばjpeg画像をやりとりする場合には「image/jpeg」を指定します。 - カテゴリ
カテゴリは定義済みの値で、コンポーネントの付加的な情報を指定します。
例えば、アプリケーション ランチャにコンポーネントを表示する場合は、「android.intent.category.LAUNCHER」を指定します、 - エクストラ
エクストラは画面遷移プログラム4の例のように、putExtraメソッド等を使ってハッシュマップのようにキーと値を指定して、呼び出し先に呼び出し元のパラメータを渡す事ができます。 - フラグ
定義済みのフラグを指定して呼び出されるコンポネントの起動方法を指定できるようです。
それぞれの要素に、どうのような値を指定するかについては、参考URLの項を参照して下さい。
インテントフィルタ
コンポーネントが認識されるようにするには、マニュフェストファイルにコンポーネントに関する情報を記述する必要があります。
そして、そのコンポーネントのタグにネストして、インテントフィルタにコンポーネントを特定するインテントの要素を指定します。
言葉だけではなかなか説明しずらいので、具体なプログラムの例をみていきます。
アクションを使って他のアプリケーションのコンポーネントを呼び出す。
インテントにアクションを指定して、他のアプリケーションのコンポーネントを呼び出してみます。
Webブラウザや地図表示等のあらかじめアンドロイドに用意されているアプリケーションを呼び出す
次のプログラムでは、Webブラウザや地図表示等の、あらかじめアンドロイドに用意されているアプリケーションを呼び出します。
地図を表示するには、エミュレータのターゲットとして「Google APIs」を選択する必要があるようです。
インテントプログラム1(IntentSample1.java)
このプログラムを実行すると、以下の画面が表示されます。
「愚鈍人サイトを表示」ボタンを押すと、Webブラウザが起動して以下のように当サイトのホーム画面が表示されます。
「地図を表示」ボタンを押すと、以下のように、私の住んでいる行田市の地図が表示されます。
「DIAL」ボタンを押すと、電話のダイヤル画面が表示されます。
「ActivityTarget2」ボタンは、まだ押さないで下さい。
後で紹介するプログラムをインストールすると、自作のActivityTarget2プログラムを呼び出す事ができますが これについては後述します。
インテントプログラム1のソースを参照して下さい。
各ボタンのイベント処理メソッドは、doIntentメソッドを呼び出しています。
doIntentメソッドでは、action引数とuri引数を指定してIntentオブジェクトを作成して、startActivityメソッドを呼び出しています。
「愚鈍人サイトを表示」ボタンが押された時に渡されるアクション引数には、Intentクラスにあらかじめ定義されているACTION_VIEW定数が指定されています。
Android DevelopersのIntentクラスのリファレンスを参照すると、 ACTION_VIEW 定数には文字列「android.intent.action.VIEW」が定義されていることがわかります。
Intentクラスには、他にもアクションを示す定数が定義されていて、アンドロイドにあらかじめ用意されているアプリケーションを呼び出す事ができます。
例えば、「DIAL」ボタンの処理のようにIntent.ACTION_DIAL定数を指定すると、電話のダイヤル画面を呼び出す事ができます。
Intentオブジェクトに、アクションだけでなく前項のインテントの要素をいろいろと組み合わせて指定すると、さまざまなアプリケーションを呼び出す事ができます。
例えば、同じアクションIntent.ACTION_VIEWに対しても、 uri引数に「http」を指定するとWebブラウザが、「geo」と地図座標を指定すると地図が表示されます。
プログラムの36行目の「geo」の後の数値36.2と139.5は地図の緯度と経度を指しています。
アクションを使って自作のアンドロイドアプリケーションを呼び出す。
アクションを使って、自作のアンドロイドアプリケーションを呼び出す事もできます。
Intent.ACTION_VIEW定数を使って呼び出す事ができる、自作のアプリケーションを作成してみます。
インテントプログラム1の「ActivityTarget2」ボタンを押す事で、このアプリケーションを呼び出す事ができます。
(このプログラムは単独でも実行できますが。)
eclipseに新しいアンドロイドプロジェクトを作成して、以下のようなアクティビティクラスを作成します。
インテントプログラム2(ActivityTarget2.java)
22行目で、このアプリケーションの呼び出しに使われたインテントオブジェクトを取得して、24~44行目でこのインテントオブジェクトの要素を取り出して、TextViewに表示しています。アプリケーションから、ActivityTarget2アクティビティを呼び出す事ができるようにするためには、マニュフェストファイルにインテントフィルタの設定が必要です。
インテントプログラム2(AndroidManifest.xml)
上記のマニュフェストファイルには、インテントフィルターが2つ存在しています。
はじめの9~12行目のインテントフィルターは、アンドロイドプロジェクトが作成された時に自動的に付加されるインテントフィルターで、 アプリケーション ランチャに、このアクティビティを表示するための設定です。
このインテントフィルターのおかげで、アンドロイドのアプリケーション ランチャに、このアプリケーションのアイコンが表示される仕組みになっています。
2番目の13~17行目のインテントフィルターが、「Intent.ACTION_VIEW」アクションで呼び出されるようにするため、新たに追加した設定です。
アプリケーションを呼び出す事ができるようにするには、categoryタグに「android.intent.category.DEFAULT」を指定する必要があるようです。
dataタグのandroid:scheme属性やandroid:host属性は、URIとして何が指定された時に呼び出されるかの条件を、指定するものです。
例えば、プログラム1の「地図を表示」ボタンでは、uriにschemeとして「geo」が指定されているので、このActivityTarget2アクティビティを呼び出す事はできません。
schemeがhttpでホスト名がlocalhostであるuriが指定された時に、このプログラムが呼び出される事になります。
dataタグにはschemeやhostの他に port, path,mimeTypeを指定する事ができます。
このプログラムを一度エミュレータで実行して、「ActivityTarget2」アプリケーションをエミュレータにインストールした後で、 さきのインテントプログラム1を実行して「ActivityTarget2」ボタンを押すと、このアクションとURIに該当するアプリケーションが他にも(Webブラウザアプリケーションが)あるため、 以下のように該当するアプリケーションのリスト画面が表示されます。
ここで、「ActivityTarget2」を選択すると、以下の画面が表示されます。
インテントプログラム1の55行目でdoIntentメソッドの引数として指定したURIの値が、TextViewに表示されているのが確認できます。
コンポーネント名を使って他のアプリケーションを呼び出す。
コンポーネント名を指定して、アプリケーションを呼び出す事もできます。
最初の「画面遷移の復習」の「画面遷移プログラム4」を自アプリケーション内からでは無く、 他のアプリケーションからコンポーネント名を指定して呼び出してみます。
他のアプリケーションからOtherActivityを呼び出す事ができるように、マニュフェストファイルを以下のように修正します。
画面遷移プログラム4(3)-呼び出される側(ActivityTarget)のマニュフェストファイル(AndroidManifest.xml)
17行目で、独自のアクションとして「gudon.sample.activityTarget.XXX」を定義しています。
このように、独自のアクションを定義する場合には、プロジェクトのパッケージ名を使って、 他のアクションと名前が重ならないようにした方が良いようです。
「画面遷移プログラム4」のOtherActivityを呼び出すアプリケーションのコードは、以下のようになります。
インテントプログラム3-呼び出し側アクティビティ(ActivityUser.java)
「画面遷移1-setActionの例」ボタンのonClickメソッドは、アクションを指定してOtherActivityを呼び出すコードの例です。
「画面遷移2-setClassNameの例」ボタンのonClickメソッドは、setClassNameメソッドを使ってコンポーネント名を指定して、OtherActivityを呼び出すコードの例です。
setClassNameメソッドの代わりに、setComponentメソッドでもコンポーネント名を指定してコンポーネントを呼び出す事ができます。
「画面遷移3-setComponentの例」ボタンの、onClickメソッドはこの例です。
「画面遷移2-setClassNameの例」や「画面遷移3-setComponentの例」のように、 コンポーネント名を指定してコンポーネントを呼び出す方法は、明示的な呼び出しとなります。
それに対して、「画面遷移1-setActionの例」のようにアクションを指定してコンポーネントを呼び出す方法は、 特定のコンポーネントを名指しで指定するのではなく、アクションにより間接的に指定しているので暗黙的な呼び出しとなります。
参考URL
- Android Developers
- 開発ガイド
- リファレンス
- インテンスの要素となるアクション,カテゴリ,エクストラ,フラグにはどのようなものがあるかについては、以下のURLが参考になりそう。