diff --git a/app/src/main/java/fr/chteufleur/mytrackingdog/models/beans/RandomString.java b/app/src/main/java/fr/chteufleur/mytrackingdog/models/beans/RandomString.java
new file mode 100644
index 0000000..e5962d2
--- /dev/null
+++ b/app/src/main/java/fr/chteufleur/mytrackingdog/models/beans/RandomString.java
@@ -0,0 +1,61 @@
+package fr.chteufleur.mytrackingdog.models.beans;
+
+import java.security.SecureRandom;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Random;
+
+public class RandomString {
+
+ /**
+ * Generate a random string.
+ */
+ public String nextString() {
+ for (int idx = 0; idx < buf.length; ++idx)
+ buf[idx] = symbols[random.nextInt(symbols.length)];
+ return new String(buf);
+ }
+
+ public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ public static final String lower = upper.toLowerCase(Locale.ROOT);
+
+ public static final String digits = "0123456789";
+
+ public static final String alphanum = upper + lower + digits;
+
+ private final Random random;
+
+ private final char[] symbols;
+
+ private final char[] buf;
+
+ public RandomString(int length, Random random, String symbols) {
+ if (length < 1) throw new IllegalArgumentException();
+ if (symbols.length() < 2) throw new IllegalArgumentException();
+ this.random = Objects.requireNonNull(random);
+ this.symbols = symbols.toCharArray();
+ this.buf = new char[length];
+ }
+
+ /**
+ * Create an alphanumeric string generator.
+ */
+ public RandomString(int length, Random random) {
+ this(length, random, alphanum);
+ }
+
+ /**
+ * Create an alphanumeric strings from a secure generator.
+ */
+ public RandomString(int length) {
+ this(length, new SecureRandom());
+ }
+
+ /**
+ * Create session identifiers.
+ */
+ public RandomString() {
+ this(36);
+ }
+}
diff --git a/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceTrackingDog.java b/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceTrackingDog.java
index 3e90276..a3e7a8f 100644
--- a/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceTrackingDog.java
+++ b/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceTrackingDog.java
@@ -69,7 +69,7 @@ public class ServiceTrackingDog implements Observer {
this.serviceGps.addObserver(this);
ServiceXmpp sx;
try {
- sx = new ServiceXmpp(resources);
+ sx = new ServiceXmpp(preferences, resources);
sx.addObserver(this);
} catch (UnknownHostException | XmppStringprepException ex) {
sx = null;
diff --git a/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceXmpp.java b/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceXmpp.java
index 147d04f..41604ff 100644
--- a/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceXmpp.java
+++ b/app/src/main/java/fr/chteufleur/mytrackingdog/services/ServiceXmpp.java
@@ -1,5 +1,6 @@
package fr.chteufleur.mytrackingdog.services;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Environment;
import android.os.StrictMode;
@@ -9,7 +10,9 @@ import com.google.zxing.WriterException;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
+import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.roster.PresenceEventListener;
@@ -25,10 +28,13 @@ import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
+import org.jivesoftware.smackx.iqregister.AccountManager;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
+import org.jxmpp.jid.parts.Localpart;
+import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
import java.io.File;
@@ -37,10 +43,12 @@ import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.Observable;
+import java.util.Random;
import fr.chteufleur.mytrackingdog.QRCodeGeneratorActivity;
import fr.chteufleur.mytrackingdog.models.Notification;
import fr.chteufleur.mytrackingdog.models.beans.MyLocation;
+import fr.chteufleur.mytrackingdog.models.beans.RandomString;
import fr.chteufleur.mytrackingdog.models.xmpp.commands.ObjectGeolocCommand;
import fr.chteufleur.mytrackingdog.models.xmpp.commands.RealTimeModeCommand;
import fr.chteufleur.mytrackingdog.models.xmpp.commands.StartTrailGeolocCommand;
@@ -53,7 +61,7 @@ import fr.chteufleur.mytrackingdog.models.xmpp.commands.send.SendStartTrailComma
import fr.chteufleur.mytrackingdog.models.xmpp.commands.send.SendStopTrailCommand;
import fr.chteufleur.mytrackingdog.models.xmpp.commands.send.SendTrailLocationCommand;
-public class ServiceXmpp extends Observable implements Runnable, PresenceEventListener, FileTransferListener {
+public class ServiceXmpp extends Observable implements Runnable, ConnectionListener, PresenceEventListener, FileTransferListener {
public static final String TAG = ServiceXmpp.class.getName();
@@ -79,15 +87,29 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
public static final String XMPP_NODE_REAL_TIME_MODE = "real_time_mode";
private static final String XMPP_IP_SERVER = "51.254.205.203";
- private static final String XMPP_DOMAIN_SERVER = "anon.xmpp.kingpenguin.tk";
+// private static final String XMPP_DOMAIN_SERVER = "anon.xmpp.kingpenguin.tk";
+// private static final String XMPP_DOMAIN_SERVER = "dog.xmpp.kingpenguin.tk";
+ private static final String XMPP_DOMAIN_SERVER = "kingpenguin.tk";
private static final int XMPP_PORT = 5222;
+ //
+ private final SharedPreferences preferences;
+ private static final String PREF_XMPP_USER = "PREF_XMPP_USER";
+ private static final String PREF_XMPP_PASSWORD = "PREF_XMPP_PASSWORD";
+ private static final String PREF_XMPP_ACCOUNT_REGISTERED = "PREF_XMPP_ACCOUNT_REGISTERED";
+
+ private String prefXmppUser;
+ private String prefXmppPassword;
+ private boolean prefAccountRegistered;
+ //
+
private String appName = "";
private final Resources resources;
private final XMPPTCPConnectionConfiguration configuration;
private AdHocCommandManager commandManager;
private FileTransferManager fileManager;
+ private AccountManager accountManager;
private AbstractXMPPConnection connection;
private String jid;
private String otherJid;
@@ -97,7 +119,8 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
private boolean isEnable = false;
private boolean isRealTimeMode = false;
- public ServiceXmpp(Resources resources) throws UnknownHostException, XmppStringprepException {
+ public ServiceXmpp(SharedPreferences preferences, Resources resources) throws UnknownHostException, XmppStringprepException {
+ this.preferences = preferences;
this.resources = resources;
this.configuration = XMPPTCPConnectionConfiguration.builder()
.setSecurityMode(ConnectionConfiguration.SecurityMode.ifpossible)
@@ -105,9 +128,30 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
.setPort(XMPP_PORT)
.setXmppDomain(XMPP_DOMAIN_SERVER)
.setDebuggerEnabled(true)
- .performSaslAnonymousAuthentication()
+// .performSaslAnonymousAuthentication()
.setKeystoreType(null)
.build();
+
+ if (!preferences.contains(PREF_XMPP_USER)) {
+ RandomString random = new RandomString();
+ prefXmppUser = random.nextString();
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(PREF_XMPP_USER, prefXmppUser);
+ editor.commit();
+ } else {
+ prefXmppUser = preferences.getString(PREF_XMPP_USER, "");
+ }
+ if (!preferences.contains(PREF_XMPP_PASSWORD)) {
+ RandomString random = new RandomString();
+ prefXmppPassword = random.nextString();
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(PREF_XMPP_PASSWORD, prefXmppPassword);
+ editor.commit();
+ } else {
+ prefXmppPassword = preferences.getString(PREF_XMPP_PASSWORD, "");
+ }
+ prefAccountRegistered = preferences.getBoolean(PREF_XMPP_ACCOUNT_REGISTERED, false);
+
this.thsi = this;
new Thread(this).start();
}
@@ -116,43 +160,19 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
this.appName = appName;
}
- public boolean connect() throws InterruptedException, XMPPException, SmackException, IOException {
+ public void connect() throws InterruptedException, XMPPException, SmackException, IOException {
if (!isEnable) {
- return false;
+ return;
}
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
boolean isConnected;
connection = new XMPPTCPConnection(configuration);
+ connection.addConnectionListener(this);
commandManager = AdHocCommandManager.getAddHocCommandsManager(connection);
fileManager = FileTransferManager.getInstanceFor(connection);
connection.connect();
- connection.login();
-
- registerCommands();
- fileManager.addFileTransferListener(this);
- Roster roster = Roster.getInstanceFor(connection);
- roster.addPresenceEventListener(this);
-
- isConnected = connection.isConnected();
- if (isConnected) {
- jid = connection.getUser().asFullJidIfPossible().toString();
- Log.i(TAG, "JID: "+jid);
- setPresenceAvailable();
- }
- Runnable r = new Runnable() {
- @Override
- public void run() {
- try {
- QRCodeGeneratorActivity.textToImageEncode(jid, resources);
- } catch (WriterException ex) {
- Log.e(TAG, "Failed to generate QR Code");
- }
- }
- };
- new Thread(r).start();
- return isConnected;
}
public void close() {
@@ -194,6 +214,7 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
command.executeCommand();
} catch (Exception e) {
e.printStackTrace();
+ sendCommandFirst(command);
}
}
}
@@ -217,6 +238,103 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
return this.isRealTimeMode;
}
+
+ //
+ @Override
+ public void connected(XMPPConnection _connection) {
+ if (!prefAccountRegistered) {
+ accountManager = AccountManager.getInstance(connection);
+ try {
+ if (accountManager.supportsAccountCreation()) {
+ accountManager.createAccount(Localpart.from(prefXmppUser), prefXmppPassword);
+ }
+ } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException | XmppStringprepException e) {
+ e.printStackTrace();
+ }
+ }
+
+ try {
+ connection.login(prefXmppUser, prefXmppPassword, Resourcepart.from("MyTrackingDog"));
+ } catch (XmppStringprepException e) {
+ e.printStackTrace();
+ } catch (InterruptedException | IOException | SmackException | XMPPException e) {
+ e.printStackTrace();
+ }
+
+ registerCommands();
+ fileManager.addFileTransferListener(this);
+ Roster roster = Roster.getInstanceFor(connection);
+ roster.addPresenceEventListener(this);
+ }
+
+ @Override
+ public void authenticated(XMPPConnection connection, boolean resumed) {
+ jid = connection.getUser().asFullJidIfPossible().toString();
+ Log.i(TAG, "JID: "+jid);
+
+ prefAccountRegistered = true;
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(PREF_XMPP_ACCOUNT_REGISTERED, prefAccountRegistered);
+ editor.commit();
+
+ try {
+ setPresenceAvailable();
+ } catch (SmackException.NotConnectedException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ QRCodeGeneratorActivity.textToImageEncode(jid, resources);
+ } catch (WriterException ex) {
+ Log.e(TAG, "Failed to generate QR Code");
+ }
+ }
+ };
+ new Thread(r).start();
+
+ }
+
+ @Override
+ public void connectionClosed() {
+ Log.i(TAG, "connectionClosed");
+ }
+
+ @Override
+ public void connectionClosedOnError(Exception e) {
+ Log.i(TAG, "connectionClosedOnError");
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(10_000);
+ connection.connect();
+ } catch (SmackException | IOException | XMPPException | InterruptedException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void reconnectionSuccessful() {
+ Log.i(TAG, "reconnectionSuccessful");
+ }
+
+ @Override
+ public void reconnectingIn(int seconds) {
+ Log.i(TAG, "reconnectingIn");
+ }
+
+ @Override
+ public void reconnectionFailed(Exception e) {
+ Log.i(TAG, "reconnectionFailed");
+ }
+ //
+
//
public void sendPresenceAvailable() throws SmackException.NotConnectedException, InterruptedException, XmppStringprepException {
if (otherJid != null) {
@@ -397,6 +515,14 @@ public class ServiceXmpp extends Observable implements Runnable, PresenceEventLi
}
}
+ private void sendCommandFirst(SendCommand command) {
+ if (command != null) {
+ synchronized (listSendCommand) {
+ listSendCommand.addFirst(command);
+ }
+ }
+ }
+
private SendCommand getNextCommand() {
SendCommand ret = null;
synchronized (listSendCommand) {