Android XMPP Service (Google Talk) + Google map = Follow Me: mobile2007/11/27
I wrote a simple program (named her follow me) on the android SDK to integrate Android XMPP services (Google Talk) & Google map, I hope that through Google Talk, I can catch up with the current location of the lists contact and communicate with each other. For example, if followme can be used, I can easily drive a car behind a friend in the car, because follwme will chase and show the locations of the drivers (including self-driving cars and self-driving cars) along the way to the destination. My (soccercheng) is in the line tracking of the tracking sting.cheng@gmail.com.
To compile this program, you must understand some program of application framework in the following section, for example:
- XMPP Service
- Google Map
- Notification Manager
- Location Manager
- Content Providers
If you only read the Google APIs & Services files provided by Android, you can easily understand what he is doing. mapview is good, and XMPP is hard to understand, so I will share with you the experience of XMPP in our workshop:
First, we must make the gphone XMPP instances upload Google Talk (this means u have to apply an Google Talk account), in Dev tools --> XMPP settings (such as above ), log on to Google Talk with your technical support.
Next, introduce the basic concepts of Android XMPP programming:
Listen to XMPP specifications
(I suggest you take a look at anatomy of an android application first, otherwise you will not understand it)
XMPP services is a notification-based method for sending messages. If you want to know the information about XMPP services, you must specify your intentreceiver & intentfilter, the file does not remember which notifications have been issued by XMPP services. google. android. xmppservice. xmppconstants does not provide the class description in the file. I directly read this xmppconstants statement in eclipse. xmppconstants mainly defines three:
- Xmppconstants. action_xmpp_connection_state. When your program bind to XMPP services, XMPP service will tell you the current state through this action.
- Xmppconstants. action_roster_or_presence_changed, the result is that when your publisher changes on Google Talk (Busy, busy, offline ,...), XMPP service will tell you through this action.
- Xmppconstants. action_new_chat
In addition, I have defined two actions to allow my program to pass through the XMPP service and tell me if someone wants my current location, it will be the location where I will reply to him:
- Action_request_location
- Action_report_location
& Intentreceiver & intentfilter
There are basically two zookeeper methods. One is to define in androidmanifest. XML, or to compile a program to the system. The main difference between the two is:
- If you are in androidmanifest. in XML, your intentreceiver is instantiate from the system. When the system calls your intentreceiver onreceiveintent (...) later, the intentreceiver object may be reclaimed by garbage collector during the upload.
- Because the program is more efficient than the program, I can cancel the program during activity's onstart () when updating and 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 = 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 );
}
....
}
Receive notification in intentreceiver
Public class xmppdatamessagereceiver extends intentreceiver {
....
@ Override
Public void onreceiveintent (context, 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 longpolling = integer. parseint (bundle. getstring ("longpolling "));
Activity. setuserlocation (reporter, latitude, longpolling );
}
} 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 );
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 = intent. getextras ();
Int I = locationindex ++ % 19;
Intent. putextra ("latitude", integer. tostring (locations [I] [0]);
Intent. putextra ("longmargin", 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
How to bind to XMPP service is not found in the exposed document. Fortunately, there are two applications in the SDK sample (xmppdatamessagereceiver. java & xmppdatamessagesender. java), used to some unauthenticated ented classes, which reveal a lot of secrets.
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
// 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 varous XMPP event intent
// Broadcast (I. e. Incoming chat, muc invitation, subscribe 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 shoshould 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 );
}
};
....
}