diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4de6905..40f5e88 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -14,8 +14,7 @@
+ android:label="@string/app_name">
@@ -24,7 +23,17 @@
-
+
+
+
+
+
+
+
diff --git a/res/layout/about.xml b/res/layout/about.xml
new file mode 100644
index 0000000..f7b419a
--- /dev/null
+++ b/res/layout/about.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/main.xml b/res/layout/main.xml
deleted file mode 100644
index e327941..0000000
--- a/res/layout/main.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/status.xml b/res/layout/status.xml
new file mode 100644
index 0000000..a659a35
--- /dev/null
+++ b/res/layout/status.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/main.xml b/res/menu/main.xml
index c5391c5..4cfe5b2 100644
--- a/res/menu/main.xml
+++ b/res/menu/main.xml
@@ -1,7 +1,14 @@
+
+
+
+
+
diff --git a/res/menu/status.xml b/res/menu/status.xml
new file mode 100644
index 0000000..3e977f4
--- /dev/null
+++ b/res/menu/status.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100644
index 0000000..dd5b0f3
--- /dev/null
+++ b/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 20dp
+ 15dp
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1070fbe..ea09ede 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,8 +1,39 @@
+
Traccar Client
- Invalid input parameters.
- About
- Android software GPS tracker. For more information visit:\n\nhttp://www.traccar.org
- Close
+ Traccar
+
+ Device identifier
+ Server address
+ Domain name or IP address
+ Server port
+ Tracking server TCP port
+ Frequency
+ Messages interval in seconds
+ Debug mode
+ Additional status messages
+ Service status
+ Start
+ Stop
+ Service stopped
+ Service running
+
+ Status
+ About
+ Clear
+
+ Real time GPS tracker for Android devices. Compatible with Traccar Server and other tracking systems.
+ This application is free and open source, source code is licensed under Apache License Version 2.0 and available on GitHub.
+ For more information visit\nwww.traccar.org/client
+
+ Service created
+ Service started
+ Service destroyed
+ Connection succeeded
+ Connection failed
+ Send failed
+ Location update
+ Preference update
+
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
new file mode 100644
index 0000000..7d02d68
--- /dev/null
+++ b/res/xml/preferences.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/traccar/client/AboutActivity.java b/src/org/traccar/client/AboutActivity.java
new file mode 100644
index 0000000..eaf9e07
--- /dev/null
+++ b/src/org/traccar/client/AboutActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 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 android.app.Activity;
+import android.os.Bundle;
+
+public class AboutActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.about);
+ }
+
+}
diff --git a/src/org/traccar/client/Connection.java b/src/org/traccar/client/Connection.java
index 23fb577..401ef34 100644
--- a/src/org/traccar/client/Connection.java
+++ b/src/org/traccar/client/Connection.java
@@ -15,139 +15,119 @@
*/
package org.traccar.client;
+import java.io.Closeable;
import java.io.OutputStream;
+import java.net.InetSocketAddress;
import java.net.Socket;
+import java.net.SocketAddress;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
+import android.os.AsyncTask;
+import android.util.Log;
/**
- * Connection with autoreconnect
+ * Asynchronous connection
+ *
+ * All methods should be called from UI thread only.
*/
-public class Connection {
+public class Connection implements Closeable {
- private String address;
- private int port;
+ public static final String LOG_TAG = "Traccar.Connection";
+ public static final int SOCKET_TIMEOUT = 10 * 1000;
- private String connectMessage;
+ /**
+ * Callback interface
+ */
+ public interface ConnectionHandler {
+ void onConnected(boolean result);
+ void onSent(boolean result);
+ }
+
+ private ConnectionHandler handler;
private Socket socket;
private OutputStream socketStream;
- private String status;
-
- private Context context;
-
- /**
- * Initialize connection parameters
- */
- public Connection(String address, int port, String message) {
- this.address = address;
- this.port = port;
- connectMessage = message;
- setStatus(Traccar.STATUS_DISCONNECTED);
+ public Connection(ConnectionHandler handler) {
+ this.handler = handler;
}
- /**
- * Get address
- */
- public String getAddress() {
- return address;
- }
+ public void connect(String address, int port) {
- /**
- * Get port
- */
- public int getPort() {
- return port;
- }
+ new AsyncTask() {
- /**
- * Set context
- */
- public void setContext(Context context) {
- this.context = context;
- }
-
- /**
- * Set connection status
- */
- private void setStatus(String status) {
- if (!status.equals(this.status)) {
- this.status = status;
- if (context != null) {
- Intent intent = new Intent(Traccar.MSG_CONNECTION_STATUS);
- intent.putExtra(Traccar.EXTRA_STATUS, status);
- context.sendBroadcast(intent);
+ @Override
+ protected Boolean doInBackground(SocketAddress... params) {
+ try {
+ socket = new Socket();
+ socket.connect(params[0]);
+ socket.setSoTimeout(SOCKET_TIMEOUT);
+ socketStream = socket.getOutputStream();
+ handler.onConnected(true);
+ } catch (Exception e) {
+ close();
+ return false;
+ }
+ return true;
}
- }
+
+ @Override
+ protected void onCancelled(Boolean result) {
+ handler.onConnected(false);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ handler.onConnected(result);
+ }
+
+ }.execute(InetSocketAddress.createUnresolved(address, port));
+
}
- /**
- * Get connection status
- */
- public String getStatus() {
- return status;
- }
-
- /**
- * Establish connection
- */
- public void connect() {
- try {
- socket = new Socket(address, port);
- socket.setSoTimeout(Traccar.SOCKET_TIMEOUT);
- socketStream = socket.getOutputStream();
- setStatus(Traccar.STATUS_CONNECTED);
- send(connectMessage);
- } catch (Exception e) {
- reconnect();
- }
- }
-
- /**
- * Send message
- */
public void send(String message) {
+
+ new AsyncTask() {
+
+ @Override
+ protected Boolean doInBackground(String... params) {
+ try {
+ socketStream.write(params[0].getBytes());
+ socketStream.flush();
+ } catch (Exception e) {
+ close();
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onCancelled(Boolean result) {
+ handler.onSent(false);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ handler.onSent(result);
+ }
+
+ }.execute(message);
+
+ }
+
+ @Override
+ public void close() {
try {
if (socketStream != null) {
- socketStream.write(message.getBytes());
- socketStream.flush();
+ socketStream.close();
+ socketStream = null;
+ }
+ if (socket != null) {
+ socket.close();
+ socket = null;
}
} catch (Exception e) {
- reconnect();
+ Log.e(LOG_TAG, e.getMessage());
}
}
- /**
- * Close connection
- */
- public void close() {
- handler.removeCallbacks(task);
- if (socket != null) {
- try {
- socket.close();
- } catch (Exception e) {
- }
- socket = null;
- }
- socketStream = null;
- setStatus(Traccar.STATUS_DISCONNECTED);
- }
-
- private void reconnect() {
- close();
- handler.postDelayed(task, Traccar.RECONNECT_DELAY);
- }
-
- private Handler handler = new Handler();
- private ReconnectTask task = new ReconnectTask();
-
- class ReconnectTask implements Runnable {
- @Override
- public void run() {
- connect();
- }
- }
}
diff --git a/src/org/traccar/client/Protocol.java b/src/org/traccar/client/Protocol.java
index ba91e96..0481f4f 100644
--- a/src/org/traccar/client/Protocol.java
+++ b/src/org/traccar/client/Protocol.java
@@ -28,7 +28,7 @@ public class Protocol {
/**
* Format device id message
*/
- public static String createId(String id) {
+ public static String createLoginMessage(String id) {
StringBuilder s = new StringBuilder("$PGID,");
Formatter f = new Formatter(s, Locale.ENGLISH);
@@ -47,9 +47,9 @@ public class Protocol {
/**
* Format location message
*/
- public static String createNmea(Location l) {
+ public static String createLocationMessage(Location l) {
StringBuilder s = new StringBuilder("$GPRMC,");
- Formatter f = new Formatter(s, Locale.ENGLISH); // Should use DecimalFormat instead
+ Formatter f = new Formatter(s, Locale.ENGLISH);
f.format("%1$tH%1$tM%1$tS.%1$tL,A,", l.getTime());
diff --git a/src/org/traccar/client/StatusActivity.java b/src/org/traccar/client/StatusActivity.java
new file mode 100644
index 0000000..29d4eed
--- /dev/null
+++ b/src/org/traccar/client/StatusActivity.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 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.text.DateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+
+public class StatusActivity extends ListActivity {
+
+ private static final List messages = new LinkedList();
+ private static final Set> adapters = new HashSet>();
+
+ private static void notifyAdapters() {
+ for (ArrayAdapter adapter : adapters) {
+ adapter.notifyDataSetChanged();
+ }
+ }
+
+ public static void addMessage(String message) {
+ DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
+ message = format.format(new Date()) + " - " + message;
+ messages.add(message);
+ notifyAdapters();
+ }
+
+ public static void clearMessages() {
+ messages.clear();
+ notifyAdapters();
+ }
+
+ private ArrayAdapter adapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.status);
+ adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, android.R.id.text1, messages);
+ setListAdapter(adapter);
+ adapters.add(adapter);
+ }
+
+ @Override
+ protected void onDestroy() {
+ adapters.remove(adapter);
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.status, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.clear) {
+ clearMessages();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+}
diff --git a/src/org/traccar/client/TraccarActivity.java b/src/org/traccar/client/TraccarActivity.java
index e1a4ff0..5dc9bc5 100644
--- a/src/org/traccar/client/TraccarActivity.java
+++ b/src/org/traccar/client/TraccarActivity.java
@@ -15,209 +15,106 @@
*/
package org.traccar.client;
-import java.util.*;
-import android.app.*;
-import android.content.*;
-import android.os.*;
-import android.text.*;
-import android.text.method.*;
-import android.text.util.*;
-import android.view.*;
-import android.widget.*;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
import android.telephony.TelephonyManager;
-
-/**
- * Global parameters
- */
-class Traccar {
- public static final String EXTRA_ADDRESS = "address";
- public static final String EXTRA_PORT = "port";
- public static final String EXTRA_PERIOD = "period";
- public static final String EXTRA_STATUS = "status";
-
- public static final String DEFAULT_ADDRESS = "193.193.165.166";
- public static final String DEFAULT_PORT = "20100";
- public static final String DEFAULT_PERIOD = "60";
-
- public static final String TRACCAR_SETTINGS = "traccar_settings";
-
- public static final long RECONNECT_DELAY = 10 * 1000;
- public static final int SOCKET_TIMEOUT = 2000;
-
- public static final String MSG_UPDATE = "org.traccar.client.MSG_UPDATE";
- public static final String MSG_SERVICE_CONFIG = "org.traccar.client.MSG_SERVICE_CONFIG";
- public static final String MSG_SERVICE_STATUS = "org.traccar.client.SERVICE_STATUS";
- public static final String MSG_CONNECTION_STATUS = "org.traccar.client.CONNECTION_STATUS";
-
- public static final String STATUS_STOPPED = "Stopped";
- public static final String STATUS_RUNNING = "Running";
-
- public static final String STATUS_CONNECTED = "Connected";
- public static final String STATUS_DISCONNECTED = "Disconnected";
-}
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
/**
* Main user interface
*/
-public class TraccarActivity extends Activity {
+@SuppressWarnings("deprecation")
+public class TraccarActivity extends PreferenceActivity {
- private EditText editAddress;
- private EditText editPort;
- private EditText editPeriod;
- private EditText editDevice;
- private EditText editService;
- private EditText editConnection;
- private ToggleButton button;
+ public static final String KEY_ID = "id";
+ public static final String KEY_ADDRESS = "address";
+ public static final String KEY_PORT = "port";
+ public static final String KEY_INTERVAL = "interval";
+ public static final String KEY_DEBUG = "debug";
+ public static final String KEY_STATUS = "status";
- public boolean isServiceRunning() {
- ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- List services = activityManager.getRunningServices(Integer.MAX_VALUE);
- for (ActivityManager.RunningServiceInfo runningServiceInfo : services) {
- if (runningServiceInfo.service.getClassName().equals(TraccarService.class.getName())){
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.preferences);
+ initPreferences();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(
+ preferenceChangeListener);
+ }
+
+ @Override
+ protected void onPause() {
+ getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
+ preferenceChangeListener);
+ super.onPause();
+ }
+
+ OnSharedPreferenceChangeListener preferenceChangeListener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key.equals(KEY_STATUS)) {
+ if (sharedPreferences.getBoolean(KEY_STATUS, false)) {
+ startService(new Intent(TraccarActivity.this, TraccarService.class));
+ } else {
+ stopService(new Intent(TraccarActivity.this, TraccarService.class));
+ }
+ }
+ }
+ };
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.status) {
+ startActivity(new Intent(this, StatusActivity.class));
+ return true;
+ } else if (item.getItemId() == R.id.about) {
+ startActivity(new Intent(this, AboutActivity.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private boolean isServiceRunning() {
+ ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
+ if (TraccarService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
+ private void initPreferences() {
- // DO SOMETHING WITH IT
- try {
- StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
- StrictMode.setThreadPolicy(policy);
- } catch(Throwable e) {
- }
-
- // Bind elements
- editAddress = (EditText) findViewById(R.id.edit_address);
- editPort = (EditText) findViewById(R.id.edit_port);
- editPeriod = (EditText) findViewById(R.id.edit_period);
- editDevice = (EditText) findViewById(R.id.edit_device);
- editService = (EditText) findViewById(R.id.edit_service);
- editConnection = (EditText) findViewById(R.id.edit_connection);
- button = (ToggleButton) findViewById(R.id.button);
-
- // Set device identifier
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- editDevice.setText(telephonyManager.getDeviceId());
+ String id = telephonyManager.getDeviceId();
- editService.setText(Traccar.STATUS_STOPPED);
- editConnection.setText(Traccar.STATUS_DISCONNECTED);
- button.setChecked(isServiceRunning());
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- //super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if(item.getItemId() == R.id.about){
- showAboutDialog();
- return true;
- }
- return false;
- }
-
- public void showAboutDialog() {
- TextView message = new TextView(this);
- SpannableString str = new SpannableString(getString(R.string.about_text));
- Linkify.addLinks(str, Linkify.WEB_URLS);
- message.setText(str);
- message.setMovementMethod(LinkMovementMethod.getInstance());
- int padding = (int) (10 * getResources().getDisplayMetrics().scaledDensity);
- message.setPadding(padding, padding, padding, padding);
+ SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
- AlertDialog.Builder dialog = new AlertDialog.Builder(this);
- dialog.setTitle(R.string.about_option);
- dialog.setView(message);
- dialog.setPositiveButton(R.string.about_close, null);
- dialog.show();
+ sharedPreferences.edit().putString(KEY_ID, id).commit();
+ findPreference(KEY_ID).setSummary(id);
+
+ sharedPreferences.edit().putBoolean(KEY_STATUS, isServiceRunning()).commit();
}
- private BroadcastReceiver serviceConfigReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- editAddress.setText(intent.getStringExtra(Traccar.EXTRA_ADDRESS));
- editPort.setText(String.valueOf(intent.getIntExtra(Traccar.EXTRA_PORT, 0)));
- editPeriod.setText(String.valueOf(intent.getIntExtra(Traccar.EXTRA_PERIOD, 0)));
- }
- };
-
- private BroadcastReceiver serviceStatusReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- editService.setText(intent.getStringExtra(Traccar.EXTRA_STATUS));
- }
- };
-
- private BroadcastReceiver connectionStatusReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- editConnection.setText(intent.getStringExtra(Traccar.EXTRA_STATUS));
- }
- };
-
- @Override
- protected void onStart() {
- super.onStart();
- loadSettings();
-
- // Register receivers
- registerReceiver(serviceConfigReceiver, new IntentFilter(Traccar.MSG_SERVICE_CONFIG));
- registerReceiver(serviceStatusReceiver, new IntentFilter(Traccar.MSG_SERVICE_STATUS));
- registerReceiver(connectionStatusReceiver, new IntentFilter(Traccar.MSG_CONNECTION_STATUS));
-
- // Request update
- sendBroadcast(new Intent(Traccar.MSG_UPDATE));
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- saveSettings();
-
- // Unregister receivers
- unregisterReceiver(serviceConfigReceiver);
- unregisterReceiver(serviceStatusReceiver);
- unregisterReceiver(connectionStatusReceiver);
- }
-
- public void onButtonClick(View v) {
- if (button.isChecked()) {
- try {
- Intent serviceIntent = new Intent(this, TraccarService.class);
- serviceIntent.putExtra(Traccar.EXTRA_ADDRESS, editAddress.getText().toString());
- serviceIntent.putExtra(Traccar.EXTRA_PORT, Integer.parseInt(editPort.getText().toString()));
- serviceIntent.putExtra(Traccar.EXTRA_PERIOD, Integer.parseInt(editPeriod.getText().toString()));
- startService(serviceIntent);
- } catch (NumberFormatException e) {
- Toast.makeText(this, R.string.error_input, Toast.LENGTH_SHORT).show();
- button.setChecked(false);
- }
- } else {
- stopService(new Intent(this, TraccarService.class));
- }
- }
-
- public void saveSettings() {
- SharedPreferences settings = getSharedPreferences(Traccar.TRACCAR_SETTINGS, 0);
- SharedPreferences.Editor editor = settings.edit();
- editor.putString(Traccar.EXTRA_ADDRESS, editAddress.getText().toString());
- editor.putString(Traccar.EXTRA_PORT, editPort.getText().toString());
- editor.putString(Traccar.EXTRA_PERIOD, editPeriod.getText().toString());
- editor.commit();
- }
-
- public void loadSettings() {
- SharedPreferences settings = getSharedPreferences(Traccar.TRACCAR_SETTINGS, 0);
- editAddress.setText(settings.getString(Traccar.EXTRA_ADDRESS, Traccar.DEFAULT_ADDRESS));
- editPort.setText(settings.getString(Traccar.EXTRA_PORT, Traccar.DEFAULT_PORT));
- editPeriod.setText(settings.getString(Traccar.EXTRA_PERIOD, Traccar.DEFAULT_PERIOD));
- }
}
diff --git a/src/org/traccar/client/TraccarService.java b/src/org/traccar/client/TraccarService.java
index e86cc90..16c02f3 100644
--- a/src/org/traccar/client/TraccarService.java
+++ b/src/org/traccar/client/TraccarService.java
@@ -16,133 +16,193 @@
package org.traccar.client;
import android.app.Service;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
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.telephony.TelephonyManager;
+import android.preference.PreferenceManager;
/**
* Background service
*/
-public class TraccarService extends Service implements LocationListener {
+public class TraccarService extends Service {
- private int period;
- private String deviceId;
+ 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;
- private LocationManager locationManager;
+ LocationManager locationManager;
- /*
- * Location methods
- */
-
- @Override
- public void onLocationChanged(Location location) {
- connection.send(Protocol.createNmea(location));
+ private void statusMessage(int message) {
+ StatusActivity.addMessage(getString(message));
}
@Override
- public void onProviderDisabled(String provider) {
+ public void onCreate() {
+ statusMessage(R.string.status_service_create);
+
+ handler = new Handler();
+ connection = new Connection(connectionHandler);
}
- @Override
- public void onProviderEnabled(String provider) {
- }
-
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- }
-
- /*
- * Status methods
- */
-
- private String status;
-
- private void setStatus(String status) {
- if (!status.equals(this.status)) {
- this.status = status;
- Intent intent = new Intent(Traccar.MSG_SERVICE_STATUS);
- intent.putExtra(Traccar.EXTRA_STATUS, status);
- sendBroadcast(intent);
- }
- }
-
- private BroadcastReceiver updateReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Send config
- intent = new Intent(Traccar.MSG_SERVICE_CONFIG);
- intent.putExtra(Traccar.EXTRA_ADDRESS, connection.getAddress());
- intent.putExtra(Traccar.EXTRA_PORT, connection.getPort());
- intent.putExtra(Traccar.EXTRA_PERIOD, period);
- sendBroadcast(intent);
-
- // Send service status
- intent = new Intent(Traccar.MSG_SERVICE_STATUS);
- intent.putExtra(Traccar.EXTRA_STATUS, status);
- sendBroadcast(intent);
-
- // Send connection status
- intent = new Intent(Traccar.MSG_CONNECTION_STATUS);
- intent.putExtra(Traccar.EXTRA_STATUS, connection.getStatus());
- sendBroadcast(intent);
- }
- };
-
- /*
- * Service methods
- */
-
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- // Read device id
- TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- deviceId = telephonyManager.getDeviceId();
+ statusMessage(R.string.status_service_start);
- // Create connection
- connection = new Connection(
- intent.getStringExtra(Traccar.EXTRA_ADDRESS),
- intent.getIntExtra(Traccar.EXTRA_PORT, 0),
- Protocol.createId(deviceId));
- connection.setContext(this);
- connection.connect();
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+ sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
+ updateServerPreferences(sharedPreferences);
+ updateIntervalPreferences(sharedPreferences);
+ updateOtherPreferences(sharedPreferences);
+
+ connection.close();
+ connection.connect(address, port);
- // Request location updates
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- period = intent.getIntExtra(Traccar.EXTRA_PERIOD, 0);
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, period * 1000, 0, this);
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval * 1000, 0, locationListener);
- // Report status
- registerReceiver(updateReceiver, new IntentFilter(Traccar.MSG_UPDATE));
- setStatus(Traccar.STATUS_RUNNING);
return START_STICKY;
}
- @Override
- public void onDestroy() {
- // Close connection
- if (connection != null) {
- connection.close();
- }
-
- // Stop location updates
- if (locationManager != null) {
- locationManager.removeUpdates(this);
- }
-
- // Report status
- unregisterReceiver(updateReceiver);
- setStatus(Traccar.STATUS_STOPPED);
- }
-
@Override
public IBinder onBind(Intent intent) {
return null;
}
+
+ @Override
+ public void onDestroy() {
+ statusMessage(R.string.status_service_destroy);
+
+ locationManager.removeUpdates(locationListener);
+
+ handler.removeCallbacksAndMessages(null);
+ connection.close();
+ connection = null;
+
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
+ }
+
+ 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));
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ };
+
+ OnSharedPreferenceChangeListener preferenceChangeListener = new OnSharedPreferenceChangeListener() {
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ statusMessage(R.string.status_preference_update);
+
+ if (updateServerPreferences(sharedPreferences)) {
+ connection.close();
+ connection.connect(address, port);
+ }
+
+ if (updateIntervalPreferences(sharedPreferences)) {
+ locationManager.removeUpdates(locationListener);
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval * 1000, 0, locationListener);
+ }
+
+ updateOtherPreferences(sharedPreferences);
+ }
+
+ };
+
}