pfa1

Processing for Android

 Processing APIを使うAndroidアプリを呆れるほど簡単に作れるようにすることが、このプロジェクトの目標です。ProcessingとAndroidの開発環境を自分のマシンに用意し、単純なコードを1行書き、Runボタン(または Ctrl-R / Cmd-R)を押せば、あなたのスケッチがAndroidアプリとしてエミュレータ上に現れます。Run on Device (Ctrl-Shift-R / Cmd-Shift-R)を選択すると、開発マシンに接続されたAndroidデバイスの上で実行されます。なんて便利!

 ただし、このプロジェクトはまだ「ベータ」品質です。未完成であり、バグを含んでいることを忘れないでください。重機の制御に使ってはいけません。卒論や修論に使うと、卒業できなくなるかもしれません。無料でダウンロードしたソフトに完成度が低いと文句をいうような人も使わないでください。

 今のところ携帯電話上で動く開発環境(PDE)を作る予定はありませんが、携帯をみんなでハックするのは楽しく、驚きがあります。

Android SDKのインストール

 Android SDKをダウンロードし、インストールします。“ADT Plugin for Eclipse”は必要ありませんが、“Available packages”を見て、次のパッケージがインストールされていることを確認してください(Installing the SDKのstep4を参照)。

  • “Android Repository” に含まれる “SDK Platform Android 2.1, API 7”
  • “Third party Add-ons” を展開すると現れる “Google Inc.” の “Google APIs by Google Inc., Android API 7”

Android-sdk-manager.png

 上の画像は2011年4月時点での私のマシンの状態です。これを参考にして、インストールされていないパッケージをチェックしてください。

 “Display updates only”を有効にすると、更新がある項目のみ表示されます。その場合、“Android SDK Tools, revision XX” や “Android SDK Platform-tools” といった項目がリストに現れないかもしれません。更新されるとまた見えるようになります。

 Android API 7 は必須です。他のリビジョンもインストールすることは可能ですが、7を省いて8をインストールするようなことはできません。なお、これらのリビジョン番号は(Android OSの各バージョンに対応する) "SDK Platforms" のために付けられたもので、前述の"Android SDK Tools"のリビジョンとは異なります(混乱してきましたか?)。

 Android SDKをインストールしたら、次の節のリンクからAndroidモードに対応しているProcessingをダウンロードしてください。

 なお、上記のような Android SDK と Google API のインストール作業は、Processingプロジェクトの理念に沿わないので、不要にしたいと願っています。 Issue 203 Issue 613

Processingのダウンロード

 現在のコードはpre-releaseバージョンです。正式版ではAndroidコンポーネントを別にダウンロードできるようにするか、メインのファイルに統合する予定です。Processing 0195が必要とするAndroid SDK Toolsはrevision 8以降です。

 古いリリースは使わず、常に最新版を元にバグを報告してください。フォーラムにバグレポートを書き込むのはやめましょう。開発者が追跡できません。バグも直りません。

2011/05/15 | 1.5.1 Windows standard without Java, Mac OS X, Linux x86

Androidモード

 Android用にビルドするときは、ツールバー右側のドロップダウンメニューを普段の “Standard” から “Android” へ切り替えてください。ウインドウが濃い緑色になったら、新世界「Androidモード」です。

 Androidモードでは、RunやExportといった機能がちょっと変化します。

  • Run in Emulator - 現在のスケッチを前処理し、Androidプロジェクトを生成して、Androidエミュレータの上で実行(デバグ)します
  • Run on Device - Runとの違いはUSBで接続されたデバイス(スマートフォン)の上で実行される点です
  • Export Android Project - androidフォルダを作成し、そこにAntでApkをビルドするのに必要なファイルをまとめます
  • Export Signed Package - マーケットでリリースするためにサインされたバージョンを生成します(未実装 coming soon)

トラブルシューティングと既知の問題

