BLOGTIMES
2011/12/23

Javaアプリケーションから Google Talk にメッセージを送る

  java  googletalk  programming 
このエントリーをはてなブックマークに追加

簡単な通知アプリを作りたかったので、しばらく Google Talk の仕様とアプリからの呼出方法について調べていました。Google Talk は XMPP を使っていると言うことが分かったので、 下記の Smack API という Java のライブラリを使ってメッセージを送るアプリを作ってみました。面倒な部分はライブラリが引き受けてくれるので簡単に実現できます。

Ignite Realtime: Smack API

Smack is an Open Source XMPP (Jabber) client library for instant messaging and presence. A pure Java library, it can be embedded into your applications to create anything from a full XMPP client to simple XMPP integrations such as sending notification messages and presence-enabling devices.

同種のアプリとしては先日 Twitter につぶやきを送る簡単なアプリを書きましたが、同じような感じで使うことができますね。
Twitterは書いた内容が無条件に公開されてしまうので、非公開にしたい通知はこちらを活用する予定です。

サンプルコード

実際に作ったサンプルはこんな感じです。サンプルを起動する前に事前準備として、あらかじめ双方のアカウントで相手のアカウントをチャットのリストに登録し、双方から相手のステータスを確認できる状態にしておく必要があります。

プログラミング時にハマりやすいポイントとしては、ソースコード中にもコメントしていますがメッセージ送信に使う ID が Google Talk にログインするときの ID と一致しない場合があるということでしょうか。これは非gmailアカウント(例えば iGoogle だけに登録しているアカウント)にみられる現象で、内部的には 1abcdabcda234@id.talk.google.com のような物理名に読み替えられています。幸いにも追加リクエストは読み替え前の メールアドレスで送ることができ、追加リクエストが済んでしまえばアプリから物理名を取得できるので、Mapを作っておいて送信時に宛先を読み替えてやれば問題ありません。それ以外は特に難しいことはないように思います。

import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence; public class GoogleTalkClient { public static final String HOST = "talk.google.com"; public static final int PORT = 5222; public static final String SERVICE_NAME = "gmail.com"; private XMPPConnection connection; Map<String,String> name2user; public static void main(String[] args) throws Exception { GoogleTalkClient gt = new GoogleTalkClient("example_from@gmail.com", "examplepassword"); // 追加リクエストを送る //gt.sendSubscribe("example_to@gmail.com"); //Thread.sleep(300000); gt.sendMsg("example_to@gmail.com", "おーい"); gt.disconnect(); } public GoogleTalkClient(String loginId, String password) throws XMPPException { // GoogleTalk サーバに接続 ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT, SERVICE_NAME); connection = new XMPPConnection(connConfig); connection.connect(); // ログイン connection.login(loginId, password); // ユーザー名をIDに読み替えるためのMapを作成 // gmail以外のアカウントは内部的には 1abcdabcda234@id.talk.google.com のような名前になっているので、 // ユーザー名によっては正常にメッセージ送信できないことがある。 name2user = new HashMap<String,String>(); Roster roster = connection.getRoster(); Collection<RosterEntry> entries = roster.getEntries(); for (RosterEntry entry : entries) { if( entry.getName() != null ){ System.out.println("Name:" +entry.getName()+" -> User:"+entry.getUser() + ", Type: " + entry.getType()); name2user.put(entry.getName().trim(), entry.getUser().trim()); } } // PacketListenerを設定 (このリスナを通してメッセージを受信する) connection.addPacketListener(new PacketListener() { @Override public void processPacket(Packet p) { if (p instanceof Message) { Message msg = (Message) p; System.out.println("PacketListener(Msg): "+msg.getFrom() + ": " + msg.getBody()); } else if (p instanceof Presence) { Presence pre = (Presence) p; System.out.println("PacketListener(Pre): "+pre.getFrom() + " -> " + pre.getTo()+ ": " + pre.getType()); } else { System.out.println("PacketListener: "+p.getFrom() + ": " + p.toString()); } } }, null); // 自分のステータスをオンラインに設定 Presence presence = new Presence(Presence.Type.available); connection.sendPacket(presence); } public void sendSubscribe(String to) { // 追加リクエストを送る Presence subscribe = new Presence(Presence.Type.subscribe); subscribe.setTo(to); connection.sendPacket(subscribe); } public void sendMsg(String to, String message){ if( name2user.containsKey(to) ){ to = name2user.get(to); } // メッセージを送る Message msg = new Message(to, Message.Type.chat); msg.setBody(message); connection.sendPacket(msg); } public void disconnect(){ // 自分のステータスをオフラインにする Presence presence = new Presence(Presence.Type.unavailable); connection.sendPacket(presence); connection.disconnect(); } }

参考

Using google talk from java example :: Andrej Koelewijn


    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/4660
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン