義援金の受付

東日本大震災の
復興支援へのご寄付
をお願い致します。

4.3 アクティビティとタスクデザイン


アクティビティとタスクデザインの概略

  • アクティビティは Android アプリケーションのメインの構成要素です。
  • 独自アクティビティの作成に加え、他の多くのアプリケーションからのインテントを介して、アクティビティを自由に再利用します。
  • アプリケーションにおいて、他のアプリケーションのインテントから開始されるようにアクティビティを有効にすることができます。
  • ほとんどすべてのケースで、アクティビティスタックは期待通りの動きをします。
  • まれなケースとして、正しい動作を保証するために文字列やフラグを設定する必要があるかもしれません。

このドキュメントの内容

  1. アプリケーション、アクティビティ、アクティビティスタック、およびタスク
  2. アクティビティとタスクのツアー
    1. Home からのアクティビティの開始
    2. BACK と HOME キーでナビゲートしてアクティビティから離れる
    3. アクティビティの再利用
    4. アクティビティの置き換え
    5. マルチタスク
    6. 2 つのエントリポイントからの起動
    7. インテント
    8. タスク間のスイッチ
  3. デザインヒント
    1. 再利用されないアクティビティにはインテントフィルタは指定しない
    2. アクティビティ不在のバンドリングをする
    3. アクティビティの起動方法を考慮する
    4. アクティビティの現在のタスクへの追加を許可する
    5. ユーザが簡単に戻れるような通知にする
    6. 通知システムを使用する
    7. 絶対に必要な場合を除き BACK ボタンに任せない

関連項目

  1. 開発の基礎

このドキュメントでは、ユーザ中心の視点で、かつアプリケーション設計者からアプリケーション開発者までを対象に、相互作用を行う上で役に立つ Android アプリケーションの中核の原理を高いレベルから説明します。

ここではアクティビティとタスクのサンプルを図で解説し、ナビゲーション、マルチタスク、アクティビティの再利用、インテント、およびアクティビティスタックといった、その基となる原理とメカニズムのいくつかを説明します。デザインを決定する上で参考とする内容や、アプリケーションの UI を通して提供されるコントロールの内容も取り上げています。

このドキュメントは、デフォルトのアプリケーション ( ダイアラーのような ) と Google アプリケーション ( マップのような ) を含むいろいろな Android アプリケーションに取り込めるサンプルを提供しています。これらのサンプルを Android エミュレータや Android 搭載のデバイスで試すことができます。デバイスを使用している場合、このドキュメントで使われているアプリケーションのサンプルのすべてを、そのデバイスに提供できないこともありうるということに注意してください。

ガイドライン、ヒント、避けるべきことについて デザインヒント セクションを必ず見てください。 このドキュメントは 開発の基礎 を補足するもので、プログラマのために基本となるメカニズムを広範囲に取り上げています。


アプリケーション、アクティビティ、アクティビティスタック、およびタスク

Android システムを理解する上で参考になる基本概念は以下の 4 つです。

  • アプリケーション
  • アクティビティ
  • アクティビティスタック
  • タスク

アプリケーション

一般に、Android アプリケーション は、ひとつ以上の関連付けされた、ユーザと相互作用するための疎結合のアクティビティが、通常はひとつのファイル ( .apk 拡張子で ) にまとめられます。Android には、Eメール、カレンダー、ブラウザ、マップ、テキストメッセージ、コンタクト、カメラ、ダイアラー、音楽プレーヤー、設定およびその他を含むリッチなアプリケーションセットが標準で含まれています。

Android には、Home 画面で使用可能なアプリケーションランチャーがあり、通常スライドするドロアーでアプリケーションをアイコンで表示し、ユーザはそれを拾い上げてアプリケーションを開始します。

アクティビティ

アクティビティ は Android アプリケーションのメインの構成要素です。アプリケーションを作成する際、作成するアクティビティおよび他のアプリケーションから再利用するアクティビティからそれを組み立てることができます。これらのアクティビティは実行時にバインドされりことにより、新しくインストールされたアプリケーションがすでにインストールされたアクティビティを利用できるようになります。いちど組み立てられると、アクティビティはまとまったユーザインターフェースを形成し、一体化して動作します。アクティビティは、照会、編集、電話のダイヤル、ピクチャー撮影、検索、データ送信、ボイスコマンドの開始、その他のなんらかのアクションの実行といった、単一のはっきりと区別された目的のためにデザインされた、目で見てはっきりと分かるユーザインターフェイスを備えています。画面に表示があるアプリケーションにはどれでも、少なくともひとつはそれを担うアクティビティがなければなりません。

Android デバイスを使用する際、ユーザは、ユーザインターフェイスを使って、その基本的な振る舞いなどまったくおかまいなしに、次から次へとアクティビティを開始して移動していきます。ユーザには、アクティビティからアクティビティ、タスク からタスクと継ぎ目ない操作性の良さを提供すべきでしょう。

アクティビティは特定のタイプのコンテントをハンドリングし、関連するユーザアクションのセットを受け付けます。一般に、各アクティビティは、そのアプリケーションやタスクの他のアクティビティとは独立した ライフサイクル を持っています。各アクティビティは独立して起動 ( 開始 ) され、ユーザまたはシステムがそれを必要の応じて、開始、一時停止、再開、停止、再起動することができます。この独立性により、アクティビティがさまざまな方法で再利用でき、他のアクティビティに置き換えできるのです。

