2010年8月10日火曜日

Android Activity, Task, Stack, Launch mode

アクティビティ と タスク と スタック と 起動モード (と ライフサイクル)

開発の基礎のアクティビティとタスク以降
がとっても(日本語が)わかりにくかったので、
私なりの解釈を書くことにしました。
(もしかしたら間違ってるかもしれないよ)

なんで、わかりにくいかと言うと、用語の定義がされてないからなんですね。

なので、ちゃんと定義(みたいなの)

・アクティビティ

 これはいいよね。いわゆる Activity です。


・ルートアクティビティ

タスクを開始するアクティビティのこと。
通常だと、AndroidManifest.xml の タグのなかに

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

になってるアクティビティのことです。


・スタック

 現在生きている(destroyされていない)アクティビティ
 を管理する入れ物みないなもの
 例えば、起動時のアクティビティが Activity A で、
 そこから、startActivity で別の Activity B に飛んで、
 さらにそこから startActivity で Activity C に飛んだとすると
 スタックの中は

 ---------
 | A-B-C
 ---------

 になっている
 ここで、Activity C を finish() したり、ユーザが[戻る]ボタンを押したりすると、

 ---------
 | A-B
 ---------

 になる。OK?


・タスク

 元ページだと、
「アクティビティをスタックにまとめたものがタスク」
と書いてあるのですが、意味がさっぱりです。
で、原文(英語)を見ると
「Simply put, a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack」
つまり、
ユーザーがあるアプリケーションを使ったとして、
その状態遷移に含まれるアクティビティの集合をタスクといいましょう、
ということです。

で、この(ここでいう)スタックとタスクの違いがよくわからない
つまり、図にするとこういうことなんです(たぶん)

 タスク1  タスク2  タスク3
 --------------------------------
 | A-B-C | A'-B'-C'-D' | A''-B''
 --------------------------------
      スタック

ここで、画面に表示されてるのは B''、
各タスクのルートアクティビティが A, A', A''
全体がスタック


ここまでで、用語はOK

説明を簡単にするために、
MyApp というアプリを仮定します。

MyApp は4個のアクティビティから構成されています。

     A : MainActivity
      ↓    ↓
B : SubActivity1   C : SubActivity2
 ↓          ↑
D : SubSubActivity1 ------


← : startActivity() / startActivityForResult()


こんな感じ。ここで、MainActivity がルートアクティビティ
なのはわかりますよね。


"タスク内のアクティビティは、1 つのユニットとして一緒に移動します。
タスク全体(アクティビティスタック全体)をフォアグラウンドに移動したり、バックグラウンドに移動したりできます。"

これは、

 タスク1  タスク2  タスク3
 --------------------------------
 | A-B-C | A'-B'-C'-D' | A''-B''
 --------------------------------
      スタック

の状態で、例えばホーム長押しでタスク2のアプリを開いたとすると、

 タスク1 タスク3  タスク2
 --------------------------------
 | A-B-C | A''-B'' | A'-B'-C'-D'
 --------------------------------
      スタック

になる、ということ(だと思います)

ただし、この動作はアクティビティを開始した Intent オブジェクトのフラグセットと、
マニフェストに指定されているアクティビティの <activity> 要素の属性セット
によって変更可能

そのための Intent フラグ としては

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP

主に使用する <activity> 属性は以下を使う

taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch



親和性と新しいタスク

まず、親和性ってなに?
。。。
原文をみると affinity

"デフォルトでは、アプリケーション内のすべてのアクティビティは相互に親和性があり、すべてのアクティビティができる限り同じタスクに属そうとします。"

ええと、つまり同じアプリから起動したアクティビティは同じタスクに
属するということですね。はい。

"ただし、 要素の taskAffinity 属性を使用して、アクティビティごとに個別の親和性を設定することもできます。"

つまり、標準なら

 タスク1 タスク3  タスク2
 --------------------------------
 | A-B-C | A''-B'' | A'-B'-C'-D'
 --------------------------------
      スタック