Processing for Androidに関する質問はこのフォーラムでしてください。一般のカテゴリーに投稿するのは混乱のもとです。既知のバグのリストはここです。バグを見つけたら、なるべく“Component-Android”というタグを付けて、ここにファイルしましょう。

よく起こる問題

 “Error: Android Virtual Device 'Processing-Android-7' already exists.” というエラーに遭遇したら、PDEのAndroidメニューから “Android SDK & AVD Manager” を起動し、“Processing-Android-7 AVD” を削除(Delete)してください。次にスケッチを実行するとき、AVDは自動的に再生成されます。

訳注: 現在のAVDは“Processing-0197”で、名前が変わったようです。エラー時にはスケッチの再実行ではなく、PDEを再起動したほうがいい場合もあるようです。

Androidデバイスでの実行

 デバイス上でスケッチを実行するときは、事前に次のようにする必要があります。

  • USBデバッグをオン。デバイスの設定メニュー "アプリケーション設定→開発→USBデバッグ" をチェックしてください。
  • WindowsとLinuxでは、追加のUSB用デバイスドライバが必要です。詳しくはandroid.comのこのページを見てください。
  • Ubuntu Lucid (10.04)では、70-android.rulesというUSB設定ファイルのリネームが必要になるかもしれません(未確認)。

Android版の開発

  • エミュレータはStopボタンを押したあとも動き続けます。エミュレータの起動には2週間ほどかかるので、時間を無駄にしないためです。
  • サポートしているArduino OSはversion 2.1以上です。何年もJava 1.1をサポートしたあとで、また、うち捨てられた古いバージョンの面倒を見るつもりはありません。2.1や2.2だけでも、たくさんのデバイス、機能、解像度があって、すでに十分大変です。
  • パフォーマンスについて考えると、Processingプロジェクトを開始した2001年当時のデスクトップマシンの性能を思い出します。Android 2.2(Froyo)で導入されたJITによって多くのスケッチが恩恵を受けていますが、高速化のためにできることはまだあります。しかし、そのためにネイティブコードを書く余力はありません。Androidプラットフォームの成長を祈りましょう。
  • Androidのスタック深度はかなり浅いようで、たぶん32コールが限界です。そのせいで、Java版のProcessingでは問題なく動いていたコードでも、 StackOverflowErrorを引き起こす可能性があります。
  • Androidの色再現性は限定的です。ほとんどのスクリーンは24ビットをフルに表現することはできず、階調表現、色数の多いスケッチ、透明処理などに影響します。階調部分に色の縞が見えたり、透明部分にノイズが現れるかもしれません。これらはカラー処理に伴う計算の副作用で、スクリーンの性能にも影響されます。
  • loadFont()よりもcreateFont()の方がテキスト表示の品質は良好で、とくに2Dレンダリングのときはそうです。そのシステムで使用可能なフォントのリストはPFont.list()で取得できます。フォントはそこから選ぶか、スケッチのdataディレクトリにある.ttfフォントか.otfフォントが使用可能です。
  • Androidのコードはすべてパッケージのなかにあるので、パッケージを指定していないあなたのスケッチも含めて、どの.javaファイルも同じパッケージ内に配置されます。これは「プリプロセッサで.javaファイルに触れない」という我々がデスクトップ側で守っているルールを破っていますが、そうしないともっとひどいことになるでしょう。現時点の我々はデスクトップ版でパッケージをサポートしないので、あなたも.javaファイルにパッケージ宣言を追加するという考えは持たないでください。それでは困るという人はEclipseを使ったほう幸せになれるでしょう。

processing.coreの変更点

わくわくするけど疲れもする、希望と混乱に満ちたガイドです。