ダイアラーアプリケーションはアプリケーションのひとつのサンプルで、以下のスクリーンショットに示すような、ダイアラー、コンタクトリスト、コンタクトの照会、新しいコンタクトの 4 つの基本的なアクティビティで構成されています。

ダイアラー
コンタクト
コンタクトの照会
新しいコンタクト

他のアプリケーションの例とそれが含むであろうアクティビティは以下になります。

  • Eメール - フォルダ参照、メッセージリスト参照、メッセージ参照、メッセージ作成、およびアカウント作成のアクティビティ
  • カレンダー - 日付参照、週参照、月参照、議題参照、イベント編集、設定編集、およびアラート参照のアクティビティ
  • カメラ - カメラ実行、ピクチャーリスト参照、ピクチャー参照、ピクチャートリミング、カメラレコーダ実行、ムービーリスト参照、およびムービー再生のアクティビティ
  • ゲーム - ゲームするためのひとつのアクティビティ、概してもうひとつの設定用アクティビティ
  • マップ - マップ上でロケーションを参照するアクティビティ、2 つ目はリスト用 ( 方角リストやフレンドリストなど ) 、3 つ目は詳細用 ( フレンドロケーション、状態、写真 ) のアクティビティ

アクティビティは、アプリケーションの 4 つのコンポーネント の中でもっとも際立った存在です。他のコンポーネントは、サービス、コンテンツプロバイダ、ブロードキャストレシーバです。アクティビティの詳細については、アプリケーションのコンポーネント のアクティビティを参照してください。

アクティビティスタック

ユーザがアプリケーションを横切って、アクティビティからアクティビティへと移動した際、Android システムはユーザが訪問したナビゲーション履歴をリニアに保持していきます。これは アクティビティスタック で、バックスタックとしても知られています。一般に、ユーザが新たなアクティビティを開始したとき、それがアクティビティスタックに追加され、BACK を押すことによりスタックにある前のアクティビティを表示できるようになります。しかしながら、ユーザは、BACK キーで最後に訪問した Home より前には戻ることはできません。現在のスタックにアクティビティを追加することにより、アクティビティが必ず新しい タスク を開始するということが起こるので ( Home に行くことなくタスクが開始されたということであれば ) 、 前に戻ることによりユーザが前のタスクのアクティビティに戻ることができるようになります。ユーザが最も最近の Home よりも前のタスクを取得するには、アプリケーションランチャーからそのルートのアクティビティか、ショートカット、または "Recent tasks" を選択します。

アクティビティスタックに追加されるのは、ビュー、ウィンドウ、メニューのアクティビティだけで、ダイアログは追加されません。つまり、ナビゲーションをデザインする際、画面 A があり、ユーザに後続の画面 B に移動させ、BACK キーを使って画面 A に戻りたい場合は、画面 A はアクティビティとして実装されている必要があります。このルールにはひとつだけ例外があり、それはアプリケーションが 自身でナビゲーションを管理 した場合です。

タスク

タスク はユーザが目的を達成するためにたどっていくアクティビティのシーケンスであり、そのアクティビティがどのアプリケーションに属しているかは問いません。新しいタスクが明示的に指定されるまでは ( "タスクの割り込み" 参照 ) 、ユーザが開始したすべてのアクティビティは、現在のタスクの一部と見なされます。これらのアクティビティがどのアプリケーションにも所属できるということは注目すべきです。つまり、すべてが同じアプリケーションでも違うアプリケーションでもいいのです。すなわち、コンタクトで開始されたタスクは、Eメールアドレスを選ぶことにより Eメールアクティビティへと続き、その後ファイルを添付することにより取り出しもとになるピクチャーギャラリーへと続いて行くことができます。コンタクトも、Eメールも、ピクチャーギャラリーもみな独立したアプリケーションです。

タスクを開始したアクティビティは、ルートアクティビティ と呼ばれます。それは、必ずというわけではありませんが、ほとんどがアプリケーションランチャー、Home 画面のショートカット、または "Recent tasks" スイッチャー ( Home を長押しすることで可能なデバイスもある ) から開始されます。ユーザは、タスクを開始したときと同じように、そのルートアクティビティのアイコンを選択することで、タスクに戻ることができます。いちどタスク内に入れば、BACK キーでタスクの前のアクティビティに移れます。アクティビティスタックは、ひとつ以上のタスクで構成されます。

以下はタスクのサンプルです。

  • 添付付きのテキストメッセージ送信する
  • YouTube ビデオを鑑賞し、Eメールで他の人とそれを共有する

タスクの割り込み - ユーザは異なるタスクを遂行するために、今していたこと ( 元のタスク ) に割り込み、その後、放っておいた元のタスクを完了するために戻ることができるという、重要なタスクの特性があります。このアイデアにより、ユーザが同時にマルチタスクを実現でき、それらの間でのスイッチが可能となるのです。他のタスクへと飛び出る方法として主に以下の 2 つの方法があり、どちらのケースでもタスクが割り込みする前の場所にユーザが戻ってこられるようにする必要があります。

  • ユーザが通知により割り込まれる – 通知が現れ、ユーザはそれに応答したくなる
  • ユーザが他のタスクを実行することを決断する – ユーザはただ Home を押しアプリケーションを開始する

