Cannot maintain persistent XMPP connection from sticky service android

Environment : For uninterrupted delivery of messages from one-to-one/one-to-many devices, I have XMPPService running in the background as STICKY service. To receive messages, I have PacketListener which fires whenever a packet arrives at the device. I am using asmack library for client side implementation and OpenFire as my XMPP server.

public class XMPPService extends Service implements INetworkReceiver {
private XMPPConnection mXmppConnection;
private XMPPMethods xmpp;
private DatabaseHandler db;
private UserDetails user;
private SmackAndroid smack;
private Registrations registrations;
private static final String TAG="XMPPService";

@Override
public IBinder onBind(final Intent intent) {
    return new LocalBinder<XMPPService>(this);
}

@Override
public void onCreate() {
    super.onCreate();
    registrations=new Registrations(getApplicationContext());
    xmpp=XMPPMethodsImpl.getInstance(getApplicationContext());
    db=DatabaseHandler.getInstance(getApplicationContext());
    if(db!=null){
        user=db.getUserDetails();
    }
    createConnection();     
}

public void createConnection()
{
    ConnectionConfiguration connConfig = new ConnectionConfiguration(
            AppConstants.HOST, AppConstants.PORT);
    connConfig.setSASLAuthenticationEnabled(false);
    connConfig.setDebuggerEnabled(true);
    connConfig.setReconnectionAllowed(true);
    connConfig.setSecurityMode(SecurityMode.disabled);
    mXmppConnection = new XMPPConnection(connConfig);


    Thread thread=new Thread(new Runnable() {
        private Handler handler=new Handler();
        @Override
        public void run() {

            try {
                if(mXmppConnection!=null && !mXmppConnection.isConnected()){
                    mXmppConnection.connect();
                    Log.i("XMPPServiceAsync",
                            "Connected to " + mXmppConnection.getHost());
                    xmpp.setConnection(mXmppConnection);
                }
            } catch (XMPPException e) {
                e.printStackTrace();
            }

            //mXmppConnection.addConnectionListener(new XmppConnectionListener());

            handler.post(new Runnable() {

                @Override
                public void run() {
                    try {
                        if(db!=null && user!=null && mXmppConnection!=null && !mXmppConnection.isAuthenticated()){
                            if(user.getUserName()!=null && !user.getUserName().isEmpty()){
                                mXmppConnection.login(user.getUserName(), "Tp@!");
                                xmpp.setPresence(2, mXmppConnection);
                                xmpp.setConnection(mXmppConnection);
                                Log.i("XMPPServiceAsync",
                                        "Logged in as " + mXmppConnection.getUser());

                            }
                        }
                    }catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (XMPPException ex) {
                        ex.printStackTrace();
                    }


                    if(mXmppConnection.isConnected()){
                        xmpp.rejoinGroups();
                        registrations.registerMessageListener(mXmppConnection);
                        registrations.registerPacketListener(mXmppConnection);
                        registrations.registerMultiUserInvitationListener(mXmppConnection, db, user);
                        registrations.registerPingListener(mXmppConnection);
                    }

                }
            });
        }
    });

    if (thread.getState() == Thread.State.NEW )
    { 
        Log.i(TAG,"Thread State: "+ thread.getState()+"");
        thread.start(); 
    } 
}

@Override
public int onStartCommand(final Intent intent, final int flags,
        final int startId) {
    //rejoining rooms
    try{
        Log.v("XMPP Connection before rejoining",mXmppConnection+"");
        if(mXmppConnection.isConnected()){
            registrations.registerMessageListener(mXmppConnection);
            registrations.registerPacketListener(mXmppConnection);
            registrations.registerMultiUserInvitationListener(mXmppConnection, db, user);
            registrations.registerPingListener(mXmppConnection);
        }
    }catch(Exception e){
        e.printStackTrace();
    }

    return Service.START_STICKY;
}


@Override
public boolean onUnbind(final Intent intent) {
    return super.onUnbind(intent);

}


@Override
public void onDestroy() {
    super.onDestroy();

}

@Override
public void reEstablishConnection() {
    createConnection();
}

}

Problem: When device remains idle for some time, device disconnects from the XMPP server and connection goes null which is against the specifications of XMPP protocol which states that XMPP server maintains persistent connection with devices until we logout forcefully. Reason behind connection going null is not known. When connection goes null, PacketListener stops working.

What all I have tried:

  • Implemented sticky service for connecting to server and initializing listeners.
  • Implemented AlarmManager to check if the service is running in the background. It also checks if the connection is alive and authenticated periodically. (Drains Battery)
  • Implemented Ping manager according to XMPP specification XEP-0199.
  • Can someone please look into this.


    When device remains idle for some time, device disconnects from the XMPP server and connection goes null

    Most likely, your process was terminated. This is perfectly normal.

    which is against the specifications of XMPP protocol which states that XMPP server maintains persistent connection with devices until we logout forcefully.

    Then no mobile device can comply with the XMPP protocol specifications, as Internet access is not guaranteed and universal. Also, users can get rid of your process whenever the user wants to.

    Implemented sticky service for connecting to server and initializing listeners.

    This will cause your process, and your service, to be restarted sometime after Android terminates the process. During the window of time between your process being terminated and your process being restarted, you will not be in communication with the XMPP server.


    What commonsware said. START_STICKY just means that Android is free to kill your service when it needs the resources otherwise. It will restart your service after some time. But you are responsible to reestablish the XMPP connection when it happens.

    链接地址: http://www.djcxy.com/p/94086.html

    上一篇: Smack Android,创建一个接收消息的服务

    下一篇: 无法保持粘滞服务android的永久XMPP连接