だけど、

 タスク1 タスク3  タスク2
           ↓ ↓ ↓
 --------------------------------
 | A-B-C | A''-B'' | A'-B'-C'-D'
 --------------------------------
                ↑
              タスク3

みたいにできるということかな。はい。

こうするための方法は2つ

1. アクティビティを起動する Intent オブジェクトに
  FLAG_ACTIVITY_NEW_TASK フラグを入れる

  この場合だと、C'から D'を起動するときの Intent に
  FLAG_ACTIVITY_NEW_TASK をセットする

2. アクティビティの allowTaskReparenting 属性が
  "true" に設定されている場合

  この場合だと、AndroidManifest.xml の D' の <activity> タグに
  allowTaskReparenting="true" をセットする

詳しくは親和性と新しいタスクのこの部分を見てください。



起動モード

これがわかりにくかった。というかややこしい。

launchMode 属性の 要素は、次の4種類

"standard"(デフォルト モード)
"singleTop"
"singleTask"
"singleInstance"

まとめてみた



*1 Intent オブジェクトに FLAG_ACTIVITY_NEW_TASK フラグが含まれている場合は、前のセクション親和性と新しいタスクで説明したとおり、別のタスクが選択

*2 複数のインスタンスを複数のタスクに割り当てることも、特定のタスクに同じアクティビティの複数のインスタンスを割り当てることも可能




スタックのクリア


"ユーザーがタスクを長時間放置すると、タスクのルート アクティビティを除くすべてのアクティビティがクリアされます。"

つまり

 タスク1  タスク2  タスク3
 --------------------------------
 | A-B-C | A'-B'-C'-D' | A''-B''
 --------------------------------
      スタック

の状態で長時間放置すると

タスク1  タスク2  タスク3
 --------------------------------
 | A | A' | A''-B''
 --------------------------------
      スタック

になる。これがデフォルト。
この動作を変更したい場合は、次のアクティビティ属性を使用する

alwaysRetainTaskState 属性
タスクのルート アクティビティでこの属性を "true" に設定すると、長時間経過しても、タスク内のすべてのアクティビティはそのまま残される。

つまり

 タスク1  タスク2  タスク3
 --------------------------------
 | A-B-C | A'-B'-C'-D' | A''-B''
 --------------------------------
      スタック



clearTaskOnLaunch 属性
タスクのルート アクティビティでこの属性を "true" に設定した場合、ユーザーがいったんタスクを離れると、戻ったときにはルートを含むすべてのアクティビティがクリアされる。

つまり

 タスク3
 --------------------------------
 | A''-B''
 --------------------------------
      スタック



finishOnTaskLaunch 属性
clearTaskOnLaunch 属性と似ているが、タスク全体ではなく単一のアクティビティに作用する。
また、ルート アクティビティを含むどのアクティビティもクリアの対象となりえる。
この属性が "true" に設定されたアクティビティは、現在のセッションの間のみタスクの一部を形成する。
ユーザーがいったんそのタスクから離れてから、再度タスクに戻ると、このアクティビティはクリアされている。

つまり、B にこの属性を設定すると、

 タスク1  タスク2  タスク3
 --------------------------------
 | A-C | A'-C'-D' | A''-B''
 --------------------------------
      スタック



アクティビティをスタックから削除する他の方法

Intent オブジェクトに FLAG_ACTIVITY_CLEAR_TOP フラグが含まれている
 +
そのインテントを処理すべきタイプのアクティビティのインスタンスが
対象タスクのスタック内に存在する
 ↓ 
そのインスタンスがスタックの最上位になってインテントに応答できるよう、
それより上位のアクティビティはすべてクリアされる


つまり、B'' が呼んだ Intent オブジェクトに FLAG_ACTIVITY_CLEAR_TOP が設定されていて、このインテントを処理するのが A' だとすると

 タスク1  タスク2   タスク3
 --------------------------------
 | A-B-C | A'-B'-C'-D' | A''-B''
 --------------------------------
      スタック

こうなる

 タスク1  タスク3  タスク2
 --------------------------------
 | A-B-C | A''-B'' | A'
 --------------------------------
      スタック

