[Android][Firefox OS]adb push/pullをrootでやりたいときの処方箋

 藪下@2課のガジェオタです。

 別の人が受けてた質問なんですが、端末内のrootなディレクトリにファイルをpushしたいんだけどadb shellに入ってからsuしないとrootで書き込めないどうしようという質問がありました。
 開発者向けの端末でないと動かないコマンドなのであまり知られてないみたいですが、adb pushとかadb pullrootでやりたいときはあらかじめadbdrootで再起動しておくことができます。

adb root

 これでrootadbdが立ち上がるので、adb pushなりadb pullなりお好きにどうぞー。

[Firefox OS][Gecko]おや? Promiseって?

 藪下@2課のガジェオタです。

 Gecko触って遊んでて気づいたんですが、Geckoで使ってるPromiseとcontentプロセスで使っているPromiseは別物みたいです。

Promise – MDN
https://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Reference/Global_Objects/Promise

 ここを見るとcatch使えますね。実際適当なHTMLとJSこさえたら使えました。
 でもGeckoいじってAPI作ってテスト書いてたらcatchは関数ちゃうでと怒られる。なんでだと思ったらgecko/toolkit/modules/Promise.jsmにcatchがいなかったんですね。ちなみにmasterのHEADだと怒られないです。遊んでた環境が古くてまだ実装されてなかったみたいです。

 でまあcatchが実装されてるとかされてないとかは割とどうでもよくて、Geckoでは実装されてないものがコンテンツにぶら下がってる方にはあったので別物だったのかーとなった次第です。
 ちなみにGecko側のにはPromise.defer()があるけどコンテンツのにはなかったりもしました。

 ざっくり見た感じGeckoでよく

let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;

 されてるものはgecko/toolkit/modules/Promise.jsmで実装されていて、コンテンツ側で使うものはgecko/dom/promiseにいるみたいです。

 まだ整理されてないだけかもしれませんが、こういうこともあるんですね。

[イベント情報]Creators Meetup 16で登壇してきました

 藪下@2課のガジェオタです。

 去る5/17にCreators Meetup 16で登壇してきました。

第16回Creators MeetUp開催しました – DSLAB
http://lab.designsatellites.jp/?p=2256

 今回はFirefox Developers Conference 2014 in Kyotoで講演した内容を、もろもろの手順の説明を端折って短くした内容で講演しました。
 途中ミスもあって焦りましたが楽しんでいただけたようなのでホッとしました。
 上記まとめにビデオもありますのでぜひごらんください。

[Firefox OS][イベント情報]中国Firefox OS勉強会 1stに登壇します!

 藪下@2課のガジェオタです。

 5/31に広島で開催される中国Firefox OS勉強会 1stに登壇することになりました。

中国Firefox OS勉強会 1st
http://atnd.org/events/50732

 今回はMozilla Japanの清水さんとコラボでFirefox OSのアーキテクチャを概観するセッションを担当します。
 清水さんのwebアプリや開発ツールの話から広い話題に対応できると思いますので、お近くの方はぜひご参加ください。

[Firefox OS][イベント情報]FxOSコードリーディングミートアップ#7を開催します

 藪下@2課のガジェオタです。

 FxOSコードリーディングミートアップ#7を開催します。

http://atnd.org/events/51175

 そろそろいろいろ読んできて話したいことがたまってきた人もいると思うので、今回はアンカンファレンスでお送りします。
 アンカンファレンスというのは、あらかじめ時間だけ決まった枠を自由にとって話す形式の勉強会です。
 ちょっと話したいから10分だけとか、思いのたけを存分に語りたいから30分など、話したいだけ枠を取って行ってください。
 今回のアンカンファレンス概要は

  • 一枠10分
    • おひとり様何枠でも取り放題
    • ただし早い者勝ち
  • お題
    • 僕の/私のコードの読み方
    • こんなところ読んでみた
    • こんなの知りたいけどどこ読むの?
    • とにかく俺の話を聞け

 となってます。枠がほしい方は当日までに@aoi_nagatsuki、藪下のFBまでお知らせいただくか、当日スタッフにお声掛けください。話したいことがある方々ぜひどうぞ!
 もちろんいつものように読みたいだけの方も大歓迎ですよ!

[Firefox OS][WebAPI] Idle API読んでみた

 藪下@2課のガジェオタです。

 世間がFirefox 29とZTE Open CとFirefox OS v1.3で賑わっているなかどこふく風でAPIの実装を読んでみたお話です。

 前回addIdleObserverが見えないと書いたのですが、geckoのソースコードを覗いてみたら実装されてるっぽいです。

http://wiki.mozilla.org/WebAPI/IdleAPI

 ここにも書いてある通りaddIdleObserverはNavigatorの下にあるのでNavigatorを見てみます。
 まずはwebidlですね。

http://reading.fxos.org/source/xref/B2G/gecko/dom/webidl/Navigator.webidl#167

  /**
   * Navigator requests to add an idle observer to the existing window.
   */
  [Throws, Func="Navigator::HasIdleSupport"]
  void addIdleObserver(MozIdleObserver aIdleObserver);

  /**
   * Navigator requests to remove an idle observer from the existing window.
   */
  [Throws, Func="Navigator::HasIdleSupport"]
  void removeIdleObserver(MozIdleObserver aIdleObserver);

 [Func]属性がついてますね。Navigator::HasIdleSupportがtrueでないと見えないということを示しています。

 webidlについては以下のページに書かれています。全訳されてませんが[Func]属性の部分は訳しておきました。

 HasIdleSupportを見てみます。

http://reading.fxos.org/source/xref/B2G/gecko/dom/base/Navigator.cpp#2049

/* static */
bool
Navigator::HasIdleSupport(JSContext*  /* unused */, JSObject* aGlobal)
{
  if (!nsContentUtils::IsIdleObserverAPIEnabled()) {
    return false;
  }

  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  return CheckPermission(win, "idle");
}

 nsContentUtils::IsIdleObserverAPIEnabled()とCheckPermission(win, “idle”)に依存してるのでそれぞれ見ていきます。

http://reading.fxos.org/source/xref/B2G/gecko/content/base/public/nsContentUtils.h#1837

  /**
   * Returns true if the idle observers API is enabled.
   */
  static bool IsIdleObserverAPIEnabled() { return sIsIdleObserverAPIEnabled; }

 sIsIdleObserverAPIEnabledが設定されているところを探します。

http://reading.fxos.org/source/xref/B2G/gecko/content/base/src/nsContentUtils.cpp#434

  sIsIdleObserverAPIEnabled = Preferences::GetBool("dom.idle-observers-api.enabled", true);

 ということで “dom.idle-observers-api.enabled” がtrueかどうかがnsContentUtils::IsIdleObserverAPIEnabled()の結果です。

 次にCheckPermission(win, “idle”)を追います。

http://reading.fxos.org/source/xref/B2G/gecko/dom/base/Navigator.cpp#1789

/* static */
bool
Navigator::CheckPermission(nsPIDOMWindow* aWindow, const char* aType)
{
  if (!aWindow) {
    return false;
  }

  nsCOMPtr<nsIPermissionManager> permMgr =
    services::GetPermissionManager();
  NS_ENSURE_TRUE(permMgr, false);

  uint32_t permission = nsIPermissionManager::DENY_ACTION;
  permMgr->TestPermissionFromWindow(aWindow, aType, &permission);
  return permission == nsIPermissionManager::ALLOW_ACTION;
}

 ということでパーミッションがALLOW_ACTIONかDENY_ACTIONかで見ているようなので設定しているところを探します。

http://reading.fxos.org/source/xref/B2G/gecko/dom/apps/src/PermissionsTable.jsm#209

                           "idle": {
                             app: DENY_ACTION,
                             privileged: DENY_ACTION,
                             certified: ALLOW_ACTION
                           },

 あれ、これなんか見たことあると思ったらMDNとmxrに書いてありました。

https://developer.mozilla.org/ja/docs/Web/Apps/App_permissions

関連情報
Firefox コード内では 許可設定一覧表 にすべての許可設定が定義されています。

https://mxr.mozilla.org/mozilla-central/source/dom/apps/src/PermissionsTable.jsm#36

 というわけでcertifiedのアプリにidleパーミッションをつけないといけないみたいです。
# MDNにもwikimoにも必要って書いてないし! ないし!

 サンプルコードを更新しました。

https://github.com/aoitan/gcg_labo/tree/master/api_reading/20140323_using_Idle_API

 マニフェストにpermissions属性を加えてます。もちろん許可するのはidleです。
 あとCSPに怒られたのでスクリプトをidle_test.jsに抜き出しました。

  "permissions": {
    "idle": {}
  },

 ビルドして動かしてみましょう。

Screenshot_from_2014-05-12 01_22_39

 とまあ動いたのですが、HasIdleSupportを見る限りパーミッションが設定されてないとやっぱりAPIが見えないはずなので、デスクトップとかfor Android的にはおかしいです。
# wikimoにはデスクトップとAndroidはデフォルト有効と書いてます。
https://wiki.mozilla.org/WebAPI
 これビルド対象合わせでパーミッションチェックしないといけない気がするのでちょっとパッチ書いてみようかと思います。

 今回Idle APIを追いかけましたが、実は書いた以上にソースコードを追いかけました。
 パーミッションマネージャを割と掘り下げたので機会があれば記事にします。お楽しみに。

[Firefox OS][Bing]Firefox OS向けにBingアプリが出てきました

 藪下@2課のガジェオタです。

 Firefox MarketplaceにBing検索アプリが出て来ました。

Bing Launches On Firefox OS, Does It Matter?
http://searchengineland.com/bing-launches-firefox-os-matter-191110

 ちょろっとエミュレータでMarketplaceを覗いて見たらしっかりトップにありました。
 ちょっと動かしてスクショ撮ってみました。

Firefox Marketplaceの様子

Screenshot_from_2014-05-13 09:42:50

Screenshot_from_2014-05-13 09:43:23

起動画面と初期画面

Screenshot_from_2014-05-13 09:45:43

Screenshot_from_2014-05-13 09:46:01

検索の様子

Screenshot_from_2014-05-13 09:47:00

Screenshot_from_2014-05-13 09:47:20

 MSさんもFirefox OS意識してたんですね。
 新興国で増えていくインターネットアクセスの中で存在感出したいってことなんですかね。

[Tizen]ロシアとインドでTizen端末が出るかも?

 藪下@2課のガジェオタです。

 Tizen端末がロシアとインドで出るとのことです。

Samsung、Tizenスマホをロシアとインドに投入予定との報道
http://itpro.nikkeibp.co.jp/article/NEWS/20140512/555983/?top_tl1

 ロシアは日本のバンドも入る端末になりそうな予感がなきにしもですね。

 グローバル版が出るかまだわからないですが出るようならちょっと入手を考えて見たり見なかったり。
 スペックがわからないのでまだ手が出る感じじゃないですけど。。。

[Firefox OS] Firefox OS v1.3が出てきました

 藪下@2課のガジェオタです。

 Firefox OSのv1.3がパートナーにリリースされました。

モジラ、「Firefox OS 1.3」をリリース–モバイルゲームの質の向上を目指す
http://japan.cnet.com/news/service/35047636/

 以前シミュレータがstableになったことをお知らせしてたんですが、実機でもv1.3がstableになったってことですね。
 端末をお持ちの方は近日中にアップデートが来ると思うのでわくわくですね。

[Firefox OS][WebAPI]Page Visibility APIの使い方 – onResumeの代わりにできること

 藪下@2課のガジェオタです。

 Firefox Developers Conference 2014 in Kyotoの準備とかその間に滞った作業のリカバリでバタバタしていたのでご無沙汰していました。今週から平常運転に戻します。

 FxOSコードリーディングの運営をお手伝いいただいているひらとりさんとノマドワーキングしてたら面白い質問をもらったので調べてみました。

Q&A

Q.Firefox OSのアプリにはAndroidのライフサイクルでいうところのonResumeがないけどアプリから離れて戻ってきた時に動作したい場合どうしたらいいの?

A.Page Visibility APIを使いましょう。

What is Page Visibility API?

 Page Visibility APIはSafari発祥みたいですね。Page Visibility APIではページが見えているかいないかを知ることができます。
 onblurとかonfocus見たいなハックは見たことありますよね。これらはフォーカスが外れたとき、フォーカスを得たときを検知してくれますがページの可視状態と必ずしも一致しません。Page Visibility APIだとちゃんと見えなくなったり見えるようになったときにvisibilitychangeイベントを呼んでくれるので正しい解決だといえます。
 gaiaだとブラウザやSMS、時計、カメラなどいろいろなところで使っています。

How to

 使い方を見ていきます。

visibilitychangeイベント

 visibilitychangeイベントはDOMイベントです。なのでいつものaddEventListenerでイベントハンドラを登録します。

document.addEventListener("visibilitychange", handler);

function handler() {
    // なんかなんか
}

document.hiddenメソッド

 hiddenメソッドはページが見えていない場合trueを、そうでない場合falseを返します。

if (document.hidden) {
    // 不可視状態
} else {
    // 可視状態
}

document.visibilityStateメソッド

 visibilityStateメソッドは可視性の状態を表す文字列を返します。

  • visible
    • ページは見えています。Page Visibility APIでの「見えている」というのは別のタブを表示していない、最小化されていないということなので、デスクトップなどでは別のウィンドウが上に乗っていてもvisibleになることがあります。
  • hidden
    • ページは見えていません。前述の通りタブの状態や最小化の状態のことを言っているのでhiddenであるということは別のタブを表示しているか最小化されているということです。
  • prerender
    • ページは見えていません。ページはまだプリレンダリングされただけでユーザに見えるように表示されていません。
    • 他の状態からprerenderになることはありません。
if (document.visibilityState == "visible") {
    // 可視状態
} else if (document.visibilityState == "hidden") {
    // 不可視状態
} else if (document.visibilityState == "prerender") {
    // プリレンダリング状態
}

Try on Firefox OS

 Firefox OS上でも試してみます。例のごとくサンプルコードは以下のURLです。

  • https://github.com/aoitan/gcg_labo/tree/master/api_reading/20140430_using_Page_visibility_API

 How toのところで示した使い方で画面に何かしら表示するようにしただけです。
 マニフェストは何も特別なことをしていないので省略します。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Using Page Visibility API Sample</title>
    <script src="index.js"></script>
  </head>
  <body>
    <ul id="output"></ul>
  </body>
</html>
init();

function init() {
  document.addEventListener("visibilitychange", handler);
  var output = document.getElementById('output');
  output.appendChild(outputVisibilityState());
}

function handler() {
  var output = document.getElementById('output');
  output.appendChild(outputVisibilityChange());

  var childUl = document.createElement('ul');
  childUl.appendChild(outputHidden());
  childUl.appendChild(outputVisibilityState());

  output.appendChild(childUl);
}

function outputVisibilityChange() {
  var li = document.createElement('li');
  li.innerHTML = 'event: visibilitychange';
  return li;
}

function outputHidden() {
  var li = li = document.createElement('li');
  if (document.hidden) {
    // 不可視状態
    li.innerHTML = 'document.hidden = hidden';
  } else {
    // 可視状態
    li.innerHTML = 'document.hidden = visible';
  }
  return li;
}

function outputVisibilityState() {
  var li = document.createElement('li');
  if (document.visibilityState == "visible") {
    // 可視状態
    li.innerHTML = 'document.visibilityState = visible';
  } else if (document.visibilityState == "hidden") {
    // 不可視状態
    li.innerHTML = 'document.visibilityState = hidden';
  } else if (document.visibilityState == "prerender") {
    // プリレンダリング状態
    li.innerHTML = 'document.visibilityState = prerender';
  }
  return li;
}

 ホーム押したりホーム長押しから戻ったりしてみました。

using_page_visibility_api

 なんだか検知できてますね!

さいごに

 これでAndroidのライフサイクルイベントをすべて賄えるわけではないんですが、既存のAndroidアプリを移植する上で引っかかる部分の一部は解決できるのではないでしょうか。