当然、このルールには例外があります。今述べたふたつの方法を超越した、タスクを開始する 3 つ目の方法があり、それは、自身を新しいタスクとして定義したアクティビティを開始することにより開始する方法です。マップとブラウザのふたつのアプリケーションはこれを行っています。たとえば、Eメールのアドレスを選択することによりマップアクティビティが新たなタスクとして開始され、Eメールのリンクを選択することによりブラウザアクティビティが新たなタスクとして開始されます。このケースでは、Home から起動されていないことから、BACK キーにより、異なるタスク ( Eメール ) の前のアクティビティに戻されます。


アクティビティとタスクのツアー

以下の例では、アプリケーション、アクティビティ、アクティビティスタック、BACK キー、タスクとインテントの基本的原理を図解しています。これは、アクティビティの開始とタスク間のスイッチといった、ユーザアクションに対してシステムがどのようの応答するのかを示しています。これらの例のほとんどで、示されているようにデバイスでのアクティビティの起動が理解できることでしょう。

Home からのアクティビティの開始

Home は、ほとんどのアプリケーションを開始する場所です ( 中には、他のアプリケーションのみから起動されるアプリケーションもあります ) 。 ユーザがアプリケーションランチャー ( または Home 画面のショートカット ) でアイコンをタッチしたとき、アプリケーションのメインアクティビティが、ユーザフォーカスを持つフォアグランドで起動されます。以下の図に示すように、Home に行きEメールアイコンをタッチするユーザアクションとがEメールアプリケーションのリストメッセージアクティビティを起動します。Home アクティビティはバックグラウンドで停止したままで、ユーザにより再度呼び出されたときの再スタートの準備をしています。

BACK と HOME キーでナビゲートしてアクティビティから離れる

アクティビティは、ユーザが HOME または BACK キーで、アクティビティからどのように離れたかに依存して、その状態を保持したり失ったりします。

デフォルトでは、BACK キーを押すことにより現在のアクティビティが終了 ( 破棄 ) され、ユーザに前のアクティビティが表示されます。下の図では、ユーザが Home 画面で Eメールアイコンをタッチしたことにより、Eメールが開始され、Eメールメッセージのリストが表示されています。ユーザはリストを下に向かってスクロールします ( 最初の状態を変更しています ) 。BACK を押すことにより、リストメッセージアクティビティが破棄され、前のアクティビティに戻りますが、それはすなわち Home になります。ユーザが再度 Eメールを起動した場合、再度メッセージとその初期画面が表示されますが、スクロールの状態はありません。

上の例では、BACK を押すことにより、最後にユーザが見ていたアクティビティが Home であることから、そこに行きます。しかし、もしユーザが他のアクティビティからリストメッセージにたどり着いたのであれば、BACK を押せばそこに戻ります。

一方、次の図では、ユーザが BACK ではなく HOME を押してリストメッセージを離れています。リストメッセージアクティビティは停止され、破棄されるのではく、バックグラウンドへと移行します。Eメールをそのアイコンから再度開始すると、リストメッセージアクティビティが単にフォアグランドになり ( 停止済みから実行中に変えて ) 、最後に残していたのと同じスクロールの状態になっています。

例外として。 フォアグランドに持って行かれたときに初期状態の画面に戻ってしまう ( スクロールなど、どの状態も失って ) バックグラウンドアクティビティもあります。コンタクトとギャラリーがそれにあてはまります。ユーザが Home > コンタクトを選び、その後、あるコンタクトを選んだ場合、そのコンタクトの詳細を参照している状態です。ユーザが、再度 Home > コンタクトを選ぶと、最後に見ていたコンタクトではなく、コンタクトの初期リストが表示されます。コンタクトは、4 つの機能を装備したそれぞれにアクセスするタブを持ち、この初期画面がメインのエントリーポイントとなっていることから、そういった設計となっています。

それに加え、すべてのアクティビティが、BACK を押されたときに破棄されるように振る舞うわけではありません。ユーザが音楽アプリケーションで音楽再生を開始し、BACK ボタンを押したとき、アプリケーションは通常の戻る振る舞いを上書きし、プレーヤーのアクティビティが破棄されることを防ぎ、たとえそのアクティビティが見えなくなっても音楽を再生し続けます。視覚的な代用として、音楽アプリケーションはステータスバーに通知として配置され、アプリケーションを停止するか音楽をコントロールするかの手段を、依然ユーザに残しておきます。画面に見えなくなったときに停止するアクティビティやバックグラウンドで実行し続けるアクティビティを作成することが可能であることに留意してください。後者が音楽プレーヤーで採用されました。

アクティビティの再利用

アクティビティ A が異なるアプリケーションのアクティビティ B を開始したとき、アクティビティ B が再利用されたと言えます。このユースケースは、アクティビティ A にその機能がなく、アクティビティ B でそれが見つかるので、通常に起こりえることです。 

