2011年5月24日火曜日

Android Open Accessory Development Kit

Android Open Accessory Development Kit

Android 3.1 プラットフォーム (そして、バックポートされた Andorid 2.3.4) で Android Open Accessory がサポートされるようになりました。これにより外部の USB ハードウェア(Android USB accessory)は、"accessory" モードの Android-powered デバイスとやりとりできるようになりました。Android-powered デバイスが accessory モードのとき、接続された機器は USB ホストとして振る舞い(バスに電力を供給しデバイスを列挙する)、Android-powered デバイスは USB デバイスとして振る舞います。Andorid USB accessory は Android-powered device に取り付けるために特別にデザインされており、accessory モードをサポートした Android-powered デバイスを検出するためのシンプルなプロトコル(Android accessory protocol)が取り付けられています。また、accessory は電力をチャージするために 5V で 500mA を提供しなければなりません。すでにリリースされている多くの Android-powered デバイスは USB デバイスとして振舞うことだけが可能で、外部の USB デバイスと接続を開始することはできません。Android Open Accessory はこの制約を克服し、accessory が接続を開始できるようにすることで、さまざまな種類の Android-powered デバイスとやりとりできる accessory を作成することができます。

注意 : accessory モードは最終的にはデバイスのハードウェアに依存し、全てのデバイスが accessory モードをサポートするわけではありません。アプリケーションの Android マニフェストで <uses-feature> エレメントを使うことで、accessory をサポートするデバイスかどうかフィルターすることができます。より詳しい情報は、USB Accessory Developer Guide を見てください。

次のリストは現在 Andorid Open Accessory と互換性のある開発ボードを扱っている代理店です。

  • RT Corp は Android ADK ボードデザインに基づいた Arduino-compatible board を提供しています。
  • Microchip は A PIC based USB microcontroller board を提供しています。
  • DIY Drones は RC (radio controlled) と UAV (unmanned aerial vehicle) と連動した Arduino-compatible board を提供しています。
  • Modem Device は ADK firmware をサポートした Arduino-compatible board を提供しています。

我々はより多くのハードウェア代理店が多種多様なキットを作成すると予測しています。ですから、将来の開発のためにも、このまま注目していてください。

---

ADK Components


Android Open Accessory Development Kit (ADK) は Arduino open source electronics prototyping platform, accessory のハードウェアデザインファイル, accessory のファームウェアを実装したコード, accessory とやりとりする Android アプリケーションに基づいた Android USB accessory の実装を提供します。ハードウェアデザインファイルとファームウェアコードは ADK package download に含まれています。

ADK に含まれている主なハードウェアとソフトウェアコンポーネントは:

  • Arduino Mega2560 と Circuits@Home USB Host Shield design (現在 ADK board と呼ばれる) に基づいた USB micro-controller board。これは後で Android USB accessory として実装されます。ADK board は、"shields" と呼ばれるアタッチメントで使うことができる入力ピンと出力ピンを提供します。カスタムファームウェアは C++ で書かれており、ボードの機能とアタッチメントシールドと Android-powered デバイス間のやりとりを定義するためにインストールされています。ボード用のハードウェアデザインファイルは hardware/ ディレクトリに配置されています。

  • ADK board 上に乗っている Android Demo Shield(ADK shield) はボードの入力と出力のポイントを実装しています。これらの実装には、ジョイスティック、LED 出力、温度と光度のセンサーが含まれています。あなたは、自分用のシールド買ったり作ったり、ADK に独自の配線をして機能をカスタマイズすることができます。シールド用のハードウェアデザインファイルは hardware/ に配置されています。

  • Arduino USB Host Shield ライブラリを基にしたライブラリは USB Host として振舞うための USB micro-controller board のロジックを提供します。これにより、ボードは USB デバイスとのトランザクションを開始することができます。このライブラリ全体の使い方の説明はこのドキュメントのスコープ外です。必要に応じて、このライブラリとの重要なやりとりを取り上げます。より詳しい情報は、firmware/arduino_libs/USB_Host_Shield ディレクトリ内の Arduino USB Host Shield library のソースコードを見てください。

  • firmware/demokit/demokit.pde の Arduino sketch にはADK board 上で動く firmware が C++ で書かれています。sketch は Android-powered デバイスとやりとりするために Android accessory protocol library を呼びます。また、ADK board とシールドからのデータを Android アプリケーションに送り、Android アプリケーションから受け取ったデータを ADK board とシールドにアウトプットします。

  • Android accessory protocol library は firmware/arduino_libs/AndroidAccessory ディレクトリに配置されています。このライブラリは、どのようにバスを列挙し、accessory mode をサポートする Android-powered デバイスに接続し、デバイスとの接続をセットアップするかを定義しています。

  • ADK board の機能をサポートする他の 3rd party ライブラリ:



---

Getting Started with the ADK


以下のセクションでは、PC 上 に Arduino software をインストールし、Arduino software を使って ADK board に ファームウェアを書き込み、ADK board 用の Android アプリケーションと一緒に動かす方法を説明します。始める前に、開発環境をセットアップするため、次のアイテムをダウンロードしてください。

  • Arduino Software : ライブラリおよびコーディングと ADK board にファームウェアをインストールするための IDE が含まれる
  • CapSence library : 人間の静電容量を感知するためのライブラリが含まれる。これは Android シールドに配置されている静電容量ボタンの為に必要
  • The ADK package : ADK board 用のファームウェアと ADK board とシールド用の hardware design files が含まれる



Installing the Arduino software and necessary libraries

Arduino software をインストールするには:

  • 1. Arduino website で説明されているように Arduino Software をダウンロードしてインストールします。
    注意: もし、Mac 上で使うなら、インストール手順ではそう言っていなくても、Arduino package に含まれている FTDI USB Serial Driver をインストールしてください。

  • 2. ADK package をダウンロードし、任意の場所に展開してください。app, firmware, hardware ディレクトリが含まれているはずです。

  • 3. CapSence をダウンロードし、任意の場所に展開します。

  • 4. 必要なライブラリをインストールします。

    On Windows:

    • firmware/arduino_libs/AndroidAccessoryfirmware/arduino_libs/USB_Host_Shield ディレクトリ (ディレクトリごと、含まれるファイルだけではなく) を <arduino_installation_root>/libraries/ ディレクトリにコピーする
    • <arduino_installation_root>/libraries/ ディレクトリに CapSense ディレクトリを作る
    • ダウンロードし展開した CapSence から CapSense.cppCapSense.h を上記の CapSense ディレクトリにコピーする


    On Mac:

    • Finder で Arduino アプリケーションを右クリックし、Show Package Contents を選択する
    • firmware/arduino_libs/AndroidAccessoryfirmware/arduino_libs/USB_Host_Shield ディレクトリ (ディレクトリごと、含まれるファイルだけではなく) を Arduino アプリケーション内の Contents/Resources/Java/libraries ディレクトリにコピーする
    • Contents/Resources/Java/libraries ディレクトリに CapSense ディレクトリを作る
    • ダウンロードし展開した CapSence から CapSense.cppCapSense.h を上記の CapSense ディレクトリにコピーする


    On Linux (Ubuntu):

    • firmware/arduino_libs/AndroidAccessoryfirmware/arduino_libs/USB_Host_Shield ディレクトリ (ディレクトリごと、含まれるファイルだけではなく) を <arduino_installation_root>/libraries/ ディレクトリにコピーする
    • <arduino_installation_root>/libraries/ ディレクトリに CapSense ディレクトリを作る
    • ダウンロードし展開した CapSence から CapSense.cppCapSense.h を上記の CapSense ディレクトリにコピーする
    • shell prompt で sudo apt-get install avr-libc と入力して、avr-libc library をインストールする



AndroidAccessory, USB_Host_Shield, CapSense の3つの新しいディレクトリが Arduino libraries ディレクトリに出来ているはずです。


Installing the firmware to the ADK board

ADK board にファームウェアをインストールするには:

  • 1. ADK board を micro-USB port を使ってあなたのコンピュータに接続する。これにより、双方向通信ができるようになり、さらに ADK board に電力が供給される。

  • 2. Arduino を起動する

  • 3. Tools > Board > Arduino Mega 2560 をクリックして ADK board のタイプを指定する

  • 4. 適切な USB port を選択する:

    • On Windows : Tools > Serial Port > COM# をクリックして通信ポートを指定する。COM ポート番号はあなたのコンピュータによって変わる。COM1 は通常はシリアルポート接続用に予約されている。COM2 もしくは COM3 になることが多い。

    • On Mac : Tools > Serial Port > dev/tty.usbserial-### をクリックし通信ポートを指定する。

    • On Linux(Ubuntu) : Tools > Serial Port > dev/ttyUSB# をクリックして通信ポートを指定する。

  • 5. File > Open をクリックして、ファームウェアコード (sketch) を開き、firmware/demokit/demokit.pde を選択する。

  • 6. Sketch > Compile/Verify をクリックして、sketch にエラーがないことを確かめる。

  • 7. File > Upload to I/O Board を選択する。board が Android-powered デバイスと通信する準備が整ったら、Arduino は Done uploading を出力する。



Running the DemoKit Android application

DemoKit Android アプリケーションはあなたの Android-powered デバイス上で動き、ADK board と通信します。ADK board は board 上の LED ライトを光らせろ、というようなコマンドを受信したり、ジョイスティックの動きや温度データなどを board から送ったりします。

