前回は、
- TEMPORARYファイルシステムのファイル一覧を取得し、
画面に表示 - Camera APIで作成したファイルをPERSISTENTファイルシステムに移動
- PERSISTENTファイルシステムに、
画像ファイルの詳細データを格納したテキストファイルを作成
今回も前回と同様、
TEMPORARYファイルシステムのファイル一覧を取得(iOS/Android)
前回紹介したFile APIのオブジェクト、
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5 <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
6 <title>File API Test (2)</title>
7 </head>
8 <body>
9 <div class="app">
10 <h1>File API Test</h1>
11 <ul id="tempfs_fileList"></ul>
12 </div>
13 <script type="text/javascript" src="cordova-2.0.0.js"></script>
14 <script type="text/javascript">
15 document.addEventListener('deviceready', init, false);
16 function init() {
17 // TEMPORARYファイルシステムを取得
18 window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, getFilesFromDirectory, fail);
19 }
20
21 function getFilesFromDirectory(fileSystem) {
22 // FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されている
23 var directoryEntry = fileSystem.root;
24
25 // DirecotryEntryオブジェクトのcreateReaderメソッドを使い、
26 // ディレクトリ内のファイルを読み込むためのDirectoryReaderオブジェクトを作成
27 var directoryReader = directoryEntry.createReader();
28
29 // DirectoryReaderオブジェクトのreadEntriesメソッドを使い、
30 // ディレクトリ内のエントリを読み込み、コールバック関数に配列として渡す
31 directoryReader.readEntries(putFileName, fail);
32 }
33
34 function putFileName(entries) {
35 // ディレクトリ内のエントリがFileEntryオブジェクトまたは
36 // DirectoryEntryオブジェクトとして配列で渡される
37 for ( index = 0; index < entries.length; index++ ) {
38 // ファイル名を格納する DOM を作成
39 var listItem = document.createElement('li');
40 listItem.textContent = entries[index].name;
41
42 // 作成した DOM を <ul id="tempfs_fileList"></ul> に挿入
43 document.getElementById('tempfs_fileList').appendChild(listItem);
44 }
45 }
46
47 function fail(error) {
48 // エラーについては http://docs.phonegap.com/en/2.0.0/cordova_file_file.md.html#FileError を参照
49 alert('エラーが発生しました。エラーコード: ' + error.code);
50 }
51 </script>
52 </body>
53 </html>
このサンプルコードでは、
![iOSシミュレータで実行 iOSシミュレータで実行](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH400_001.jpg)
![Androidエミュレータで実行 Androidエミュレータで実行](/assets/images/dev/serial/01/phonegap2/0006/002.jpg)
リスト1サンプルコードで行っている処理の流れは次のとおりです。
- requestFileSystemでTEMPORARYファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、
TEMPORARYファイルシステムのルートディレクトリの情報 (DirectoryEntryオブジェクト) を取得 - DirectoryEntryオブジェクトのcreateReaderメソッドを用いて、
DirectoryReaderオブジェクトを作成 - DirectoryReaderオブジェクトのreadEntriesメソッドを用いて、
ディレクトリ内のファイル/ディレクトリエントリを読み込む - readEntriesメソッドから渡されたFileEntry/
DirectoryEntryの配列を受け取り、 ファイル名を<li>要素で列挙
第4回の記事を参照し、
18行目のrequestFileSystemメソッドは、
18 window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, getFilesFromDirectory, fail);
FileSystemオブジェクトのrootプロパティには、
22 // FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されている
23 var directoryEntry = fileSystem.root;
24
25 // DirecotryEntryオブジェクトのcreateReaderメソッドを使い、
26 // ディレクトリ内のファイルを読み込むためのDirectoryReaderオブジェクトを作成
27 var directoryReader = directoryEntry.createReader();
DirectoryReaderオブジェクトには1つだけメソッドが用意されています。ディレクトリ内のエントリを読み込むメソッド--readEntriesメソッドを用いて、
29 // DirectoryReaderオブジェクトのreadEntriesメソッドを使い、
30 // ディレクトリ内のエントリを読み込み、コールバック関数に配列として渡す
31 directoryReader.readEntries(putFileName, fail);
あるディレクトリ内にディレクトリが1つ、
[<DirectoryEntry>, <FileEntry>, <FileEntry>, <FileEntry>]
putFileName関数はDirectoryEntry/
34 function putFileName(entries) {
35 // ディレクトリ内のエントリがFileEntryオブジェクトまたは
36 // DirectoryEntryオブジェクトとして配列で渡される
37 for ( index = 0; index < entries.length; index++ ) {
38 // ファイル名を格納する DOM を作成
39 var listItem = document.createElement('li');
40 listItem.textContent = entries[index].name;
41
42 // 作成した DOM を <ul id="tempfs_fileList"></ul> に挿入
43 document.getElementById('tempfs_fileList').appendChild(listItem);
44 }
45 }
fail関数はFile APIでファイルを操作している場合にエラーが起こった際に呼び出される関数です。FileErrorオブジェクトを受け取り、
// cordova-2.0.0.js 2180-2195
// File error codes
// Found in DOMException
FileError.NOT_FOUND_ERR = 1;
FileError.SECURITY_ERR = 2;
FileError.ABORT_ERR = 3;
// Added by File API specification
FileError.NOT_READABLE_ERR = 4;
FileError.ENCODING_ERR = 5;
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
FileError.INVALID_STATE_ERR = 7;
FileError.SYNTAX_ERR = 8;
FileError.INVALID_MODIFICATION_ERR = 9;
FileError.QUOTA_EXCEEDED_ERR = 10;
FileError.TYPE_MISMATCH_ERR = 11;
FileError.PATH_EXISTS_ERR = 12;
Camera APIで作成したファイルをPERSISTENTファイルシステムに移動(iOS/Android)
Camera APIで作成されるファイルを、
ソースコードは次のとおりです。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5 <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
6 <title>File API Test (3)</title>
7 </head>
8 <body>
9 <div class="app">
10 <h1>File API Test</h1>
11 <input type="button" value="Camera API" id="camera">
12 </div>
13 <script type="text/javascript" src="cordova-2.0.0.js"></script>
14 <script type="text/javascript">
15 var persistentDirectoryEntry;
16 document.addEventListener('deviceready', init, false);
17
18 function init() {
19 // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
20 window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);
21
22 document.getElementById('camera').addEventListener('click', camera, false);
23 }
24
25 function getPersistentDirectoryEntry(fileSystem) {
26 persistentDirectoryEntry = fileSystem.root;
27 }
28
29 function camera() {
30 sourceType = Camera.PictureSourceType.PHOTOLIBRARY;
31 if ( 'Android' === device.platform ) {
32 sourceType = Camera.PictureSourceType.CAMERA;
33 }
34 navigator.camera.getPicture(getPictureSuccess, failCamera,
35 {
36 quality: 50,
37 destinationType: Camera.DestinationType.File_URI,
38 sourceType: sourceType
39 });
40 }
41
42 function getPictureSuccess(uri) {
43 // Camera APIから渡されるファイルパスと、resolveLocalFileSystemURIメソッドを用いて
44 // TEMPORARYファイルシステムに作成された画像ファイルのFileEntryオブジェクトを取得する
45 window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);
46 }
47
48 function moveToPersistent(fileEntry) {
49 // あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトと
50 // resolveLocalFileSystemURIメソッドで取得したFileEntryオブジェクトを用いて、ファイルをPERSISTENTに移動
51 fileEntry.moveTo(persistentDirectoryEntry, fileEntry.name, moveToSuccess, failFS);
52 }
53
54 function moveToSuccess(fileEntry) {
55 alert('画像ファイル「' + fileEntry.name + '」を移動しました。\n' + fileEntry.fullPath);
56 }
57
58 function failCamera(message) {
59 alert('カメラ操作に失敗しました。\n' + message);
60 }
61
62 function failFS(error) {
63 alert('ファイルシステム操作に失敗しました。\nエラーコード: ' + error.code);
64 }
65 </script>
66 </body>
67 </html>
まずはiOSで実行してみましょう。iOSシミュレータのアプリケーション上でボタンをクリックすると、
![アルバムから画像を選択 アルバムから画像を選択](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH400_003.jpg)
画像を選択すると、
![ファイルの移動に成功するとアラートでその旨が通知される ファイルの移動に成功するとアラートでその旨が通知される](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH280_004.jpg)
![ターミナルでPERSISTENT(Documents/以下)にファイルが移動されていることを確認 ターミナルでPERSISTENT(Documents/以下)にファイルが移動されていることを確認](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH800_005.jpg)
なお、
![「Application supports iTunes file sharing」を追加し、iTunesファイル共有を有効に 「Application supports iTunes file sharing」を追加し、iTunesファイル共有を有効に](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH800_006.jpg)
続けてAndroidで動作を確認してみます。Androidエミュレータのアプリケーション上でボタンをクリックし、
![撮影した写真がPERSISTENT(/mnt/sdcard以下)に移動されていることを確認 撮影した写真がPERSISTENT(/mnt/sdcard以下)に移動されていることを確認](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH280_007.jpg)
![EclipseのDDMS、File Explorerで/mnt/sdcard以下に画像ファイルが移動されていることを確認 EclipseのDDMS、File Explorerで/mnt/sdcard以下に画像ファイルが移動されていることを確認](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH800_008.jpg)
リスト1のサンプルコードで行っている処理の流れは次のとおりです。
- requestFileSystemでPERSISTENTファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、
PERSISTENTファイルシステムのルートディレクトリの情報 (DirectoryEntryオブジェクト) を取得 - navigator.
camera. getPictureを用いて、 iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成 - destinationTypeにCamera.
DestinationType. File_ URIを指定しているので、 コールバック関数にはファイルパスが渡される - ファイルパスとresolveLocalFileSystemURIを用いて、
作成したファイルのFileEntryオブジェクトを取得 - FileEntryオブジェクトのmoveToメソッドと、
2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動
15行目でまずグローバル変数persistentDirectoryEntryを宣言します。アプリケーション起動時に、
19 // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
20 window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);
…
25 function getPersistentDirectoryEntry(fileSystem) {
26 persistentDirectoryEntry = fileSystem.root;
27 }
45行目ではnavigator.
45 window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);
resolveLocalFileSystemURIで取得したFileEntryオブジェクトと、
51 fileEntry.moveTo(persistentDirectoryEntry, fileEntry.name, moveToSuccess, failFS);
PERSISTENTファイルシステムに、画像ファイルの詳細データを格納したテキストファイルを作成(iOS/Android)
File API Test (3)のソースコード
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5 <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
6 <title>File API Test (4)</title>
7 </head>
8 <body>
9 <div class="app">
10 <h1>File API Test</h1>
11 <input type="button" value="Camera API" id="camera">
12 <img id="image" style="display: none;">
13 <pre id="result"></pre>
14 </div>
15 <script type="text/javascript" src="cordova-2.0.0.js"></script>
16 <script type="text/javascript">
17 var persistentDirectoryEntry;
18 document.addEventListener('deviceready', init, false);
19
20 function init() {
21 // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
22 window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);
23 document.getElementById('camera').addEventListener('click', camera, false);
24 }
25
26 function getPersistentDirectoryEntry(fileSystem) {
27 persistentDirectoryEntry = fileSystem.root;
28 }
29
30 function camera() {
31 sourceType = Camera.PictureSourceType.PHOTOLIBRARY;
32 if ( 'Android' === device.platform ) {
33 sourceType = Camera.PictureSourceType.CAMERA;
34 }
35 navigator.camera.getPicture(getPictureSuccess, failCamera,
36 {
37 quality: 50,
38 destinationType: Camera.DestinationType.File_URI,
39 sourceType: sourceType
40 });
41 }
42
43 function getPictureSuccess(uri) {
44 // Camera APIから渡されるファイルパスと、resolveLocalFileSystemURIメソッドを用いて
45 // TEMPORARYファイルシステムに作成された画像ファイルのFileEntryオブジェクトを取得する
46 window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);
47 }
48
49 function moveToPersistent(fileEntry) {
50 filename = new Date().getTime() + '.jpg';
51
52 // あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトと
53 // resolveLocalFileSystemURIメソッドで取得したFileEntryオブジェクトを用いて、ファイルをPERSISTENTに移動
54 fileEntry.moveTo(persistentDirectoryEntry, filename, moveToSuccess, failFS);
55 }
56
57 function moveToSuccess(fileEntry) {
58 // Fileオブジェクトを作成
59 fileEntry.file(readImageInfo, failFS);
60 }
61
62 function readImageInfo(file) {
63 // Imageオブジェクトを取得し、srcにFileオブジェクトのパス情報を代入
64 var imageObj = document.getElementById('image');
65 imageObj.src = file.fullPath;
66
67 imageObj.onload = function() {
68 // 画像のロード完了後、<pre id="result"></pre> に画像情報を書き込み
69 document.getElementById('result').textContent =
70 'width: ' + this.naturalWidth + '\n' +
71 'height: ' + this.naturalHeight + '\n' +
72 'name: ' + file.name + '\n' +
73 'type: ' + file.type + '\n' +
74 'lastModifiedDate: ' + file.lastModifiedDate + '\n' +
75 'size: ' + file.size;
76
77 // PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて
78 // getFileメソッドを使用して、新規にファイルを作成
79 persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);
80 }
81 }
82
83 function newFileEntry(fileEntry) {
84 // 新規に作成したファイルのFileEntryオブジェクトにおいて
85 // createWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成
86 fileEntry.createWriter(writingImageInfo, failFS);
87 }
88
89 function writingImageInfo(fileWriter) {
90 // FileWriterオブジェクトを受け取り、シークポイントを先頭に移動
91 fileWriter.seek(0);
92
93 // <pre id="result"></pre> の中身を書き込み
94 fileWriter.write(document.getElementById('result').textContent);
95
96 // 書き込み完了時にアラートを表示
97 fileWriter.onwriteend = function() {
98 alert('画像の情報を' + fileWriter.fileName + 'に書き出しました。');
99 }
100 }
101
102 function failCamera(message) {
103 alert('カメラ操作に失敗しました。\n' + message);
104 }
105
106 function failFS(error) {
107 alert('ファイルシステム操作に失敗しました。\nエラーコード: ' + error.code);
108 }
109 </script>
110 </body>
111 </html>
まずはiOSで実行してみましょう。アルバムから画像を選択し、
続けて、
![選択した画像の情報を、画像ファイルと同名のテキストファイルに書き込み 選択した画像の情報を、画像ファイルと同名のテキストファイルに書き込み](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH280_009.jpg)
![pre要素内に画像情報を表示 pre要素内に画像情報を表示](/assets/images/dev/serial/01/phonegap2/0006/010.jpg)
![選択した画像の情報を、画像ファイルと同名のテキストファイルに書き込み ターミナルのcatコマンドでテキストファイルの中身を確認。File APIでファイルの書き込みに成功していることがわかる](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH800_011.jpg)
同様に、
![撮影した画像の情報を、画像ファイルと同名のテキストファイルに書き込み 撮影した画像の情報を、画像ファイルと同名のテキストファイルに書き込み](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH280_012.jpg)
![コマンドプロンプトでadb shellでSSH接続を行い、catコマンドでテキストファイルの中身を確認 コマンドプロンプトでadb shellでSSH接続を行い、catコマンドでテキストファイルの中身を確認](/assets/images/dev/serial/01/phonegap2/0006/thumb/TH800_013.jpg)
AndroidではFileオブジェクトのMIME取得に成功していますが、
サンプルコードで行っている処理の流れは次のとおりです。7以降の処理が新規に追加されています。
- requestFileSystemでPERSISTENTファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、
PERSISTENTファイルシステムのルートディレクトリの情報 (DirectoryEntryオブジェクト) を取得 - navigator.
camera. getPictureを用いて、 iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成 - destinationTypeにCamera.
DestinationType. File_ URIを指定しているので、 コールバック関数にはファイルパスが渡される - ファイルパスとresolveLocalFileSystemURIを用いて、
作成したファイルのFileEntryオブジェクトを取得 - FileEntryオブジェクトのmoveToメソッドと、
2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動 - 移動したあとのFileEntryオブジェクトのfileメソッドで、
Fileオブジェクトを作成 - Fileオブジェクトからパス情報を取得し、
Imageオブジェクトのsrc属性に格納。Fileオブジェクトに格納されている情報や、 画像の幅/高さの情報を取得 - PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて、
getFileメソッドで新規にファイルを作成 - 新規に作成したファイルのFileEntryオブジェクトにおいて、
createWriterメソッドでFileWriterオブジェクトを作成 - ファイルに8で取得した情報を書き込み。アラートで結果を表示
ファイルの移動成功時に呼び出されるmoveToSuccess関数から見てみましょう。moveToメソッドではファイルの移動成功時に、
57 function moveToSuccess(fileEntry) {
58 // Fileオブジェクトを作成
59 fileEntry.file(readImageInfo, failFS);
60 }
FileEntryのfileメソッドを用いて、
62 function readImageInfo(file) {
63 // Imageオブジェクトを取得し、srcにFileオブジェクトのパス情報を代入
64 var imageObj = document.getElementById('image');
65 imageObj.src = file.fullPath;
66
67 imageObj.onload = function() {
68 // 画像のロード完了後、<pre id="result"></pre> に画像情報を書き込み
69 document.getElementById('result').textContent =
70 'width: ' + this.naturalWidth + '\n' +
71 'height: ' + this.naturalHeight + '\n' +
72 'name: ' + file.name + '\n' +
73 'type: ' + file.type + '\n' +
74 'lastModifiedDate: ' + file.lastModifiedDate + '\n' +
75 'size: ' + file.size;
76
77 // PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて
78 // getFileメソッドを使用して、新規にファイルを作成
79 persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);
80 }
81 }
Imageオブジェクトのsrc属性に、
その後、
79 persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);
第1引数にはファイル名を指定しています。同名のファイルになるように、
第2引数にはFlagsオブジェクトで動作を指定します。各プロパティ値については次のとおりです。
- create
- trueを指定した場合、
ファイルやディレクトリが存在しなければ新規に作成します - exclusive
- trueを指定した場合、
ディレクトリが存在しなければ指定した階層まで再帰的に作成します
Flagsオブジェクトのcreateプロパティにtrueを指定していますので、
83 function newFileEntry(fileEntry) {
84 // 新規に作成したファイルのFileEntryオブジェクトにおいて
85 // createWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成
86 fileEntry.createWriter(writingImageInfo, failFS);
87 }
FileWriterオブジェクトの作成に成功した場合、
FileWriterオブジェクトのseekメソッドでシークポイントを先頭に移動し、
89 function writingImageInfo(fileWriter) {
90 // FileWriterオブジェクトを受け取り、シークポイントを先頭に移動
91 fileWriter.seek(0);
92
93 // <pre id="result"></pre> の中身を書き込み
94 fileWriter.write(document.getElementById('result').textContent);
95
96 // 書き込み完了時にアラートを表示
97 fileWriter.onwriteend = function() {
98 alert('画像の情報を' + fileWriter.fileName + 'に書き出しました。');
99 }
100 }
FileWriterオブジェクトに用意されているメソッドは次のとおりです。(使い方のfileWriterは、
メソッド名 | 内容 |
---|---|
使い方 | |
abort | ファイルへの書き込みを中止します。 |
fileWriter. |
|
seek | シークポインタをバイト単位で指定します。 |
fileWriter. |
|
truncate | 指定された長さになるように、 |
fileWriter. |
|
write | ファイルにデータを書き込みます。エンコーディングはUTF-8です。 |
fileWriter. |
次回は、