マウス、モーション、キー、そして入力
  • 互換性のため、mouseXとmouseYは元のAPIと同様に直近のマウス位置を保持します。加えて、motionX、motionY、pmotionX、pmotionY、motionPressureの各イベントが相対的モーションを追跡するために使われます。これらの変数はmouseXやmouseYと違いfloat型です。
  • mouseButton変数はありません。
  • マウスベースのインタフェイスの常識が、タッチインタフェイスには通用しません。Androidデバイスのハードウエアに合った使い勝手を実現するためには、ほとんどのスケッチを書き直すことになるでしょう。
  • Menuキーの長押しでバーチャルキーボードをオンオフするのがAndroidのデフォルトですが、その操作に不慣れなユーザーもいます。
  • Backキーはデスクトップ版ProcessingのESCに似た働きをし、デフォルトでは、アプリケーションを終了します。このキーをもっと有効に使いたいときは、keyPressed()をオーバーライドしてkeyに0をセットし、基底クラスに拾われないようにします。
 void keyPressed() {
   // なにか他のことをここでして
   if (key == CODED && keyCode == KeyEvent.KEYCODE_BACK) {
     keyCode = 0;  // 終了しない
   }
 }
  • keyEvent変数とmouseEvent変数はありません。イベントオブジェクトを使いたい場合は、キーとモーションのハンドラをオーバーライドする必要があります。SurfaceView? の内部で onTouchEvent() が呼ばれるので、Processingのタッチハンドラをオーバーライドする必要もあるでしょう。
 public boolean surfaceTouchEvent(MotionEvent event) {
   // ここにあなたのコード。
   // motionX/motionY, mouseX/mouseYなどを使いたいときは
   // super.surfaceTouchEvent()を呼ばないと正しく動作しません
   return super.surfaceTouchEvent(event);
 }

マルチタッチをサポートしているライブラリを組み込むために、このようなハンドラを使うことができます。 キーボード関連のメソッドにも同様の手法が使えます。

 public boolean surfaceKeyDown(int code, KeyEvent event) {
   return super.surfaceKeyDown(code, event);
 }
 public boolean surfaceKeyUp(int code, KeyEvent event) {
   return super.surfaceKeyDown(code, event);
 }

これら3つの関数はjava.awtのカウンターパートとは少し違った振る舞いをします。混乱しないよう、違いを把握しておきましょう。

変数が保存されない理由はKeyEventとMotionEventの両オブジェクトが再利用されるからです。これは、コスト高な複製処理をせずには再利用できないことを意味しています。また、それらがProcessingでは滅多に使われない、という理由もあって、単純に削除してしまったほうがベターなのです。イベントを当てにする高度なユーザーはオーバーライドしてください。

let advanced users who would otherwise rely on the events to handle the overrides themselves
  • ALT、CONTROL、SHIFTといった定数はありません。SHIFTは復活するかもしれませんが、他の2つはAndroidには存在しません。
  • LEFT、RIGHT、UP、DOWN定数は方向パッドに割り当てられています。パッドの中央を検出するときは、DPADを使います。これらのキーはハードウエアによって意味が違ってきます。実際にはトラックボールや光学パッドかもしれませんし、普通の機械式ボタンかもしれません。
 void keyPressed() {
   if (key == CODED) {
     if (keyCode == DPAD) {
       // ユーザーがパッドの中央を押したときの処理
     } else if (keyCode == UP) {
       // 上
     } else if (keyCode == DOWN) {
       // 下
     } else if (keyCode == LEFT) {
       // 左
     } else if (keyCode == RIGHT) {
       // 右
     }
   }
 }
  • リビジョン0190から、BACKとMENUという定数が使えるようになりました。
 void keyPressed() {
   if (key == CODED) {
     if (keyCode == BACK) {
       // Backボタンの動作をここに
       // 終了しないようにするためにはkeyCodeを0に
     } else if (keyCode == MENU) {
       // Menuボタンが押されたときの処理はここ
     }
   }
 }

Androidのドキュメントにはほかにもキーコードが記載されていますが、名前空間をあまり汚染したくないので、不可欠なものだけを取り入れました。他の定数を使用したいときは次の例のようにするといいでしょう。KEYCODE_HOMEを他のキーコードに変更します。たとえば、KEYCODE_VOLUME_DOWN、KEYCODE_VOLUME_UP、KEYCODE_CAMERAなどが使えます。

 void keyPressed() {
   // ここでなにかの処理
   if (key == CODED && keyCode == KeyEvent.KEYCODE_HOME) {
     // ホームキーをオーバーライド
   }
 }
スクリーンとその向き、size()
  • size()は、モバイルデバイスではあまり意味を持ちません。過去のスケッチとの互換性維持という目的を除けば、スケッチの幅や高さを指定するほうが良いとする理由はありません。
  • Androidにおけるsize()メソッドは違う働きをします。size()メソッドがない場合、そのスケッチはディスプレイ全体を使います。width変数とheight変数はあなたに割り当てられているディスプレイのサイズを示します。デバイスが回転して向きが変わると、スケッチはリセットされ、widthとheightの値も更新されます。
  • size()メソッドが必要になるのは、レンダラを3Dに設定するときです (デフォルトはデスクトップ版と同様、ビルトインの2Dレンダラ)。3Dを使うときは、次のようにするのがお勧めです。
 size(screenWidth, screenHeight, P3D);
  • Androidでは、パラメータのないsize()メソッドは避けましょう。なぜなら、size()は暗黙裏にスケッチから削除され、違うコードに分解されるからです。
 void setup() {
   size(screenWidth, screenHeight, P3D);
 }

このコードは前処理の段階で取り除かれて、次のようになります。

 void setup() {
 }
 public int sketchWidth() {
   return screenWidth;
 }
 public int sketchHeight() {
   return sketchHeight;
 }
 public String sketchRenderer() {
   return P3D;
 }

デスクトップ版で使われている、setup中にスケッチを変更するための黒魔術は再利用しないことにしました。

  • Androidで有効なレンダラは2種類だけです。P2DやJAVA2Dを指定すると、Android 2Dレンダラが使われます。P3DやOPENGLを指定した場合は、OpenGLによる3Dグラフィクスレンダラです。
  • 古いリビジョンにはA2DとA3Dというエイリアスがありましたが、混乱のもとなので、rev.0198以降にはありません。
  • size()コマンドはプリプロセッサで処理されるので、Eclipseユーザーは sketchWidth()、sketchHeight()、sketchRenderer()の各メソッドを自分で書いて、サイズをコントロールする必要があります。そうする必要はあまりないはずですが、P3Dを使うためにsketchRenderer()メソッドをオーバーライドすることはあるでしょう。
  • Eclipseユーザーのためにポイントを整理します。Eclipseを使うときは…… (1) size()を一切コールしない。(2) sketchWidth/Heightを使って大きさを指定しない (3) 2Dではなく3Dを使うならスケッチに次のコードを追加する
 public String sketchRenderer() {
   return P3D;
 }
  • ひとつのスケッチにsize()とsketchXxxx()メソッドを含めるとエラーになります。
  • screen.widthとscreen.heightの代わりに、screenWidthとscreenHeightを使ってください。Processing 1.2でscreen変数は廃止されました。そうでなくとも、Androidにはscreenが必要とするjava.awt.Dimensionは存在しません。そもそもscreenは、内部処理用の変数を他の人たちが使い始めてしまったので、よく考えずにドキュメント化してしまったという経緯があります。
  • キーパッドの7か9でエミュレータを回転させることができます。クパチーノの天才たちが作ったラップトップを使っている人は Ctrl-F12 (Ctrl-Fn-F12 on OS X)を押すと回ります。
  • 向き(orientation)をロックしたいときは、setup()内で次のコードのどちらかを実行します。
 orientation(PORTRAIT);		// ハンバーガーの向き
 orientation(LANDSCAPE);	// ホットドッグの向き
  • ポートレートとランドスケープのどちらで開くかべきかというヒントをエミュレータに与えるためにsize()を使うことも検討しましたが、複雑になるのでやめました。
  • スクリーンの密度やDPIはデバイスによって大きく違います。アプリケーションの開発に必要なそうした情報を得るためにandroid.utilのDisplayMetricsクラスがあります。密度とdensityDpiを取得するコードは次のとおりです。
 // Place this at the top of your sketch
 import android.util.DisplayMetrics;
 // Place this inside your setup() method
 DisplayMetrics dm = new DisplayMetrics();
 getWindowManager().getDefaultDisplay().getMetrics(dm);
 float density = dm.density;
 int densityDpi = dm.densityDpi;
 println("density is " + density);
 println("densityDpi is " + densityDpi);

Androidドキュメントで密度(density)はこう定義されています。

 This is a scaling factor for the Density Independent Pixel unit,
where one DIP is one pixel on an approximately 160 dpi screen
(for example a 240x320, 1.5"x2" screen), providing the baseline
of the system's display. Thus on a 160dpi screen this density value
will be 1; on a 120 dpi screen it would be .75; etc.

160dpiスクリーンのdensityDpiは単純に160です。240dpiのときの値は推測できるでしょう。

  • OpenGLレンダラはAndroidに組み込まれているので、import processing.opengl.*;とする必要はありません。仮にこの文があったとしても、プリプロセッサが削除してくれるので、Androidモードに移行するときにユーザーがコメントアウトする必要はありません。

APIの変更と廃止と忘却

  • Androidでもコアライブラリ用のパッケージにprocessing.coreが残っています。初期のリリースではprocessing.android.coreを使っていましたが、2系統のコードセットをメンテナンスすることは面倒なので、同じパッケージ名を使うことにしました。
  • 先述のとおり、size()メソッドの動作が異なります。
  • P3D/OPENGLでcreateGraphics()が使えるのは、FBO拡張をサポートしているAndroid 2.2以上のデバイスに限ります。それ以前のデバイスでも動くかもしれませんが、とてもbuggyです。
  • 先述のとおり、 screen.widthとscreen.heightはなくなり、screenWidthとscreenHeightに代替されました。
  • beginRecord、endRecord、beginRaw、endRawは使えません。携帯端末では意味がないため、サポートする予定はありません。
  • registerPost()、registerDraw()などのレジスタリングメソッドはサポートされません。利益が少ないわりにオーバーヘッドが大きいためです。将来のリリースでは対応するかもしれません。
  • カーソルに関連するメソッドはすべて削除されました。
  • 全部小文字のarraycopy()は削除されました。
  • openStream()メソッドは削除されました。createInput()を使ってください。
  • PImage.imageは PImage.bitmapです。目的は同じながら、異なるオブジェクトタイプであることを反映しています。
  • 同じ理由で、PFont.fontは PFont.typefaceです。
  • online変数は無効です。これはアプレットがオンラインで実行されているかどうかを判定するためのもので、Androidでは意味がないからです。

ファイルの読み込み、インターネット接続、パーミッション

  • データの読み込みやその他の目的で他のサーバに接続するときは、INTERNETパーミッションを有効にしておく必要があります。PDEのAndroidメニューからSketch Permissionsを実行すると現れるリストで設定します。
  • saveStrings()やcreateWriterといったメソッドを使いたいときは、WRITE_EXTERNAL_STORAGEを有効にして、Flashメモリへの保存を許可します。
  • 電話、コンパスといった機能ごとにパーミッションがあります。先ほどのリストや他の資料を調べてみましょう。

マルチタッチ、GPS、SMS、コンパスは使える?

シンプルなサンプルコードとライブラリが必要ですが、我々が本格的に取りかかれるのは、processing.coreをはじめとするソフトウエアのデバグが済んでからです。

rev 0193で、コンパスと加速度センサの基本的なサンプルを追加しました。

訳注: 原文のページに、協力者から寄せられたサンプルのリストがあります。

Eclipseで開発する

Ok、賢いあなたなら可能です。いくつか注意点があります。

  • ProcessingのEclipse用チュートリアルはAndroid開発には役立ちません。Eclispeでの開発に慣れた人がprocessing.coreライブラリを使いたい場合に限って、そうすべきでしょう。
  • size()の扱いついては前述のとおりです。
  • dataフォルダのかわりに、assetsフォルダを使います。Processingプロジェクトをコンバートする場合は、フォルダ名を変更してください。
  • processing/android/coreのコードをSubclipseを使ってチェックアウトするのが、Androidアプリを作るときのベストな方法です。そうしてから、Eclipse ADTを使って新しいAndroidプロジェクトを作り、android-coreをrequired projectとしてインクルードします。

他のAndroidコードとの統合

Android GUIコンポーネントをProcessingスケッチに取り込むことは、絶対におすすめしません。動作するケースもあるかもしれませんが、Android OSのバージョンによって一貫性のない挙動となるでしょう。その理由は、ProcessingスケッチがひとつのAndroidアクティビティとして、他のアプリケーションに埋め込まれているからです。将来的にはもっと良い実装にしたいのですが、現状は次のような理由により難しいです。

  • スケッチを単一のSurfaceViewとすることは可能でしょうが、Androidの描画サーフェイスは2Dと3Dで別の基底クラスを持っているので、それぞれに対応する実装を用意しなくてはいけません。
  • そうしたとしても、プリプロセッサは2Dか3Dかを検出して、コンパイル時にサブクラスPApplet2DかPApplet3Dを選択する必要があります。これは動的にレンダラを選択できる現在のデスクトップ版のやり方からかけ離れています。
  • 同様に、壁紙やウィジェットを実装する場合も、それぞれ別の基底クラスがあるので、さらに複製する必要があります。

こうした課題は乗り越えがたいものです。Activityクラスをより薄いレイヤにして、2D、3D、Wallpaper、Widgetを扱う一連の基底クラスを作るためには、PAppletの大幅なリファクタリングが必要です。これは一大事業であり、デスクトップ版からの逸脱でもあります。少人数の開発者で対応できる作業量ではありません。

当面は、大多数のProcessingユーザーのためにAndroid開発を普及させることを優先したほうがいいと判断しています。それが落ち着いたら将来のリリースに向けて次の課題に取り組みます。

アプリの配布

作ったアプリをみんなでシェアしたら楽しいでしょうね。マーケットで公開する方法をクリアにするために(あるいは自分のWebページで配布できるようにするために)、この章を用意しました。GoogleのガイドラインPreparing to Publishは読んでおいたほうがいいでしょう。

サイン

マーケットで公開するには、アプリがサインされていないといけません。現状では、コードをExportしたら、Googleによるこの解説に従って、自分でサインする必要があります。将来的にはPDEでこの処理ができるようにしたいです。

アイコン

rev.0190からスケッチのアイコンを指定できるようになりました。Androidはいろんな解像度とコンテキストに対応するためにたくさんのアイコンを要求します。画像をicon-36.png、icon-48.png、icon-72.pngという名前で、スケッチフォルダに保存してください(dataフォルダなどのサブフォルダではありません)。次回のビルドからそのアイコンが使われます。アイコン用の画像がない場合は、デフォルトのものが使われます。

アイコンとして使う画像は、アイコンのエリア全体を使ってはいけません。詳しくはデザインガイドラインを見てください。

AndroidManifest?.xml

rev.0190から、Android版スケッチはスケッチフォルダ内にAndroidManifest.xmlを持つようになりました。これはスケッチのネーミングやパーミッションをコントロールするためのものです。このファイルを自分で編集することもできますが、壊してしまうとたくさんのトラブルを引き起こします。バックアップをとってから、変更しましょう。

Export や Export to Applicationで生成されるファイルではなく、バックアップのほうを修正したほうがいいでしょう。Exportはファイルを上書きするので、修正済みのファイルは別の名前になっていないと、元に戻ってしまいます。


原文

翻訳: 船田巧 Takumi Funada

Content is available under Attribution-Noncommercial-Share Alike 3.0

Last modified:2014/03/04 06:00:25
Keyword(s):
References: