Android XMPP Service (Google Talk) + Google Map == Follow Me
我在 Android SDK 上寫了一個簡單的程式 (姑且把她叫 Follow Me),來測試 Android 的 XMPP Services (Google Talk) & Google Map 整合,我希望可以透過 Google Talk,來追蹤 Contact Lists 現在的位置及互相通訊。例如可以透過 FollowMe ,我就可以很順利的開車跟在領導車的朋友後面,因為 FollwMe 會在地圖上追蹤及顯示共同出遊的車子(包含領導車及自己)的位置,一路順暢的共同到達目的地。畫面如下圖,我 (soccercheng) 在追蹤 sting.cheng@gmail.com 的行蹤。
要寫這個程式,必須要對下圖中,Application Framework 的一些項目進行了解,如:
- XMPP Service
- Google Map
- Notification Manager
- Location Manager
- Content Providers
如果只看 Android 提供的 Google APIs & Services 文件,很難看的懂他在寫甚麼,MapView 還好,XMPP 就不好懂,所以我把在測試 XMPP 的經驗和大家分享一下:
首先,我們必須讓 GPhone 的 XMPP 掛載上 Google Talk (This means U have to apply an Google Talk account),在 Dev Tools --> XMPP Settings (如上圖),用你的帳號讓登入 Google Talk。
接下來,介紹一下 Android XMPP Programming 的基本概念:
Listen to XMPP Notifications
(建議你先看一下 Anatomy of an Android Application,不然你會看不懂)
XMPP Services 是透過 Notification 的方式,來發佈消息,所已入你的程式想知道 XMPP Services 的訊息,就必須掛載 IntentReceiver & IntentFilter,文件中並未記載 XMPP Services 到底發布了哪些 Notifications,相關的定義在 com.google.android.xmppService.XmppConstants 中,不過文件上並沒有這個class 的說明,我是直接在 eclipse 看這個 XmppConstants 的說明,XmppConstants 最主要定義了三個:
- XmppConstants.ACTION_XMPP_CONNECTION_STATE,當你程式 bind 到 XMPP Services 時,XMPP Service 會透過這個 Action 告知你現在的 state。
- XmppConstants.ACTION_ROSTER_OR_PRESENCE_CHANGED,我測試的結果是當你的聯絡人在 Google Talk 上的狀態有變化時 (忙碌、線上、下線、...),XMPP Service 會透過這個 Action 告知你。
- XmppConstants.ACTION_NEW_CHAT
另外,我有定義了兩個 Action,讓我的程式透過 XMPP Service ,來告知我是否有人跟我要我現在位置,會是跟我回報他的位置:
- ACTION_REQUEST_LOCATION
- ACTION_REPORT_LOCATION
註冊 & 掛載 IntentReceiver & IntentFilter
註冊方式基本上有兩種,一種是在 AndroidManifest.xml 中定義,或是寫程式向系統註冊,兩者最主要的差異是:
- 如果你是在 AndroidManifest.xml 中定義,則你的 IntentReceiver 是由系統來 instantiate ,當系統呼叫完你的 IntentReceiver 的 onReceiveIntent(...) 之後,這個物件 IntentReceiver Object 隨時可能被 Garbage Collector 收回。
- 由程式註冊,比較有彈性,我可以在Activity's onStart() 註冊,onStop() 時取消註冊。
public class FollowMe extends MapActivity
implements View.OnClickListener {
....
/** Called when the activity is becoming visible to the user. */
/* For example, you can register an IntentReceiver in onStart()
* to monitor for changes that impact your UI, and unregister it in onStop()
* when the user an no longer see what you are displaying.
* The onStart() and onStop() methods can be called multiple times,
* as the activity becomes visible and hidden to the user.
*/
@Override
protected void onStart() {
super.onStart();
// Register XMPP Data MessageReciver
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(XmppDataMessageReceiver.ACTION_REQUEST_LOCATION);
intentFilter.addAction(XmppDataMessageReceiver.ACTION_REPORT_LOCATION);
intentFilter.addAction(XmppDataMessageReceiver.ACTION_NEW_CHAT);
intentFilter.addAction(...ACTION_XMPP_CONNECTION_STATE...);
intentFilter.addAction(...ACTION_ROSTER_OR_PRESENCE_CHANGED...);
....
this.registerReceiver(xmppDataMessageReceiver, intentFilter);
}
@Override
protected void onStop() {
super.onStop();
// unregister XMPP Data MessageReciver
this.unregisterReceiver(xmppDataMessageReceiver);
}
....
}
在 IntentReceiver 中接收 Notification
public class XmppDataMessageReceiver extends IntentReceiver {
....
@Override
public void onReceiveIntent(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(ACTION_REQUEST_LOCATION)) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
String requester = bundle.getString("requester");
//showMessage(context, requester);
if(requester != null)
activity.reportLocation(requester);
}
}else if(action.equals(ACTION_REPORT_LOCATION)) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
String reporter = bundle.getString("reporter");
int latitude = Integer.parseInt(bundle.getString("latitude"));
int longitude = Integer.parseInt(bundle.getString("longitude"));
activity.setUserLocation(reporter, latitude, longitude);
}
}else if(action.equals(ACTION_XMPP_CONNECTION_STATE)) {
Bundle bundle = intent.getExtras();
int state = bundle.getInteger("state").intValue();
if(state == com.google.android.xmppService.ConnectionState.REQUESTED_ROSTER) {
// Get the base URI for IM contacts.
try {
ContentURI myPerson = new ContentURI("content://im/contacts");
// Query for this record.
Cursor cur = activity.managedQuery(myPerson, null, null, null);
String[] names = cur.getColumnNames();
// TODO There is no document for IM Contact operation,
// 2 hard for me to hacking it
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} else if(action.equals(ACTION_ROSTER_OR_PRESENCE_CHANGED)) {
//showMessage(context, ACTION_ROSTER_OR_PRESENCE_CHANGED);
} else if(action.equals(ACTION_NEW_CHAT)) {
//showMessage(context, ACTION_NEW_CHAT);
}
}
....
}
Reporting Location
public class XmppDataMessageReceiver extends IntentReceiver {
....
private Intent getRequestIntentToSend() {
Intent intent = new Intent(XmppDataMessageReceiver.ACTION_REQUEST_LOCATION);
intent.putExtra("requester", userName);
return intent;
}
private Intent getResponseIntentToSend() {
Intent intent = new Intent(XmppDataMessageReceiver.ACTION_REPORT_LOCATION);
intent.putExtra("reporter", userName);
//Bundle bundle = intent.getExtras();
int i = locationIndex++ % 19;
intent.putExtra("latitude", Integer.toString(locations[i][0]));
intent.putExtra("longitude", Integer.toString(locations[i][1]));
//intent.putExtra("location", new Point(locations[i][0], locations[i][1]));
return intent;
}
public void reportLocation(String requester) {
Intent intent = getResponseIntentToSend();
if (mXmppSession == null) {
showMessage(getText(R.string.xmpp_service_not_connected));
return;
}
try {
mXmppSession.sendDataMessage(requester, intent);
} catch (DeadObjectException ex) {
showMessage(getText(R.string.found_stale_xmpp_service));
mXmppSession = null;
bindXmppService();
}
}
....
}
Binding to XMPP Service
如何 bind to XMPP Service,在現在接露的 document 中找不到,還好在 SDK 的 sample 中,有兩個應用 (XmppDataMessageReceiver.java &XmppDataMessageSender.java),有用到一些 undocumented classes,其中接露了不少秘密。
public class XmppDataMessageReceiver extends IntentReceiver {
....
private void bindXmppService() {
bindService((new Intent()).setComponent(
com.google.android.xmppService.XmppConstants.XMPP_SERVICE_COMPONENT),
null, mConnection, 0);
}
private IXmppSession mXmppSession = null;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the XmppService has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
IXmppService xmppService = IXmppService.Stub.asInterface(service);
// Increment the event monitor reference count. When application UI
// is alive and listening for the various XMPP event intent
// broadcast (i.e. incoming chat, muc invitation, subscription invitation),
// call this so XmppService will send the appropriate intent broadcast
// instead of posting a titlebar notification.
try {
xmppService.incrementEventMonitorRef();
} catch (DeadObjectException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return;
}
try {
mXmppSession = xmppService.getDefaultSession();
if (mXmppSession == null) {
// this should not happen.
showMessage(getText(R.string.xmpp_session_not_found));
return;
}
//if()
mXmppSession.requestRosterAndSendInitialPresence();
userName = mXmppSession.getUsername();
} catch (DeadObjectException ex) {
//Log.e(LOG_TAG, "caught " + ex);
showMessage(getText(R.string.found_stale_xmpp_service));
return;
}
okButton.setEnabled(true);
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mXmppSession = null;
okButton.setEnabled(false);
}
};
....
}
分享到:
相关推荐
Android XMPP例子(Openfire+asmack+spark)是一个典型的基于Android平台的即时通讯(Instant Messaging,IM)应用实现,利用了XMPP协议、Openfire服务器、asmack库以及Spark客户端工具。XMPP(Extensible Messaging ...
在Android平台上实现XMPP(Extensible Messaging and Presence Protocol)好友列表和聊天功能是一项常见的任务,尤其是在构建即时通讯应用时。XMPP是一种开放标准的实时通信协议,它基于XML,广泛用于实现聊天、视频...
XMPP+Openfire4.5.1+Smack4.3.4+MySql,支持手机对手机,手机对PC(Spark)的消息收发
5. **即时通讯架构**:在Android应用中,通常会有一个后台运行的服务(Service)负责维持与OpenFire服务器的持久连接,处理网络事件,如接收消息、更新用户状态。此外,还有一个Activity负责展示聊天界面,接收来自...
Android XMPP(Extensible Messaging and Presence Protocol)是用于在Android平台上实现即时通讯(IM)的一种技术,它基于开放源码的XMPP协议栈。Openfire是XMPP服务器的一个实现,用Java编写,提供了实时、双向的...
Android XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的开放标准协议,常用于实现即时通讯(Instant Messaging, IM)和在线状态管理。这个名为"AndroidXMPP-master"的项目显然是一个针对...
【即时通讯技术详解:XMPP、Android、Openfire与Asmack】 即时通讯(Instant Messaging,简称IM)是现代通信技术的重要组成部分,尤其在移动互联网领域应用广泛。本篇文章将深入探讨基于XMPP协议的Android即时通讯...
在android应用程序中使用xmpp协议的网络操作实例
android 电子文档 XMPP总结 文档
在Android平台上实现XMPP(Extensible Messaging and Presence Protocol)客户端是一项常见的任务,因为XMPP是一种广泛使用的即时通讯协议,尤其适用于构建实时通信应用,如聊天、视频通话等。本篇文章将深入探讨...
**Android XMPP 教程:实现文字、表情、语音及图片发送** XMPP(Extensible Messaging and Presence Protocol)是一种开放的即时通讯协议,常用于构建实时通讯应用,如聊天、语音通话和文件共享等。本教程将围绕一...
本项目是一套基于android+asmack+openfire+xmpp的安卓即时聊天服务端,项目直连google talk服务器,可以使用谷歌帐号登录客户端,测试需要至少两个谷歌帐号。在程序里添加好友即可聊天。聊天核心功能使用的smack库
在Android平台上实现XMPP(Extensible Messaging and Presence Protocol)聊天应用是一个常见的需求,尤其是在构建即时通讯系统时。本文将深入探讨如何使用asmack库来创建一个Android XMPP客户端。 首先,XMPP是一...
在Android平台上实现XMPP协议的语音、图片和文本聊天功能是一项常见的需求,XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通讯协议,广泛应用于即时通讯应用的开发。以下将详细介绍如何在...
**Android平台上使用XMPP详解** XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通信协议,广泛用于实现即时消息、在线状态检测以及多用户聊天等应用。在Android平台上,利用XMPP协议进行...
在Android平台上构建一个基于XMPP协议的聊天应用是一项复杂但有趣的工作。XMPP(Extensible Messaging and Presence Protocol)是一种开放标准的即时通讯协议,广泛应用于实时通讯系统,如聊天、群聊、约会场景切换...
Android XMPP库演示 在移动应用开发中,尤其是在即时通讯(IM)领域,XMPP(Extensible Messaging and Presence Protocol)是一种广泛使用的开放标准协议。它允许应用程序之间进行实时通信,如发送消息、创建群组...
Android基于xmpp即时通讯软件,界面简洁大方,功能简单小巧,bug倒是不多不少。 编码方式是utf-8,不能直接导入eclipse,请自己新建一个工程,将源码覆盖过去,并将编码方式修改为utf-8。 了解更多,请移步:...
Android XMPP推送是一种在Android应用中实现即时通讯(Instant Messaging, IM)和推送通知的技术。XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的开放标准协议,常用于实现聊天和实时通信。...