I was using Smack API in my application JabberTwitterBridge. It is jabber API. I use it to connect to server like Google Talk.

But when I was connected to Google, I couldn’t update my status by sending a standard Presence packet. I search a long time before finding why. In fact, google used a feature to manage old status list. It is described on this page :

http://code.google.com/apis/talk/jep_extensions/shared_status.html

Google give important information on this page, for example :

The server rewrites and sends out the following value to all subscribed contacts and other instances. Note that the <status> value used is the current shared value, not the value just sent by the <presence> stanza.

That’s mean with must use a special command, we found it on this page to

<iq type='set' to='romeo@gmail.com/orchard' id='ss-2'>
  <query xmlns='google:shared-status' version='2'>
    <status>Juliet's here</status>
    <show>default</status>
    <status-list show='default'>
        <status>Juliet's here</status>
        <status>Pining away</status>
        <status>Wherefor indeed</status>
        <status>Thinking about the sun</status>
    </status-list>
    <status-list show='dnd'>
        <status>Chilling with Mercutio</status>
        <status>Visiting the monk</status>
    </status-list>
    <invisible value='false'/>
  </query>
</iq>

In fact, Smack give a class call IQ that it is easy to evolve. Just make a new class which herit this IQ class.  Then just implement the function writing the query tag into xml. Easy isin’t it.

package com.cba.jabberTwitterBridge.arch.com.jabber;
 
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Presence;
 
public class PresenceGoogle extends IQ {
 
        protected String userName;
        protected String status;
        protected boolean visible;
        protected Presence.Mode mode;
 
 
 
 
        /**
         * Override toXML in the case of mode is away
         * Because Google Talk interprets the 'away' 
         * status as idle, and idleness is a 
         * per-connection property, you cannot set an 
         * 'away' status using this method. To set an 
         * idle status message, send a 
         * standard <presence> stanza.  : 
         */
        @Override
        public String toXML() {
                if ( mode.equals(Presence.Mode.away) )
                {
                        Presence p = new Presence(Presence.Type.available);
                        p.setMode(mode);
                        p.setStatus(status);
                        return p.toXML();
                }
                else
                {
                        return super.toXML();
                }
        }
 
 
        /**
         * Constructor
         * @param userName the userName
         * @param status the new status
         * @param visible the visible state > false to be invisble
         */
        public PresenceGoogle(String userName, String status, boolean visible) {
                super();
                this.userName = userName;
                this.status = status;
                this.visible = visible;
                setType(IQ.Type.SET);
 
                // I am not sure this code must be test
                // in case of a domain different of gmail.com
                // using gmail.com...
        if(  userName.indexOf("@")  != -1)
        {
                setTo(userName + "");
        }
        else
        {
                setTo(userName + "@gmail.com");
        }
 
                mode = Presence.Mode.available;
        }
 
        /**
         * Constructor
         * @param userName the userName
         * @param status the new status
         */
        public PresenceGoogle(String userName, String status) {
                this(userName,status,false);            
        }
 
        /**
         * Return the XML of changing status
         * for google
         * according 
         * http://code.google.com/apis/talk/jep_extensions/shared_status.html
         */
        @Override
        public String getChildElementXML() {
                StringBuilder buf = new StringBuilder();
 
                // set query header
                buf.append("<query xmlns='google:shared-status' version='2'>");
                // set status
                buf.append("<status>").append(status).append("</status>");
                // set mode
                buf.append("<show>").append(mode).append("</show>");
                // set invisible mode
                if ( visible )
                {
                        buf.append("<invisible value='false'/>");       
                }
                else
                {
                        buf.append("<invisible value='true'/>");        
                }
                // close query
                buf.append("</query>");
 
                return buf.toString();
        }
 
 
        public Presence.Mode getMode() {
                return mode;
        }
 
 
        public void setMode(Presence.Mode mode) {
                this.mode = mode;
        }
 
}

If you have any question let me a comment.