コンタクトがピクチャーの取得にギャラリーを再利用する - コンタクトアクティビティにはコンタクトのピクチャーフィールドがありますが、普通はギャラリーがピクチャー ( トリミングすることを予定している ) を保存しています。よって、コンタクトはピクチャーの取得のためにギャラリーアクティビティを再利用することができます。下の図は、これを行うシーケンスを図解しています。ユーザが複数のコンタクトを選択し、そこからあるコンタクトを特定し、MENU > 編集を選択しピクチャーのフィールドをタッチし、それがギャラリーアクティビティを起動します。その後ユーザは希望のピクチャーを選び、それをトリミングして保存します。それを保存したことにより、コンタクトのピクチャーフィールドにそのピクチャーが挿入されます。それがこのシーケンスを実現する方法です。

ギャラリーを開始したコンタクトアプリケーションにピクチャーを返していることに気づくでしょう。次の例では、結果を返さないアクティビティの再利用を図解しています。下の図がアクティビティを介したナビゲーション履歴やアクティビティスタックを図解していることも分かると思います。ユーザは各アクティビティを通して、Home までの道のりをバックアップしています。

アプリケーションを設計するとき、他のアプリケーションにあるアクティビティをいかに再利用するのか、および作成したアクティビティが他のアプリケーションによりいかに再利用される可能性があるのかを考えることは良いことです。既存のアクティビティと同じ インテントフィルタ をアクティビティに追加すれば、双方のアクティビティ間の選択を、システムがユーザに提起します。

ギャラリーがピクチャーを共有するためにメッセージングを再利用する - 共有は、あるアプリケーションが異なるアプリケーションからのアクティビティを再利用しているもうひとつの良い例です。下の図に示すように、ユーザはギャラリーを開始し、ビューにピクチャーを拾い上げ、MENU > Share を選んで "Messaging" を拾い上げます。これにより、メッセージングアクティビティが開始され、新しいメッセージが作成され、オリジナルのピクチャーにそれが添付されます。ユーザはその後、"To" フィールドを入力し、ショートメッセージを書いてそれを送信します。ユーザフォーカスはメッセージングプログラムに残っています。ユーザがギャラリーに戻りたい場合は、BACK キーを押す必要があります ( ユーザは各アクティビティを通して、Home までの道のりをバックアップしています ) 。

前の例とは対照的に、このメッセージングアクティビティの再利用は、それを開始したギャラリーアクティビティになにも返していません。

これら両方の例で、目的を達成するアクティビティのシーケンス、すなわちタスクを図解しています。それぞれのケースで 2 つの異なるアプリケーションからアクティビティを使用して仕事をこなしました。

アクティビティの置き換え

これは、アクティビティ A が異なるアプリケーションのアクティビティ B に置き換わるユースケースです。この状況は、アクティビティ A がアクティビティ B より仕事をうまくこなせるということもあり、普通に起こりえます。言い換えると、A が B に置き換えられるくらい A と B は十分に等価だと言えます。このケースは、 A と B がまったく違うアクティビティでお互いを補い合っているアクティビティの再利用とは対照的な見解となります。

この例では、ユーザは、拡張版着信音と呼ばれる着信音アクティビティの代替品をダウンロードしました。そこで、設定、サウンドと表示、着信音へと行くと、システムで Android システムの着信音アクティビティが提示されているので、それを新しいものにします。このダイアログには、この選択を記憶するために "デフォルトでこのアクションに使用する" というオプションがあります。ユーザが "拡張版着信音" を選択すると、そのアクティビティがロードされ、オリジナルの Android 着信音アクティビティを置き換えます。

マルチタスク

前に述べたように、アクティビティが起動されたとき、ユーザは Home へと行き、最初のアクティビティを破棄することなく、2 番目のアクティビティを起動することができます。このシナリオをマップアプリケーションを起動してデモしてみます。

  • 状況 1 - ユーザはビューマップアクティビティを起動し、マップロケーションを検索します。ネットワークが遅いと仮定すると、地図が描画されるまでかなりの時間がかかります。
  • 状況 2 - ユーザはそれを待つ間に何か他のことをしたいと思い、HOME キーを押しますが、これによりマップのネットワーク接続は割り込まれず、地図はバックグラウンドでロードをし続けることができます。

    アクティビティを作成するときは、それがバックグラウンドに遷移したときに停止させることも実行を続けることもできます ( アクティビティのライフサイクル  の onStop() を参照 ) 。ユーザがマルチタスクを実現できるようにするには、ネットワークからデータをダウンロードするアクティビティを支持して、ダウロードし続けることが望ましいでしょう。

  • 状況 3 - マップアクティビティは、今バックグラウンドで実行中で、Home がフォアグランドです。その後ユーザはカレンダーアクティビティを起動して、それをフォアグランドで起動しユーザフォーカスを受け入れ、今日のカレンダーを参照します ( 太線で示しているように ) 。

  • 状況 4 - ユーザは Home を押し、その後マップアクティビティが地図に戻ると、そのすべてがロードされていました。

アプリケーションランチャーは Home で "ビューマップ" と "日付ビュー" のアクティビティを別の独立した タスク 内で起動しました。従って、システムはマルチタスク、つまり複数の タスク で実行中です。

2 つのエントリポイントからの起動

すべてのアプリケーションは、最低でもひとつのエントリーポイントがあり、これは、システムやユーザがアプリケーション内部のアクティビティにアクセスするひとつの方法です。Home のアプリケーションランチャーの各アイコンは、ひとつのエントリーポイントを表現しています。アプリケーションは他のアプリケーションからも起動できます。各アクティビティはアプリケーション内の潜在的なエントリーポイントです。  

電話のアプリケーションは、コンタクトとダイアラーの 2 つのエントリーポイントを持っています。ユーザはコンタクトから入り、ダイアラーを起動するために電話番号を選択します。下の図にあるように、ユーザはコンタクトアクティビティを起動するために、コンタクトを選択することができ、その後ダイアラアクティビティを起動するために電話番号を拾って電話をかけます。

ユーザがいちどアプリケーションの内部に入ると、タブ、メニューアイテム、リストアイテム、画面上のボタン、その他のユーザインターフェイスコントロールを介して、新しいコンタクトやコンタクトの編集などの他のアクティビティにアクセスすることができます。

インテント

ユーザはなんらかのデータ上のにある、mailto:info@example.com のリンクをタッチするといったような行動をとったとき、ユーザは実際には Intent オブジェクトを初期化しているか、まさに意図して ( intent ) そうしていて、その後、そのインテントには特定のコンポーネントが解決されます ( ここではアクティビティコンポーネントのみについて考えます ) 。よって、ユーザが mailto: リンクをタッチしたことにより、システムはアクティビティとなんらかのインテントオブジェクトを 一致させようと試みることになります。そのインテントオブジェクトが明示的にアクティビティの名前を明記している ( 明示インテント ) 場合、システムは、そのアクションに応え、直ちにそのアクティビティを起動します。しかしながら、このインテントオブジェクトがアクティビティの名前なしで記述されている ( 暗黙インテント ) 場合は、システムはインテントオブジェクトと利用可能なアクティビティの インテントフィルタ とを比較します。もしアクションとデータをハンドリング可能なアクティビティがひとつ以上ある場合は、システムは、ユーザが選択できるようにアクティビティ選択肢を表示します。

以下の図では、mailto: リンクをタッチする例を示しています。デバイスに 2 つの Eメールアプリケーションがセットアップされている場合、ユーザがウェブページにある mailto: の Eメールアドレスをタッチしたとき、Eメールを作成する 2 つのアクティビティ ( Gmail と Email ) を選択するダイアログボックスが表示されるインテントオブジェクトが生じます。

以下にインテントオブジェクトとそれらが解決するアクティビティの例をいくつか挙げます。

  • コンタクトのリスト参照 - コンタクトリストビューアアクティビティを解決
  • 特定のコンタクト参照 - コンタクトビューアアクティビティを解決
  • 特定のコンタクト編集 - コンタクトエディタアクティビティを解決
  • 特定の Eメール送信 - メールアクティビティを解決
  • 電話番号のダイアル - 電話ダイアラーアクティビティを解決
  • イメージのリスト参照 - イメージリストビューアアクティビティを解決
  • 特定のイメージ参照 - イメージビューアアクティビティを解決
  • 特定のイメージのトリミング - イメージトリミングアクティビティを解決

インテントオブジェクトはアクションとデータの 2 つに以下を設定します。

  • 実行される一般的なアクション。この例では、参照、編集、ダイアル、またはトリミング
  • アクションの対象となる特定のデータ。この例では、コンタクトリスト、特定のコンタクト、電話番号、イメージのリスト、または特定のイメージ

Home にあるアプリケーションランチャーからアクティビティを開始するユーザアクションはどれも、特定のアクティビティへの明示インテントであることに注意してください。同じように、アプリケーション内でだけでプライベートなアクティビティを明示インテントとして起動するアクティビティもあり、それには他のアクティビティがそれにアクセスすることはできません。

インテントについてはさらに、Intent クラスインテントフィルタ を参照してください。

タスク間のスイッチ

これはユーザが 2 つのタスク間をいかにスイッチするのかを示すシナリオです。この例では、ユーザがテキストメッセージを書き、ピクチャーを添付するのですが、その動作の前にカレンダーをちょっとだけ見に行きます。その後、放っておいたところに戻り、ピクチャーを添付してからメッセージを送信します。

  1. 最初のタスクを開始します。テキストメッセージと写真を添付して送信したいと思います。以下を選択します。

    Home > メッセージング > 新しいメッセージ > メニュー > 添付 > ピクチャー。 この最後のステップで写真を拾い上げるためにピクチャーギャラリーが起動されます。ピクチャーギャラリーが独立したアプリケーションのアクティビティであることに気づくでしょう。

    この時点で、ピクチャーを拾う前にそれを止めてカレンダーをちょっとだけ見に行くことにしましたが、これは独立したタスクです。現在のアクティビティには直接カレンダーに行くボタンはないため、Home からそれを開始する必要があります。

  2. 2 番目のタスクを開始します。Home > カレンダーを選択し、カレンダーのイベントを見ます。アプリケーションランチャーは起動する各アプリケーション用に新しいタスクを作成することから、カレンダーは新しいタスクとして Home から起動されます。

  3. 最初のタスクへスイッチして作業を完了します。カレンダーを見終わったら、そのタスクのルートアクティビティを開始することによりピクチャーを添付するために戻ることができ、 Home > メッセージングを選択し、メッセージングへと導かれるのではなく、放っておいた場所のピクチャーギャラリーへと直接導かれます。それで写真を拾うことができ、メッセージに追加し、メッセージを送信して最初のタスクが完了します。
           

