diff --git a/res/xml-v14/preferences.xml b/res/xml-v14/preferences.xml
new file mode 100644
index 0000000..3cb1472
--- /dev/null
+++ b/res/xml-v14/preferences.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 3cb1472..d0df23e 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -33,13 +33,11 @@
android:defaultValue="true"
android:enabled="false" />
-
diff --git a/src/org/traccar/client/ClientController.java b/src/org/traccar/client/ClientController.java
new file mode 100644
index 0000000..5c7c856
--- /dev/null
+++ b/src/org/traccar/client/ClientController.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.client;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+import android.content.Context;
+import android.os.Handler;
+
+
+public class ClientController implements Connection.ConnectionHandler {
+
+ public static final long RECONNECT_DELAY = 10 * 1000;
+
+ private Context context;
+
+ private Handler handler;
+ private Queue messageQueue;
+
+ private Connection connection;
+
+ private String address;
+ private int port;
+ private String loginMessage;
+
+ public ClientController(Context context, String address, int port, String loginMessage) {
+ this.context = context;
+ messageQueue = new LinkedList();
+ this.address = address;
+ this.port = port;
+ this.loginMessage = loginMessage;
+ }
+
+ public void start() {
+ handler = new Handler();
+ connection = new Connection(this);
+ connection.connect(address, port);
+ }
+
+ public void stop() {
+ connection.close();
+ handler.removeCallbacksAndMessages(null);
+ }
+
+ private void reconnect() {
+ handler.removeCallbacksAndMessages(null);
+ connection.close();
+ connection = new Connection(this);
+ connection.connect(address, port);
+ }
+
+ private void delayedReconnect() {
+ connection.close();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ connection = new Connection(ClientController.this);
+ connection.connect(address, port);
+ }
+ }, RECONNECT_DELAY);
+ }
+
+ public void setNewServer(String address, int port) {
+ this.address = address;
+ this.port = port;
+ reconnect();
+ }
+
+ public void setNewLogin(String loginMessage) {
+ this.loginMessage = loginMessage;
+ reconnect();
+ }
+
+ public void setNewLocation(String locationMessage) {
+ messageQueue.offer(locationMessage);
+ if (!connection.isClosed() && !connection.isBusy()) {
+ connection.send(messageQueue.poll());
+ }
+ }
+
+ @Override
+ public void onConnected(boolean result) {
+ if (result) {
+ StatusActivity.addMessage(context.getString((R.string.status_connection_success)));
+ connection.send(loginMessage);
+ } else {
+ StatusActivity.addMessage(context.getString((R.string.status_connection_fail)));
+ delayedReconnect();
+ }
+ }
+
+ @Override
+ public void onSent(boolean result) {
+ if (result) {
+ if (!messageQueue.isEmpty()) {
+ connection.send(messageQueue.poll());
+ }
+ } else {
+ StatusActivity.addMessage(context.getString((R.string.status_send_fail)));
+ delayedReconnect();
+ }
+ }
+
+}
diff --git a/src/org/traccar/client/Connection.java b/src/org/traccar/client/Connection.java
index 401ef34..0d4abd8 100644
--- a/src/org/traccar/client/Connection.java
+++ b/src/org/traccar/client/Connection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2012 - 2013 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ import java.io.Closeable;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
-import java.net.SocketAddress;
import android.os.AsyncTask;
import android.util.Log;
@@ -47,44 +46,64 @@ public class Connection implements Closeable {
private Socket socket;
private OutputStream socketStream;
- public Connection(ConnectionHandler handler) {
- this.handler = handler;
+ private boolean closed;
+ private boolean busy;
+
+ public boolean isClosed() {
+ return closed;
}
- public void connect(String address, int port) {
+ public boolean isBusy() {
+ return busy;
+ }
- new AsyncTask() {
+ public Connection(ConnectionHandler handler) {
+ this.handler = handler;
+ closed = false;
+ busy = false;
+ }
+
+ public void connect(final String address, final int port) {
+ busy = true;
+
+ new AsyncTask() {
@Override
- protected Boolean doInBackground(SocketAddress... params) {
+ protected Boolean doInBackground(Void... params) {
try {
socket = new Socket();
- socket.connect(params[0]);
+ socket.connect(new InetSocketAddress(address, port));
socket.setSoTimeout(SOCKET_TIMEOUT);
socketStream = socket.getOutputStream();
- handler.onConnected(true);
+ return true;
} catch (Exception e) {
- close();
+ Log.w(LOG_TAG, e.getMessage());
return false;
}
- return true;
}
@Override
protected void onCancelled(Boolean result) {
- handler.onConnected(false);
+ if (!closed) {
+ busy = false;
+ handler.onConnected(false);
+ }
}
@Override
protected void onPostExecute(Boolean result) {
- handler.onConnected(result);
+ if (!closed) {
+ busy = false;
+ handler.onConnected(result);
+ }
}
- }.execute(InetSocketAddress.createUnresolved(address, port));
+ }.execute();
}
public void send(String message) {
+ busy = true;
new AsyncTask() {
@@ -93,21 +112,27 @@ public class Connection implements Closeable {
try {
socketStream.write(params[0].getBytes());
socketStream.flush();
+ return true;
} catch (Exception e) {
- close();
+ Log.w(LOG_TAG, e.getMessage());
return false;
}
- return true;
}
@Override
protected void onCancelled(Boolean result) {
- handler.onSent(false);
+ if (!closed) {
+ busy = false;
+ handler.onSent(false);
+ }
}
@Override
protected void onPostExecute(Boolean result) {
- handler.onSent(result);
+ if (!closed) {
+ busy = false;
+ handler.onSent(result);
+ }
}
}.execute(message);
@@ -116,14 +141,13 @@ public class Connection implements Closeable {
@Override
public void close() {
+ closed = true;
try {
if (socketStream != null) {
socketStream.close();
- socketStream = null;
}
if (socket != null) {
socket.close();
- socket = null;
}
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
diff --git a/src/org/traccar/client/TraccarService.java b/src/org/traccar/client/TraccarService.java
index 16c02f3..4d2e4e3 100644
--- a/src/org/traccar/client/TraccarService.java
+++ b/src/org/traccar/client/TraccarService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com)
+ * Copyright 2012 - 2013 Anton Tananaev (anton.tananaev@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
@@ -33,45 +32,39 @@ import android.preference.PreferenceManager;
*/
public class TraccarService extends Service {
- public static final long RECONNECT_DELAY = 10 * 1000;
-
private String id;
private String address;
private int port;
private int interval;
- private Handler handler;
- private Connection connection;
- LocationManager locationManager;
-
- private void statusMessage(int message) {
- StatusActivity.addMessage(getString(message));
- }
+ private SharedPreferences sharedPreferences;
+ private ClientController clientController;
+ private LocationManager locationManager;
@Override
public void onCreate() {
- statusMessage(R.string.status_service_create);
-
- handler = new Handler();
- connection = new Connection(connectionHandler);
+ StatusActivity.addMessage(getString((R.string.status_service_create)));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- statusMessage(R.string.status_service_start);
+ StatusActivity.addMessage(getString((R.string.status_service_start)));
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
- updateServerPreferences(sharedPreferences);
- updateIntervalPreferences(sharedPreferences);
- updateOtherPreferences(sharedPreferences);
+ sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- connection.close();
- connection.connect(address, port);
+ address = sharedPreferences.getString(TraccarActivity.KEY_ADDRESS, null);
+ port = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_PORT, null));
+ interval = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_INTERVAL, null));
+ id = sharedPreferences.getString(TraccarActivity.KEY_ID, null);
+
+ clientController = new ClientController(this, address, port, Protocol.createLoginMessage(id));
+ clientController.start();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval * 1000, 0, locationListener);
+ sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
+
return START_STICKY;
}
@@ -82,92 +75,21 @@ public class TraccarService extends Service {
@Override
public void onDestroy() {
- statusMessage(R.string.status_service_destroy);
+ StatusActivity.addMessage(getString((R.string.status_service_destroy)));
+
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
locationManager.removeUpdates(locationListener);
- handler.removeCallbacksAndMessages(null);
- connection.close();
- connection = null;
-
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
+ clientController.stop();
}
- private boolean updateServerPreferences(SharedPreferences sharedPreferences) {
- boolean changed = false;
-
- String address = sharedPreferences.getString(TraccarActivity.KEY_ADDRESS, null);
- if (!address.equals(this.address)) {
- this.address = address;
- changed = true;
- }
-
- int port = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_PORT, null));
- if (port != this.port) {
- this.port = port;
- changed = true;
- }
-
- return changed;
- }
-
- private boolean updateIntervalPreferences(SharedPreferences sharedPreferences) {
- boolean changed = false;
-
- int interval = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_INTERVAL, null));
- if (interval != this.interval) {
- this.interval = interval;
- changed = true;
- }
-
- return changed;
- }
-
- private boolean updateOtherPreferences(SharedPreferences sharedPreferences) {
- id = sharedPreferences.getString(TraccarActivity.KEY_ID, null);
- return false;
- }
-
- private void reconnect() {
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- connection.close();
- connection.connect(address, port);
- }
- }, RECONNECT_DELAY);
- }
-
- private Connection.ConnectionHandler connectionHandler = new Connection.ConnectionHandler() {
-
- @Override
- public void onConnected(boolean result) {
- if (result) {
- statusMessage(R.string.status_connection_success);
- connection.send(Protocol.createLoginMessage(id));
- } else {
- statusMessage(R.string.status_connection_fail);
- reconnect();
- }
- }
-
- @Override
- public void onSent(boolean result) {
- if (!result) {
- statusMessage(R.string.status_send_fail);
- reconnect();
- }
- }
-
- };
-
private LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
- statusMessage(R.string.status_location_update);
- connection.send(Protocol.createLocationMessage(location));
+ StatusActivity.addMessage(getString((R.string.status_location_update)));
+ clientController.setNewLocation(Protocol.createLocationMessage(location));
}
@Override
@@ -188,19 +110,34 @@ public class TraccarService extends Service {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- statusMessage(R.string.status_preference_update);
+ StatusActivity.addMessage(getString((R.string.status_preference_update)));
- if (updateServerPreferences(sharedPreferences)) {
- connection.close();
- connection.connect(address, port);
+ boolean serverChanged = false;
+
+ if (key.equals(TraccarActivity.KEY_ADDRESS)) {
+ address = sharedPreferences.getString(TraccarActivity.KEY_ADDRESS, null);
+ serverChanged = true;
}
- if (updateIntervalPreferences(sharedPreferences)) {
+ if (key.equals(TraccarActivity.KEY_PORT)) {
+ port = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_PORT, null));
+ serverChanged = true;
+ }
+
+ if (serverChanged) {
+ clientController.setNewServer(address, port);
+ }
+
+ if (key.equals(TraccarActivity.KEY_INTERVAL)) {
+ interval = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_INTERVAL, null));
locationManager.removeUpdates(locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval * 1000, 0, locationListener);
}
- updateOtherPreferences(sharedPreferences);
+ if (key.equals(TraccarActivity.KEY_ID)) {
+ id = sharedPreferences.getString(TraccarActivity.KEY_ID, null);
+ clientController.setNewLogin(Protocol.createLoginMessage(id));
+ }
}
};