Project

General

Profile

[Android] Connecting/disconnecting from XMPP server when application is closed or gone to background. Best practices with JaXMPP.

Ildar Zaripov
Added 8 months ago

Keeping long-live connection with XMPP server is not effective, since, in one hand, Android can notify user that app consumes a lot of energy (bad user experience) and, in the other hand, Android can kill service (because of lack of memory), responsible for XMPP connection.

I think it would be more correct to disconnect (or to pause somehow... is it posssible?) from XMPP server each time the app is gone to background and turn on Push Notification service.

Does this approach correct? Won't it take too much time to recover connection to the server? (ssh, encryption, handshake are long processes) How one can optimise connection recovery process?


Replies (6)

Added by Andrzej Wójcik IoT 1 CloudTigaseTeam 8 months ago

As far as we can tell from our tests and from measurements done using Tigase Android Messenger, keeping app idle in the background and keeping idle TCP connection is not using a lot of energy. Especially if you are using mobile optimizations or CSI on the server side. With those enabled, the server is not sending presence updates to the client unless the client is in the foreground which helps with energy usage. As for sending empty TCP packets to keep-alive TCP connection, those are not so energy consuming as actual data transfer.

Of course, you can try to be more energy efficient and disconnect from the server and only connect when the app is in the foreground and display notifications based on Push Notifications. However, depending on the performance of the server and quality of your connection, it may be fast or slow.

Added by Ildar Zaripov 8 months ago

Thanks for reply!
But how to implement it? I mean JaXMPP part, not Android part. Suppose, there is a listener to check whether the app is in background or foreground:

listener = new Listener() {
  @Override
  public void onBackground(){

  }

  @Override
  public void onForeground(){

  }

};

According to the documentation( https://tigase.tech/projects/jaxmpp2/wiki/Example_codes_(3x) ), I can send presence explicitly:

PresenceModule presenceModule = contact.getModulesManager().getModule(PresenceModule.class);
presenceModule.sentDirectPresence(JID.jidInstance("tigase2@atlantiscity"), Presence.Show.away, "...", 65);

Will it be enough to set Presence.Show.away when app is in background and set Presence.Show.online, when app is in foreground?
Does JaXMPP "send empty TCP packets to keep-alive TCP connection" on its own or should I control it somehow?

Added by Andrzej Wójcik IoT 1 CloudTigaseTeam 8 months ago

No, setting presence to away or xa will not do anything.

You need to handle it using https://tigase.tech/projects/jaxmpp2/repository/revisions/master/entry/jaxmpp-core/src/main/java/tigase/jaxmpp/core/client/xmpp/modules/ClientStateIndicationModule.java or our separate MobileOptimizations feature. However, to use any of that you need to have them enabled on the server side. For that please check our Tigase XMPP Server documentation at http://docs.tigase.org/.

You can also check our publicly available source code of Tigase Android Messenger https://tigase.tech/projects/tigase-mobilemessenger/repository. In it we are using CSI and MobileOptimizations.

(1)

Added by Ildar Zaripov 8 months ago

Great!
So I edited config.tdsl file and restarted server:

'sess-man' (class: tigase.server.xmppsession.SessionManager) {
        .... 

        'urn:xmpp:csi:0' (class: tigase.xmpp.impl.ClientStateIndication, active:true) {
            logic (class: tigase.xmpp.impl.MobileV2) {
            }
        }

        ...
}

Then in Android app I created 2 public methods that will be called when the app state is changed:

import tigase.jaxmpp.core.client.xmpp.modules.ClientStateIndicationModule;
import tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule;

def PresenceModule presenceModule = jaxmpp.getModulesManager().getModule(PresenceModule.class);

def ClientStateIndicationModule clientStateIndicationModule = new ClientStateIndicationModule();
jaxmpp.getModulesManager().register(clientStateIndicationModule);


public void onAppInBackground(){
     try {
         presenceModule.setPresence(Presence.Show.offline, "", 50);
     } catch (JaxmppException e) {
         e.printStackTrace();
     }

     clientStateIndicationModule.inactive();

     // Turn on Push notifications
}

public void onAppInForeground(){
     try {
         presenceModule.setPresence(Presence.Show.online, "", 50);
     } catch (JaxmppException e) {
         e.printStackTrace();
     }

     clientStateIndicationModule.active();

     // Turn off Push Notifications
}

What do you think, does such logics is correct?

By the way, I checked, it seems, the code above is correct (at least presence stanzas are no longer sent or received)

Added by Andrzej Wójcik IoT 1 CloudTigaseTeam 8 months ago

I think that there is no point in turning push notifications on and off. Tigase will send those notifications only for resources which are unavailable, so I would suggest to keep it on all the time.

As for setting Presence.Show.offline - I would set xa or away. As during this time you are connected until Android kills your app, so messages may be delivered directly thru XMPP. But when your client will get disconnected (or killed), then Tigase will know that and your client will become unavailable and will send push notifications for incoming messages.

Added by Ildar Zaripov 8 months ago

Thank you, you helped me a lot!

    (1-6/6)