デザインヒント

以下はアプリケーションの設計者と開発者に向けたヒントとガイドラインです。

再利用されないアクティビティを作成するときはインテントフィルタは使用せず明示インテントを使用する

他のアクティビティに使用を許さないアクティビティを作成する場合、そのアクティビティにはインテントフィルタを絶対に追加しないでください。 そうすることでアプリケーションランチャーから、またはアプリケーション内の他のアクティビティからのみしか起動しないアクティビティを適用したことになります。その代わり、起動するための明示的なコンポーネントに指定したインテント、つまり、明示インテントを作成するだけです。このケースでは、インテントフィルタの必要性はまったくありません。インテントフィルタは、他のすべてのアプリケーションに公開されるものであり、インテントフィルタを作ったということは、作成したアクティビティにアクセスを公開していることと同じで、セキュリティホールを生み出す原因になり得ることを意味します。

他のオーナーのアクティビティを再利用するときはアクティビティ不在のバンドリングをする

アプリケーションは他のアプリケーションから利用可能となっているアクティビティを再利用することができます。そのようにする場合は、使用するインテントが合致した外部のアクティビティに常に解決されると仮定することはできません。つまり、そのインテントをハンドイングできるアプリケーションがデバイスにインストールされていないケースをハンドリングする必要があります。

アクティビティにインテントを合致させるテストする、これはアクティビティを開始する前にできるし、アクティビティの開始に失敗した場合の例外をキャッチすることのどちらかが可能です。このインテントは使用可能か? のブログの投稿で両方のアプローチが説明されています。

インテントが解決されるかことができるかどうかをテストするには、コードでパッケージマネージャを問い合わせすることで実現できます。ブログのt投稿では、isIntentAvailable() ヘルパーメソッドでサンプルを提供しています。ユーザインターフェイスの初期化のときにこのテストを実行することが可能です。たとえば、Intent オブジェクトを初期化するユーザコントロールを無効にしたり、ユーザにそのアプリケーションをダウンロードするようマーケットのようなロケーションに行くようメッセージを表示することもできるようになるでしょう。この方法で、解決するアクティビティが実際に存在することを、インテントがテスト済みの場合のみ、コードでアクティビティを開始 ( startActivity() か startActivityForResult() のどちらかを使って ) することが可能となります。

他のアプリケーションによるアクティビティの起動と使用についての望ましい方法を考慮する

