Skip to content

Commit

Permalink
Add simple visual feedback about connection status
Browse files Browse the repository at this point in the history
  • Loading branch information
Flowdalic committed Aug 28, 2016
1 parent d31ed1d commit dbdec0a
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 18 deletions.
2 changes: 1 addition & 1 deletion aSmack/build.gradle
Expand Up @@ -6,7 +6,7 @@ ext {

android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
buildToolsVersion "24.0.2"

defaultConfig {
minSdkVersion 19
Expand Down
69 changes: 58 additions & 11 deletions aSmack/src/main/java/org/asmack/core/AndroidSmackManager.java
Expand Up @@ -24,6 +24,7 @@

import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
Expand All @@ -34,6 +35,7 @@

import java.io.IOException;
import java.text.Normalizer;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
Expand Down Expand Up @@ -82,7 +84,7 @@ public static synchronized AndroidSmackManager getInstance(Context context) {

private final Context context;

private final Map<XMPPTCPConnection, XmppConnectionStatus> xmppTcpConnections = new WeakHashMap<>();
private final Map<XMPPTCPConnection, ManagedXmppConnection<XMPPTCPConnection>> mManagedConnections = new WeakHashMap<>();

private final Set<NewManagedConnectionListener> mNewConnectionListeners = new CopyOnWriteArraySet<>();

Expand All @@ -92,17 +94,25 @@ private AndroidSmackManager(Context context) {

public XMPPTCPConnection createManagedConnection(XMPPTCPConnectionConfiguration configuration) {
XMPPTCPConnection connection = new XMPPTCPConnection(configuration);
ManagedXmppConnection managedConnection = new ManagedXmppConnection(connection);

for (NewManagedConnectionListener newManagedConnectionListener : mNewConnectionListeners) {
newManagedConnectionListener.newConnection(connection);
newManagedConnectionListener.newConnection(managedConnection);
}

synchronized (xmppTcpConnections) {
xmppTcpConnections.put(connection, new XmppConnectionStatus());
synchronized (managedConnection) {
mManagedConnections.put(connection, managedConnection);
}

return connection;
}

public ManagedXmppConnection<XMPPTCPConnection> getManagedXmppConnectionFor(XMPPTCPConnection connection) {
synchronized (mManagedConnections) {
return mManagedConnections.get(connection);
}
}

public void addNewManagedConnectionListener(NewManagedConnectionListener newManagedConnectionListener) {
mNewConnectionListeners.add(newManagedConnectionListener);
}
Expand All @@ -126,30 +136,67 @@ private void sendIntentToService(String action) {
}

void connectConnections() {
synchronized (xmppTcpConnections) {
for (XMPPTCPConnection connection : xmppTcpConnections.keySet()) {
forAllManagedConnections(new WithXmppConnection<XMPPTCPConnection>() {
@Override
public void withXmppConnection(XMPPTCPConnection connection, ManagedXmppConnection managedXmppConnection) {
try {
connection.connect();
} catch (SmackException | XMPPException | InterruptedException | IOException e) {
LOGGER.log(Level.WARNING, "connect() throw", e);
continue;

managedXmppConnection.getStatus().setStatus(XmppConnectionState.WaitingForRetry);

Iterator<ManagedXmppConnectionListener> it = managedXmppConnection.getListeners().iterator();
while (it.hasNext()) {
ManagedXmppConnectionListener listener = it.next();
listener.connectionAttemptFailed(e, managedXmppConnection);
}

return;
}

try {
connection.login();
} catch (SmackException | XMPPException | InterruptedException | IOException e) {
LOGGER.log(Level.WARNING, "login() throw", e);
continue;

managedXmppConnection.getStatus().setStatus(XmppConnectionState.WaitingForRetry);

Iterator<ManagedXmppConnectionListener> it = managedXmppConnection.getListeners().iterator();
while (it.hasNext()) {
ManagedXmppConnectionListener listener = it.next();
listener.loginAttemptFailed(e, managedXmppConnection);
}

return;
}
}
}
});
}

void disconnectConnections() {
synchronized (xmppTcpConnections) {
for (XMPPTCPConnection connection : xmppTcpConnections.keySet()) {
forAllManagedConnections(new WithXmppConnection<XMPPTCPConnection>() {
@Override
public void withXmppConnection(XMPPTCPConnection connection, ManagedXmppConnection managedXmppConnection) {
connection.disconnect();
}
});
}

void forAllManagedConnections(WithXmppConnection<XMPPTCPConnection> withXmppConnection) {
synchronized (mManagedConnections) {
for (ManagedXmppConnection<XMPPTCPConnection> managedXmppConnection : mManagedConnections.values()) {
final XMPPTCPConnection connection = managedXmppConnection.getConnection();
if (connection == null) {
mManagedConnections.remove(managedXmppConnection);
continue;
}
withXmppConnection.withXmppConnection(connection, managedXmppConnection);
}
}
}

interface WithXmppConnection<C extends XMPPConnection> {
void withXmppConnection(C connection, ManagedXmppConnection<C> managedConnection);
}
}
57 changes: 57 additions & 0 deletions aSmack/src/main/java/org/asmack/core/ManagedXmppConnection.java
@@ -0,0 +1,57 @@
/*
* Copyright ⓒ 2016 Florian Schmaus.
*
* This file is part of XIOT.
*
* XIOT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* XIOT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XIOT. If not, see <http://www.gnu.org/licenses/>.
*/

package org.asmack.core;

import org.jivesoftware.smack.XMPPConnection;

import java.lang.ref.WeakReference;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class ManagedXmppConnection<C extends XMPPConnection> {

private final WeakReference<C> mConnection;
private final XmppConnectionStatus mStatus = new XmppConnectionStatus();
private final Set<ManagedXmppConnectionListener> listeners = new CopyOnWriteArraySet<>();

ManagedXmppConnection(C connection) {
mConnection = new WeakReference<>(connection);
}

public C getConnection() {
return mConnection.get();
}

public void addListener(ManagedXmppConnectionListener listener) {
listeners.add(listener);
}

public boolean removeListener(ManagedXmppConnectionListener listener) {
return listeners.remove(listener);
}

Set<ManagedXmppConnectionListener> getListeners() {
return listeners;
}

XmppConnectionStatus getStatus() {
return mStatus;
}
}
@@ -0,0 +1,30 @@
/*
* Copyright ⓒ 2016 Florian Schmaus.
*
* This file is part of XIOT.
*
* XIOT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* XIOT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XIOT. If not, see <http://www.gnu.org/licenses/>.
*/

package org.asmack.core;

public interface ManagedXmppConnectionListener {

void connectionAttemptFailed(Exception e, ManagedXmppConnection connection);

void loginAttemptFailed(Exception e, ManagedXmppConnection connection);

void stateChanged(XmppConnectionState oldState, XmppConnectionState newState, ManagedXmppConnection connection);

}
Expand Up @@ -19,9 +19,7 @@

package org.asmack.core;

import org.jivesoftware.smack.tcp.XMPPTCPConnection;

public interface NewManagedConnectionListener {

void newConnection(XMPPTCPConnection connection);
void newConnection(ManagedXmppConnection connection);
}
12 changes: 10 additions & 2 deletions aSmack/src/main/java/org/asmack/core/XmppConnectionStatus.java
Expand Up @@ -21,7 +21,15 @@

public class XmppConnectionStatus {

private XmppConnectionState state;
private String optionalInfo;
private XmppConnectionState mState;
private String mOptionalInfo;

void setStatus(XmppConnectionState state) {
setStatus(state, null);
}

void setStatus(XmppConnectionState state, String optionalInfo) {
mState = state;
mOptionalInfo = optionalInfo;
}
}
2 changes: 1 addition & 1 deletion app/build.gradle
Expand Up @@ -24,7 +24,7 @@ if (keystorePropertiesFile.exists()) {

android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
buildToolsVersion "24.0.2"

defaultConfig {
applicationId "com.clayster.xmppiotdemo"
Expand Down
21 changes: 21 additions & 0 deletions app/src/main/java/com/clayster/xmppiotdemo/XmppManager.java
Expand Up @@ -25,6 +25,8 @@
import android.widget.Toast;

import org.asmack.core.AndroidSmackManager;
import org.asmack.core.ManagedXmppConnection;
import org.asmack.core.ManagedXmppConnectionListener;
import org.asmack.core.XmppConnectionState;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
Expand Down Expand Up @@ -116,6 +118,25 @@ public void adoptXmppConfiguration() {
XMPPTCPConnectionConfiguration conf = builder.build();

xmppConnection = asmackManager.createManagedConnection(conf);
ManagedXmppConnection<XMPPTCPConnection> managedXmppConnection = asmackManager.getManagedXmppConnectionFor(xmppConnection);
managedXmppConnection.addListener(new ManagedXmppConnectionListener() {
@Override
public void connectionAttemptFailed(Exception e, ManagedXmppConnection connection) {
withMainActivity((ma) -> Toast.makeText(ma, "Connection failed: " + e, Toast.LENGTH_LONG).show());
}

@Override
public void loginAttemptFailed(Exception e, ManagedXmppConnection connection) {
withMainActivity((ma) -> Toast.makeText(ma, "Login failed: " + e, Toast.LENGTH_LONG).show());
}

@Override
public void stateChanged(XmppConnectionState oldState, XmppConnectionState newState, ManagedXmppConnection connection) {
withMainActivity((ma) -> Toast.makeText(ma,
"Connection state change from " + oldState + " to " + newState, Toast.LENGTH_LONG).show());
}
});


for (XmppConnectionListener listener : mXmppConnectionStatusListeners) {
listener.newConnection(xmppConnection);
Expand Down

0 comments on commit dbdec0a

Please sign in to comment.