JavaでBiff
Javaでかんたんタスクトレイ常駐アプリで、Javaでの常駐アプリ作成について書きました。
んで、何を作ったかっていうとBiffなんです。
Thunderbirdを使っていて、タスクトレイに収まんないのが嫌で作ってみました。
動作イメージ
タスクトレイに常駐します。
ソース
各種設定をGUIでなく、プロパティファイルにしたので
ソースもすごく少なくなりました。
まあ、自分用のツールなら十分ではないでしょうか。
MyBiff.java
メインのクラスです。
package biff; import java.awt.*; import java.awt.TrayIcon.MessageType; import java.awt.event.*; import java.io.*; import java.util.*; import java.util.List; import javax.imageio.ImageIO; /** 僕のBiff */ public class MyBiff { /** 秒 */ private static final long SEC = 1000; /** 分 */ private static final long MIN = 60 * SEC; /** プロパティファイル名 */ private static final String PROP_FILE_NAME = "mybiff.properties"; /** トレイアイコン */ private final TrayIcon icon; /** * コンストラクタ * @param props プロパティ * @throws IOException * @throws AWTException */ public MyBiff(Properties props) throws IOException, AWTException { // タスクトレイアイコン Image image = ImageIO .read(getClass().getResourceAsStream("mybiff.png")); icon = new TrayIcon(image); // ポップアップメニュー PopupMenu menu = new PopupMenu(); // メーラー起動メニュー MenuItem mailerItem = new MenuItem("Mailer"); final String mailer = props.getProperty("mailer"); mailerItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { Runtime.getRuntime().exec(mailer); } catch (Exception ex) { dispException(ex); } } }); menu.add(mailerItem); // 今すぐチェック final TimerTask task = new MailCheckingTask(props, this); MenuItem checkNowItem = new MenuItem("Check Now"); checkNowItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { task.run(); } }); menu.add(checkNowItem); // 終了メニュー MenuItem exitItem = new MenuItem("Exit"); exitItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.exit(0); } }); menu.add(exitItem); icon.setPopupMenu(menu); // タスクトレイに格納 SystemTray.getSystemTray().add(icon); // タスクのスケジューリング long interval = Long.parseLong(props.getProperty("interval")) * MIN; Timer timer = new Timer(); timer.scheduleAtFixedRate(task, 0, interval); } /** * メッセージ到着時のアクション * @param msgs メッセージ概要 */ void onMessageArrival(List<MailDigest> digests) { icon.displayMessage("新着", editMsg(digests), MessageType.INFO); } /** * 例外発生時のアクション * @param e 例外 */ void onException(Exception e) { dispException(e); } /** * メッセージを編集する * @param list * @return */ private String editMsg(List<MailDigest> digests) { StringBuilder sb = new StringBuilder(); for (MailDigest digest : digests) { sb.append(digest); sb.append("\r\n"); } return sb.toString(); } /** * 例外を表示する。 * @param e 例外 */ private void dispException(Exception e) { Writer w = new StringWriter(); PrintWriter pw = new PrintWriter(w); e.printStackTrace(w); String msg = pw.toString(); icon.displayMessage("エラー", msg, MessageType.ERROR); } public static void main(String[] args) throws Exception { File propFile = new File(PROP_FILE_NAME); Properties props = new Properties(); InputStream is = null; try { is = new FileInputStream(propFile); props.load(is); } finally { try { if (is != null) { is.close(); } } catch(IOException e) { } } new MyBiff(props); } }
MailCheckingTask.java
一定間隔で起動されるタスクのクラスです。
java.util.TimerTaskのサブクラスになります。
起動されたらメールをチェックします。
一度表示したメールは表示しないようにしています。
JavaMailを使いました。
package biff; import java.io.UnsupportedEncodingException; import java.util.*; import javax.mail.*; /** メールチェックタスク */ class MailCheckingTask extends TimerTask { /** ホスト名 */ private final String host; /** ユーザ */ private final String user; /** パスワード */ private final String password; /** コールバック */ private final MyBiff callback; /** キャッシュ(一度読んだメールを記憶) */ private final Set<MailDigest> cache = new HashSet<MailDigest>(); /** コンストラクタ */ public MailCheckingTask(Properties props, MyBiff myBiff) { this(props.getProperty("host"), props.getProperty("user"), props .getProperty("password"), myBiff); } /** コンストラクタ */ public MailCheckingTask(String host, String user, String pass, MyBiff myBiff) { this.host = host; this.user = user; this.password = pass; this.callback = myBiff; } /** * タイマータスクの実行 */ @Override public void run() { try { List<MailDigest> result = getMail(); if (result.isEmpty()) { return; } callback.onMessageArrival(result); } catch (Exception e) { callback.onException(e); } } /** メール取得 */ private List<MailDigest> getMail() throws MessagingException, UnsupportedEncodingException { Folder folder = null; Store store = null; try { // 接続 Session session = Session.getDefaultInstance( System.getProperties(), null); store = session.getStore("pop3"); store.connect(host, -1, user, password); // フォルダを開く folder = store.getFolder("INBOX"); folder.open(Folder.READ_ONLY); // メッセージを取得する Message[] messages = folder.getMessages(); List<MailDigest> result = new ArrayList<MailDigest>(); for (Message m : messages) { MailDigest digest = new MailDigest(m); if (!cache.contains(digest)) { result.add(digest); cache.add(digest); } } return result; } finally { if (folder != null && folder.isOpen()) { folder.close(false); } if (store != null && store.isConnected()) { store.close(); } } } }
MailDigest.java
package biff; import java.io.UnsupportedEncodingException; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.MimeUtility; /** * メール概要 */ class MailDigest { /** メッセージID */ public final String messageId; /** 題目 */ public final String subject; /** 差出人 */ public final String from; /** * コンストラクタ * @param message メッセージ * @throws UnsupportedEncodingException * @throws MessagingException */ public MailDigest(Message message) throws UnsupportedEncodingException, MessagingException { messageId = message.getHeader("Message-ID")[0]; subject = message.getSubject(); from = MimeUtility.decodeText(message.getFrom()[0].toString()); } @Override public String toString() { return from + subject; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((messageId == null) ? 0 : messageId.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MailDigest other = (MailDigest) obj; if (messageId == null) { if (other.messageId != null) return false; } else if (!messageId.equals(other.messageId)) return false; return true; } }
mybiff.properties
mailer=C:/Program Files/Mozilla Thunderbird/thunderbird.exe interval=10 host=your.pop3.host.name user=youraccount password=yourpassword