アプリケーションやそのアクティビティをどのようにユーザに開始させるかを決定するのは、設計者や開発者にゆだねられます。アプリケーションはアクティビティのセットであることから、ユーザはそれらのアクティビティを Home や 他のアプリケーションから開始することができます。

  • Home にあるアイコンからメインのアクティビティを起動する - 作成するアプリケーションがスタンドアローンで動く場合は、おそらくは、アプリケーションランチャー  ( 通常はスライドドロアーとして Home 画面で実装されている ) にあるアイコンをタッチするか、Home 画面のショートカットアイコンをからか、タスクスイッチャー ( これはアクションが MAIN かつカテゴリが LAUNCHER の インテントフィルタ を持つアクティビティ用にあるメカニズムです ) から開始されるべきです。
  • 別のアプリケーション内部からアクティビティを起動する - おそらく作成するアクティビティは再利用向きのものです。たとえば、多くのアプリケーションが他のユーザと共有したいデータを持っているような場合です。他のユーザとのデータ共有が可能なアクティビティには、Eメール、テキストメッセージ、および公開のウェブサイトへのアップロードなどがあります。

    別のアプリケーションの既存のアクティビティに代用できるひとつ以上のアクティビティがある場合、そのアクティビティが要求された時点でユーザがそれを使用できるようにすることができます。たとえば、作成するアクティビティが他にデータを送信する ( Eメール、テキストメッセージ、アップロードなど ) 場合、ユーザに選択肢を出現させるアクティビティの設定を検討してください。具体的な例を挙げるとすれば、ギャラリーはユーザにピクチャーの参照と共有を可能にします。ユーザがメニューから "共有" を選択したとき、システムは "共有" の要求 ( インテントオブジェクト ) と利用可能なアクティビティ ( そのインテントフィルタを見に行き ) とを比較し、共有するための選択肢を表示します。このケースでこれに合致するのは、Eメール、Gmail、メッセージング、および Picassa です。作成するアクティビティがピクチャーを送信したりそれをウェブサイトにアップロード可能な場合は、それ自体を共有可能に ( インテントフィルタで設定することにより ) することがやるべきことのすべてです。

    別のアクティビティは、結果の返却を期待してもしなくても、対象のアクティビティを開始することができます。

    • 結果を期待してアクティビティを開始する - このアプローチはループで閉じられ、ここでは開始されるアクティビティは有効な結果が返されるかキャンセルされるかのどちらかである必要があります。ギャラリーから写真を共有する前の例では、ユーザは、送信またはアップロードの処理が完了したら最後にギャラリーに戻ってきます。これらは、ギャラリーを外部でのアクティビティとして開始する例です ( そのようなアクティビティは startActivityForResult()で開始されます ) 。
    • 結果を期待しないでアクティビティを開始する - これは結果のないアプローチです。Eメールメッセージ ( またはウェブページで ) 住所を選択する例です。ここでマップアクティビティはその場所の地図の描画を開始します。Eメールメッセージに返されるマップからの結果は期待しません。ユーザは BACK キーを押して戻ることができます ( そのようなアクティビティは startActivity() で開始されます ) 。

  • 別のアプリケーション内部から のみ アクティビティを起動する - Eメール、Gmail、メッセージング、および Picassa を経由して( ギャラリー内から ) 共有する前のケースでは、すべてのアクティビティを Home にあるアプリケーションランチャーからでも開始することができます。それとは対照的に、ピクチャーのトリミングとファイル添付のアクティビティは、スタンドアローンでなく、コンテキストを必要としないことから、Home から開始することはできません。
  • 実際には、すべてのアプリケーションにアイコンがあるわけではなく、Home から開始できるわけでもありません。ほとんどまれにしか使用されず、既存の機能を置き換える小さなアプリを例に取り上げます。既存のアプリケーションの内部には元からのエントリーポイントがすでにあります。たとえば、Android フォーンには通常組み込まれた着信音選択機能があり、設定アプリケーションのサウンド設定から選択することができます。自作のカスタムの着信音選択アプリケーションを組み込みの着信音選択と同じインテントにより起動することができます。ユーザが "電話着信音" を選んだ時点で、以下の図に示すような "Android System" と作成した "着信音選択" との選択肢 ( およびその選択したものを保存させる ) を提供するダイアログが表示されます。着信音は、それほど頻繁に設定するものではなく、明確な開始ポイントをすでに持っていることから、おそらく Home にはアプリケーションアイコンは必要ないでしょう。 

  • Home にある独立したアイコンから単一のアプリケーション内にある 2 つ以上のメインアクティビティを起動する - 前に定義していますが、単一の .apk ファイルに入っている全コードがひとつのアプリケーションとみなされます。Home から起動可能なメインのアクティビティを 2 つ持つアプリケーションを作成することができます。
  • Camera.apk アプリケーションは、カメラとビデオカメラという2 つの独立したメインのアクティビティを持つアプリケーションの良い例で、それぞれがアプリケーションランチャーに独自のアイコンを持っていて、単独で起動ができるので、ユーザには別のアプリケーションに見えます。両方が同じレンズを共有し、両方がギャラリーにそれぞれのイメージ ( 静止画と動画 ) を保存します。  

    アプリケーションに、Home から起動可能な 2 つの異なる、独立したアクティビティを持たせるには、異なるタスクでそれらを関連付けする定義が必要になります ( これは、各タスク用のメインアクティビティに異なるタスク親和性を設定することを意味します。このケースでは、"com.android.camera" と "com.android.videocamera" です ) 。

    コンタクトとダイアラーは、Home から起動可能な 2 つのメインアクティビティのもうひとつの例で、両方が同じアプリケーションに属しています。

  • ウィジェットとしてアプリケーションを利用できるようにする - アプリケーションはその一部分を アプリウィジェット として表示することも可能で、 Home または別のアプリケーションに組み込まれ、定期的な更新を受け付けます。

アクティビティの現在のタスクへの追加を許可する

作成したアクティビティが別のアプリケーションから開始できる場合は、そのアクティビティを現在の タスク ( またはそれと親和性のある既存のタスク ) に追加できるよう許可してください。 アクティビティがタスクに追加されると、ユーザは作成したアクティビティが含まれるタスクと他のタスク間でのスイッチが可能になります。ひとつのインスタンスしかないアクティビティはその例外です。 

この振る舞いに対しては、アクティビティを、singleTask や singleInstance モードではなく、標準モードまたは singleTop モードで起動する必要があります。 これらのモードは、実行されるアクティビティの複数インスタンスも可能にします。

ユーザが前のアクティビティに簡単に戻れるような通知にする

バックグランドにあるか実行中でないアプリケーションは、ユーザに関心を抱かせるイベントを知らせる通知を送信することができます。2 つ例を挙げると、ひとつはカレンダーで、もうすぐやってくるイベントの通知を送信でき、もうひとつはEメールで、新しいメッセージが届いたときに通知を送信できます。ユーザがアクティビティ A にいるときに、アクティビティ B への通知を取得し、その通知を拾い、ユーザが BACK キーを押したとき、ユーザがアクティビティ A に戻るべきであるというのがユーザインターフェイスのひとつのガイドラインとなっています。 

これは、ユーザが通知に応答したときにアクティビティスタックがどのように機能するのかを示すシナリオです。

  1. ユーザがカレンダーにイベントを作成する。ユーザは、Eメールメッセージの一部をコピーしてイベントに貼り付ける必要があることに気づく
  2. ユーザは、Home > Gmail を選択する
  3. Gmail にいる間、カレンダーからの間近にあるイベントの通知を受け取る
  4. そこでユーザは通知を選択し、その通知が、間近のミーティングの簡潔な詳細を表示した専用のカレンダーアクティビティへと導く
  5. ユーザはその通知のショートカットを選択してさらに詳細を参照する
  6. そのイベント見終わったら、ユーザが BACK キーを押す。ユーザは、通知を受け取ったときにいた、Gmail へと導かれているべきである。

この現象は必ずしもデフォルトでは発生しません。

