その他の必要条件

  • Adobe Flash Professional CS5 Extension for AIR 2.5
    Adobe Labs からダウンロードしてインストール
  • Android デバイス
    Android 2.2 以降がインストールされているもの
  • Android SDK
    バージョン 2.2 以降

Andoid は 4 つの仮想キー (ホームメニューサーチバック) を持つデバイス上で実行されます。これらのキーは、デバイスによって、ハードウェアキーとして実装されることもあれば、ソフトウェアキーとして実装されることもあります。この記事では、これら 4 つのキーが押された場合の処理方法と、AIR アプリケーションに固有の注意点を解説します。

仮想キーイベントの処理

AIR アプリケーションでは、ハードウェアキー、ソフトウェアキーに関わらず、キーが押されるとキーボードイベントが発生します。このイベントを通して、AIR アプリケーションはキーが押されたことを知ります。AIR 2.5 からは、新しく、ホームメニュー、サーチバックの 4 つのキーもサポートされるようになりました。

キーボードイベントには、以下の 2 種類があります。

  • KeyboardEvent.KEY_DOWN:キーを指で押したときに発生する
  • KeyboardEvent.KEY_UP:キーから指を離したときに発生する

1 つ目はキーを押したタイミングで発生します。2 つ目はキーを離したタイミングで発生します。イベントハンドラーを使い、それぞれのタイミングでの適切な処理を記述できます。

キーボードイベントは、NativeApplication オブジェクトにより送出されます。そのため、イベントハンドラーも NativeApplication に追加します。下は KEY_DOWN イベントに対するハンドラーを追加する例です。

NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);

キーボードイベントにより呼び出されるハンドラー内では、押されたキーの種類により処理を振り分けます。その際、押されたキーの種類の判別は、各々のキーに割り当てられた固有の番号を使います。ホームを除く 3 つの仮想キーには以下の値が割り振られています。

  • Keyboard.MENU:メニューキー
  • Keyboard.SEARCH:サーチキー
  • Keyboard.BACK:バックキー

以下は、これらの値を使い仮想キーのみを処理するイベントハンドラーのサンプルです。switch 文を使って、押されたキーに対応する処理を割り振っています。

public function onKeyDown(event:KeyboardEvent):void { switch (event.keyCode) { case Keyboard.MENU: trace("メニューキーが押された"); break; case Keyboard.SEARCH: trace("サーチキーが押された"); break; case Keyboard.BACK: trace("バックキーが押された"); break; } }

メニューキーとサーチキー

AIR アプリでも、仮想キーが押されたときの処理は、できるだけネイティブアプリケーションの動作と一致しているのが望ましいでしょう。あるアプリケーションだけ他のアプリと振る舞いが異なるとユーザは混乱するかもしれませんし、不満を覚えて 2 度と使って貰えなくなるかもしれません。

メニューキーは、画面に利用可能な操作メニューを呼び出すためのキーです。Android アプリにはメニューバーが無いため、代わりに使われます。特に提供する機能がない場合は、メニューキーが押されてもメニューを表示しなくても構いません。

サーチキーは、関連する情報の検索バーを表示するためのキーです。こちらも必要なときだけ表示される機能です。

下の画像は、メニューキーとサーチキーの例です。左はブラウザーからメニューバーを押したとき、右は電話アプリからサーチキーを押したときのスクリーンショットです。メニューは画面下部に、検索バーは画面上部に表示されます。