タスク3がバックグラウンドに移動して、A'より上位のアクティビティ B', C', D' はクリアされる


指定されたアクティビティの起動モードが "standard"
 ↓
そのアクティビティもスタックから削除され、
新しいインスタンスが起動してインテントを処理します。

つまり、
上記の場合、(B', C', D' は同じようにクリアされ)A' もクリアされて新しく A' のインスタンスが起動する


FLAG_ACTIVITY_CLEAR_TOP は、ほとんどの場合 FLAG_ACTIVITY_NEW_TASK と組み合わせて使用する
 ↓
別のタスクに既に存在しているアクティビティを探し、それをインテントに応答できる位置に配置できる



タスクの開始

アクティビティをタスクのエントリ ポイントとして設定

アクションに "android.intent.action.MAIN"
カテゴリに  "android.intent.category.LAUNCHER"

を指定したインテント フィルタをアクティビティに追加

このタイプのフィルタを追加すると、アクティビティのアイコンとラベルがアプリケーションランチャに表示される

アクティビティに MAIN と LAUNCHER フィルタが指定されている場合は、必ずタスクが開始される起動モード("singleTask" または "singleInstance")を使用する必要がある。


例えば、

インテントが "singleTask" アクティビティを起動し
 ↓
新しいタスクが開始
 ↓
ユーザーが作業
 ↓
ユーザーが [ホーム] キーを押す
 ↓
ホーム画面が表示=先ほどのタスクはバックグラウンドに移動

もし、このフィルタを指定しなかったら、ユーザーがタスクに戻るための手段がない!
また、"standard" や "singleTop" を指定した場合アクティビティは複数回インスタンス可能なため、ここでランチャーから新しく起動した場合別のインスタンスが作成される可能性がある。

FLAG_ACTIVITY_NEW_TASK フラグを指定したアクティビティでは、新しいタスクを開始した後にユーザーが [ホーム] キーを押してそのタスクを離れた場合に、タスクに戻るための手段を用意しておく必要がある。

外部エンティティから呼び出すことのできるアクティビティでこのフラグが使用されている可能性がある場合は、開始されたタスクにユーザーが戻るための手段を別途提供する。

ユーザーがアクティビティに戻ることができるようにしない場合は、 要素の finishOnTaskLaunch を "true" に設定する

2010年8月9日月曜日

Android UI Design Tips

Android UI Design Tips
という資料があったので、日本語でまとめてみました。





■ UIを意識すべきなのはどうして?
  良いUI 
   → ユーザーが洗練された質に気が付く
     → 評価が良くなる
      → アプリのランキングが良くなる
        → さらにたくさんのインストール&購入につながる

■ Agenda

  1. やるべきことと、やっちゃいけないこと

  2. デザイン哲学と考慮すること

  3. 絶対に使うべき UI framework の機能・特徴

  4. 新しい UI デザインパターン

  5. アイコンとガイドライン



■ やるべきことと、やっちゃいけないこと

 * やっちゃいけないこと

  ・単に他のプラットフォームのUIを移植しない!
    ・ユーザーがプラットフォームとアプリが合っていると感じるべき
    ・アプリのブランドとプラットフォームとのバランス

  ・modal progress と確認用ダイアログを使い過ぎない!

  ・柔軟性を持つ!(absolute-positioned layout はダメ)

  ・px単位を使わない!(dp(dip)やspを使う)

  ・小さい文字はダメ!


 * やるべきこと

  ・すべてのリソースに対して、high density screen 用バージョンを用意する

  ・ボタンやリストアイテムなど、明らかにタップするものは大きくする

  ・Android のアイコンガイドラインにしたがう

  ・適切なマージン/パディングを使う

  ・D-pad とトラックボールをサポートする

  ・activity stack を適切に運用する

  ・orientation changes(画面回転)を適切に処理する

  ・theme/style, dimension, color resources を使用して
   冗長性を減らす

  ・visual and interaction designer(s) と一緒に仕事する!!!



■ デザイン哲学と考慮すること

 * Android デザイン哲学

 ・ Clear vs. "simple"
   明確 vs シンプル

 ・ Conetnt vs chrome
   内容 vs 外観のカスタマイズ

 ・ Consistent yet engaging
   一貫性があり魅力的
    - エレガントなバリエーション

 ・ Enhanced by the cloud
   クラウドで機能強化
    - ユーザー環境をデスクトップとモバイルで維持する


 * good interface design の原理

  1. ユーザーにフォーカスする

  2. 正しいものを可視化する

  3. 適切なフィードバックを示す

  4. 予測可能にする

  5. fault-tolerant にする


 * ユーザーにフォーカスする

  ・自分のアプリのユーザーを知る
    - 年齢・スキルレベル・文化・身体障害、などなど
    - あなたのアプリで彼らが何をしたいのか?
    - 彼らはどんな種類のデバイスを使うのか?
    - どこで/いつ/どのように 彼らがそのデバイスをつかうのか?
 
  ・'user-first' mentality (ユーザーを第1に考えて)でデザインする

  ・実際のユーザーに早く/しばしばテストしてもらう


 * 正しいもの可視化する

  ・もっとも一般的な(頻繁に使われる)操作が、すぐ見えてすぐ操作できるべき
    = 左上が一番目がいきやすい

  ・付属的な機能は MENU ボタンに割り当てることができる


 * 適切なフィードバックを示す

  ・ すべてのインタラクティブなUI要素は、少なくとも4個の状態
   (default, desabled focused, pressed など)を
   を使って持つようにする

  ・ 1つのアクションの効果は、明確に見える(=わかる)ようにする

  ・ 控えめだけど十分なプログレスインジケータを表示する


 * 予測可能にする

  ・ ユーザーが期待することをする
    - activity stack の適切な運用
    - ユーザーが見ることを期待する情報とアクションを示す
    (テストと観測が必要)

  ・ 適切なアフォーダンスを使う
    - もしそれがクリック可能なら、クリック可能だとわかるようにする!!

  ** もし複雑な操作が必要ならば、デザインを考えなおすべき! **


 * fault-tolerant にする

  ・意味があるものだけ、操作可能にする
    - UI要素を適切に Enable/Disable する

  ・不可逆的なアクションの数を制限する

  ・確認ダイアログは '使わない'('undo') ようにする
    - 実際は、できるだけ少ない modal dialog を使う
     だって目障りだもん

  "If an error is possible, someone will make it. "
   - Donald Norman, author, The Design of Everyday Things




 * デザインで考慮すること

  ・物理的なスクリーンサイズ
  ・解像度
  ・縦画面 & 横画面
  ・主要なUIインタラクションメソッド
    - タッチスクリーン
    - Dパッド/トラックボール
  ・ソフト/ハードキーボード

  ・デバイスによって、方法が異なる可能性があるということに対する
   意識はすごく重要

  ・デバイスのUIバリエーションについてCDDを読んで学ぶ
    - http://source.android/com/compatibility

  ・スクリーンサイズと解像度に対応する
    - http://developer.android.com/resources/dashboard/screens.html



■ 絶対に使うべき UI framework の機能・特徴

 ・<RelativeLayout>

 ・1つの .apk にすべてのリソースを含む
   - drawable
   - drawable-hdpi
   - drawable-mdpi
   - layout
   - layout-port
   - layout-land
   - layout-large-land
   - layout-large-port

  ・システムが runtime時にどのリソースを使うか選択する

 ・9-patch drawables (foo.9.png)
  ・CSS3 border-image に似てる
  ・border pixels が拡張可能な領域を示す
  ・ -mdpi と -hdpi バージョンを用意する!!

 ・Selector (state list) drawables
  ・状態(state) (desabled, pressed, focused, default...)
   によってボタンの色や画像をかえる

 ・Layer drawables (XML + PNGs)
   foo_border.9.png + foo_mask.9.png
       + Drawable.setColorFilter(0xA4C639, ...);
     → Rendered output (resizable w/9-patch)


■ 新しい UI デザインパターン

もともとは、Google I/O 2010 の Android UI design patterns で話された内容
http://code.google.com/events/io/2010/sessions/android-ui-design-patterns.html

 ・Dashboard

 ・Action Bar

 ・Quick Actions

 Google I/O 2010 では、これに加えて

 ・Search Bar

 ・Companion Widget

 が紹介されている

 詳しくはこちら http://dl.google.com/googleio/2010/android-android-ui-design-patterns.pdf


 * Dashboard



  "このアプリで何ができるのか?"
  "新しくなったことはなにか?"

  を表示

  - Recommendations
   ・ 3 - 6 個の重要なアプリセクションにフォーカス
   ・ what's new にハイライトする
   ・ Be flavorful (魅力的に!)ー ここが第一印象


 * Action Bar



  "よく使うアクションをすばやく行う"
   ・検索、リロードなど

  - Recommendations
   ・アプリのキーやアプリ全体のアクションを画面上にみせる
   ・場所の感覚を伝えるのに役立つ
   ・アプリ内で一貫して使う
   ・'home'メカニズムを提供する - logo や 専用ボタン
   ・状況に依存したアクションは使わない!!


 * Quick Actions



  "このオブジェクトで何ができるのか?"


■ アイコンとガイドライン

 http://developer.android.com/quide/practices/ui_guidelines/icon_design.html

 新しいアイコンスタイル
  ・Tactile(触感)

  ・Rendered

  ・Forward Facing(正面向き)

  ・Top-lit(トップから照明)

  ・Synecdoche(提喩法、代喩:一部で全体を、
   または全体で一部を比喩で表現する方法)

  ・Diverse shapes, materials(さまざまな形状、質感)

2010年8月7日土曜日

Gadget1 に行ってきました

第2回ガジェットワンに行ってきました。
「Gadget1 R2 Bekkoame」

第1回が2月にあったのですが、この時はいけなくて今回リベンジ!
ということではりきって参加です。

場所はオラクル青山センター (http://www.oracle.com/lang/jp/corporate/aoyama.html)。
外苑前駅から直結です。

すごくきれいな会場で、空間も余裕があっていいです。

プログラムはこちら

展示もあります。

Ustream のアーカイブはこちらからたどれます


会場の様子(午前中)はこんな感じ
まだまだ空きがあります。
みんな午後から本気出すんですね。わかります。




なんと Android 女子部も展示をだしました!!





端末がいっぱいw (結局こーなってしまった)

なぜかセカイカメラのシールを配布



女子部員の個人アプリの紹介パネル
  &
女子部アプリ「ネイル・ド・ロンジョ」の紹介パネル



Xperia の裏蓋のデコサンプル
 &
女子部デコ勉強会 8月28日(土)の紹介チラシ





やっぱりガンプラデコは大人気でした。



その他の展示ブースでは PLUS さんのプレゼン用ツール
(お絵描きボードみたいな感じ?)がおもしろかったです。
手元のボードにペンで書き込むと、プロジェクターで
映している画面上のパワポにお絵描きできます。
線をマーカーにしたり、○にしたりできました。
ボード上の全面にドットパターンの模様があって、これを
カメラがついたペンで認識しているそうです。
ボードに電池がいらないので、軽くて使いやすかったです。

めぐさんがモグタソを書きまくってましたw




他にも、

ネットブックに電子コンパスを内蔵した展示




Corona のデモ




BeatCraft さんの評価ボード






午後は人が増えてこんな感じに





女子部ブースにずっといたので、ほとんど講演を聞けなかったのですが、
LTはがっつり見ました。5分間なので、みんなの焦りが。。。
トークがうまいのはいいですね。たくさん笑わせていただきました。



「Gadget1 R2 ガジェットカフェでソーシャル電子工作を始めよう!」の資料が公開されてました。


# ドラは奥が深いっす



帰りはサーバーを横目に。




次回はなんと大阪です!
11月5日-6日、Gadget1 R3 Chitoseame!KOF2010にて開催!


# 当日はこんな感じでした by めぐ画伯