アプリケーションを Eclipse にインストールして実行するには:

  • 1. accesory モードをサポートする 2.3.4 デバイス用の Open Accessory library を含む Google APIs API Level 10 add-on library をインストールする。
    このライブラリは accessory mode をサポートする Android 3.1 以上のデバイスと前方互換性があります。もし、Android 3.1 以上のデバイスのみ対象にするなら、API Level 12 だけで十分です。どちらの API レベルを使うか決めるためのより詳しい情報は USB Accessory ドキュメントを見てください。

  • 2. File > New > Project... をクリックし、次に Android > Android Project を選択します。

  • 3. Project name: に DemoKit と入力します。

  • 4. Create project from existing source を選択し、Browse をクリックし、app ディレクトリを選択して Finish をクリックします。

  • 5. Build Target に Google APIs(Platform 2.3.3, API Level 10) を選択します。

    注意: add-on が 2.3.3 とラベルされていても、最新の Google API add-on library for API level 10 には、2.3.4 デバイスに対する USB Open Accessory API サポートが追加されています。

  • 6. Finish をクリックします。

  • 7. アプリケーションをあなたのデバイスにインストールします。

  • 8. ADK board (USB-A) をあなたの Android-powered デバイス (micro-USB) に接続します。accessory への電源ケーブルが刺さっているか、もしくは accessory の micro-USB ポートが電力供給のためにあなたのコンピュータに接続されている(この場合は ADK board をモニターすることもできます。)ことを確認してください。接続したら、DemoKit アプリケーションが accessory に接続してもいいか尋ねるプロンプトが出るので、許可を選択します。もしプロンプトが出なかったら、accessory を接続もしくは再接続してください。


これで、LED カラーやサーボ(サーボが接続されている場合)のスライダーを動かしたり、リレーボタンを押したりして、ADK board とやりとりすることができます。ADK シールドでは、ボタンを押したり、ジョイスティックを動かして、それらの出力をアプリケーションで見ることができます。


Monitoring the ADK board

ADK ファームウェアは、あなたが自身の accessory を作成したいときに見るべきいくつかのファイルで構成されています。firmware/arduino_libs/AndroidAccessory ディレクトリ内のファイルは最も重要なファイルで、accessory モードをサポートした Android-powered デバイスを検出し接続するためのロジックが入っています。arduino_libraries_directory/AndroidAccessory ディレクトリ内のコードと firmware/demokit/demokit.pde sketch に自由にデバッグステートメント(Arduino の Serial.print() ステートメント) を追加して再アップロードし、どのようにファームウェアが動くか見ることができます。

Tools > Serial Monitor をクリックし、baud を 115200 に設定して Arduino Serial Monitor でデバッグステートメントを見ることができます。
次の、どのように accessory が Android-powered デバイスと通信するかのセクションでは、あなたが自分の accessory でするべきことについて説明します。


---

Implementing the Android Accessory Protocol


Android USB accessory には、Android-powered デバイスを検出して通信をセットアップする方法が定義された Android Accessory Protocol が取り付けられている必要があります。一般的には、accessory は次のステップを行います。

  • 1. 接続されたデバイスを検出するまで待つ
  • 2. デバイスが accessory モードをサポートしているかどうか確かめる
  • 3. 必要であれば accessory mode でデバイスを開始するよう試みる
  • 4. デバイスが Android accessory protocol をサポートしていたら、通信を確立する


次のセクションでは、これらのステップをどのように実装するかより詳しく見ていきます。

Wait for and detect connected devices

あなたの accessory に Android-powered device が接続されたことを定期的にチェックするロジックを組み込むようにしてください。デバイスが接続されたら、デバイスが accessory モードをサポートしているかどうか確かめるようにしてください。


Determine the device's accessory mode support

Android-powered デバイスが接続されたら、次の3つの状態のどれかになるでしょう。

  • a. 取り付けられたデバイスは Android accessory モードをサポートし、すでに accessory モードになっている
  • b. 取り付けられたデバイスは Android accessory モードをサポートしているが、accessory モードにはなっていない
  • c. 取り付けられたデバイスは Android accessory モードをサポートしていない


最初の接続の間に、accessory は接続されたデバイスの USB device descriptor の vendor ID と product ID をチェックするようにしてください。デバイスがすでに accessory モード (case A) であれば、vendor ID は Google's ID (0x18D1) と、product ID は 0x2D00 もしくは 0x2D01 と一致するはずです。そうであれば、accessory は自身の通信プロトコルでバルク転送エンドポイントを通して デバイスとの通信を確立することができます。ここでは、デバイスを accessory モードで開始する必要はありません。

注意: 0x2D00 は accessory モードをサポートする Android-powered デバイス用に予約されています。0x2D01 は ADB (Android Debug Bridge) protocol をサポートするデバイス用に予約されています。これは、ADB 用に2つのバルクエンドポイントを持つ2番目のエンドポイントを公開します。もしコンピュータで accessory のシミュレーションを行うなら、これらのエンドポイント使って accessory アプリケーションをデバッグすることができます。一般的には、デバイスの ADB へのパススルーが実装されている accessory 以外ではこのインタフェースは使用しないでください。

もし、vendor ID と product ID が一致しなかったら、状態 b と状態 c を区別する方法はありません。よって、accessory はデバイスがサポートされているかどうか確かめるために accessory モードでデバイスを開始するよう試みます。


Attempt to start the device in accessory mode

vendor ID と product ID が accessory mode の Android-powered デバイスと一致しない場合、accessory はデバイスが accessory モードをサポートしているがその状態ではないのか、それとも accessory モードをサポートしていないのか識別することができません。なぜなら、accessory モードをサポートしているがその状態ではないデバイスは、Android Openn Accessory 用の特別なものではなくメーカーの vendor ID と product ID を最初に報告するからです。いずれの場合においても、accessory はデバイスが accessory モードをサポートしているかどうか確かめるために、accessory mode でデバイスを開始するよう試みるべきです。次のステップはそれをどのように行うかを説明しています:

  • 1. 51 control request ("Get Protocol") を送ってデバイスが Android accessory protocol をサポートしているか確かめます。protocol がサポートされている場合、0 以外の値が返ってきます。返ってくる値はデバイスがサポートする protocol のバージョンを表します(現在は、version 1 だけ存在しています)。このリクエストは次のような特徴を持つエンドポイント0での control request です。

    requestType: USB_DIR_IN | USB_TYPE_VENDOR
    request: 51
    value: 0
    index: 0
    data: protocol version number (16 bits little endian sent from the device to the accessory)


  • 2. デバイスが適切なプロトコルバージョンを返したら、デバイスに識別文字列情報を送ります。この情報によって、デバイスはこの accessory に対する適切なアプリケーションを見つけることができ、また、もし適切なアプリケーションが存在しない場合にユーザーに URL を表示することができます。これらのリクエストは次のような特徴を持つエンドポイント0 (各 string ID に対して) での control request です。

    requestType: USB_DIR_OUT | USB_TYPE_VENDOR
    request: 52
    value: 0
    index: string ID
    data zero terminated UTF8 string sent from accessory to device

    次の string ID がサポートされています。各文字列に対して最大サイズは 256 bytes です。(\0 を使って 0 で終わる必要があります)

    manufacturer name: 0
    model name: 1
    description: 2
    version: 3
    URI: 4
    serial number: 5


  • 3. 識別文字列を送ったら、デバイスに accessory mode でスタートするようにリクエストします。このリクエストは次のような特徴を持つエンドポイント0での control request です。

    requestType: USB_DIR_OUT | USB_TYPE_VENDOR
    request: 53
    value: 0
    index: 0
    data: none



最後の contorl request を送った後、接続された USB デバイスが自身を accessory モードでバスに再紹介したら、accessory は接続されたデバイスを再列挙できるようになります。ここで determining the device's accessory mode support のアルゴリズムまで戻って、再び vendor ID と product ID をチェックします。デバイスが正しく accessory モードに移ったならば、vendor ID と product ID は最初のメーカーの値とは異なり、Google の vendor ID と product ID に一致するようになります。これで、accessory はデバイスとの通信を確立できるようになります。

これらのステップで失敗するということは、このデバイスは Android accessory モードをサポートしていないということであり、accessory は次のデバイスが接続されるまで待つようにしてください。


Establish communication with the device

Android-poweredデバイスが accessory モードとして検出されたら、accessory はデバイスとの通信に使用するバルクエンドポイントを取得するためにインタフェースとエンドポイントのディスクリプタを問い合せます。0x2D00 の product ID を持つ Android-powered デバイスは、入力と出力の2つの通信用バルクエンドポイントがあるインタフェースを1つ持ちます。0x2D01 の product ID を持つデバイスは、入力と出力の2つの通信用バルクエンドポイントがあるインタフェースを2つ持ちます。1つ目のインタフェースは標準の通信用、2つ目のインタフェースは ADB 通信用のインタフェースです。あるインタフェースで通信するためにすることは、最初のバルク入力・出力エンドポイントを見つけて、デバイスの設定を SET_CONFIGURATION (0x09) デバイスリクエストで 1 に設定することです。そうすれば、エンドポイントを使って通信できるようになります。

---

How the ADK board implements the Android Accessory protocol


次のセクションでは ADK board にインストールする firmware コードについて説明します。ファームウェアはどのように Android Accessory protocol を実装するかの実例を示しています。たとえあなたが ADK board と shild を持っていなくても、どのようにハードウェアがデバイスを検出し、accessory mode でやりとりするかを読むことは、自分の accessory 上にコードをポートしたい場合にとても役に立ちます。

ファームウェアの重要なピースは firmware/demokit/demokit.pde sketch にあります。これは Android-powered デバイスで動いている DemoKit アプリケーションにデータを送受信するコードです。Android-powered デバイスを検出して通信をセットアップするコードは firmware/arduino_libs/AndroidAccessory/AndroidAccessory.hfirmware/arduino_libs/AndroidAccessory/AndroidAccessory.cpp ファイルに含まれています。このコードには、あなたが自分の accessory のファームウェアに実装する助けになるほとんどのロジックが含まれています。次のセクションを通して読めるように、これら3つのファイルをテキストエディターで開いておくと便利でしょう。

