2008/11/15

AIRアプリから関連付けられたアプリケーションでファイルを開く

Adobe AIRでちょっとおかしなファイラを作ろうと思ったんだけど、大体のOSでは可能な「ファイルをダブルクリックしたら関連付けられたアプリケーションで開く」という機能を作ろうとしたところで行き詰まった。
AIRではJavaで提供されてるようなRuntime.exec()やProcessBuilderチックなAPIがないんだった・・・。

ここであきらめるのも悔しいのでAIRで「ファイルをダブルクリックしたら関連付けられたアプリケーションで開く」という機能を無理矢理実装してみた。
なお、AIRだけじゃ実現するのは無理なので、実際にファイルを開く部分はJavaプログラムにヘルプをお願いしている。
(AIRとJavaの2つを使わないと実現できていない時点であまりイケてない)

ちなみに、一から作るのは面倒なので下記記事のサンプルプログラムを拡張して動作確認を行った。

ディレクトリ検索アプリケーションの構築
http://www.adobe.com/jp/devnet/air/flex/quickstart/directory_search.html

まずは記事で紹介されているFileSearch.zipをダウンロードして展開する。
そして、展開したフォルダにあるFileSearchFlex.mxmlに下記のようにコードを追加する。
ここではファイル一覧が表示されるDataGridの行をダブルクリックした際のハンドラを定義しており、Javaプログラムへ選択されたファイルのパスを送っている。
    (省略)  
private var socket:XMLSocket;

private function onDoubleClick(event:MouseEvent):void {
if(!socket) {
socket = new XMLSocket();
}

if(!socket.connected) {
socket.connect('localhost', 5050);
}

socket.send(event.target.data.path + "\n");
}
(省略)
<mx:DataGrid id="resultsGrid" doubleClickEnabled="true" doubleClick="onDoubleClick(event)"
(省略)


次に以下のようなJavaプログラムを用意する。
やりたいのはこれ。
Java 6から追加になったDesktopクラスのopenメソッドを利用すること。
File file = new File(path);
Desktop.getDesktop().open(file);

これがFileSearchFlex側から送られてきたパスのファイルをOS側で関連付けられたアプリケーションを使用して開くという働きをする。

FileOpener.java
package net.air_life.sample;

import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class FileOpener {
public static final int DEFAULT_PORT = 5050;
private static FileOpener server;

ServerSocket socket;
Socket incoming;
BufferedReader readerIn;
PrintStream printOut;

public static void main(String[] args) {
int port = DEFAULT_PORT;

try {
port = Integer.parseInt(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
}

try {
server = new FileOpener(port);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(server.socket != null) {
try {server.socket.close();} catch (IOException e) {}
}
}
}

private FileOpener(int port) throws IOException {
System.out.println(">> Starting FileOpener Server");
socket = new ServerSocket(port);

while (true) {
try {
incoming = socket.accept();
readerIn = new BufferedReader(new InputStreamReader(incoming.getInputStream(), "UTF-8"));
printOut = new PrintStream(incoming.getOutputStream());

String str = readerIn.readLine();

if(str != null && str.trim().length() > 0) {
openFile(str);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(printOut != null) {
printOut.close();
}
if(readerIn != null) {
try {readerIn.close();} catch (IOException e) {}
}
if(incoming != null && !incoming.isClosed()) {
try {incoming.close();} catch (IOException e) {}
}
}
}
}

private void openFile(String path) throws IOException {
File file = new File(path);
if(file.exists() && file.isFile()) {
Desktop.getDesktop().open(file);
}
}
}

実行する場合は、
1. FileOpenerのJavaプログラム
2. FileSearchFlexのAIRプログラム
という順で実行する。

これでFileOpenerを実行している間はFileSearchFlexから「選択したファイルをダブルクリックしたら関連付けられたアプリケーションで開く」ということができる。

4 件のコメント:

Ko:ki さんのコメント...

始めまして。
Prana のことを調べていてここにたどり着きました。
で、Pranaとは関係ないのですが、偶然にも昨日見つけた記事が有用かもしれないと思い、コメントさせていただきました。
AIRアプリで特定のファイルフォーマットのファイルを開く方法
http://blog.s2factory.co.jp/yoshizu/2008/03/air-1.html
もうご存知なのかもしれませんが...

shoito さんのコメント...

有益な情報ありがとうございます。
リンク先の情報は知らなかったので、これで一つ勉強になりましたー。

あ、、、AIRアプリ上に表示されているファイルのアイコンをダブルクリックすると、それがOS側で関連づけられているアプリで立ち上がるってのはできませんか?

Ko:ki さんのコメント...

すみません。あんまり記事を読まずしてコメントしたのが丸分かりですよね。。
失礼しました。

>AIRアプリ上に表示されているファイルのアイコンをダブルクリックすると、それがOS側で関連づけられているアプリで立ち上がる

これができると良いのでしょうけど、今のところAIRのみではできないようですね。
僕はJavaとか使えないので、shoitoさんの記事を読んで勉強させてもらいます。

shoito さんのコメント...

> これができると良いのでしょうけど、今のところAIRのみではできないようですね。

セキュリティ上の問題があるのかも知れませんけど、実現したいことですねー。

コメントありがとうございます。
また、どうぞ気軽に書き込みくださいませ。