How to keep a XMPP connection stable on Android with (a)smack? - android

I use asmack-android-7-beem library for Android. I have a background service running, such as my app stays alive. But sooner or later XMPP connection dies without any notice. The server says that the client is still online but no packets are sent or received.
For example the client doesn't receive any presence packets when other clients have a new presence. I have XMPPConnection as an attibute of my main Application class.
I set ConnectionConfiguration config.setReconnectionAllowed(true) before the connection was made.
But reconnection doesn't happen. XMPPConnection connection.isConnected() returns true.
So the client is not aware that connection is actually lost.
Is there any way to keep the connection alive?

When using asmack put some code like this in your app to make Dalvik load the ReconnectionManager class and run it's static initialization block:
static {
try {
Class.forName("org.jivesoftware.smack.ReconnectionManager");
} catch (ClassNotFoundException ex) {
// problem loading reconnection manager
}
}

Actually There is not any problem with Reconnection manager. First you need to add connection listener to your connection manager.
connection.addConnectionListener(new ConnectionListener() {
#Override
public void reconnectionSuccessful() {
Log.i("","Successfully reconnected to the XMPP server.");
}
#Override
public void reconnectionFailed(Exception arg0) {
Log.i("","Failed to reconnect to the XMPP server.");
}
#Override
public void reconnectingIn(int seconds) {
Log.i("","Reconnecting in " + seconds + " seconds.");
}
#Override
public void connectionClosedOnError(Exception arg0) {
Log.i("","Connection to XMPP server was lost.");
}
#Override
public void connectionClosed() {
Log.i("","XMPP connection was closed.");
}
});
if any error occurred the connectionClosedOnError(Exception arg0) will automatically called
when connection is closed
public void connectionClosed() {
Log.i("","XMPP connection was closed.");
//You can manually call reconnection code if you want to reconnect on any connection close
}
then check it this will call reconnectingin() method and try to reconnect.
Hope so this will help you.
use below code for check connection
PingManager pingManager = PingManager.getInstanceFor(connection); pingManager.setPingInterval(5000);
add listner for ping fail handling to handle connection is connected or not because isConnected method is not reliable for check state of connection.
pingManager.registerPingFailedListener(PingFailedListener);
For mobile network connectivity is very big problem so you need to check network connectivity for mobile using broadcast receiver and on data reconnection you can use pingMyServer method to check connection is alive or not, if you are getting ping reply from server, means connection is alive otherwise on ping fail you can reconnect connection manually.

Here's my code work fine for ReconnectionManager
1) Add addConnectionListener on xmpp connection
XMPPConnectionListener mConnectionListener = new XMPPConnectionListener(username);
connection.addConnectionListener(mConnectionListener);
2) if connection closed then reconnect automatically using ReconnectionManager class
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.setEnabledPerDefault(true);
3) ConnectionListener for reconnect, connect and authenticated on server. if connection authenticated successfully with server also register PingManager and ServerPingWithAlarmManager class.
public class XMPPConnectionListener implements ConnectionListener {
String username="";
public XMPPConnectionListener(String username){
this.username=username;
}
#Override
public void connected(final XMPPConnection connectionObeject) {
sendPresenceAvailable();
Log.d(TAG, "xmpp Connected()");
connected = true;
}
#Override
public void connectionClosed() {
Log.d(TAG, "xmpp ConnectionCLosed()");
isAuthenticatedPreviouly=false;
connected = false;
loggedin = false;
}
#Override
public void connectionClosedOnError(Exception arg0) {
Log.d(TAG, "xmpp ConnectionClosedOnError() :"+System.currentTimeMillis());
isAuthenticatedPreviouly=false;
connected = false;
loggedin = false;
}
#Override
public void reconnectingIn(int arg0) {
Log.d(TAG, "xmpp reconnectingIn() :"+System.currentTimeMillis());
loggedin = false;
}
#Override
public void reconnectionFailed(Exception arg0) {
Log.d(TAG, "xmpp ReconnectionFailed!");
connected = false;
// chat_created = false;
loggedin = false;
try {
connection.connect();
} catch (SmackException | IOException | XMPPException | InterruptedException exception) {
exception.printStackTrace();
}
}
#Override
public void reconnectionSuccessful() {
Log.d(TAG, "xmpp ReconnectionSuccessful");
connected = true;
sendPresenceAvailable();
loggedin = false;
}
#Override
public void authenticated(XMPPConnection connection2, boolean resumed) {
Log.d(TAG, "xmpp Type Main Authenticated() :" + connection.isAuthenticated());
if(connection.isAuthenticated()) {
ServerPingWithAlarmManager.getInstanceFor(connection).setEnabled(true);
PingManager pingManager = PingManager.getInstanceFor(connection);
pingManager.setPingInterval(10);
try {
pingManager.pingMyServer();
pingManager.pingMyServer(true,10);
pingManager.pingServerIfNecessary();
pingManager.registerPingFailedListener(new PingFailedListener() {
#Override
public void pingFailed() {
Log.d("Ping","pingFailed");
disconnect();
connect();
}
});
registerAllListener();
}
}

I have the same problem, except that My program run on server side JVM.
I used smack 4.0 in the first place. Then I updated to smack 4.1, but the problem still happened. Finally I found a configuration module: PingManager
After using this, the occurrence of this situation was drop down.
connection = new XMPPTCPConnection(config);
PingManager pingManager = PingManager.getInstanceFor(connection);
pingManager.setPingInterval(300); // seconds

In Smack 4.1, I use ServerPingWithAlarmManager. You can find more details about keeping connection alive ramzandroid blog here.

For these case you need to handle the disconnection manually I mean you should intercept any disconnection, connection listener notified when you got a disconnection over.
public void connectionClosedOnError(Exception exception)
import android.util.Log;
import com.dagm8.core.protocols.ConnectionState;
import com.dagm8.core.service.XMPPService;
import com.dagm8.events.ConnectionStateEvent;
import org.greenrobot.eventbus.EventBus;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import java.io.IOException;
import static com.dagm8.core.protocols.ConnectionState.CONNECTED;
import static com.dagm8.core.protocols.ConnectionState.DISCONNECTED;
import static com.dagm8.core.protocols.ConnectionState.RECONNECTING;
/**
* dagm8-android
* Created by Bedoy on 8/28/17.
*/
public class ConnectionController implements ConnectionListener {
private String TAG = getClass().getCanonicalName();
private XMPPTCPConnection mConnection;
public void setConnection(XMPPTCPConnection connection) {
mConnection = connection;
}
public void init(XMPPTCPConnection connection) throws InterruptedException, XMPPException, SmackException, IOException {
setConnection(connection);
mConnection.setPacketReplyTimeout(10000);
mConnection.addConnectionListener(this);
mConnection.connect();
}
#Override
public void connected(XMPPConnection connection) {
XMPPService.connectionState = RECONNECTING;
notifyConnectionState(RECONNECTING);
try {
mConnection.login();
} catch (XMPPException | SmackException | IOException | InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "connected()");
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
XMPPService.connectionState = CONNECTED;
notifyConnectionState(CONNECTED);
Log.i(TAG, "authenticated()");
}
#Override
public void connectionClosed() {
XMPPService.connectionState = DISCONNECTED;
notifyConnectionState(DISCONNECTED);
Log.i(TAG, "connectionClosed()");
}
#Override
public void connectionClosedOnError(Exception e) {
XMPPService.connectionState = DISCONNECTED;
notifyConnectionState(DISCONNECTED);
try {
mConnection.connect();
} catch (SmackException | IOException | XMPPException | InterruptedException exception) {
exception.printStackTrace();
}
Log.i(TAG, "connectionClosedOnError()");
}
#Override
public void reconnectingIn(int seconds) {
XMPPService.connectionState = RECONNECTING;
notifyConnectionState(RECONNECTING);
Log.i(TAG, "reconnectingIn()");
}
#Override
public void reconnectionSuccessful() {
XMPPService.connectionState = CONNECTED;
notifyConnectionState(CONNECTED);
Log.i(TAG, "reconnectionSuccessful()");
}
#Override
public void reconnectionFailed(Exception e) {
XMPPService.connectionState = DISCONNECTED;
notifyConnectionState(DISCONNECTED);
Log.i(TAG, "reconnectionFailed()");
}
private void notifyConnectionState(ConnectionState state) {
EventBus.getDefault().post((ConnectionStateEvent) () -> state);
}
public boolean isAuthenticated()
{
return mConnection.isAuthenticated();
}
public void login() {
try {
mConnection.login();
} catch (XMPPException | SmackException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}

Related

MQTT Paho Client not reconnect automatically to broker on Android Service

I've a Service to manage my MQTT Client connection, the MQTT works fine, but the problem is when I restart Broker Server, the Android client not reconnect. A exception is triggered on onConnectionLost() callback.
Notes
I'm using Moquette Broker at same computer -> Moquette
I've two Android clients app, a using Service (the problematic) and other working on a Thread, without Service (this works fine, reconnect is ok).
I can't run the Android Client MQTT lib, because this I'm using the Eclipse Paho MQTT.
Yes, I make setAutomaticReconnect(true);
Problem
The Android app that use Service, to works forever, not reconnect to MQTT Broker.
Code
MQTTService.java
public class MQTTService extends Service implements MqttCallbackExtended {
boolean running;
private static final String TAG = "MQTTService";
public static final String ACTION_MQTT_CONNECTED = "ACTION_MQTT_CONNECTED";
public static final String ACTION_MQTT_DISCONNECTED = "ACTION_MQTT_DISCONNECTED";
public static final String ACTION_DATA_ARRIVED = "ACTION_DATA_ARRIVED";
// MQTT
MqttClient mqttClient;
final String serverURI = "tcp://"+ServidorServices.IP+":1883";
final String clientId = "Responsavel";
String topicoId;
Thread mqttStartThread;
public boolean subscribe(String topic) {
try {
Log.i(TAG,"Subscripe: " + topic);
mqttClient.subscribe(topic);
mqttClient.subscribe("LOCATION_REAL");
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
// Life Cycle
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG,"onBind()");
return null;
}
#Override
public void onCreate() {
Log.d(TAG,"onCreate()");
running = true;
topicoId = getSharedPreferences("myprefs",MODE_PRIVATE).getString("tag_id_aluno","0");
mqttStartThread = new MQTTStartThread(this);
if(topicoId.equals("0")) {
Log.i(TAG,"Error to subscribe");
return;
}
mqttStartThread.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
class MQTTStartThread extends Thread {
MqttCallbackExtended mqttCallbackExtended;
public MQTTStartThread(MqttCallbackExtended callbackExtended) {
this.mqttCallbackExtended = callbackExtended;
}
#Override
public void run() {
try {
mqttClient = new MqttClient(serverURI,clientId,new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
options.setCleanSession(true);
mqttClient.setCallback(mqttCallbackExtended);
mqttClient.connect();
} catch (Exception e) {
Log.i(TAG,"Exception MQTT CONNECT: " + e.getMessage());
e.printStackTrace();
}
}
}
#Override
public void onDestroy() {
Log.d(TAG,"onDestroy()");
running = false;
if (mqttClient != null) {
try {
if (mqttClient.isConnected()) mqttClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG,"onUnbind()");
return super.onUnbind(intent);
}
// Callbacks MQTT
#Override
public void connectComplete(boolean reconnect, String serverURI) {
Log.i(TAG,"connectComplete()");
if (topicoId == null) {
Log.i(TAG,"Erro ao ler ID da Tag");
return;
}
sendBroadcast(new Intent(ACTION_MQTT_CONNECTED));
subscribe(topicoId);
}
#Override
public void connectionLost(Throwable cause) {
Log.i(TAG,"connectionLost(): " + cause.getMessage());
cause.printStackTrace();
sendBroadcast(new Intent(ACTION_MQTT_DISCONNECTED));
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG,"messageArrived() topic: " + topic);
if (topic.equals("LOCATION_REAL")) {
Log.i(TAG,"Data: " + new String(message.getPayload()));
} else {
Context context = MQTTService.this;
String data = new String(message.getPayload());
Intent intent = new Intent(context,MapsActivity.class);
intent.putExtra("location",data);
LatLng latLng = new LatLng(Double.valueOf(data.split("_")[0]),Double.valueOf(data.split("_")[1]));
String lugar = Utils.getAddressFromLatLng(latLng,getApplicationContext());
NotificationUtil.create(context,intent,"Embarque",lugar,1);
if (data.split("_").length < 3) {
return;
}
double latitude = Double.valueOf(data.split("_")[0]);
double longitude = Double.valueOf(data.split("_")[1]);
String horario = data.split(" ")[2];
Intent iMqttBroadcast = new Intent(ACTION_DATA_ARRIVED);
iMqttBroadcast.putExtra("topico",String.valueOf(topic));
iMqttBroadcast.putExtra("latitude",latitude);
iMqttBroadcast.putExtra("longitude",longitude);
iMqttBroadcast.putExtra("evento","Embarcou");
iMqttBroadcast.putExtra("horario",horario);
sendBroadcast(iMqttBroadcast);
}
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG,"deliveryComplete()");
}
}
Exception Stacktrace
I/MQTTService: connectionLost(): Connection lost
W/System.err: Connection lost (32109) - java.io.EOFException
W/System.err: at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: java.io.EOFException
W/System.err: at java.io.DataInputStream.readByte(DataInputStream.java:77)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
W/System.err: at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
W/System.err: ... 1 more
I think you forgot to include MqttConnectOptions with MqttClient object.
Please try like following
mqttClient.connect(options);
instead of
mqttClient.connect();
Hope it may help to resolve your re-connect issue.
As method description says.
options.setAutomaticReconnect(true);
The client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will doubleuntil it is at 2 minutes at which point the delay will stay at 2 minutes.
Another option would be you could manage retry interval in case of connection lost events.

Android sockets reconnect to server

I'm building a android app that using connection with Java server (on computer).
I have a problem- when I find that there is no connection with the server, I'm trying to reconnect to the server but it doesn't work.
Here is the Client class code:
public class Client extends AsyncTask {
private final int port = 1978;
private final String ip = "192.168.14.22";
private Socket socket;
private DataOutputStream output;
private DataInputStream input;
public Client() {
}
#Override
protected Object doInBackground(Object[] objects) {
try {
socket = new Socket(ip, port);
output = new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(socket.getInputStream());
Log.d("Network c1", "Connected");
} catch (IOException e) {
socket = null;
Log.d("Network c1", "Not connected");
}
return null;
}
public boolean checkConnection() {
if (output == null)
return false;
try {
output.writeUTF("abc");
return true;
} catch (IOException e) {
return false;
}
}
#Override
protected void onProgressUpdate(Object[] values) {
}
}
And the Activity code:
public class LogInActivity extends AppCompatActivity {
Client client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log_in);
client = new Client();
client.execute();
//I used timer because it didn't work without it- That saied always 'not connected' message/Toast
new CountDownTimer(5, 0) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
check();
}
}.start();
}
private void check() {
boolean isProcess;
isProcess = !checkConnection();
if (isProcess) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert);
builder.setTitle(getResources().getString(R.string.app_name));
builder.setMessage("Unable connect to the library");
builder.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//See note 1.
check();
}
});
builder.setCancelable(false);
builder.show();
}
}
public boolean checkConnection() {
if (client.checkConnection()) {
Toast.makeText(getApplicationContext(), "Connected to the library", Toast.LENGTH_SHORT).show();
return true;
} else {
Toast.makeText(this, "Unable connect to the library", Toast.LENGTH_SHORT).show();
return false;
}
}
}
Note 1:
The problem is here.
This Dialog need to be shown until the server/Library connected.
If the server is on before the app turned on, the check() method works well and says 'Connected successful' and the Dialog doesn't show.
But if when the app started, the server was unreachable, and turned on later (And became reachable)- the check() method don't work and always shows the Dialog.
What is the problem?
By the way, I tried to restart the client AsyncTask Class, but i didn't succeed.
(I tried to do close(true) to it, and after do excute() to it again, but the cancel() method didn't worked, and was a error that said that after a AsyncTask Class excuted, it can't excute again)
Thanks.
You should not check for connectivity periodically (every couple of seconds like you do in this code).
Instead you should let the OS do this for you, it will be more reliable and more efficient in terms of battery and CPU.
Take a look at this answer

Connection issue in smack Client is not or no longer connected

I am working on a mobile chat application, last few days I started facing issues with connection (my case is first time my connection works fine but when my app got disconnected (by loosing net connection or wifi turned off or poor network) then my app is reconnected but not able to send messages but at the same time app can receive message): For reconnection I am using reconnectionmanager
I am using smack4.1 library.
Error Details: Client is not or no longer connected
Thanks
my connection and reconnection code is -
XMPPTCPConnectionConfiguration.Builder connConfig = XMPPTCPConnectionConfiguration
.builder();
connConfig
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
connConfig.setUsernameAndPassword(user, pass);
connConfig.setServiceName(SERVICE_NAME);
connConfig.setHost(SERVER_HOST);
connConfig.setPort(SERVER_PORT);
connConfig.setDebuggerEnabled(true);
connConfig.setConnectTimeout(25000);
XMPPTCPConnectionConfiguration configuration = connConfig.build();
connection = new XMPPTCPConnection(configuration);
connection.setUseStreamManagement(true);
connection.setUseStreamManagementResumption(true);
connection.setReplyToUnknownIq(true);
connection.setPacketReplyTimeout(25000);
ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
manager.setFixedDelay(10);
ReconnectionManager.setDefaultReconnectionPolicy (ReconnectionManager.ReconnectionPolicy.FIXED_DELAY);
manager.enableAutomaticReconnection();
ReconnectionManager.setEnabledPerDefault(true);
connection.addConnectionListener(new ConnectionListener() {
#Override
public void connected(XMPPConnection xmppConnection) {
IsConnected = true;
}
#Override
public void authenticated(XMPPConnection xmppConnection, boolean bt) {}
#Override
public void connectionClosed() {
IsConnected = false;
}
#Override
public void connectionClosedOnError(Exception e) {
IsConnected = false;
}
#Override
public void reconnectionSuccessful() {
IsConnected = true;
}
#Override
public void reconnectingIn(int i) {
}
#Override
public void reconnectionFailed(Exception e) {
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
For sending message to user
connection.sendStanza(messsageObj);

XMPP Connection keeps getting disconnected android

im using a service to keep my xmpp connection active at all times here is the code :
public class XMPPService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new ConnectionStatus().execute();
return START_STICKY;
}
#Override
public void onCreate() {
Log.i("service", "created");
}
public class ConnectionStatus extends AsyncTask{
#Override
protected Object doInBackground(Object[] params) {
XMPPClient.getConnection().addConnectionListener(
new AbstractConnectionListener() {
public void connectionClosed() {
Log.i("connection", "closed");
}
public void connectionClosedOnError(Exception e) {
Log.i("connection", "closed on error");
}
public void reconnectionFailed(Exception e) {
Log.i("reconnection", "failed");
}
public void reconnectionSuccessful() {
if (XMPPClient.getConnection().isAuthenticated()) {
Log.i("isauthenticauted : ", String.valueOf(XMPPClient.getConnection().isAuthenticated()));
Log.i("reconnection", "succesful");
} else {
try {
XMPPClient.getConnection().login(new TinyDB(getApplicationContext()).getString("username"), new TinyDB(getApplicationContext()).getString("password"));
} catch (XMPPException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.i("reconnection", "succesful");
}
}
public void reconnectingIn(int seconds) {
Log.i("reconnectingIn", String.valueOf(seconds));
}
}
);
return null;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
but the connection keeps getting disconnected at regular intervals and i get this:
org.jivesoftware.smack.SmackException: Parser got END_DOCUMENT event. This could happen e.g. if the server closed the connection without sending a closing stream element
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1148)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:937)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:952)
at java.lang.Thread.run(Thread.java:818)
and after that it starts reconnecting to the server and then i get this :
09-07 17:56:03.916 17754-20996/com.sports.unity D/SMACK﹕ SENT (0): `09-07 17:56:04.217 17754-20997/com.sports.unity D/SMACK﹕ RECV (0): <?xml version='1.0'?><stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='2025993121' from='mm.io' version='1.0' xml:lang='en'><stream:features><c xmlns='http://jabber.org/protocol/caps' hash='sha-1' node='http://www.process-one.net/en/ejabberd/' ver='Kyn00yB1iXiJLUJ0gVvn7tZREMg='/><register xmlns='http://jabber`
how to keep a stable conenction to the xmpp server
This basically happens when your client is idle greater then idle time (“Idle Connections Policy”) specified on your server.For this you need to implement XMPP Ping classes in your smack/asmack library wherein you have to send XMPP Pong as reply to server ping.
And you could also implement XMPP reconnection classes.

XMPP Connection in seperate thread - Still gets closed by Android OS?

I've got an app with many many services (delivery application for businesses), which connects to an XMPP server to post reports. It's mainly working brilliantly. However, on the odd occasion when connecting over (1/3G) the connection takes too long and the OS kills the app. What's annoying me is that the connection is spawned by a service started by Alarm manager, and I'm using AndroidConnectionConfiguration (aSmack lib), which apparently spawns a seperate thread for connecting to get away from NetworkOnMainUIException. Yet, every so often, my app is still sent a sigabrt signal 6. Why is this happening? I'm not doing anything on the UI, or near it and thought that regardless of time, Android would leave it alone until it was finished or times out itself? Or am I wrong?
Is there anything else I can do to stop this happening? I don't care if XMPP is connected or not, as it will always retry and send when its able, but I can't have the app crashing.
Edit I should say that I'm using aSmack 0.8.10 - And Openfire 3.9.1. But they aren't the problem and work wonderfully well. It's only on the odd occasion that the connection takes too long and Android kills it.
Edit 2 Some code:
package com.goosesys.dta_pta_test.Singletons;
import org.jivesoftware.smack.AndroidConnectionConfiguration;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackAndroid;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import android.content.Context;
import com.google.gson.Gson;
import com.goosesys.dta_pta_test.MessageListenerService;
import com.goosesys.gooselib.Logging;
import com.goosesys.gooselib.Utilities.AppSettings;
import com.goosesys.gooselib.Utilities.Utility;
public class XmppConnector
{
private static XmppConnector instance;
private static boolean isConnected = false;
private static AndroidConnectionConfiguration acc;
private static XMPPConnection xConnection;
private static Context context;
public static void init(Context contxt)
{
if(instance == null)
{
instance = new XmppConnector();
}
context = contxt;
}
public static XmppConnector getInstance()
{
return instance;
}
public static boolean connect() throws XMPPException
{
if(isConnected)
return true;
SmackAndroid.init(context);
acc = new AndroidConnectionConfiguration(AppSettings.XMPP_SERVER_HOST,
AppSettings.XMPP_SERVER_PORT, "Smack");
acc.setSecurityMode(SecurityMode.disabled);
xConnection = new XMPPConnection(acc);
xConnection.addConnectionListener(new ConnectionListener(){
#Override
public void reconnectionSuccessful()
{
Logging.Debug("XmppConnector", "...reconnected to XMPP Server");
}
#Override
public void reconnectionFailed(Exception e)
{
Logging.Debug("XmppConnector", "...reconnection failed: " + e);
}
#Override
public void reconnectingIn(int seconds)
{
Logging.Debug("XmppConnector", "...reconnecting in: " + seconds);
}
#Override
public void connectionClosedOnError(Exception e)
{
Logging.Debug("XmppConnector", "...connection closed on error: " + e);
}
#Override
public void connectionClosed()
{
Logging.Debug("XmppConnector", "...connection closed");
}
});
xConnection.connect();
if(xConnection.isConnected())
{
isConnected = true;
// LOGIN ONCE CONNECTED TO THE SERVER //
xConnection.login(Utility.getAndroidID(context),
AppSettings.XMPP_KEYSTORE_PASSWORD);
// CREATE CHAT MANAGER //
xConnection.getChatManager().addChatListener(new ChatManagerListener(){
#Override
public void chatCreated(final Chat chat, boolean createdLocally)
{
if(!createdLocally)
chat.addMessageListener(new MessageListenerService(context));
}
});
}
else
{
isConnected = false;
}
return isConnected;
}
public static boolean sendMessage(String jsonObj)
{
Message m = new Gson().fromJson(jsonObj, Message.class);
if(m == null)
{
Logging.Error("XmppConnector", "Message object is null.. Aborting");
return false;
}
if(isConnected)
{
xConnection.sendPacket(m);
return true;
}
else
{
return false;
}
}
}
and the small service that kicks it off:
public class BGCollectorProc extends IntentService
{
private DatabaseHelper dbHelper;
public BGCollectorProc()
{
super("BGCollectorProc");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Logging.Debug("BGCollectorProc", "Spinning...");
//dbHelper = DatabaseHelper.getHelper(getApplicationContext());
try
{
// initialise the connection
XmppConnector.init(this);
// get the static reference
XmppConnector.getInstance();
// connect to the server
if(XmppConnector.connect())
{
Logging.Info("BGCollectorProc", "CONNECTED TO XMPP SERVER");
}
}
catch(XMPPException e)
{
e.printStackTrace();
}
/*
// Worker thread area //
try {
postDeliveries();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
postGeoLogs();
*/
return Service.START_NOT_STICKY;
}
Cheers.
SIGABRT usually means that something fatal has happened within dalvik. It's not Android ActivityManager that kills your process. It's the VM that terminates itself because of a VM fault. Usually there will be more information about the fault. Maybe you didn't recognize the logs as related to the SIGABRT. At least I would expect to find some more information about the cause of the SIGABRT in the logs.
BTW: A service that holds an active XMPPConnection is an ideal candidate for a sticky Android service, that should be running as long as the XMPPConnection should be active.

Categories

Resources