次のセクションでは、Android Accessory Protocol の実装で説明したアルゴリズムの、コンテキスト内のファームウェアコードについて説明します。


Wait for and detect connected devices

ファームウェアコード (demokit.pde) 内の loop() 関数はファームウェアが実行されている間繰り返し呼び出されます。この loop() 関数内で AndroidAccessory::isConnected() を呼ぶことでデバイスが接続されているか定期的にチェックしています。接続されているデバイスがある場合、継続的に board とアプリケーションへの/からの入力と出力のストリームをアップデートしています。なにも接続されていない場合は、デバイスが接続されているか継続的にチェックします。:


...

AndroidAccessory acc("Google, Inc.",
"DemoKit",
"DemoKit Arduino Board",
"1.0",
"http://www.android.com",
"0000000012345678");

...
void loop()
{
...
if (acc.isConnected()) {
//communicate with Android application
}
else{
//set the accessory to its default state
}
...
}



Determine the connected device's accessory mode support

デバイスが ADK board に接続されたとき、そのデバイスがすでに accessory mode になっている場合と、accessory mode をサポートしてるがその状態ではない場合と、accessory mode をサポートしていない場合があります。AndroidAccessory::isConnected() メソッドはこれらのケースをチェックし、loop() 関数から呼ばれたらチェック結果を返します。この関数では最初に、すでに接続されているがまだ処理されていないデバイスかどうかチェックしています。そうでない場合は、接続されているデバイスのデバイスディスクリプタを取得し、それを使って AndroidAccessory::isAccessoryDevice() を呼んでデバイスがすでに accessory モードかどうか確かめます。このメソッドはデバイスディスクリプタの vendor ID と product ID をチェックします。デバイスが accessory モードであれば、vendor ID は 0x18D1, product ID は 0x2D00 もしくは 0x2D01 になります。デバイスが accessory モードの場合は、ADK board はデバイスとの通信を確立することができます。そうでなければ、board は accessory mode でデバイスを開始するように試みます。


bool AndroidAccessory::isConnected(void)
{
USB_DEVICE_DESCRIPTOR *devDesc = (USB_DEVICE_DESCRIPTOR *) descBuff;
byte err;

max.Task();
usb.Task();

if (!connected &&
usb.getUsbTaskState() >= USB_STATE_CONFIGURING &&
usb.getUsbTaskState() != USB_STATE_RUNNING) {
Serial.print("\nDevice addressed... ");
Serial.print("Requesting device descriptor.");

err = usb.getDevDescr(1, 0, 0x12, (char *) devDesc);
if (err) {
Serial.print("\nDevice descriptor cannot be retrieved. Program Halted\n");
while(1);
}

if (isAccessoryDevice(devDesc)) {
Serial.print("found android accessory device\n");

connected = configureAndroid();
} else {
Serial.print("found possible device. switching to serial mode\n");
switchDevice(1);
}
} else if (usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {
connected = false;
}

return connected;
}



Attempt to start the device in accessory mode

デバイスがまだ accessory モードになっていない場合、ADK board はデバイスが accessory モードをサポートしているかどうか確かめなければなりません。そのために、control request 51 を送ってデバイスがサポートする USB accessory protocol のバージョンをチェックします(AndroidAccessory::getProtocol()を参照)。現在ではプロトコルのバージョンは 1 だけですが、将来的には 0 以上の値になります。適切なプロトコルバージョンが返ってきたら、board は control request 52 を送って(各文字列に対して AndroidAccessory:sendString())自身の識別情報を送信し、control request 53 でデバイスを accessory mode で開始するよう試みます。この処理は AndroidAccessory::switchDevice() メソッドで行われます。


#define ACCESSORY_GET_PROTOCOL 51
#define ACCESSORY_SEND_STRING 52
#define ACCESSORY_START 53
...

bool AndroidAccessory::switchDevice(byte addr)
{
int protocol = getProtocol(addr);
if (protocol == 1) {
Serial.print("device supports protocol 1\n");
} else {
Serial.print("could not read device protocol version\n");
return false;
}

sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer);
sendString(addr, ACCESSORY_STRING_MODEL, model);
sendString(addr, ACCESSORY_STRING_DESCRIPTION, description);
sendString(addr, ACCESSORY_STRING_VERSION, version);
sendString(addr, ACCESSORY_STRING_URI, uri);
sendString(addr, ACCESSORY_STRING_SERIAL, serial);

usb.ctrlReq(addr, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE,
ACCESSORY_START, 0, 0, 0, 0, NULL);
return true;
}

void AndroidAccessory::getProtocol(byte addr)
{
uint16_t protocol = -1;
usb.ctrlReq(addr, 0,
USB_SETUP_HOST_TO_DEVICE |
USB_SETUP_TYPE_VENDOR |
USB_SETUP_RECIPIENT_DEVICE,
ACCESSORY_GET_PROTOCOL, 0, 0, 0, 2, (char *)&protocol);
}

void AndroidAccessory::sendString(byte addr, int index, const char *str)
{
usb.ctrlReq(addr, 0,
USB_SETUP_HOST_TO_DEVICE |
USB_SETUP_TYPE_VENDOR |
USB_SETUP_RECIPIENT_DEVICE,
ACCESSORY_SEND_STRING, 0, 0, index,
strlen(str) + 1, (char *)str);
}


swtichDevice() メソッドが false を返したら、board は次の新しいデバイスが接続されるまで待ちます。このメソッドが成功したら、ADK board が bus を再列挙したとき、デバイスは自身を accessory モードで開始した状態として USB bus 上に表示します。デバイスが accessory モードであれば、accessory はデバイスとの通信を確立することができます。


Establish communication with the device

デバイスが accessory モードで開始されていることが検出できたら、accessory は適切なバルクエンドポイントを見つけてデバイスとの通信をセットアップする必要があります。ADK board が accessory モードの Android-powered デバイスを見つけたら、AndroidAccessory::configureAndroid() 関数を呼びます。


...
if (isAccessoryDevice(devDesc)) {
Serial.print("found android acessory device\n");

connected = configureAndroid();
}
...


ここでは findEndpoints() 関数を呼びます


...
bool AndroidAccessory::configureAndroid(void)
{
byte err;
EP_RECORD inEp, outEp;

if (!findEndpoints(1, &inEp, &outEp))
return false;
...


AndroidAccessory::findEndpoints() 関数は Android-powered デバイスの構成ディスクリプタを問い合わせて USB デバイスと通信するためのバルクデータエンドポイントを見つけます。こうするために、まずデバイスの構成ディスクリプタの最初の4バイト(必要なのは descBuff[2] と descBuff[3] のみ)を取得します。ここにはディスクリプタを取得することで返されたデータの全データ長が含まれています。また、このディスクリプタには全インタフェースとエンドポイントディスクリプタについての情報も含まれています。ディスクリプタが適切なサイズであれば、メソッドは構成ディスクリプタ全体を読み込み、ディスクリプタバッファーに格納します。なんらかの理由でディスクリプタに到達できない場合はエラーを返します。


...

bool AndroidAccessory::findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp)
{
int len;
byte err;
uint8_t *p;

err = usb.getConfDescr(addr, 0, 4, 0, (char *)descBuff);
if (err) {
Serial.print("Can't get config descriptor length\n");
return false;
}


len = descBuff[2] | ((int)descBuff[3] << 8);
if (len > sizeof(descBuff)) {
Serial.print("config descriptor too large\n");
/* might want to truncate here */
return false;
}

err = usb.getConfDescr(addr, 0, len, 0, (char *)descBuff);
if (err) {
Serial.print("Can't get config descriptor\n");
return false;
}

...


一度ディスクリプタがメモリに格納されたら、ポインターはバッファの最初の位置に割当てられ、バッファ読み込みのインデックスとして使われます。ここには AndroidAccessory::findEndpoints() に渡される2つのエンドポイント用ポインタ(入力用と出力用)があり、それぞれのアドレスは 0 にセットされています。なぜなら、コードはまた適切なバルクエンドポイントを見つけていないからです。ループでは構成、インタフェースもしくはエンドポイントの各ディスクリプタを解析し、バッファを読み取ります。各ディスクリプタに対し、位置 0 には常にディスクリプタのサイズ(バイト単位)が格納されており、位置 1 には常にディスクリプタのタイプが格納されています。これらの2つの値を使ってループでは任意の構成、インタフェースディスクリプタをスキップし、次のディスクリプタを取得するために descLen 変数でバッファをインクリメントします。

 注意:accessory モードの Android-powered デバイスは潜在的に2つのインタフェースを持つことができます。1つはデバイスとのデフォルトの通信用、もう1つは ADB 通信用です。デフォルトの通信インタフェースは常に最初にインデックスされており、最初に見つける入力と出力のバルクエンドポイントはデフォルトの通信エンドポイントを返します。demokit.pde sketch ではそのように処理しています。自身のファームウェアを書く場合、あなたの accessory に対する適切なエンドポイントを見つけるロジックは異なる可能性があります。

最初の入力と出力のエンドポイントディスクリプタを見つけたら、これらのアドレスにエンドポイントポインタをセットします。findEndpoints() 関数は入力と出力両方のエンドポイントを見つけたら true を返します。この関数は、他のエンドポイント(ADB インタフェースなど)が見つかっても無視します。


...
p = descBuff;
inEp->epAddr = 0;
outEp->epAddr = 0;
while (p < (descBuff + len)){
uint8_t descLen = p[0];
uint8_t descType = p[1];
USB_ENDPOINT_DESCRIPTOR *epDesc;
EP_RECORD *ep;

switch (descType) {
case USB_DESCRIPTOR_CONFIGURATION:
Serial.print("config desc\n");
break;

case USB_DESCRIPTOR_INTERFACE:
Serial.print("interface desc\n");
break;

case USB_DESCRIPTOR_ENDPOINT:
epDesc = (USB_ENDPOINT_DESCRIPTOR *)p;
if (!inEp->epAddr && (epDesc->bEndpointAddress & 0x80))
ep = inEp;
else if (!outEp->epAddr)
ep = outEp;
else
ep = NULL;

if (ep) {
ep->epAddr = epDesc->bEndpointAddress & 0x7f;
ep->Attr = epDesc->bmAttributes;
ep->MaxPktSize = epDesc->wMaxPacketSize;
ep->sndToggle = bmSNDTOG0;
ep->rcvToggle = bmRCVTOG0;
}
break;

default:
Serial.print("unkown desc type ");
Serial.println( descType, HEX);
break;
}

p += descLen;
}

if (!(inEp->epAddr && outEp->epAddr))
Serial.println("can't find accessory endpoints");

return inEp->epAddr && outEp->epAddr;
}

...


configureAndroid() 関数に戻りましょう。エンドポイントが見つかったら、通信用に適切にセットアップします。デバイスのコンフィグレーションを 1 にセットし、さらにデバイス状態を "running" にします。これはデバイスがあなたの USB accessory と通信するために正しくセットアップされたことを意味します。この状態に設定することで、AndroidAccessory::isConnected() 関数でデバイスの再検出や再設定が行われるのを防ぎます。


bool AndroidAccessory::configureAndroid(void)
{
byte err;
EP_RECORD inEp, outEp;

if (!findEndpoints(1, &inEp, &outEp))
return false;

memset(&epRecord, 0x0, sizeof(epRecord));

epRecord[inEp.epAddr] = inEp;
if (outEp.epAddr != inEp.epAddr)
epRecord[outEp.epAddr] = outEp;

in = inEp.epAddr;
out = outEp.epAddr;

Serial.print("inEp: ");
Serial.println(inEp.epAddr, HEX);
Serial.print("outEp: ");
Serial.println(outEp.epAddr, HEX);

epRecord[0] = *(usb.getDevTableEntry(0,0));
usb.setDevTableEntry(1, epRecord);

err = usb.setConf( 1, 0, 1 );
if (err) {
Serial.print("Can't set config to 1\n");
return false;
}

usb.setUsbTaskState( USB_STATE_RUNNING );

return true;
}


最後に、適切なエンドポイントに読み書きするメソッドが必要です。demokit.pdf sketch では Android-powered デバイスから読むか、ADK board から送られたかによって、これらのメソッドを呼んでいます。例えば、ADK shield 上でジョイスティックが動くとデータが書き込まれ、Android-powered デバイス上の DemoKit アプリケーション によって読み込まれます。DemoKit アプリケーション上のスライダーが動くと、demokit.pde sketch によって読み込まれ、LED ライトの色が変わったり明るくなるなど accessory の状態が変わります。


int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit) {
return usb.newInTransfer(1, in, len, (char *)buff, nakLimit); }

int AndroidAccessory::write(void *buff, int len) {
usb.outTransfer(1, out, len, (char *)buff);
return len; }


ADK board がどのように読み書きしているかの情報は firmware/demokit/demokit.pde ファイルを見てください。

2011年5月23日月曜日

Android + App Engine: A Developer's Dream Combination を試してみた。

Google IO 2011 の Session ビデオはこちら

最初にスピーカーが、なぜこのプロジェクトを始めたのかを語っているのですが、
「約1年まえ、Google に入ったくらいの頃、すごく Android が好きだったんだよね。(省略)ただ、1つだけがっかりしたことがあって、Android のアプリのゲームであるレベルまでいっても、ほかの端末でそのレベルの続きから始められないんだよね。だから、この良くないユーザー体験を良くするために、何かできることがないかって何人かで話てたんだよね。」

なるほど、家では大きな画面のタブレットで、通勤・通学中はスマホで続きを、というスタイルは自然ですよね。もちろんゲームだけじゃなくて、普通のアプリでも十分データを共有/シンクすることの利点があります。セッションでは、例として ToDo 管理アプリ(CloudTask という名前)を作っていくデモがあります。
# ログイン名に LarryPage を使ってるのがシャレてるねw

でも、「Android 開発者にとって、Google App Engine と組み合わせるのって簡単じゃないよね?」

ということで、Google IO の当日から

 「Google Plugin for Eclipse (GPE) 2.4 Beta がダウンロードできるようになりました。」

 GPE 2.4 Beta には以下の機能が!すばらしい!
  ・ Android Application のサポート
  ・ RPC Tooling のサポート (Android -> GAE)
  ・シームレスな C2DM のサポート (GAE -> Android)
 

■ さっそくやってみた。

 1. GPE 2.4 Beta についてはここ

  Eclipse plugin で指定する update site URL が通常とは違って beta が含まれます

  Eclipse 3.6 (Helios)
  http://dl.google.com/eclipse/plugin/beta/3.6

  Eclipse 3.5 (Galileo)
  http://dl.google.com/eclipse/plugin/beta/3.5

  Eclipse 3.4 (Ganymede)
  http://dl.google.com/eclipse/plugin/beta/3.4

  Eclipse で [Help] -> [Install New Software...] で上記のリンクを指定



  GWT の SDK は最新のβ版の 2.4.0.beta, GAE は 1.5.0 が入りました。
  Android SDK, ADT は別途入れる必要があります。

 2. プロジェクトを作成

  ・[File] -> [New] -> [Project...] -> [Google] -> [App Engine Connected Android Project]



  ・Project name: と Package name: を追加
  (Android SDK, GAE SDK, GWT SDK が正しく設定されていない場合は、ここから設定できる)

  ・C2DM のアカウントを設定
  (まだ C2DM に sign up してない場合は、ここから sing up page へいける)



  完了したら、Android のプロジェクトと、GAE + GWT のプロジェクトが作られます。



  ざっと中をみると、
   Android のプロジェクトには
    ・RequestFactory のライブラリ(requestFactory-client.jar)
    ・C2DM のライブラリ (c2dm.jar)
    ・認証 (validation) のライブラリ (validation-api-1.0.0.GA.jar)
    ・いくつかの Activity とその他のクラス (src/***/)
    ・shared で GAE + GWT の方の shared package を参照 (share/)

   GAE + GWT のプロジェクトには
    ・JSON のライブラリ (json-1.5.jar)
    ・C2DM のライブラリ(c2dm-server.jar)
    ・認証 (validation) のライブラリ (validation-api-1.0.0.GA.jar, validation-api-1.0.0.GA-sources.jar)
    ・UI Binder を使った入り口ページ用レイアウト(src/***.client/***Widget.ui.xml)
    ・サーバー側実装 (src/***.server/)
    ・Android のプロジェクトから参照される shared package (shared/)

  などが含まれています。



  最初から、RPC や C2DM のロジックが含まれた状態のプロジェクトが作られるので、そのまま動かして、RPC や C2DM がどう動くか確かめることができます。すごいね。

  まず、Android アプリを [Debug As] -> [Local App Engine Connected Android Application] で実行します。
  通常の Android Application 実行ではないので注意!



  そうすると、App Engine 側も立ち上がって、こんな感じに、
  GWTのローカルのアクセス用URLが表示されるので、ダブルクリックしてブラウザで開きます。


  動かすと、Android アプリはこんな画面
  (注意:Android エミュレータでC2DMのテストをするには、Google アカウントの設定が必要なので、AVD の Target Name には Google APIs (Google Inc.) を指定してください)



  まず、C2DMにアカウントを設定します。
  メニューの Accounts をタップすると、端末に設定されているアカウントの一覧がでます。



  C2DMに設定するアカウントを選択して Connect を押すと



  このアプリで Google Account を使うけどいいですか?という画面がでるので、Allow をタップします。



  しばらくして認証が完了すると、Notification Bar に register できましたというメッセージがでます。



  認証に成功したら、Android アプリから SayHello ボタンを押すと、GAE に RPC でリクエストを投げた返事が表示されるようになります。やった!




  同じことが、GWT クライアントからもできます。
  次に、GWTのページを開くと、最初にログイン用のページが表示されるので、Sign Up for Android Cloud to Device Messaging で指定したアカウントでログインします。



  ブラウザに Plugin が入ってない場合は、入れるように表示がでるので、それに従って入れます。


  
  ログインすると、こんなページ
  


  SAY HELLO ボタンを押すと、GAE に RPC でリクエストして、その返事が表示されます。



 
  いよいよ、メインイベントのC2DM!
  フォームにメッセージをいれて SEND MESSAGE をクリック。



  きたー。


  うまく送れないときは、GWT 側で最初にログインしたアカウントがちゃんと
  Sign Up for Android Cloud to Device Messaging
  で登録したアドレスかどうか確認すること。
  別のアカウントで AuthToken がすでにできてしまっている場合は、ログアウトしてから
  http://127.0.0.1:8888/_ah/admin/
  にいって、C2DMConfig の Entities を削除してから正しいアカウントログインしたほうが安全。


  ローカルのエミュレータと、ローカルデバッグモードの GAE でちゃんとC2DM動くんだね。すごーい。



   

2011年5月20日金曜日

Android Holo theme を使う

Android 3.0 から標準で使われている holographic theme "Holo" を使うには

 android:minSdkVersion もしくは android:targetSdkVersion に >=11 を指定する

必要があります。


Android 3.0 以上では Holo theme を使い、それより前のプラットフォームでは通常の Theme を使う場合には

res/values/styles.xml
res/values-v11/styles.xml

を用意して

res/values/styles.xml

<style name="MyLightTheme" parent="android:Theme.Light">
...
</style>


res/values-v11/styles.xml

<style name="MyLightTheme" parent="android:Theme.Holo.Light">
...
</style>


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<uses-sdk android:targetSdkVersion="11" android:minSdkVersion="7"/>
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@style/MyLightTheme">
<activity ... >
</activity>
</application>
</manifest>

のように指定します。


Holo 関係の Theme は R.style あたりにあります。

・Theme.Holo
・Theme.Holo.Panel
・Theme.Holo.NoActionBar
・Theme.Holo.NoActionBar.Fullscreen
・Theme.Holo.Wallpaper
・Theme.Holo.Wallpaper.NoTitleBar
・Theme.Holo.Dialog
・Theme.Holo.Dialog.MinWidth
・Theme.Holo.Dialog.NoActionBar
・Theme.Holo.Dialog.NoActionBar.MinWidth
・Theme.Holo.DialogWhenLarge
・Theme.Holo.DialogWhenLarge.NoActionBar
・Theme.Holo.InputMethod

・Theme.Holo.Light
・Theme.Holo.Light.Panel
・Theme.Holo.Light.NoActionBar *
・Theme.Holo.Light.NoActionBar.Fullscreen *
・Theme.Holo.Light.Dialog
・Theme.Holo.Light.Dialog.MinWidth
・Theme.Holo.Light.Dialog.NoActionBar
・Theme.Holo.Libht.Dialog.NoActionBar.MinWidth
・Theme.Holo.Light.DialogWhenLarge
・Theme.Holo.Light.DialogWhenLarge.NoActionBar

* R.style | Android Developers には漏れているけれど、SDK には含まれている


何個かキャプチャーをとってみた。

Theme.Holo
 Honeycomb の holographic theme の Dark version


Theme.Holo.Panel
 これまでの Translucent みたいなものみたい


Theme.Holo.NoActionBar
 Theme.Holo の Action Bar なし version


Theme.Holo.Wallpaper


Theme.Holo.Dialog
 Dialog 用の theme


Theme.Holo.Dialog.MinWidth


Theme.Holo.DialogWhenLarge.NoActionBar




Theme.Holo.Light


Theme.Holo.Light.Panel


Theme.Holo.Light.Dialog


Theme.Holo.Light.Dialog.NoActionBar


Theme.Holo.Light.Dialog.MinWidth


Theme.Holo.Light.DialogWhenLarge

2011年5月19日木曜日

Android Fragment を使う

Fragment のサブクラス

DialogFragment
ListFragment
PreferenceFragment
WebViewFragment

■ その他のヘルパークラス

FragmentManager
FragmentTransaction


Activity のレイアウトにフラグメントのレイアウトを挿入する


■ Activity のレイアウトファイルに <fragment> タグで入れる

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>


各 <fragment> には一意の識別子が必要
識別子をつける方法は次の3つ
 ・ android:id で一意のIDをつける
 ・ android:tag で一意の文字列をつける
 ・ 両方指定しない場合、システムは container view の ID を使う

---
findFragmentById(int id) : 戻り値は見つかった fragment もしくは null
findFragmentByTag(String tag) : 戻り値は見つかった fragment もしくは null
---


■ すでに存在している Activity のレイアウトの ViewGroup にコードで入れる

FragmentTransaction を使う

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();


FragmentTransaction に変更を加えたあとは、commit() を呼ばなければ反映されない。


■ UI なしの Fragment を追加する

Activity で add(Fragment fragment, String tag) を呼び出す。
第1引数が追加するフラグメントのインスタンス、第2引数が追加するフラグメントの文字列識別子("tag")

---
FragmentTransaction add (int containerViewId, Fragment fragment)
 tag に null を指定して add(int, Fragment, String) を呼ぶ

FragmentTransaction add (Fragment fragment, String tag)
 containerViewId に 0 を指定して add(int, Fragment, String) を呼ぶ

FragmentTransaction add (int containerViewId, Fragment fragment, String tag)
 containerViewId : このフラグメントが配置されるコンテナの ID, コンテナに配置されない場合は 0
 fragment : 追加されるフラグメント, 事前に Activity に追加されていてはならない
 tag : フラグメントのタグ名, FragmentManager.findFragmentByTag(String) で使われる

 戻り値 : 同じ FragmentTransaction インスタンス
---


Fragment の管理


・FragmentManager で行う
・FragmetnManager は getFragmentManager() で取得する

FragmentManager fragmentManager = getFragmentManager();

・FragmentManager でできること
  ・findFragmentById() もしくは findFragmentByTag() で Activity に存在する Fragment を取得
  ・popBackStack() でバックスタックの Fragment を pop off (ユーザーが BACK ボタンを押したときと同じ動作)
  ・addOnBackStackChangedListener() を使って、バックスタックの変更用リスナーを登録
  ・FragmentTransaction を開く


Fragment Transaction を行う


・各トランザクションは一度に行いたい変更の組み合わせ
・実行したいすべてのトランザクションを add(), remove(), replace() などを使ってセットし、それから commit() を呼び出してトランザクションを適用させる
・例えば、以前の状態をバックスタックに保存して、別のフラグメントに置き換えるにはこんな感じになる

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

addToBackStack() を呼ぶことで置換トランザクションがバックスタックに保存され、ユーザーはバックボタンを押すことでトランザクションをリバースして前のフラグメントに戻すことができる。

複数のトランザクション(add() や remove())の変更を追加して、addToBackStack() を読んだ場合、commit() が呼ばれる前のすべての変更が1つのトランザクションとしてバックスタックに保存され、BACK キーを押した場合、すべての変更が一緒にリバースされる。

FragmentTransaction に加える変更の順番は、次を除いて重要ではない:
 ・最後に commit() を呼ばなければならない
 ・同じコンテナに複数のフラグメントを追加した場合、追加した順番によって View 階層に現れる順番が決まる

フラグメントを削除するトランザクションを実装する際に、addToBackStack() を呼ばないと、フラグメントは commit 時に破棄され、バック操作で戻すことはできない。一方、addToBackStack() を呼べば、フラグメントの削除時にフラグメントはストップし、バック操作で再開できる。

commit() する前に setTransition() を呼ぶことで、トランザクションのアニメーションを設定できる

・commit() を呼び出し直後にトランザクションが実行されるわけではない
・UI スレッドで実行が可能になったらすぐに実行できるようにスケジュールされる
・しかし、必要であれば、executePendingTransaction() を UI スレッドから呼ぶことで commit() でサブミットされたトランザクションを直ちに実行できる
・他のスレッドがトランザクションに依存しているのでない限り、この方法は必要ない


Activity とやりとりする


Fragment から自身を含む Activity のインスタンスを取得するには getActivity() メソッドを使う

View listView = getActivity().fintViewById(R.id.list);


Activity から自身が含む Fragment のインスタンスを取得するには、findFragmentById() や findFragmentByTag() を使う

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);



■ Activity へのイベントコールバックを作る

Activity と Fragment でイベントを共有するいい方法は、
 ・Fragment にコールバックインタフェースを定義
 ・Activity がそのインタフェースを実装
という方法

例えば、リストの FragmentA とAで選択された記事の詳細を表示する FragmentB が Activity に含まれているとする

FragmentA --- 選択されたリストアイテムを通知 --> Activity
|
FragmentB <-- 選択されたリストに応じた記事を表示 ----


FragmentA --- onListItemClick() で onArticleSelected() 呼び出し --> Activity
|
FragmentB <-- onArticleSelected()内で処理 -----------------------------



public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}


フラグメントが Activity に追加される時点で呼ばれる onAttach() コールバックメソッド内で、Activity をキャストしてインタフェースが実装されているかチェックする

public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
...
}


FragmentA が ListFragment を継承したものだとすると、リストアイテムがクリックされたときに呼ばれる onListItemClick() ないで、インタフェースで定義したメソッドを呼ぶことでイベントを Activity に通知できる。

public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}



■ Action Bar にアイテムを追加する

・Fragment は onCreateOptionsMenu() を実装することで、Option Menu (従って、Action Bar)のメニューアイテムに寄与できる
・このメソッドが呼び出しを受けるためには、onCreate() 内で setHasOptionMenu() を呼ばなければならない
・Fragment から Option Menu に追加するアイテムは、既存のメニューアイテムに追加される
・メニューアイテムが選択された場合、Fragment は onOptionsItemSelected() へのコールバックを受け取る
・registerForContextMenu() を呼ぶことで、コンテキストメニューを提供するためにフラグメントのレイアウトに View を登録できる
・ユーザーがコンテキストメニューを開くと、Fragment は onCreateContextMenu() への呼び出しを受け取る
・ユーザーがコンテキストメニューのアイテムを選択すると、Fragment は onContextItemSelected() への呼び出しを受け取る

・Fragment は自身が追加したメニューアイテムがユーザーによって選択されたときに、 on-item-selected callback を受け取るが、一番最初は Activity が対応するコールバックを受け取る
・Activity の on-item-selected callback が選択されたアイテムを処理しない場合、そのイベントは Fragment のコールバックに渡される


■ Fragment のライフサイクル

onAttach()
・onCreate()
onCreateView()
onActivityCreated()
・onStart()
・onResume()
・onPause()
・onStop()
onDestroyView()
・onDestroy()
onDetach()




from http://developer.android.com/guide/topics/fundamentals/fragments.html


参考


http://developer.android.com/guide/topics/fundamentals/fragments.html
http://developer.android.com/guide/topics/ui/menus.html
http://developer.android.com/guide/topics/ui/actionbar.html

 

2011年5月18日水曜日

Android Fragment について思うこと。



Fragment についての詳細(デザイン上の哲学とかもろもろ)は省きますが、端的に Fragment の何がありがたいかというと、

”画面サイズに応じて画面上の情報量を変えられる”

点です。

これまでのバージョンでも Android にはマルチスクリーン対応のための機能がありました。
layout-small, layout-normal, layout-large や layout-port, layout-land などで View の大きさを変えたり、配置を変えたりすることができました。しかし、画面上に表示される情報は同じだったわけです。画面が大きければ ListView のアイテムがたくさん見えるよ、っていうのは情報量が増えたわけではないです。だってスクロールすれば見れるでしょ。
つまり、画面上で”アクセスできる”情報量を変えられるということです。

タブレット用のデザインを layout-** で対応するのが難しい原因として、情報量を変えられないことが大きいです。画面が大きいなら、その分別の情報がみたいですよね。
さらに、タブレット(10インチ程度)くらいの大きさだと、ぱっとみて全体の情報を把握することはかなり難しいです。Galaxy Tab 10.1 の画面の大きさは Nexus S 4個分以上あります。一度に見れるのは半分くらいが限界のような気がします。

例えば、リストがタブレットの画面いっぱいになっていると、頭を左右に振らないと読めません。これはとても読みづらいです。そこで、リストを半分にすると残り半分が開いてしまいますよね。ここに別の情報を簡単に組み合わせられるのが Fragment の一番の機能です。

ここまで読んで気づいたひともいるかもしれませんが、これってタブレットとスマートフォンのレイアウトを同じアプリで対応するための機能なんですね。もしタブレットだけなら別の方法もあったはずです。つまり、最初からタブレットとスマートフォン両方に対応(= Ice-cream sandwich )するためのものだったってことなんでしょうね。

# Fragment の作り方とかは、いずれ別のエントリで。

Google IO 2011 のセッションごとの YouTube プレイリストつくったよ。

プレイリストにしておくと、自動で次の動画を再生してくれるのでBGMにもってこい。

Android



Chrome



App Engine



Developer Tools



Google APIs



Geo



Google Apps



Commerce



Tech Talk



  

2011年5月17日火曜日

Android 3.1 Platform

API Level: 12

開発者は Android SDK のコンポーネントとして Android 3.1 platform をダウンロードできるようになりました。このプラットフォームには Android library と system image, emulator skin などが含まれていますが、外部のライブラリは含まれていません。

Android 3.1 向けの開発とテストを始めるには、Android SDK Manager を使って自分の SDK にプラットフォームをダウンロードします。より詳しい情報は Adding SDK Components を見てください。Android が初めての人は、まず download the SDK Starter Package から始めてください。

Android 3.1 のより高レベルの紹介は Platform Highlights を見てください。


Reminder: あなたがすでに Android アプリを公開しているなら、できるだけ早く、あなたのアプリを Android 3.0, Android 3.1 向けにテストおよび最適化を行なってください。最新の Android-powered デバイスで、あなたのアプリのベストな体験を受けられるようにするべきです。そのために何をするか・できるかの情報は Optimizing Apps for Android 3.0 を読んでください。

---

API Overview


以下のセクションは Android 3.1 で開発者が新しくできるようになったもののテクニカルオーバービューです。新しい機能や、前回のバージョンからの framework API の変更点が含まれています。



USB APIs


Android 3.1 はプラットフォームで動作するアプリケーションと接続された周辺機器間の統合を目的としたパワフルな新しい API を紹介します。この API はプラットフォーム内に組み込まれた USB (Universal Serial Bus) のスタックとサービスに基づいており、USB host とデバイスとのやりとり両方のサポートが含まれています。この API を使うことで、開発者は USB を介して様々なタイプのデバイスを見つけ、やりとりし、管理するアプリケーションを作ることができます。

スタックと API は、プラットフォーム自身がホストとして振舞うか、はたまた外部のハードウェアが振舞うかに基づいた、USB ハードウェアの2つの基礎タイプを区別します。

  • USB デバイスはホストとして機能する Android-powered デバイスに依存した接続先のハードウェアの一部です。例えば、ほとんどの入力デバイス、マウス、ジョイスティックは USB デバイスです。同様にカメラやハブなどもあります。

  • USB accessory はホストコントローラをもち、電力を供給し、USB を介して Android-powered デバイスとやりとりするようデザインされた接続先のハードウェアの一部です。ロボットコントローラから音楽機器、エクササイズバイクなどまで、多くの周辺機器が accessory として接続できます。


USB デバイスと USB accessory 両方のタイプに対してプラットフォームの USB API は取り付け時と取り外し時の broadcast intent による検出をサポートします。また、標準のインタフェース、エンドポイント、転送モード (コントロール、バルク、割り込み)も同様にサポートします。

USB API は android.hardware.usb パッケージにあります。中心クラスは UsbManager で、USB デバイスと USB accessory 両方に対する識別とやりとりのヘルパーメソッドを提供します。
アプリケーションは UsbManager のインスタンスを取得して、取り付けられているデバイスもしくは accessory の一覧を得るためのクエリを投げるたり、やりとりしたり、管理したりすることができます。また UsbManager には、USB デバイスや accessory の取り付け時・取り外し時にシステムが broadcast する intent action が定義されています。

他の含まれているクラスとして:

  • UsbDevice は USB デバイスとして接続されている外部のハードウェアを表す(Android-powered デバイスがホストとして振舞う)

  • UsbAccessory は接続された USB ホストである外部のハードウェアを表す(Android-powered デバイスが USB デバイスとして振舞う)

  • UsbInterfaceUsbEndpoint は標準の USB インタフェースへのアクセスとデバイスへのエンドポイントを提供する

  • UsbDeviceConnectionUsbRequest は同期または非同期に USB デバイスへデータを送ったり、受け取ったり、メッセージをコントロールしたりする

  • UsbConstants はエンドポイントタイプやデバイスのクラスなどを宣言するための定数を提供する


USB スタックはプラットフォーム内に組み込まれていますが、実際に特定のデバイスで USB host と open accessory mode をサポートするかどうかはそのデバイスのメーカーが決定します。特に、host mode は Android-powered デバイスの適切な USB コントローラーハードウェアに依存します。

加えて、開発者は適切な USB サポートが提供されていないデバイスのユーザーにアプリケーションを利用できないように、Android Market でフィルタリングを依頼することができます。フィルタリングをリクエストするには、必要に応じて次のエレメントのいずれかもしくは両方をアプリケーションのマニフェストに追加します。

  • アプリケーションが USB host mode (USB デバイスと接続)をサポートしているデバイスにのみ見えるようにするには、次のエレメントを宣言する

    <uses-feature android:name="android.hardware.usb.host" android:required="true">

  • アプリケーションが USB accessory(USB host と接続)をサポートしているデバイスにのみ見えるようにするには、次のエレメントを宣言する

    <uses-feature android:name="android.hardware.usb.accessory" android:required="true">


USB accessory とやり取りするアプリケーションを開発するための全ての情報はdeveloper documentation を参照してください。

USB host API を使ったサンプルアプリケーションを参照するには、ADB TestMissile Launcher を見てください。



MTP/PTP API


Android 3.1 は新しい MTP API を公開しました。これにより、アプリケーションは接続されたカメラや他の PTP デバイスと直接やりとりすることができます。新しい API によって、アプリケーションはデバイスの取り付け・取り外しの通知を簡単に受けられるようになり、それらのデバイス上でのファイルやストレージの管理や、ファイルやメタデータの転送も簡単にできるようになりました。MTP API は MTP (Media Transfer Protocol) 仕様の PTP (Picture Transfer Protocol) サブセットを実装しています。

MTP API は android.mtp パッケージで使用できます。ここでは以下のクラスが提供されています。

  • MtpDevice は USB host bus を介して接続された MTP デバイスをカプセル化したものです。アプリケーションはこのタイプのオプジェクトをインスタンス化し、そのメソッドを使ってデバイスの情報や保存されているオブジェクトを取得することができます。同様に接続をオープンしてデータを転送することもできます。
    例えば、含まれているメソッドとして、

    • getObjectHandles() はデバイス上の指定された format と parent に一致する全てのオブジェクトに対するハンドルのリストを返す。オブジェクトの情報を取得するには、getObjectInfo() をハンドルへ渡す。

    • importFile() でオブジェクト用のデータを外部ストレージ内のファイルにコピーすることができる。この呼び出しはデータのサイズとデバイスのスピードに応じて任意の時間ブロックする可能性があるため、別のスレッド行うべきである。

    • open() で 接続された MTP/PTP デバイスを開くことができる。

    • getThumbnail() はバイト配列としてオブジェクトのサムネイルを返す

  • MtpStorageInfo は MTP 仕様の section 5.2.2 で記述されている StorageInfo Dataset に対応する MTP デバイスのストレージユニット情報を保持する。このクラスのメソッドをつかってストレージユニットを記述する文字列、フリースペース、最大ストレージ容量、ストレージID、ヴォリューム識別子を取得できる。

  • MtpDeviceInfo は MTP 仕様の section 5.1.1 で記述されている DeviceInfo Dataset に対応する MTP デバイスの情報を保持する。このクラスのメソッドを使ってデバイスのメーカー、モデル、シリアルナンバー、バージョンを取得できる。

  • MtpObjectInfo は MTP 仕様の section 5.3.1 で記述されている ObjectInfo Dataset に対応する MTP デバイスに保存されているオブジェクトの情報を保持する。このクラスのメソッドを使ってオブジェクトのサイズ、データフォーマット、アソシエーションタイプ、作成日、サムネイル情報を取得できる。

  • MtpConstants は MTP ファイルフォーマットコード、アソシエーションタイプ、プロテクションステータスを宣言するための定数を提供する




Support for new input devices and motion events


Android 3.1 は全てのビューとウィンドウにわたって新しい入力デバイスと新しいモーションイベントタイプをサポートすることで、入力のサブシステムを拡張します。開発者はユーザーがキーボードやタッチスクリーンに加えて、マウス、トラックボール、ジョイスティック、ゲームパッド、その他のデバイスを使ってプリケーションを操作できるように、これらの機能を構築することができます。

マウス、スクロールホイール、トラックボールによる入力をハンドリングするために、プラットフォームは2つの新しいモーションイベントアクションをサポートします:

  • ACTION_SCROLL, マウスのスクロールホイールなどによるノンタッチスクロールモーションのときのポインターの位置を表す。MotionEvent で、AXIS_HSCROLLAXIS_VSCROLL 軸の値が相対的なスクロール運動を指定する。

  • ACTION_HOVER_MOVE, ボタンが押されていないときに、マウスの現在の位置を報告する。また、最後の HOVER_MOVE イベントからの任意の中間点も報告する。マウスを動かして入った時と出た時の通知はまだサポートされていません。


ジョイスティックとゲームパッドをサポートするために、InputDevice クラスは新しく次のデバイスソースを含むようになりました:


これらの新しいソースからのモーションイベントを示すために、KeyEvent においてキーコードが定義されているように、プラットフォームは MotionEvent において軸コードを新しく定義します。ジョイスティックとゲームコントローラ用の新しい軸には AXIS_HAT_X, AXIS_HAT_Y, AXIS_RTRIGGER, AXIS_ORIENTATION, AXIS_THROTTLE, 他多くが含まれます。すでに存在している MotionEvent の軸は AXIS_X, AXIS_Y, AXIS_PRESSURE, AXIS_SIZE, AXIS_TOUCH_MAJOR, AXIS_TOUCH_MINOR, AXIS_TOOL_MAJOR, AXIS_TOOL_MINOR, AXIS_ORIENTATION として表されます。

加えて、MotionEvent には、フレームワークが特定の軸をどのようにマップするか知らない場合に使用する汎用的な軸コードも定義します。特定のデバイスはカスタムモーションデータをアプリケーションに渡すために汎用的な軸コードを使うことができます。軸の全リストとそれらの意図するものの解釈は MotionEvent クラスのドキュメントを見てください。

プラットフォームはバッチ処理でアプリケーションにモーションイベントを提供します。そのため、1つのイベントは現在の位置といわゆる運動の履歴を含みます。アプリケーションは getHistorySize() を使って履歴サンプルの数を取得し、それから順番に getHistoricalAxisValue() を使って全ての履歴サンプルの取得と処理を行うべきです。そのあと、アプリケーションは getAxisValue() を使って現在のサンプルを処理します。

いくつかの軸は特別なアクセサメソッドを使って取得することができます。例えば、getAxisValue() を呼ぶ代わりに、getX() を呼ぶことができます。ビルトインのアクセサが含む軸は、AXIS_X, AXIS_Y, AXIS_PRESSURE, AXIS_SIZE, AXIS_TOUCH_MAJOR, AXIS_TOUCH_MINOR, AXIS_TOOL_MAJOR, AXIS_TOOL_MINOR, AXIS_ORIENTATION です。

各入力デバイスはユニークな、システムが割り当てた ID を持ち、複数のソースを提供することがあります。デバイスが複数のソースを提供する場合、1つ以上のソースが同じ軸を使って軸データを提供できます。例えば、タッチイベントはスクリーンの位置データとしてX軸を使うソースからきますが、ジョイスティックイベントは代わりにジョイスティックの位置データとしてX軸を使ったソースからきます。つまり、どのソースによって発生したかによって軸の値を解釈することが重要です。モーションイベントを処理するとき、アプリケーションは InputDevice クラスのメソッドを使ってデバイスやソースがサポートする軸を決めるべきです。特にアプリケーションはデバイスの全ての軸や、デバイスの特定のソースの全ての軸をクエリするために getMotionRanges() を使うことができます。両方のケースで、軸の範囲情報は 各軸値のソースを指定する < InputDevice.MotionRange オブジェクトで返されます。

最後に、ジョイスティック、ゲームパッド、マウス、トラックボールからのモーションイベントはタッチイベントではありません。プラットフォームには、これらを "汎用的な" モーションイベントとして View に渡すための新しいコールバックメソッドが追加されています。具体的には、onTouchEvent() ではなく、onGenericMotionEvent() を呼ぶことで View にノンタッチモーションイベントを通知します。

プラットフォームはイベントソースクラスに依存して異なる汎用的モーションイベントを送ります。SOURCE_CLASS_POINTER イベントは、どのようにタッチイベントが動くかと似て、ポインターの下の View に行きます。その他の全ては、現在フォーカスされている View に行きます。例えば、ジョイスティックのイベントを受け取るためには、View はフォーカスされていなければならないという意味です。代わりに、必要であればアプリケーションはこれらのイベントを onGenericMotionEvent() を実装することで Activity や Dialog のレベルで処理することができます。

ジョイスティックモーションイベントを使ったアプリケーションのサンプルは GameControllerInputGameView です。



RTP API


Android 3.1 にはビルトイン RTP(Real-time Transport Protocol) の API があります。アプリケーションはオンデマントやインタラクティブのデータストリーミングを管理するために使うことができます。特に VOP, push-to-talk, 電話会議(conferencing), 音声ストリーミングを提供するアプリは、利用可能な任意ネットワークを介して、セッションの初期化とデータストリームの転送・受信を行うのに、このAPIを使うことができます。

RTP API は android.net.rtp パッケージで利用可能です。
含まれるクラスとして:

  • RtpStream, RTP を介してメディアペイロードのネットワークパケットを送信・受信するストリームのベースクラス

  • AudioStream, RTP を介してオーディオペイロードを運ぶ RtpStream のサブクラス

  • AudioGroup, デバイススピーカー、マイク、AudioStream を管理・ミキシングするためのローカルオーディオハブ

  • AudioCodec, AudioStream 用に定義したコーデックのコレクションを保持する


音声会議とそれに似た使い方をサポートする為に、アプリケーションはストリームのエンドポイントして2つのクラスをインスタンス化します。

  • AudioStream はリモードエンドポイント、ネットワークマッピングの構成、AudioCodec の設定を指定する

  • AudioGroup は1つ以上の AudioStream のローカルエンドポイントを表す。AudioGroup は全ての AudioStream をミックスし、オプションとして、同時にデバイススピーカーとマイクをやりとりします。


もっともシンプルな使い方は、1つのリモートエンドポイントと1つのロカールエンドポイントから構成されます。
より複雑な使い方は、AudioGroup に記述されている limitation を参照してください。

RTP API を使うには、アプリケーションはユーザーにパーミッションをリクエストしなければなりません。そのためには、マニフェストファイルに <uses-permission android:name="android.permission.INTERNET"> を宣言してください。
デバイスのマイクを取得するなら、<uses-permission android:name="android.permission.RECORD_AUDIO"> パーミッションも必要です。



Resizable app widgets


Android 3.1 から、開発者は自分のホームスクリーンウィジェットを縦方向、横方向、両方の軸でサイズ変更可能にすることができるようになりました。ユーザーはウィジェットをタッチ-ホールドすることでリサイズハンドルを表示します。そして、縦と/もしくは横にハンドルをドラッグしてレイアウトグリッド上のサイズを変更します。

開発者はウィジェットの AppWidgetProviderInfo メタデータ内に resizeMode 属性を定義することで全てのホームスクリーンウィジェットをサイズ変更可能にできます。resizeMode 属性用の値は "horizontal", "vertical", "none" です。ウィジェットを縦横両方でサイズ変更可能にするには "horizontal|vertical" のように書きます。

例)


<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/preview"
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure"
android:resizeMode="horizontal|vertical" >
</appwidget-provider>


ホームスクリーンウィジェットのより詳しい情報は、App Widgets のドキュメントを見てください。



Animation framework


  • New ViewPropertyAnimator class

    • 新しい ViewPropertyAnimator クラスは View オブジェクトの選択されたプロパティでアニメートする便利な方法を提供します。このクラスはプロパティのアニメーションを自動的に最適化し、View オブジェクト上の複数の同時アニメーションの管理を簡単にします。
      ViewPropertyAnimator を使い方は簡単です。View のプロパティをアニメートするには、animate() を呼び出してその View 用の ViewPropertyAnimator オブジェクトを生成します。ViewPropertyAnimator 上のメソッドを使って、どのプロパティをどのようにアニメートさせるのかを指定します。例えば、View を透明にフェイドするには alpha(0); を呼び出します。ViewPropertyAnimator オブジェクトは基礎となる Animator クラスの詳細な設定を処理し、それを開始し、そしてアニメーションをレンダリングします。


  • Animation background color

    • 新しい getBackgroundColor()setBackgroundColor(int) メソッドによって、ウィンドウアニメーションに対してのみ、アニメーションの背景色を取得/設定することができます。現在は、任意のアルファレベルで、黒である必要があります。

  • Getting animated fraction from ViewAnimator

    • 新しい getAnimatedFraction() メソッドによって現在のアニメーションフラクション(最新のフレームアップデートでは elapsed/interpolated フラクションが使われている)を ValueAnimator から得ることができます。





UI framework


  • Forced rendering of a layer

    • 新しい buildLayer() メソッドによってアプリケーションは生成される View のレイヤーを強制することができ、View は直ちにそこにレンダリングされます。例えば、アプリケーションはこのメソッドを使って、アニメーションがスタートする前に、そのレイヤーに View をレンダリングすることができます。View が複雑な場合、アニメーションが開始される前にそのレイヤーにレンダリングしておくことで、フレームがスキップされるのを防ぐことができます。


  • Camera distance

    • アプリケーションは新しいメソッド setCameraDistnace(float) を使ってカメラと View の距離を設定できるようになりました。これにより、アプリケーションは回転などの View の3D変換上のコントロールを改善することができます。


  • Getting a calnendar view from a DatePicker


  • Getting callbacks when views are detached


  • Fragment breadcrumb listener, new onInflate() signature


  • Display search result int new tab

    • ACTION_WEB_SEARCH intent 用の EXTRA_NEW_SEARCH データキーによって、現在のタブではなく新しいブラウザータブで検索結果を開くことができます。


  • Drawable text cursor

    • 新しいリソース属性の textCursorDrawable を使ってテキストカーソルに使われる画像を指定できるようになりました。


  • Setting displayed child in remote views


  • Generic keys for gamepads and other input devices

    • KeyEvent にゲームパッドボタンに対応する汎用的なキーコード範囲が追加されました。このクラスには、さらに isGamepadButton(int) などキーコード用のいつくかのヘルパーメソッドが追加されました。





Graphics


  • Helper for managing bitmaps

    • setHasAlpha(boolean) を使って、アプリケーションは Bitmap 内の全てのピクセルが不透明(false)かいつくかのピクセルが不透明ではないアルファ値(true)を含むかどうかを示すことができます。いくつかの設定(RGB_565など)では、per-pixel アルファ値がサポートされていないため、この呼び出しが無視されることに気をつけてください。このメソッドは描画のヒントを与えることを意味しています。いくつかのケースでは、不透明だと分かっているビットマップの描画は、不透明ではない per-pixel アルファ値が含まれている可能性があるときの描画よりも速くなることが知られています。

    • getByteCount() でバイト単位での Bitmap のサイズを取得する

    • getGenerationId() を使ってキャッシュ用などに Bitmap が変更されたかどうかを見つけることができます。

    • sameAs(android.graphics.Bitmap) は、与えられた Bitmap が現在の Bitmap と寸法、設定、もしくはピクセルデータで異なるかどうかを決定する。

  • Setting camera location and rotation

    • 3D変換用に camera の位置をコントロールするための rotate()setLocation() という新しいメソッドが Camera に追加されました。





Network


  • High-performance Wi-Fi lock

    • High-performance Wi-Fi lock によって、デバイスのスクリーンがオフの状態であっても、アプリケーションはハイパフォーマンス Wi-Fi 接続を制御することができます。長期間、音楽、ビデオ、音声をストリームするアプリケーションは high-performance Wi-Fi lock によって画面オフの状態でもストリーミングパフォーマンスを確実に保つことができます。この状態はより電力を使うため、アプリケーションは長時間アクティブな接続が必要なとき high-performance Wi-Fi を得るようにすべきです。

  • More traffic stats

    • アプリケーションは TrafficStats 内の新しいメソッドを使うことで、より多くのタイプのネットワーク使用の統計情報にアクセスできるようになりました。アプリケーションはメソッドを使って、UDP状態, パケットカウント, TCP 転送/受信 ペイロードバイト、特定の UID のセグメント を取得することができます。

  • SIP auth username

    • アプリケーションは新しいメソッドの getAuthUserName()setAuthUserName() を使ってプロファイル用の SIP auth username を取得できるようになりました。





Download Manager


  • Handling of completed downloads

    • 完了したときだけユーザーに通知するようにダウンロードを初期化することができます。このタイプのダウンロードを初期化するには、VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION をリクエストオブジェクトの setNotificationVisibility() メソッドに渡します。

    • 新しいメソッド addCompletedDownload() によってアプリケーションはファイルをダウンロードデータベースに追加することができます。これにより、Download アプリケーションによってそのファイルを管理できるようになります。

  • Show downloads sorted by size





IME framework


  • Getting and input method's extra value key

    • subtype に対する ExtraValue 文字列が保存されているかどうかをチェックする containsExtraValueKey() メソッドと、ExtraValue ハッシュマップから特定のキー値をとりだす getExtraValueOf() メソッドが InputMethodSubtype に追加されました。





Media


  • New streaming audio formats

    • ストリーミングオーディオを改善するために、メディアフレームワークに raw ADTS AAC コンテンツのビルドインサポートが追加されました。同様に、高品質(lossless)圧縮オーディオコンテンツ用に FLAC audio のサポートも追加されました。より詳しい情報は Supported Media Formats を見てください。





Launch controls on stopped applications


Android 3.1 から、システムのパッケージマネジャーは stopped 状態のアプリケーションをトラックし続けるようになりました。そして、バックグラウンドプロセスや他のアプリケーションからの起動を制御する手段を提供します。

アプリケーションの stopped 状態は Activity の stopped 状態とは異なることに気をつけてください。システムはこれら2つの状態を別々に管理します。

プラットフォームは2つの新しい intent flag を定義します。これにより stopped アプリケーション内のコンポーネントをアクティブすることを、そのインテントが許可すべきかどうかを送信側が指定することができます。

  • FLAG_INCLUDE_STOPPED_PACKAGES - intent を解決する可能性のあるターゲットのリストに stopped アプリケーションの intent filter を含める

  • FLAG_EXCLUDE_STOPPED_PACKAGES - ターゲットのリストに stopped アプリケーションの intent filter を含めない


これらのフラグの両方がインテントに定義されている場合、デフォルトの振る舞いは、可能性のあるターゲットのリストに stopped アプリケーションのフィルターを含みます。

システムはずべての broadcast intent に FLAG_EXCLUDE_STOPPED_PACKAGES を追加することに注意してください。これは不注意によるバックグラウンドサービスからの broadcast や、不必要な stopped アプリケーションのコンポーネント起動を防ぎます。バックグラウンドサービスやアプリケーションは、 stopped アプリケーションをアクティブにするべき broadcast intent にFLAG_INCLUDE_STOPPED_PACKAGE フラグを加えることで、この振る舞いをオーバーライドすることができます。

アプリケーションは最初にインストールされて、また起動されたいない状態とき、stopped 状態になります。また、アプリケーション管理でユーザーが手動でストップしたときも stopped 状態になります。



Notification of application first launch and upgragde


次の2つの intent action を通してアプリケーションの最初の起動とアップグレードの改善された通知がプラットフォームに追加されました。

  • ACTION_PACKAGE_FIRST_LAUNCH - アプリケーションが最初に起動したとき(つまり、stopped state から最初に外れたとき)にアプリケーションのインストーラパッケージに送る。データにはパッケージ名が含まれる。

  • ACTION_MY_PACKAGE_REPLACED - アップデートされた(規存のバージョンを新しいバージョンで上書きインストールされた)アプリケーションを通知する。これは置き換えられたアプリケーションにのみ贈られる。付加的なデータは含まれない。これを受け取るには、この intent action を intent filter に宣言する。アップグレード後に適切な起動状態にアプリケーションを戻すためのトリガーコードとして使うことができる。
    このインテントは、アップグレードされたアプいrケーションが started 状態のときのみアプリケーションに直接送られる。(stopped 状態では送られない)




Core utilities


  • LRU cache

    • 新しい LruChacke クラスによってアプリケーションは効果的なキャッシュによる利益を受けられます。キャッシュされたデータのための賢いメモリフットプリントを維持することで、アプリケーションは計算やネットワークからのデータのダウンロードに費やす時間を減らすことができます。LruCache は限られた数の値への強力なリファレンスを保持するキャッシュです。値がアクセスされるたびに、キューの先頭に移動します。値がフルキャッシュに追加されたとき、そのキューの最後の値は立ち退かされ、ガーベージコレクションの対象になります。

  • File descriptor as int





WebKit


  • File scheme cookies

    • CookieManagerfile: URI scheme を使うクッキーをサポートするようになりました。WebView CookieManager をインスタンス化する前に、setAcceptFileSchemeCookies() を使って file scheme cookies のサポートを有効/無効にすることができます。CookieManager インスタンスでは、allowFileSchemeCookies() を呼ぶことで file scheme cookies が有効になっているかどうかをチェックできます。

  • Notification of login request

    • Android 3.0 で紹介されたブラウザオートログイン機能をサポートするために、新しい onReceivedLoginRequest() メソッドはユーザーのオートログインリクエストが処理されたことをホストアプリケーションに通知します。

  • Removed classes and interfaces

    • 以前から deprecated 状態になっていたいくつかのクラスとインタフェースは公開 API から削除されました。より詳しい情報は API Differences Report を見てください。





Browser


ブラウザアプリケーションにはウェブアプリケーションをサポートするために次の機能が追加されました:

  • HTML5 <video> タグに埋込まれたビデオのインラインプレイバックがサポートされました。可能であればプレイバックはハードウェアアクセラレイトされます。

  • 全てのサイト(モバイルとデスクトップ)に対して固定位置エレメントのレイヤーがサポートされました。




New feature constants


開発者がアプリケーションマニフェストで宣言できるハードウェアの機能定数が追加されました。Android Market のような外部のエンティティに、アプリケーションがこのプラットフォームのバージョンで新しくサポートされたハードウェアの機能が必要であることを知らせることができます。開発者はこれらおよび他の機能定数を <uses-feature> マニフェストエレメントに宣言します。

  • android.hardware.usb.accessory - アプリケーションは USB API を使ってUSB を介して接続されたホストとして機能する外部のハードウェアデバイスとやりとりすることができます。

  • android.hardware.usb.host - アプリケーションは USB API を使って USB を介して接続されたデバイスとして機能する外部のハードウェアデバイスとやりとりすることができます。


Android Market は <uses-feature> マニフェストエレメントに宣言された機能に基づいてアプリケーションをフィルターします。アプリケーションマニフェストに機能を宣言するためのより詳しい情報は Android Market Filters を読んでください。