From b992ee0a8db29d1900e337157b4d4c70a793fe65 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 4 Apr 2013 23:53:34 +1300 Subject: [PATCH] Rework location provider system --- res/values-es/strings.xml | 8 +- res/values-ru/strings.xml | 6 +- res/values/strings.xml | 8 +- res/values/values.xml | 10 ++ res/xml-v14/preferences.xml | 66 ++++----- res/xml/preferences.xml | 58 ++++---- src/org/traccar/client/ClientController.java | 6 +- src/org/traccar/client/PositionProvider.java | 136 +++++++++++++++++++ src/org/traccar/client/TraccarActivity.java | 3 + src/org/traccar/client/TraccarService.java | 60 ++++---- 10 files changed, 244 insertions(+), 117 deletions(-) create mode 100644 res/values/values.xml create mode 100644 src/org/traccar/client/PositionProvider.java diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 045c318..f7f4b0a 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -23,11 +23,8 @@ Proveedor GPS Proveedor de red - - - gps - red - + Proveedor mixto + Estado Acerca de… @@ -44,7 +41,6 @@ Fallo en la conexión Erro en el envío Posición actualizada - Estado proveedor cambiado Preferencias actualizadas diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 01579e4..b6f2fb9 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -23,10 +23,7 @@ GPS провайдер Сетевой провайдер - - - gps - network + Смешанный провайдер Состояние @@ -44,7 +41,6 @@ Ошибка установки соединения Ошибка отправки Обновление местоположения - Изменилось состояние провайдера Обновление настроек diff --git a/res/values/strings.xml b/res/values/strings.xml index 280a3d6..6e11689 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -23,12 +23,9 @@ GPS provider Network provider + Mixed provider - - gps - network - - + Status About Clear @@ -44,7 +41,6 @@ Connection failed Send failed Location update - Provider status changed Preference update diff --git a/res/values/values.xml b/res/values/values.xml new file mode 100644 index 0000000..6a7ddb1 --- /dev/null +++ b/res/values/values.xml @@ -0,0 +1,10 @@ + + + + + gps + network + mixed + + + diff --git a/res/xml-v14/preferences.xml b/res/xml-v14/preferences.xml index 5163775..bcb6d2f 100644 --- a/res/xml-v14/preferences.xml +++ b/res/xml-v14/preferences.xml @@ -1,52 +1,52 @@ - + - - - + android:title="@string/settings_address_title" /> - - - + android:title="@string/settings_port_title" /> - + + - + android:key="provider" + android:summary="@string/settings_provider_summary" + android:title="@string/settings_provider_title" /> + + android:enabled="false" + android:key="debug" + android:summary="@string/settings_debug_summary" + android:title="@string/settings_debug_title" /> + android:summaryOn="@string/settings_status_on_summary" + android:switchTextOff="@string/settings_status_off" + android:switchTextOn="@string/settings_status_on" + android:title="@string/settings_status_title" /> - + \ No newline at end of file diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 366aaf2..6ebf83c 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -1,50 +1,50 @@ - + - - - + android:title="@string/settings_address_title" /> - - - + android:title="@string/settings_port_title" /> - + + + android:key="provider" + android:summary="@string/settings_provider_summary" + android:title="@string/settings_provider_title" /> + android:enabled="false" + android:key="debug" + android:summary="@string/settings_debug_summary" + android:title="@string/settings_debug_title" /> + android:summaryOn="@string/settings_status_on_summary" + android:title="@string/settings_status_title" /> diff --git a/src/org/traccar/client/ClientController.java b/src/org/traccar/client/ClientController.java index 5c7c856..f6cba03 100644 --- a/src/org/traccar/client/ClientController.java +++ b/src/org/traccar/client/ClientController.java @@ -95,10 +95,10 @@ public class ClientController implements Connection.ConnectionHandler { @Override public void onConnected(boolean result) { if (result) { - StatusActivity.addMessage(context.getString((R.string.status_connection_success))); + StatusActivity.addMessage(context.getString(R.string.status_connection_success)); connection.send(loginMessage); } else { - StatusActivity.addMessage(context.getString((R.string.status_connection_fail))); + StatusActivity.addMessage(context.getString(R.string.status_connection_fail)); delayedReconnect(); } } @@ -110,7 +110,7 @@ public class ClientController implements Connection.ConnectionHandler { connection.send(messageQueue.poll()); } } else { - StatusActivity.addMessage(context.getString((R.string.status_send_fail))); + StatusActivity.addMessage(context.getString(R.string.status_send_fail)); delayedReconnect(); } } diff --git a/src/org/traccar/client/PositionProvider.java b/src/org/traccar/client/PositionProvider.java new file mode 100644 index 0000000..5bfb5e5 --- /dev/null +++ b/src/org/traccar/client/PositionProvider.java @@ -0,0 +1,136 @@ +/* + * 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.Date; + +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.LocationProvider; +import android.os.Bundle; +import android.os.Handler; + +public class PositionProvider { + + public static final String PROVIDER_MIXED = "mixed"; + public static final long PERIOD_DELTA = 10 * 1000; + public static final long RETRY_PERIOD = 60 * 1000; + + public interface PositionListener { + public void onPositionUpdate(Location location); + } + + private final Handler handler; + private final LocationManager locationManager; + private final long period; + private final PositionListener listener; + + private boolean useFine; + private boolean useCoarse; + + public PositionProvider(Context context, String type, long period, PositionListener listener) { + handler = new Handler(context.getMainLooper()); + locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + this.period = period; + this.listener = listener; + + // Determine providers + if (type.equals(PROVIDER_MIXED)) { + useFine = true; + useCoarse = true; + } else if (type.equals(LocationManager.GPS_PROVIDER)) { + useFine = true; + } else if (type.equals(LocationManager.NETWORK_PROVIDER)) { + useCoarse = true; + } + } + + public void startUpdates() { + if (useFine) { + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, period, 0, fineLocationListener); + } + if (useCoarse) { + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, period, 0, coarseLocationListener); + } + handler.postDelayed(updateTask, period); + } + + public void stopUpdates() { + handler.removeCallbacks(updateTask); + locationManager.removeUpdates(fineLocationListener); + locationManager.removeUpdates(coarseLocationListener); + } + + private final Runnable updateTask = new Runnable() { + + private boolean tryProvider(String provider) { + Location location = locationManager.getLastKnownLocation(provider); + + if (location != null && new Date().getTime() - location.getTime() <= period + PERIOD_DELTA) { + listener.onPositionUpdate(location); + return true; + } else { + return false; + } + } + + @Override + public void run() { + if (useFine && tryProvider(LocationManager.GPS_PROVIDER)) { + } else if (useCoarse && tryProvider(LocationManager.NETWORK_PROVIDER)) { + } else { + listener.onPositionUpdate(null); + } + handler.postDelayed(this, period); + } + + }; + + private final InternalLocationListener fineLocationListener = new InternalLocationListener(); + private final InternalLocationListener coarseLocationListener = new InternalLocationListener(); + + private class InternalLocationListener implements LocationListener { + + @Override + public void onLocationChanged(Location location) { + } + + @Override + public void onProviderDisabled(String provider) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onStatusChanged(final String provider, int status, Bundle extras) { + if (status == LocationProvider.TEMPORARILY_UNAVAILABLE || status == LocationProvider.OUT_OF_SERVICE) { + handler.postDelayed(new Runnable() { + @Override + public void run() { + locationManager.removeUpdates(InternalLocationListener.this); + locationManager.requestLocationUpdates(provider, period, 0, InternalLocationListener.this); + } + }, RETRY_PERIOD); + } + } + + } + +} diff --git a/src/org/traccar/client/TraccarActivity.java b/src/org/traccar/client/TraccarActivity.java index f8dd33a..3ffa547 100644 --- a/src/org/traccar/client/TraccarActivity.java +++ b/src/org/traccar/client/TraccarActivity.java @@ -23,6 +23,7 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; import android.telephony.TelephonyManager; import android.view.Menu; import android.view.MenuInflater; @@ -110,6 +111,8 @@ public class TraccarActivity extends PreferenceActivity { } private void initPreferences() { + PreferenceManager.setDefaultValues(this, R.xml.preferences, false); + TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String id = telephonyManager.getDeviceId(); diff --git a/src/org/traccar/client/TraccarService.java b/src/org/traccar/client/TraccarService.java index c94b433..deb2b8a 100644 --- a/src/org/traccar/client/TraccarService.java +++ b/src/org/traccar/client/TraccarService.java @@ -16,15 +16,10 @@ package org.traccar.client; import android.app.Service; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.location.LocationProvider; -import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; @@ -44,7 +39,7 @@ public class TraccarService extends Service { private SharedPreferences sharedPreferences; private ClientController clientController; - private LocationManager locationManager; + private PositionProvider positionProvider; @Override public void onCreate() { @@ -70,8 +65,8 @@ public class TraccarService extends Service { clientController = new ClientController(this, address, port, Protocol.createLoginMessage(id)); clientController.start(); - locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(provider, interval * 1000, 0, locationListener); + positionProvider = new PositionProvider(this, provider, interval * 1000, positionListener); + positionProvider.startUpdates(); sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener); @@ -89,35 +84,18 @@ public class TraccarService extends Service { sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener); - locationManager.removeUpdates(locationListener); + positionProvider.stopUpdates(); clientController.stop(); } - private LocationListener locationListener = new LocationListener() { + private PositionProvider.PositionListener positionListener = new PositionProvider.PositionListener() { @Override - public void onLocationChanged(Location location) { - StatusActivity.addMessage(getString(R.string.status_location_update)); - clientController.setNewLocation(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) { - StatusActivity.addMessage(getString(R.string.status_location_status)); - - if (status == LocationProvider.TEMPORARILY_UNAVAILABLE || - status == LocationProvider.OUT_OF_SERVICE) { - locationManager.removeUpdates(locationListener); - locationManager.requestLocationUpdates(provider, interval * 1000, 0, locationListener); + public void onPositionUpdate(Location location) { + if (location != null) { + StatusActivity.addMessage(getString(R.string.status_location_update)); + clientController.setNewLocation(Protocol.createLocationMessage(location)); } } @@ -130,22 +108,34 @@ public class TraccarService extends Service { StatusActivity.addMessage(getString(R.string.status_preference_update)); try { if (key.equals(TraccarActivity.KEY_ADDRESS)) { + address = sharedPreferences.getString(TraccarActivity.KEY_ADDRESS, null); clientController.setNewServer(address, port); + } else if (key.equals(TraccarActivity.KEY_PORT)) { + port = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_PORT, null)); clientController.setNewServer(address, port); + } else if (key.equals(TraccarActivity.KEY_INTERVAL)) { + interval = Integer.valueOf(sharedPreferences.getString(TraccarActivity.KEY_INTERVAL, null)); - locationManager.removeUpdates(locationListener); - locationManager.requestLocationUpdates(provider, interval * 1000, 0, locationListener); + positionProvider.stopUpdates(); + positionProvider = new PositionProvider(TraccarService.this, provider, interval * 1000, positionListener); + positionProvider.startUpdates(); + } else if (key.equals(TraccarActivity.KEY_ID)) { + id = sharedPreferences.getString(TraccarActivity.KEY_ID, null); clientController.setNewLogin(Protocol.createLoginMessage(id)); + } else if (key.equals(TraccarActivity.KEY_PROVIDER)) { + provider = sharedPreferences.getString(TraccarActivity.KEY_PROVIDER, null); - locationManager.removeUpdates(locationListener); - locationManager.requestLocationUpdates(provider, interval * 1000, 0, locationListener); + positionProvider.stopUpdates(); + positionProvider = new PositionProvider(TraccarService.this, provider, interval * 1000, positionListener); + positionProvider.startUpdates(); + } } catch (Exception error) { Log.w(LOG_TAG, error);