ネイティブアプリケーションでは、Android SDK に用意されているコンポーネントを使って同じような見た目を実現することができます。しかし、Flash Professional CS5 には、同様のコンポーネントが用意されていません。そのため Android らしく見えるコンポーネントが欲しい場合は、自前で作成する必要があります。その際、ゼロから始める代わりに、既に公開されているものをベースにすることは可能です。(参考:Kevin Hoyt のコンポーネント

バックキー

バックキーは、1 つ前の "アクティビティ"(画面) に戻るためのキーです。開いたメニューを閉じる等にも使われます。(メニューもアクティビティの 1 種類)

ネイティブの Android アプリケーションでは、個々の画面は独立した "アクティビティ" です。バックキーを押せば、特別な処理を記述しなくても、自動的に前のアクティビティ、すなわち前の画面に戻ります。

ところが、AIR アプリケーションは "全体で 1 つのアクティビティ" です。そのため、バックキーを押すと、アプリケーションの状態に関わらず、アプリを起動する前の画面に戻ってしまいます。これは、多くの場合、ユーザーが期待するのとは異なる動作でしょう。

このような状況を避けるには、バックキーの振る舞いを標準から変更する必要があります。下はそのサンプルです。キーボードイベントで Keyboard.BACK が押されたことを発見したら、デフォルトの動作をキャンセルして、画面遷移を制御するロジックを呼び出します。

public function onKeyDown(event:KeyboardEvent):void { switch (event.keyCode) { case Keyboard.BACK: // アプリが画面から消えないようにデフォルトの動作をキャンセル event.preventDefault(); // 以下に、画面遷移のロジックを記述 // ... break; } }

preventDefault() は、バックキーに対する標準の動作をキャンセルするメソッドです。preventDefault() の呼び出しは、KEY_DOWN イベントに対する処理として行わなければなりません。KEY_UP イベントのタイミングでは、既にキャンセルには遅すぎるためです。

ベータ版が公開中の Flex SDK のモバイル向けのフレームワークでは、バックキーに対する処理がフレームワーク内に組み込まれています。そのため、モバイル Flex アプリケーションは、特に処理が記述されていなくても、バックキーを押すと前の画面に戻ります。

Flex SDK は、各ビューをスタックで管理しており、スタックの一番上にあるビューが表示される仕組みになっています。新しいビューをスタックの上に積むとそれが表示され、スタックの一番上のビューを取り除くと 1 つ下にあったビューに戻るという訳です。Flash Professional CS5 での開発では同様の仕組みを実装する必要があります。

ホームキー

他の 3 つの仮想キーと異なり、ホームキーが押されてもキーボードイベントは発生しません。他のキーと異なり、ホームキーが押されたときの振る舞いには、アプリケーションから関与することができません。ホームキーが押されると、アプリケーションは選択の余地無くバックグラウンドにまわされます。

アプリケーションがバックグラウンドでの実行に変わるとき、NativeApplication オブジェクトにより DEACTIVATE イベントが送出されます。従って、イベントハンドラーを使えば、画面に表示されなくなるタイミングで、アプリケーションの状態を保存することは可能です。

NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, onDeactivate);

DEACTIVATE イベントハンドラー内では、主に 2 つの処理を行います。

  • 再びアクティブになったとき、あるいは強制終了させられたときのために、アプリケーションの状態を保存
  • 電力やメモリなど、システムのリソースを無駄にしないように、アプリケーションの状態を変更
    • Accelerometer と Geolocation のオブジェクトからイベントハンドラーを削除 (データを記録するアプリは除く)
    • オーディオ再生の停止 (音楽再生アプリは除く)
    • ビデオ、アニメーション再生の一時停止
    • フレームレートの変更

Android アプリは、ホームキーが押されたからといって、直ぐに終了されることはありません。たいていは、そのままバックグラウンドで実行されます。システムのリソースが少なくなると、バックグラウンドで実行中のアプリが終了させられるかもしれません。

もし、ホームキーが押されたら自らアプリケーションを終了さたいという場合には、DEACTIVATE イベントのハンドラー内で exit() を呼びます。

public function onDeactivate(event:Event):void { // 自らアプリケーションを終了させる NativeApplication.nativeApplication.exit(); }

アプリケーションがバックグラウンドで実行されるとき、AIR は自動的にフレームレートを秒 4 フレームまで落とします。この状態をスリープモードと呼びます。

スリープモードでは、スクリプトでフレームレートを 4 fps に設定した場合と異なり、描画処理が行われません。スクリプトのみ、見えないところでひっそりと実行されます。スクリプトの実行も止める (0 fps) 代わりに 4 fps が選ばれたのは、ネットワーク接続 (NetConnection, NetStream, Socket 等) を利用可能な状態にしておくためです。多くのデバイスが、状態の再確認を 4 fps で行うため、これが効率の良いフレームレートだということです。ネットワークを利用しないアプリケーションでは、ホームキーが押されたらフレームレートを 0.01 fps の様なより小さな値にすることで、更に電力消費を押さえられるかもしれません。

アプリケーションが、再び画面に表示されるとき、今度は NativeApplication オブジェクトから ACTIVATE イベントが送出されます。このタイミングで、ホームキーが押される前の状態に戻します。削除したイベントハンドラーの追加やオーディオ再生の再開なども忘れずに行います。

NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, onActivate);

アプリケーションが復帰ではなく、最初に実行されるときには NativeApplication オブジェクトが InvokeEvent.INVOKE イベントを送出します。この場合でも、以前に DEACTIVATE イベントのタイミングで保存しておいたデータがあれば、それを使用できます。また、INVOKE イベントからは、起動時の引数も取得することができます。

NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke); public function onInvoke(event:InvokeEvent):void { // 引数を確認する trace(event.arguments); }

INVOKE と対になるイベントは EXITING イベントです。こちらは、OS が AIR アプリを終了させるときに送出されます。送出が保証されないケースもあるため、データの保管等はできるだけ DEACTIVATE イベントで行うのが良さそうです。

最後に

この記事では 4 つの仮想キーに関連する情報を紹介しました。仮想キーの処理を適切に行うことで、より使いやすく Android アプリらしいアプリを作ることができるようになると思います。