SQLiteに接続する際に、テーブルが存在していなかったらファイルをcreateするAIRアプリを作成する場合、以下のコードのようなコードを書いてしまうと、アンインストールしてもファイルは削除されません。
package { import flash.data.SQLResult; import flash.data.SQLStatement; import flash.events.SQLEvent; import flash.filesystem.File; public class TestManager { private var _connection:ConnectionManager; private var arr:Object; public function TestManager() { } public function initTest():void { var file:File = File.applicationStorageDirectory.resolvePath("test.db"); var str:String = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + "original VARCHAR(10));" _connection = new ConnectionManager(); _connection.initConnection(file); _connection.execute(str, initTestHandler) } private function initTestHandler(event:SQLEvent):void { _connection.execute( "SELECT * FROM test " + "ORDER BY id desc;", selectHandler); } private function selectHandler(event:SQLEvent):void { var stmt:SQLStatement = event.currentTarget as SQLStatement; stmt.removeEventListener(SQLEvent.RESULT, arguments.callee); var result:SQLResult = stmt.getResult(); if (result.data != null) { arr = result.data; } } public function load():Object { return arr; } } }
この例では、FileクラスのapplicationStorageDirectoryプロパティを利用しています。VistaではC:Usersユーザ名AppDataRoamingアプリケーション名Local Store、XPではC:Documents and Settingsユーザ名Application Dataアプリケーション名Local Storeに出力されます。なら、AIRアプリのカレントディレクトリに出力すればいいのでは?よーし、applicationDirectoryプロパティを試してみよう。
AIR-only applicationDirectory プロパティ
applicationDirectory:File [読み取り-専用]
インストールされたアプリケーションファイルが格納されているフォルダです。
このオブジェクトの url プロパティは、app URL スキーム (file URL スキームではない) を使用します。したがって、url ストリングの指定は “app:” (file: ではない) で始めます。また、File.applicationDirectory ディレクトリを基準とする相対位置に (resolvePath() メソッドを使用して) File オブジェクトを作成すると、その File オブジェクトの url でも app URL スキームが使用されます。
メモ : app URL スキームを使用するパスを持つファイルまたはディレクトリに書き込むことはできません。また、app URL スキームを使用するパスを持つファイルやフォルダの削除または作成を行うこともできません。セキュリティ上の理由から、アプリケーションディレクトリの内容は変更しないでください。アプリケーション固有のデータを格納する必要がある場合は、アプリケーションの記憶領域ディレクトリ (File.applicationStorageDirectory) を使用することを検討してください。アプリケーションの記憶領域ディレクトリ内のコンテンツがアプリケーション特権機能 (AIR API) にアクセスできるようにする必要がある場合は、サンドボックスブリッジを使用してその機能を公開します。
File – ActionScript 3.0 言語およびコンポーネントリファレンスガイドより引用。
あれ?だめじゃん。ファイル出力できないじゃん。実はこれには抜け道があって、”app:”で始まるパスではなく、ローカルのフルパスにすればいいんです(c:Dcouments and Settings・・・)。nativePathプロパティを使います。
var file:File = File.applicationDirectory.resolvePath("test.db"); file = new File(file.nativePath); var str:String = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + "original VARCHAR(10));" _connection = new ConnectionManager(); _connection.initConnection(file); _connection.execute(str, initHistoryHandler)
早速試してみよう!XPでは、起動は特に問題なし。アンインストールしてみる。あれ。だめだ。test.dbファイルが削除されない。ディレクトリも残ってる。う~ん。
AIR アプリケーションのアンインストール
ユーザは AIR アプリケーションを次の方法でアンインストールできます。
* Windows :「プログラムの追加と削除」パネルを使用してアプリケーションを削除します。
* Macintosh:インストール場所から app ファイルを削除します。
AIR アプリケーションを削除すると、アプリケーションディレクトリ内のすべてのファイルが削除されます。ただし、アプリケーションがアプリケーションディレクトリ以外のディレクトリに書き込みを行ったファイルは削除されません。AIR アプリケーションを削除すると、AIR アプリケーションがアプリケーションディレクトリ以外のディレクトリに行った変更は元に戻りません。
Adobe AIR * インストールとアップデートより引用。
ん!ちょっと待てよ。test.dbファイル自体をairにパッケージングしたらどうなるんだろう?アンインストールはうまくいくような気がするな。試してみよう!とりあえず、assetsに突っ込んで、、、
リリースビルドしてみよう。
パッケージングできた。インストールしてみよう。
インストールできた。実行してみよう!
実行できた!アンインストールしてみよう。おおお、test.dbもディレクトリーもきれいさっぱりなくなってる!!!んん?ちょっとまてよ。Vista。よくよくみるとSQLiteへの出力ができてないじゃん!?サンプルだと「set」ボタンを押すと、新たなレコードが作られるはずなんだけど、再読込(「load」ボタンクリック)しても、追加されていない。TkSQLiteでレコード追加して再実行すると、、、あれ?読み込めた。あー、読込だけならできるのね。
Problem
Working with File.applicationDirectory in Windows Vista fails silently and
stops code execution
Solution
Avoid to copy or write data in File.applicationDirectory; use other folder
to work with files.
Detailed description
If you have an application that works with files (copy or write) and they
are in the File.application folder, you can’t manipulate them in Windows
Vista and your code fails silenty. Also, all code after file manipulation,
doesn’t execute. Use another folder when working with files.
Adobe AIR cookbook beta – File.applicationDirectory issue in Windows Vistaより引用。
Vistaではカレントディレクトリにはファイル出力できない上に、アプリケーションが(静かに)停止してしまいます。Exceptionも発生しないんです。。。
ちなみに、flashcast:フリーで働くITエンジニア集団のブログ: ActionScript3.0でJSONを読み込む方法で掲載しているgoogle翻訳APIの翻訳結果JSONを読み込むswfで翻訳するとこんな感じになります。
問題
作業File.applicationDirectory Windows Vistaでのサイレントモードで失敗すると、コードが実行を停止
ソリューション
コピーまたはFile.applicationDirectoryのデータの書き込みを避ける;ファイルで動作するように、他のフォルダを使用します
詳細な説明
場合は、アプリケーションがファイルで動作(コピーまたは書き込み)があるが、これはFile.applicationフォルダ内には、 Windows Vistaで、それらを操作することはできませんsilentyあなたのコードは失敗します。また、すべてのコードファイルを操作した後、実行されません。別のフォルダにファイルと一緒に仕事を使用します。
XPのみ対象であれば.dbファイルをairにパッケージングするやりかたで、アンインストール後にゴミが残ることもないですが、Vistaはちょっと厄介ですね。初期設定等を読み込むような使い方であればパッケージングする意味はあります。インストーラでインストール/アンインストール時にカスタムスクリプトが組めれば一番良いのですけど。もうちょっと調べてみますっ!
※ 後でnativePathを使用しないで試したところ、XPではtest.dbはちゃんと出力されてました。なんでだろ??