GTalk系イベントリスナーの使い方
com.google.android.gtalkserviceパッケージには以下のようなイベントリスナーがあります。
- IChatListener
- IGroupChatInvitationListener
- IRosterListener
なぜかというとGTalkサービスがUIと別のプロセスで動いているからです。
じゃあどうやって使うのかというとこんな感じで使います。
以下の例ではIRosterListenerを使っていますが他のイベントも基本は同じです。
public class SampleActivity extends Activity { private IGTalkSession gtalkSession; ServiceConnection conn = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { try { gtalkSession = IGTalkService.Stub.asInterface(service).getDefaultSession(); gtalkSession.addRemoteRosterListener(rosterListener); gtalkSession.requestRoster(); gtalkSession.setPresence(new Presence(Im.PresenceColumns.AVAILABLE,"ほげほげ")); } catch (DeadObjectException ex) { // } } public void onServiceDisconnected(ComponentName className) { gtalkSession = null; } } IRosterListerner.Stub rosterListener = new IRosterListerner.Stub() { public void presenceChanged(String arg0) throws DeadObjectException { runOnUIThread(new Runnable() { public void run() { Toast.makeText(SampleActivity.this, "presence changed!", Toast.LENGTH_LONG).show(); } }); } public void rosterChanged() throws DeadObjectException { runOnUIThread(new Runnable() { public void run() { Toast.makeText(SampleActivity.this, "roster changed!", Toast.LENGTH_LONG).show(); } }); } } public void onCreate(Bundle icicle) { setContentView(R.layout.sample); …省略 bindService(new Intent().setComponent( GTalkServiceConstants.GTALK_SERVICE_COMPONE), conn, 0); } }
リスナーインターフェースを直接実装するのじゃなくてStubクラスを使うのがコツです。
またUIに関係する処理を実行するときはActivityクラスのrunOnUIThreadメソッドを使わないとうまく動きません(Handler使っても動きます)。
インナークラス使いまくりで少し汚いコードになってしまうのが欠点ですね。
あと上記実装だとConcurrencyModificationExceptionがかなりの頻度で発生するのでイベントの中でgtalkSessionオブジェクトをロックしたほうがいいです。