2013年3月17日日曜日

Firefox OS Simulator の画面サイズを変える

変えられますが、、、現状では使い物になりませぬ。

ABC 2013 Spring で @dynamis さんにコマンド引数で指定できるはず、ということを聞いたので調べてみた。

手元の Mac だと

/Users/[username]/Library/Application Support/Firefox/Profiles/vr2npksq.default/extensions/r2d2b2g@mozilla.org/resources/r2d2b2g/data/content/js/main.js

が Firefox OS Simulator のダッシュボードの js で、window の postMessage() でフックしてます。

toggle: function() { $(this.toggler).prop('indeterminate', true); window.postMessage({ name: "toggle" }, "*"); },

実際に Simulator のプロセス(b2g-bin)を起動してるのが

/Users/[username]/Library/Application Support/Firefox/Profiles/vr2npksq.default/extensions/r2d2b2g@mozilla.org/resources/r2d2b2g/lib/remote-simulator-client.js

です。

... // compute current b2g file handle get b2gExecutable() { if (this._executable) return this._executable; let executables = { WINNT: "win32/b2g/b2g-bin.exe", Darwin: "mac64/B2G.app/Contents/MacOS/b2g-bin", Linux: (Runtime.XPCOMABI.indexOf("x86_64") == 0 ? "linux64" : "linux") + "/b2g/b2g-bin", }; let url = Self.data.url(executables[Runtime.OS]); let path = URL.toFilename(url); let executable = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); executable.initWithPath(path); let executableFilename = executables[Runtime.OS]; // Support B2G binaries built without GAIADIR. if (!executable.exists()) { let executables = { WINNT: "win32/b2g/b2g.exe", Darwin: "mac64/B2G.app/Contents/MacOS/b2g", Linux: (Runtime.XPCOMABI.indexOf("x86_64") == 0 ? "linux64" : "linux") + "/b2g/b2g", }; let url = Self.data.url(executables[Runtime.OS]); let path = URL.toFilename(url); executable.initWithPath(path); executableFilename = executables[Runtime.OS]; } this._executable = executable; this._executableFilename = executableFilename; return executable; }, // compute b2g CLI arguments get b2gArguments() { let args = []; let profile = URL.toFilename(profileURL); args.push("-profile", profile); // NOTE: push dbgport option on the b2g-desktop commandline args.push("-dbgport", ""+this.remoteDebuggerPort); args.push("-pbport", ""+this.pingbackServerPort); if (this.jsConsoleEnabled) { args.push("-jsconsole"); } //args.push("--screen=320x480@160"); //args.push("--screen=480x800@240"); //args.push("--screen=iphone"); //args.push("--screen=tattoo"); args.push("--screen=galaxy_nexus"); if (this._defaultApp != null) { args.push("--runapp", this._defaultApp); } return args; }, ... b2gArguments() がコマンドライン引数を設定しているところなので、 ここに args.push("--screen=320x480@160"); とか追加すれば画面サイズを変えることができます。

注意:remote-simulator-client.js を変更したあと、Firefox を再起動する必要があります。

指定方法は

--screen=[width]x[height]@[resolution]

です。@[resolution]部分は省略できます。

ほかにもデバイス名で指定できるものもあって、https://developer.mozilla.org/ja/docs/Mozilla/Boot_to_Gecko/Using_the_B2G_desktop_client によると
  • iphone
  • ipad
  • nexus_s
  • galaxy_nexus
  • galaxy_tab
  • wildfire
  • tattoo
  • salsa
  • chacha
が指定できるそうです。いくつか(tattoo, iphone, nexus_s, galaxy_nexus)試してみましたがちゃんと画面サイズが変わりました。

HTC tattoo 持ってます。懐かしい。どこいったかな。。。



--screen=tattoo

レイアウト崩れます。。。





--screen=iphone

画面サイズを指定しない場合と同じっぽい





--screen=nexus_s

ホームボタンの部分が画面の途中にでて、ロック解除できません。。。





--screen=galaxy_nexus

nexus_s と同じような状態に。。。



ということで最初に指摘したとおり、全然使える状態ではありませんでした。。。



Firefox OS Simulator で console.log() ってどこで見れるの?

出てくるはずらしいのですが、なぜかうまくいかず、、、

index.html <html> <head> <meta charset="utf-8"> <title>Hello World</title> <script type="text/javascript" src="main.js"></script> </head> <body> Hello World! </body> </html> main.js console.log("Hello world"); manifest.webapp { "name": "My App", "description": "my first web app", "launch_path": "/index.html", "icons": { "16": "/img/icons/mortar-16.png", "48": "/img/icons/mortar-48.png", "128": "/img/icons/mortar-128.png" } } たったこれだけのアプリなんですけどねぇ。

デスクトップ版ではもちろんコンソールに出てます。



Simulator の Console にチェックいれて、おれおれアプリをダッシュボードにいれて起動!



Error Console はこんな感じ。それっぽいのはでない。。。



追記:
$ /.../b2g-bin -v
Mozilla B2G 18.0


追記その2:

わかった!
下にでるのか(てっきり上に追加されるのかと思っていたよ)
いつの間にかスクロールできるようになってたよ!
常にスクロールバーを表示するか、自動でスクロールしてほしい!



2013年3月2日土曜日

Web Activities と Android の Intent の対応

Web Activities は Android の Intent みたいな機能で、Firefox OS でサポートされています。

Web Activities を使うにはアプリのマニフェストファイルに宣言します。
AndroidManifest は XML でしたが、こちらは JSON です。 { "name": "My App", "description": "my first web app", "launch_path": "./index.html", "activities": { "share": { "filters": { "type": ["image/png", "image/gif"] }, "href": "./index.html", "disposition": "window" } } } "activities" 部分が Web Activities の宣言です。
Android でいうと Activity の <intent-filter> 部分です。
この中に、このアプリが処理できる activity を記述していきます。

"share" 部分が Android でいう ACTION にあたる部分です。ここに指定できる activity 名はまだ完全には決まっていないようです。
典型的なものとして

・view 表示する
・share 共有する
・dial 電話をかける
・pick 画像や動画を選択する
・new メールなどを作成する

があります。
他の activity は上記のサイトで紹介していますが、個人的にはこれ以外はあんまり使わないと思います。

Android と比較すると

Web ActivitiesAndroid
viewACTION_VIEW
shareACTION_SEND
dialACTION_DIAL
pickACTION_PICK
newACTION_SENDTO

に対応します。

"filters" は対応するデータを指定するプロパティです。Android だと <intent-filter>タグ内の <data>タグにあたります。

"filter" の中の "type" はデータのタイプを指定するプロパティです。MIME Type というわけではないようで、"url" を指定することができます(でも将来的に url は text/html になるかもしれないらしい)。普通に "image/png" とかも指定できます。多分 "text/*" とか指定できると思うけど情報がないのでわかりません。Android だと <data> タグの mimeType 属性にあたります。
"url" というプロパティもあるらしいですが情報が少なすぎてよくわからないです。

"href" にはこの activity を処理するときに開くページを指定します。Android だと <intent-filter> タグを含む<activity> タグにあたります。

"disposition" はページを開くときの方法として "window" もしくは "inline" を指定します。
"window" の場合が画面全体が遷移先のアプリになり、"inline" ではダイアログで遷移先のアプリが開きます。



Android で registerReceiver() メソッドで BroadcastReceiver を動的に登録できたように、Web Activities でも Activity Handler を動的に登録することができます。
* どうもまだ実装されていないみたい? bug 775181 var register = navigator.mozRegisterActivityHandler({ name: "pick", disposition: "inline", filters: { type: "image/png" }
 }); register.onerror = function () { console.log("can not register activity");
 } mozUnregisterActivityHandlerで登録を解除することができます。(* どうもまだ実装されていないみたい? bug 775181 navigator.mozUnregisterActivityHandler(activityHandlerDescription);
mozIsActivityHandlerRegistered で登録されているか確かめることができます。(* どうもまだ実装されていないみたい? bug 775181 var bool = navigator.mozIsActivityHandlerRegistered(activityHandlerDescription);


マニフェストで宣言した場合でも、動的に Activity Handler を登録した場合でも、activity を受けとったときの処理は次のように行います。 navigator.mozSetMessageHandler("activity", function (req) {
 req.source; // ActivityOptions read-only // 処理 // ユーザーが操作をキャンセルした(= 前の画面に戻ることを意図している)ときは req.postError("user canceled"); // のように postError() を呼びます。 // そうしないと前の画面に戻れません。 // "pick" など値を返す場合は req.postResult(any result); // を呼びます。 }); 呼び出し元から渡されたデータは source パラメータで参照することができます。これは ActivityOptions オブジェクトで、次の様に定義されています。 interface ActivityOptions { attribute DOMString name; attribute Object? data; // a dictionary };



acitivty を呼び出すほうは、MozActivity のオブジェクトを作成します。

例)pick
*実際に動かしてみてOKだった var pick = new MozActivity({ name: "pick", data: { type: "image/png" } }); pick.onsuccess = function() { // データが返される場合、this.result の中にいろいろ入ってるらしい // 情報が少なくてよくわからない // 画像が返ってくる場合は this.result.blob; // にデータが入っている }; pick.onerror = function() { // エラー }


例)view
*実際に動かしてみてOKだった var pick = new MozActivity({ name: "view", data: { type: "url", url: "http://y-anz-m.blogspot.jp" } }); pick.onsuccess = function() { // view のときは普通値は返ってこないと思う }; pick.onerror = function() { // エラー } type: "url" はいずれ type: "text/html" になるかもしれないらしい。


例)dial
*実際に動かしてみてOKだった var pick = new MozActivity({ name: "dial", data: { number: "+46777888999" } }); pick.onsuccess = function() { // view のときは普通値は返ってこないと思う }; pick.onerror = function() { // エラー } + っているのかな?よくわからない。。。


例)share : URL を送る
*実際に動かしてみてOKだった var pick = new MozActivity({ name: "share", data: { type: "url", url: "http://y-anz-m.blogspot.jp" } }); pick.onsuccess = function() { // share のときは普通値は返ってこないと思う }; pick.onerror = function() { // エラー }


例)share : プレインテキストを送る

type をどうしたらいいのかまったくリファレンスがないのでわかりません。 うぁーん。
そもそも Brower の share 機能がないってどういうこと???


例)share : 画像を送る var image = getImage(); // blob かな? var pick = new MozActivity({ name: "share", data: { type: "image/png", number: "1", // なくてもいいかもしれない blobs: blob, filenames: "hogefile", // なくてもいいかもしれない filepaths: "hogepath" // なくてもいいかもしれない } }); pick.onsuccess = function() { // share のときは普通値は返ってこないと思う }; pick.onerror = function() { // エラー }



ぜんぜんドキュメントがまとまってなくて、ぐぬぬ、ぐぬぬ、ですよー。


実際に試してみた

1. ギャラリーアプリからの画像の共有を処理する

"share": { "filters": { "type": ["image/png", "image/gif", "image/jpg", "image/jpeg"] }, "href": "./index.html", "disposition": "window" } だと、ギャラリーからの共有にアプリが現れませんでしたが、 "share": { "filters": { "type": "image/*" }, "href": "./index.html", "disposition": "window" } だと、共有にアプリが現れました。
呼び出し元で指定してる type が "image/*" なので(以下を参照)、image/* にしとかないと受けとれないっぽいです。
呼び出し元が image/* ってのもどうかと思うけど。。。

こういう javascript にしておくと function init() { navigator.mozSetMessageHandler("activity", function (req) {
 var ao = req.source; // ActivityOptions var s = ao.name + ", data : "; for (var p in ao.data) { s += p + ", "; } alert(s); }); } window.addEventListener("load", init); data に含まれているプロパティが取得できます。これによると type, number, blobs, filenames, filepaths というプロパティがあることがわかりました。

そこで次の様にしてみると function init() { navigator.mozSetMessageHandler("activity", function (req) {
 var ao = req.source; // ActivityOptions var s = "name = " + ao.name + "\ndata : "; for (var p in ao.data) { s += p + ", "; } s += "\n"; s += "data.type = " + ao.data.type + "\n"; s += "data.number = " + ao.data.number + "\n"; s += "data.blobs = " + ao.data.blobs + "\n"; s += "data.filenames = " + ao.data.filenames + "\n"; s += "data.filepaths = " + ao.data.filepaths + "\n"; alert(s); }); } window.addEventListener("load", init); こうなりました。


2. Twitter アプリから Email で送るを処理する

"share": { "filters": { "type": ["image/*", "url"] }, "href": "./index.html", "disposition": "window" } のようにしてみたけど、起動候補にでませんでした。そこで "new": { "href": "./index.html", "disposition": "window" } にしたらでました。
type に "mail"、URI というプロパティに mailto:subject=... のような URI が入ってました。


3. pick を呼び出してみる

function init() { var pick = new MozActivity({ name: "pick", data: { type: "image/png" } }); pick.onsuccess = function() { // データが返される場合、this.result の中にいろいろ入ってるらしい // 情報が少なくてよくわからない // 画像が返ってくる場合は alert(this.result.blob); // にデータが入っている }; pick.onerror = function() { // エラー } } window.addEventListener("load", init);

画像を選択したあと


4. url を view で表示してみる

function init() { var pick = new MozActivity({ name: "view", data: { type: "url", url: "http://y-anz-m.blogspot.jp" } }); } window.addEventListener("load", init);


まとめ

受け渡されるデータ構造は上のリンク先の記事は全くあてにならなかったので注意してください。実際に動かした結果は次の様になりました。

ギャラリーから画像 share
ActivityOptions ao = req.source
ao.name : "share"
ao.data.type : "image/*"
ao.data.number
ao.data.blobs
ao.data.filenames
ao.filepaths

Twitter アプリからEmailで送る new
ActivityOptions ao = req.source
ao.name : "new"
ao.data.type : "mail"
ao.data.URI


同じ activity を複数登録できません。なので、 "activities": { "share": { "filters": { "type": "image/*" }, "href": "./index_for_image.html", "disposition": "window" }, "share": { "filters": { "type": "url" }, "href": "./index_for_url.html", "disposition": "window" } } のように type によって処理するページを変えたりとかできません。えーなんでー。。。


なんといってもプリインの Browser に share 機能がなくてすごく残念です。。。




2013年3月1日金曜日

Firefox OS さわってみた。

メインのサイト

http://www.mozilla.jp/firefoxos/


Firefox OS Simulator

https://developer.mozilla.org/en-US/docs/Mozilla/Firefox_OS/Using_Firefox_OS_Simulator

  • デスクトップ版 Firefox の add-on として利用する
  • Firefox 17 以降であれば使える
  • テスト環境にアプリを追加する機能が含まれている
  • テスト環境には、リモートデバッグ、リモート Web コンソール、その他機能のサポートが設定されている
  • クリックできるホームボタンがある
  • Firefox OS のデバイスで使われている user-agent 文字列がセットされている
インストール

Firefox で https://addons.mozilla.org/en-US/firefox/addon/firefox-os-simulator/?src=ss にアクセス
http://www.youtube.com/watch?v=g6oLUmc2iOQ の動画がわかりやすい

起動

Tools (ツール)→ Web Developer(Web 開発)→ Firefox OS Simulator で Dashboard を開いて、左の Simulator のスライドをクリックして Running にする。Console にチェックを入れて起動すると、ログがみれる。

上にスワイプしたあと鍵を押してロック解除(最初上にスワイプだけかと思って、わからなかった)

Firefox Marketplace アプリをインストール

Firefox OS Simulator の Dashboard 画面で右側のフォームに https://marketplace.firefox.com/ を入力して Add URL をクリック

任意の Web サイトも URL に指定することでアプリとしてインストールできる。


Firefox Marketplace

http://www.mozilla.jp/apps/
Android デバイスで試すには、Firefox Aurora をインストールする必要がある。
アプリを公開する方法 → https://marketplace.firefox.com/developers/


開発者向け情報

  • https://developer.mozilla.org/ja/docs/Apps 日本語
  • https://developer.mozilla.org/en-US/docs/Apps 英語
  • https://developer.mozilla.org/en-US/docs/Apps/Reference APIリファレンス

現在の印象&気になっている点

  • アプリの完全終了方法がわからなかった → アプリの完全終了はホームボタン長押しして x ボタン
  • Home ボタンを押しただけだと、次にランチャーから起動したときは前回の続きになる(起動 → 画面遷移 → Homeボタン → 起動 → 遷移先が表示される)。完全終了すると最初からになる

  • Android の Intent みたいな機能 Web Activities があるのはいいね!でもハードキーのバックボタンがないから、遷移先のアプリからもとの画面に戻れるかどうかは遷移先のアプリの実装しだい(戻る処理をしてくれるボタンなどが用意されているかどうか)
    例えば、
    Camera アプリのギャラリーから share → Twitter アプリ(Marketplace で配布されている Twitter Inc のもの)→ 左上の Cancel ボタン → なぜか Twitter の TL 画面

    Cancel ボタンでギャラリーには戻れないんですねー。。。 もちろん戻れる様になってるアプリもあります。

  • セキュリティってどうなってるの?アプリのコードとか見放題なのかしら?
  • マニフェストが壊れてる?とディレクトリがそのままでちゃうっぽい → サンプルで入ってる Share Receiver とか Image Uploader とか
  • 画面サイズに合ってないアプリがけっこうある。サンプルで入ってる PenguinPop とか。Marketplace から入れた Browser Pair というゲーム可愛くていいんだけど、上下ともスクロールしないと全体が見えない。。。
  • Firefox OS Simulator で画面サイズ変更できないの?どうやって他の画面サイズのデバイスの確認するの?

  • Web GL でぬるぬるだったりするのかな? → サンプルで入ってる CuveVid や CrystalSkull はサクサク動く、でも Simulator だからなんとも。でも CrystalSkull すごいね。

  • 課金系ってどうなってるのかな?アプリ内課金とか簡単にできる? → 課金の API はあるらしい



追記

・マニフェストは JSON なので、JSON として正しくない構文(例えば { } の最後の項目の後に , があるとか)だと Firefox OS Simulator の Dashboard からアプリを追加しようとしたときに Syntax Error といわれるし、Firefox Marketplace の Validator ではなんと Packaged app missing manifest と言われる(正しくは manifest はあるけど構文エラーというべき)ので注意が必要。

・マニフェストで icon を指定しないと、Validator では問題なくても Firefox OS Simulator でアプリを追加しようとしたときに追加されない(でも上記の Syntax Error とかは表示されないから追加しても何も起こらないようにみえる)ので注意が必要。

・ローカルのアプリを Firefox OS Simulator にインストールしていて、ローカルのコードを変更した場合、一旦 Simulator を終了してから、アプリの右の Update ボタンを押して Simulator を起動させないと反映されてないっぽい。Hot じゃないんですねー。。。