きままなたぐりぶろ(日記)

ピンときたネタ・イベント(IT、旅行、日常etc)があれば書いていこうと思います。

FirefoxOSを試した:SDカードを利用する

2013年02月14日 00時22分48秒 | 技術
前回にひき続いてFirefoxOSを試した話。

実機はGalaxy Nexusしか試せるものがないので、あと頼りになるのは
Firefox OS Simulatorだ。
すでに設定が織り込み済みなのでハードの設定的なことはできないようだが、それ以外は
ほぼすべてSimulatorで確認できそうなのでこれからも活用する。

※今回SDカード読み書きを試したテストアプリはこちらです。
他のテスト内容が入っていますが気にしないでください。
ご興味がありましたらお試しください。ものすごく簡単なレベルのサンプルです。

test-my02.zip


SDカードを試す


今回はSDカードを試した。これが使えるのと使えないのでは大違いだ。
AndroidはSDカードスロットありなしバラバラだが、内蔵ストレージとしてユーザーが自由に使える領域が
必ず確保されている。

iOSは共通的なストレージ領域はなく、あくまですべてひっくるめての容量(だったはず)。
ちなみにWP8もiOSと同じ管理方法のようだ。
iOSとWP8はアプリごとに自由に使える領域が決められているようで、ファイラー・ファイルエクスプローラ系の
アプリを使うとよく分かるだろう。iOSではiTunesを介してファイラーアプリの中に自由にファイルを
放り込み、そのアプリ内で一覧管理し、ときにはファイルをプレビューしたりする。
そのアプリに放り込んだファイルは別のファイラーアプリでは見られない。WP8もいくつかのファイラーで
試したら同じ現象になったので、この2つのOSはユーザーやアプリが自由に、しかも共通的に使えるストレージ領域を
持っていないことになる。

Firefox OSではどうなのかと不安になったところから今回の調査は始まる。
公式サイトなどを見ているとSDカードを使えることはわかっていたのだが、それがどういう管理なのかまではわからなかった。
もしiOSやWP8のようにアプリごとの領域の管理だったら悲惨なことになるなと一抹の不安を感じていた。


今回試した実機、Galaxy Nexus(用のROM)はSDカードが使えない仕様のため、Firefox OSで言うところの
メディアストレージが使えない状態だった。
そうなると何が困るかというと・・・

・スクリーンショットが保存できない
・SDカードを利用するアプリが使えない

2番めはかなり大事。
色々試していて、一昨日はSDカードを読み取るオブジェクトが用意されてないんじゃないかとか、
MediaDBという写真、音楽、動画を統合的に扱えるDBがあるのでそれを介してしか
SDカードを使えないんじゃないかとかいろいろ悩んで調べていたが、それが次の一文で解決した。
確認したのはgaia/test_apps/geoloc/js/geoloc.js内にあったオブジェクトのメソッド。

var storage = navigator.getDeviceStorage('sdcard')

これの後にstorage.addNamedという一文もあったので、これはSDカードにファイルを書き込んでいると容易に想像付いた。
更に解析し、テストアプリを作ってみた。


SDカードをテストした


テストアプリのソースは本記事の上に用意しているリンクからダウンロードできるので、ご興味があれば
参考にしてみてください。非常にシンプルなサンプルです。

そもそもシステム上、ハードウェア上大事な機能を使う場合、AndroidやiOSと同じように、使うための許可、権限を
宣言しておく必要がある。それがmanifest.webappというJSON形式のファイルだ。

そこの中に "permissions"という項目を定義できる。permissionsの配下に
"device-strage:sdcard"することで、自身のアプリでSDカードを扱えるようになる。
他にも次のような定義がある。
device-strage:pictures
device-strage:videos
device-strage:music
それぞれ、それらのメディアファイルを扱うのに特化した権限だ。安全な配慮ということだ。
ちなみにほとんどの権限は"type"が"privileged"か、"certified"でないと効果がないようだ。

今回はmanifest.webappに次のように書き込んだ。

...
"type" : "privileged",
"permissions":{
"device-storage:sdcard": {
"access" : "readcreate"
}
},
...

これで下準備はできた。

次にJavaScriptファイル。FirefoxOS用のGeckoには、navigatorオブジェクトにいろいろ専用のプロパティや
メソッドが追加されている。今回使うnavigator.getDeviceStorageもそうだ。

navigator.getDeviceStorageメソッドが返すのはDeviceStorageオブジェクトだ。
次を参考にしてほしい。WebAPI/DeviceStorageAPI - MozillaWiki

getDeviceStorageメソッドにはpermissionsで定義したdevice-strage:****の****の部分を引数として渡せる。
今回はSDカードを使うので"sdcard"を渡す。

ファイルを書き込む


ファイルを書き込む、つまりファイルを作成するので、permissions内、device-storage:sdardのaccessにはreadcreateか、createonlyが必須だ。
今回はファイルを書き込んで、読むアプリなのでreadcreateを使った。
(ちなみにreadwriteではSecurityErrorが出てファイルを作成できないので注意!)


function btn_dir_clicked() {
var storage = navigator.getDeviceStorage('sdcard');
if (!storage) {
console.log("No storage available!");
console.log(file);
alert("No storage available!");
return false;
}
alert("storage available!");
var blob = new Blob(["file test"], {type: 'text/plain'});
var fname = "testfile" + ".txt";
var svtxt = storage.addNamed(blob,fname);
svtxt.onsuccess = function() {
alert("Successfully saved " + fname);
};
svtxt.onerror = function() {
alert("Error while saving to " + fname + ": " + this.error.name);
};
return true;
}

getDeviceStorageで取得して、もしSDカードがなければエラーとするところは特に問題ないと思う。
ポイントとなるのは、Blobオブジェクトを作成する部分だ。
DeviceStorageオブジェクトのaddNamedでファイルを作成するのだが、その際単にFileオブジェクトや文字列型では
書き込めない
。Blobオブジェクトでファイルの内容と、ファイルのMIMEタイプを指定して
適切にオブジェクトを作成する必要がある。
次にaddNamedメソッドを使ったら返されるDOMRequestオブジェクトを適切に処理する必要がある。
DOMRequestは非同期なものなので、onsuccessとonerrorにファンクションを指定してその中で
続ける処理を記述することになる。

これでファイルをSDカードに保存できる。また、この処理をする最中にSDカードにアクセスするがよいかというメッセージで出てくる。

これはシステム的なメッセージなので、一度トグルスイッチをRemember~にしておけば次回から
問われなくて済む。


ファイルを読み込む


次に先ほど保存したファイルを読み込んでみる。どうでも良い箇所は省略してます。

function btn_sdget_clicked() {
var storage = navigator.getDeviceStorage('sdcard');

}
var req = storage.get("testfile.txt");
req.onsuccess = function(e){
var fl = e.target.result;
alert("fl.name=" +fl.name+"\nfl.type+"+fl.type+"\nfl.size="+fl.size);
document.getElementById("dir_lst").innerHTML = "";
var flre = new FileReader();
var li = document.createElement("li");
flre.readAsText(fl);
flre.addEventListener("load",function(e) {
li.innerHTML = "file contents in storage=" + e.target.result;
document.getElementById("dir_lst").appendChild(li);
});
flre.addEventListener("error",function(e){
alert("file read error: " + e.target.error.code);
return false;
});
return true;
};

}

今回はファイル名がわかっているので固定で指定している。DeviceStorageオブジェクトには
enumerateメソッドがあるので、それを使えば再帰的にファイルを検知できるはず。それは次の機会に試してみたい。
ファイルを取得するにはgetメソッドを使う。ここには直接ファイル名を書いてOKのようだ。
getメソッドで返されるのはやはりDOMRequest。onsuccessとonerrorにファンクションを割り当てることは今回も同じ。

onsuccess、onerror内で、getメソッドの結果を得るには引数のオブジェクトを使う。(これはEventオブジェクト)
e.target.resultで結果を取得できる。
onsuccessの場合はFileオブジェクトが返される。
ここで注意したいのは、GeckoのWebAPIのページにあるFileHandleではなさそうということ。
色々試した結果、FileHandleオブジェクトのプロパティやメソッドは使えなかった。
ここで返ってくるFileオブジェクトは、HTML5で標準で規定されているFileオブジェクトだ。
したがってその後の処理の仕方は一般的な方法が使える。

今回はFileオブジェクトにあるnameやsizeで情報を取得して、その後FileReaderを使用して
テキストデータとしてファイルの中身を読み取り、表示している。
ここでのポイントは、getメソッドで返されるDOMRequestに付属するFileオブジェクトだろう。
Firefox OS用のGecko特有のオブジェクトから返されるのはHTML5標準のオブジェクトということさえ
覚えておけば、あとは一般的な処理方法が使えるので自由に扱える。
特別変わった手順を踏むことはないので、一度覚えてしまえば楽だろう。

そうしてアプリを試すと、こんな感じに画面が表示される。
1,SDカードにアクセスするか確認メッセージが出る


2,SDカードにファイルを書き込む。(メッセージは今回用のテストメッセージ)


3,SDカードからファイルを読み込む。


最後に


SDカードに書き込んでしまえばあとは他のアプリからでもそのファイルを読み取ることができるので、
ファイラー・ファイルエクスプローラ系アプリはiOS/WP8のソレよりか遥かに真価を発揮できるだろう。
今度試すWebActivityを使えば、まさにAndroid並にアプリ同士・ファイル同士の連携ができる。

ここまで試して、Firefox OSで使える保存領域はこういうことになると思う。
WebStorage/WebDatabase・・・HTML5の標準機能。ユーザーに勝手に扱われたくない大事なデータなど
DeviceStorage・・・FirefoxOS用Geckoの専用機能? 端末のストレージを扱う場合に使用する。自由に扱えるので処理は適切に。
個人的にはAndroid、iOSより馴染みやすい機能(HTML5とか一般的だし)の揃い方だと思う。


このあたり、私が調査して勝手にまとめた内容なので、正式名称や分類は公式サイト、Wikiを必ず
参考にしてください。

まだまだ試したいことはやまほどある。今回は単にSDカードが自由に扱えることがわかっただけでも良しとしたい。

コメントを投稿