一般的に、通知は主に以下の 2 つの方法の 1 つで発生します。

  • 選択されたアクティビティは通知だけの専用である - たとえば、ユーザがカレンダーの通知を受信したとき、その通知を選択することにより、間近のカレンダーイベントのリストを表示する特別なアクティビティが開始されます。このビューは通知からのみで利用可能で、カレンダー独自のユーザインターフェイスを介したものではありません。この間近にイベントを参照した後、ユーザが BACK キーを押してユーザが通知を拾ったときにいたアクティビティに戻るような動作を保証するには、この専用アクティビティを、カレンダーや他のどのアクティビティとも同じタスク親和性に絶対にしないでください ( タスク親和性を空文字に設定することにによりこれが実現でき、これは他のどれとも親和性がないことという意味になります ) 。これに対する解釈は以下です。

    タスクが動作する方式により、専用アクティビティの taskAffinity がデフォルトのままで、BACK キーを押す ( 上のステップ 6 の ) ことにより、Gmail ではなくカレンダーへと導かれてしまいます。この理由として、デフォルトでは、任意のアプリケーションでのすべてのアクティビティは同じタスク親和性を持っています。 その結果、専用のアクティビティのタスク親和性は、すでにステップ 1 で実行中のカレンダーのタスクと一致してしまいます。このことは、ステップ 4 で、通知を選んだことにより既存のカレンダーイベント ( ステップ 1 の ) の方へ導かれ、先頭の専用のアクティビティが開始されることを意味します。 これは起きてほしくない現象です。専用のアクティビティの taskAffinity を空文字に設定すると、この問題を解決できます。

  • 選択されたアクティビティは専用ではなく、その初期状態で常にフォアグランドになる - たとえば、通知に応答して Gmail アプリケーションがフォアグランドにきたときは、常に会話のリストが提示されています。通知のきっかけとなるインテントに "clear top" フラグを設定することにより、このようになることが保証されます。この設定により、アクティビティが起動されたときに初期アクティビティを表示することが保証され、 ユーザがそれを見た最後の状態で Gmail がフォアグランドにくることがないようにします。(これを行うには、startActivity() に渡すインテントに FLAG_ACTIVITY_CLEAR_TOP を設定します ) 。

他にも通知をハンドリングするのに、特定のデータを表示しながらアクティビティをフォアグランドに持って行くといった方法や、新しいテキストメッセージを送信した人だけのテキストメッセージスレッドを表示するといったする方法があります。

通知はアクティビティを常に新しいタスクとして開始します ( つまり、startActivity() に渡すインテントに FLAG_ACTIVITY_NEW_TASK を設定します ) 。タスクに対する割り込みがそのタスクの一部になってはならないということがその理由です。

通知の代わりにダイアログを使用せずに通知システムを使用する

バックグランドサービスでユーザに通知する必要がある場合は、ダイアログやトーストでユーザに通知するのではなく、標準の通知システムを使用してください。ダイアログやトーストは即座にフォーカスされ、ユーザに対して割り込み、作業していることからフォーカスを奪います。ユーザは、テキストを打っている最中でダイアログが現れ、誤ってダイアログで操作してしまう可能性があります。ユーザは通知とやり取りを行い、メッセージに答える際は都合の良いときに通知シェードを引き下ろして使用ことに慣れています。

絶対に必要な場合を除き BACK ボタンに任せない

ユーザがあるアクティビティから次へとナビゲートすると、システムはそれをアクティビティスタックに追加します。これはBACK キーでアクセス可能となるナビゲーションヒストリを形成します。ほとんどのアクティビティは比較的、コンタクトリストの参照や、Eメールの作成、または写真を撮るなどといった、ひとつのデータのセットだけのスコープで制限されていています。しかし、もしある大きなアクティビティにいくつもののコンテンツがあり、BACK キーによる細かなコントロールが必要だとしたらどうなるでしょうか?Google アプリケーションを例に挙げると、ひとつはブラウザで、これはいちどにいくつものページを開くことができ、もうひとつはマップで、これはいくつもの切り替え可能な地理データのレイヤを持っています。その両方のアプリケーションとも、BACK キーによるコントロールを受け付け、それらのアプリケーションがフォーカスされたときだけ機能する独自の内部バックスタックを保持しています。

たとえばマップはユーザに対し、レイヤー を使ってマップ上に検索した結果のロケーションを表示したり、フレンドのロケーションを表示したり、ポイント間の方向を提供する道しるべとなる線を表示したりして、さまざまな情報を提供します。BACK キーで前のレイヤーに戻ってもいいように、マップはそれらのレイヤーを独自の履歴に保存しているのです。

同じように、ブラウザはユーザにブラウザウィンドウ を使って、さまざまなページを提供しています。各ウィンドウで独自のナビゲーション履歴を持っていて、これはデスクトップオペレーティングシステム ( Windows、 Macintosh または Linux など ) のタブブラウザに相当します。たとえば、Android ブラウザのひとつのウィンドウで、Google ウェブサーチを行ったとしたら、検索結果のリンクをクリックすることにより同じウィンドウにウェブページが表示され、その後 BACK を押すことで検索結果ページに戻るでしょう。BACK で前のウィンドウに戻るのは、 現在のウィンドウが前のウィンドウにより起動された場合のみです。 ユーザがBACK を押し続けたら、いつかはブラウザアクティビティから離れてHome へと戻ります。