From b56cf7ab0bd847245532741b3ac5c58b1dbe43ed Mon Sep 17 00:00:00 2001 From: Alexandr Timoshenko Date: Thu, 9 Jul 2020 16:55:27 +0200 Subject: [PATCH 1/9] correctly stop services foreground services --- .../sending/MessageSendingService.java | 1 - .../app/services/TrackingService.java | 15 ----- .../app/data/InMemoryDataStore.java | 6 +- .../app/services/RaceStateService.java | 64 ++++++++++--------- .../SendingServiceAwareActivity.java | 14 ++-- 5 files changed, 44 insertions(+), 56 deletions(-) diff --git a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java index 3b6b88c907d..5b3ad9ca225 100644 --- a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java +++ b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java @@ -243,7 +243,6 @@ public class MessageSendingService extends Service implements MessageSendingList CharSequence name = getString(R.string.service_info); NotificationHelper.createNotificationChannel(this, NotificationHelper.getNotificationChannelId(), name); - startForeground(NotificationHelper.getNotificationId(), NotificationHelper.getNotification(this, NotificationHelper.getNotificationChannelId())); ExLog.i(this, TAG, "Sending Service on Create."); } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java index a66bf9e200b..6b0c03a6e3a 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java @@ -161,7 +161,6 @@ public class TrackingService extends Service implements LocationListener { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_INTERVAL_IN_MILLIS_DEFAULT, minLocationUpdateDistanceInMeters, this); ExLog.i(this, TAG, "Started Tracking"); - showNotification(); prefs.setTrackerIsTracking(true); prefs.setTrackerIsTrackingCheckinDigest(checkinDigest); @@ -395,20 +394,6 @@ public class TrackingService extends Service implements LocationListener { // provider (GPS) (re)enabled by the user while tracking } - private void showNotification() { - // Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel - CharSequence name = getText(R.string.service_info); - NotificationHelper.createNotificationChannel(this, NotificationHelper.getNotificationChannelId(), name); - - Intent intent = new Intent(this, TrackingActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); - - Notification notification = NotificationHelper.getNotification(this, NotificationHelper.getNotificationChannelId(), getText(R.string.app_name), - getString(R.string.tracking_notification_text, event.name), pendingIntent); - startForeground(NotificationHelper.getNotificationId(), notification); - } - public void registerGPSQualityListener(GPSQualityListener listener) { gpsQualityListener = listener; } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java index f3c9fb300b8..47c7ac6bae9 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java @@ -55,8 +55,10 @@ public enum InMemoryDataStore implements DataStore { if (mContext == null) { mContext = context.getApplicationContext(); } - Intent intent = new Intent(mContext, RaceStateService.class); - mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + if (!mBound) { + Intent intent = new Intent(mContext, RaceStateService.class); + mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } } @Override diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java index 8778ec1c764..833d4dc7cff 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java @@ -83,8 +83,6 @@ public class RaceStateService extends Service { super.onCreate(); - Notification notification = setupNotification(null); - startForeground(NotificationHelper.getNotificationId(), notification); ExLog.i(this, TAG, "Started."); } @@ -160,6 +158,7 @@ public class RaceStateService extends Service { managedIntents.clear(); ExLog.i(this, TAG, "All races unregistered."); + stopForeground(true); } public void unregisterRace(ManagedRace race) { @@ -178,7 +177,7 @@ public class RaceStateService extends Service { } managedIntents.remove(race.getId()); } else { - ExLog.w(this, TAG, "Couldn't find any managed intents for race "+race.getId()); + ExLog.w(this, TAG, "Couldn't find any managed intents for race " + race.getId()); } ExLog.i(this, TAG, "Race " + race.getId() + " unregistered"); updateNotification(); @@ -203,33 +202,33 @@ public class RaceStateService extends Service { if (action != null) { switch (action) { - case AppConstants.INTENT_ACTION_CLEAR_RACES: - handleClearRaces(); - break; - - case AppConstants.INTENT_ACTION_CLEANUP_RACES: - handleCleanupRaces(); - break; - - default: - String id = intent.getStringExtra(AppConstants.INTENT_EXTRA_RACE_ID); - ManagedRace race = dataManager.getDataStore().getRace(id); - if (race == null) { - ExLog.w(this, TAG, "No race for id " + id); - return; - } - - switch (action) { - case AppConstants.INTENT_ACTION_ALARM_ACTION: - long timePoint = intent.getLongExtra(AppConstants.INTENT_EXTRA_TIMEPOINT_MILLIS, 0); - String eventName = intent.getStringExtra(AppConstants.INTENT_EXTRA_EVENTNAME); - RaceStateEvent event = new RaceStateEventImpl(new MillisecondsTimePoint(timePoint), - RaceStateEvents.valueOf(eventName)); - ExLog.i(this, TAG, String.format("Processing %s", event.toString())); - race.getState().processStateEvent(event); - clearAlarmByName(race, event.getEventName()); + case AppConstants.INTENT_ACTION_CLEAR_RACES: + handleClearRaces(); break; - } + + case AppConstants.INTENT_ACTION_CLEANUP_RACES: + handleCleanupRaces(); + break; + + default: + String id = intent.getStringExtra(AppConstants.INTENT_EXTRA_RACE_ID); + ManagedRace race = dataManager.getDataStore().getRace(id); + if (race == null) { + ExLog.w(this, TAG, "No race for id " + id); + return; + } + + switch (action) { + case AppConstants.INTENT_ACTION_ALARM_ACTION: + long timePoint = intent.getLongExtra(AppConstants.INTENT_EXTRA_TIMEPOINT_MILLIS, 0); + String eventName = intent.getStringExtra(AppConstants.INTENT_EXTRA_EVENTNAME); + RaceStateEvent event = new RaceStateEventImpl(new MillisecondsTimePoint(timePoint), + RaceStateEvents.valueOf(eventName)); + ExLog.i(this, TAG, String.format("Processing %s", event.toString())); + race.getState().processStateEvent(event); + clearAlarmByName(race, event.getEventName()); + break; + } } } } @@ -288,7 +287,10 @@ public class RaceStateService extends Service { int numRaces = managedIntents.keySet().size(); String content = getString(R.string.service_text_num_races, numRaces); Notification notification = setupNotification(content); - startForeground(NotificationHelper.getNotificationId(), notification); + if (numRaces > 0) { + ExLog.i(this, TAG, "Starting foreground"); + startForeground(NotificationHelper.getNotificationId(), notification); + } } public void registerRace(ManagedRace race) { @@ -338,7 +340,7 @@ public class RaceStateService extends Service { } @TargetApi(Build.VERSION_CODES.KITKAT) - /* package */ void setAlarm(ManagedRace race, RaceStateEvent event) { + /* package */ void setAlarm(ManagedRace race, RaceStateEvent event) { PendingIntent intent = createAlarmPendingIntent(race, event); managedIntents.get(race.getId()).add(Pair.create(intent, event.getEventName())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SendingServiceAwareActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SendingServiceAwareActivity.java index b2f1038a791..6754d6e166d 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SendingServiceAwareActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SendingServiceAwareActivity.java @@ -59,6 +59,7 @@ public abstract class SendingServiceAwareActivity extends ResilientActivity SendingServiceAwareActivity activity = mActivity.get(); if (activity != null) { activity.boundSendingService = false; + activity.sendingServiceConnection = null; } } @@ -89,14 +90,10 @@ public abstract class SendingServiceAwareActivity extends ResilientActivity private static String TAG = SendingServiceAwareActivity.class.getName(); - public SendingServiceAwareActivity() { - sendingServiceConnection = new MessageSendingServiceConnection(this); - } - @Override public void onStart() { super.onStart(); - + sendingServiceConnection = new MessageSendingServiceConnection(this); Intent intent = new Intent(this, MessageSendingService.class); ExLog.i(this, TAG, "bindSendingService"); bindService(intent, sendingServiceConnection, Context.BIND_AUTO_CREATE); @@ -107,8 +104,11 @@ public abstract class SendingServiceAwareActivity extends ResilientActivity super.onStop(); ExLog.i(this, TAG, "unbindSendingService"); - unbindService(sendingServiceConnection); - boundSendingService = false; + if (sendingServiceConnection!=null) { + unbindService(sendingServiceConnection); + boundSendingService = false; + sendingServiceConnection = null; + } } protected void updateSendingServiceInformation() { From 965716cd8565d9ff0fe82e70c0bbc02ab4a77966 Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Mon, 10 Aug 2020 14:27:54 +0200 Subject: [PATCH 2/9] refactor: bound services to foreground and default background services --- .../sending/MessageSendingService.java | 31 +-- .../app/services/TrackingService.java | 90 +++------ .../AndroidManifest.xml | 6 +- .../racecommittee/app/AppConstants.java | 3 +- .../racecommittee/app/data/DataManager.java | 28 +-- .../racecommittee/app/data/DataStore.java | 12 +- .../app/data/InMemoryDataStore.java | 76 +++----- .../handlers/ManagedRacesDataHandler.java | 55 ++---- .../app/services/RaceStateService.java | 180 ++++++------------ .../polling/RaceLogPollingService.java | 97 ++++------ 10 files changed, 196 insertions(+), 382 deletions(-) diff --git a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java index 5b3ad9ca225..fd1ea49d29a 100644 --- a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java +++ b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/services/sending/MessageSendingService.java @@ -95,7 +95,7 @@ public class MessageSendingService extends Service implements MessageSendingList * Can be used to keep messages from being sent; the race manager app, for example, uses this to avoid sending * messages back to the server that were received from the server in the first place. */ - private Set suppressedMessageIds = new HashSet(); + private Set suppressedMessageIds = new HashSet<>(); private APIConnectivityListener apiConnectivityListener; @@ -248,18 +248,7 @@ public class MessageSendingService extends Service implements MessageSendingList @Override public void onDestroy() { - stopForeground(true); - stopSelf(); ExLog.i(this, TAG, "Message Sending Service is being destroyed."); - super.onDestroy(); - } - - @Override - public void onTaskRemoved(Intent rootIntent) { - super.onTaskRemoved(rootIntent); - stopForeground(true); - stopSelf(); - ExLog.i(this, TAG, "Message Sending Service is being removed."); } @Override @@ -269,17 +258,17 @@ public class MessageSendingService extends Service implements MessageSendingList return START_STICKY; } ExLog.i(this, TAG, "Sending Service is called by following intent: " + intent.getAction()); - handleCommand(intent, startId); + handleCommand(intent); // We want this service to continue running until it is explicitly // stopped, so return sticky. return START_STICKY; } - private void handleCommand(Intent intent, int startId) { + private void handleCommand(Intent intent) { String action = intent.getAction(); - if (action.equals(getString(R.string.intent_send_saved_intents))) { + if (getString(R.string.intent_send_saved_intents).equals(action)) { handleDelayedMessages(); - } else if (action.equals(getString(R.string.intent_send_message))) { + } else if (getString(R.string.intent_send_message).equals(action)) { handleSendMessages(intent); } } @@ -443,7 +432,7 @@ public class MessageSendingService extends Service implements MessageSendingList public static String getRaceLogEventSendAndReceiveUrl(Context context, final String raceGroupName, final String raceName, final String fleetName) throws UnsupportedEncodingException { - String url = String.format( + return String.format( "%s/sailingserver/rc/racelog?" + RaceLogServletConstants.PARAMS_LEADERBOARD_NAME + "=%s&" + RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME + "=%s&" + RaceLogServletConstants.PARAMS_RACE_FLEET_NAME + "=%s&" @@ -452,7 +441,6 @@ public class MessageSendingService extends Service implements MessageSendingList R.string.preference_server_url_default), URLEncoder.encode(raceGroupName, charsetName), URLEncoder.encode(raceName, charsetName), URLEncoder.encode(fleetName, charsetName), uuid); - return url; } /** @@ -493,9 +481,9 @@ public class MessageSendingService extends Service implements MessageSendingList * Listener interface for reporting of connectivity and number of unsent GPS-fixes. */ public interface APIConnectivityListener { - public void apiConnectivityUpdated(APIConnectivity apiConnectivity); + void apiConnectivityUpdated(APIConnectivity apiConnectivity); - public void setUnsentGPSFixesCount(int count); + void setUnsentGPSFixesCount(int count); } /** @@ -520,11 +508,10 @@ public class MessageSendingService extends Service implements MessageSendingList public static String getRacePositionsUrl(Context context, final String regattaName, final String raceName) throws UnsupportedEncodingException { - String url = String.format("%s/sailingserver/api/v1/regattas/%s/races/%s/marks/positions", + return String.format("%s/sailingserver/api/v1/regattas/%s/races/%s/marks/positions", PrefUtils.getString(context, R.string.preference_server_url_key, R.string.preference_server_url_default), URLEncoder.encode(regattaName, charsetName).replace("+", "%20"), URLEncoder.encode(raceName, charsetName.replace("+", "%20")));// , - return url; } } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java index 6b0c03a6e3a..eedfd417ab7 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/services/TrackingService.java @@ -1,26 +1,26 @@ package com.sap.sailing.android.tracking.app.services; -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.hardware.GeomagneticField; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.widget.Toast; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.services.sending.MessageSendingService; import com.sap.sailing.android.shared.ui.customviews.GPSQuality; -import com.sap.sailing.android.shared.util.NotificationHelper; import com.sap.sailing.android.tracking.app.BuildConfig; import com.sap.sailing.android.tracking.app.R; -import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity; import com.sap.sailing.android.tracking.app.utils.AppPreferences; import com.sap.sailing.android.tracking.app.utils.DatabaseHelper; import com.sap.sailing.android.tracking.app.valueobjects.EventInfo; @@ -31,24 +31,19 @@ import com.sap.sse.common.Duration; import com.sap.sse.common.Speed; import com.sap.sse.common.impl.DegreeBearingImpl; -import android.app.Notification; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.hardware.GeomagneticField; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.os.Binder; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.widget.Toast; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; + +import static android.os.Process.THREAD_PRIORITY_BACKGROUND; public class TrackingService extends Service implements LocationListener { @@ -71,7 +66,6 @@ public class TrackingService extends Service implements LocationListener { public final static int UPDATE_INTERVAL_IN_MILLIS_DEFAULT = 1000; public final static String GPS_DISABLED_MESSAGE = "gpsDisabled"; - private float minLocationUpdateDistanceInMeters = 0f; private String checkinDigest; private EventInfo event; @@ -110,15 +104,6 @@ public class TrackingService extends Service implements LocationListener { @Override public void onCreate() { - super.onCreate(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - /** - * prior to JellyBean, the minimum time for location updates parameter MIGHT be ignored, so providing a - * minimum distance value greater than 0 is recommended - */ - minLocationUpdateDistanceInMeters = .5f; - } - locationsQueuedBasedOnSendingInterval = new LinkedHashMap<>(); prefs = new AppPreferences(this); @@ -158,8 +143,7 @@ public class TrackingService extends Service implements LocationListener { @SuppressWarnings("MissingPermission") private void startTracking() { - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_INTERVAL_IN_MILLIS_DEFAULT, - minLocationUpdateDistanceInMeters, this); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_INTERVAL_IN_MILLIS_DEFAULT, 0f, this); ExLog.i(this, TAG, "Started Tracking"); prefs.setTrackerIsTracking(true); @@ -343,18 +327,9 @@ public class TrackingService extends Service implements LocationListener { @Override public void onDestroy() { stopTracking(); - stopForeground(true); Toast.makeText(this, R.string.tracker_stopped, Toast.LENGTH_SHORT).show(); } - @Override - public void onTaskRemoved(Intent rootIntent) { - super.onTaskRemoved(rootIntent); - stopTracking(); - stopForeground(true); - ExLog.i(this, TAG, "Tracking Service is being removed."); - } - /** * Methods implemented through LocationManager */ @@ -420,8 +395,7 @@ public class TrackingService extends Service implements LocationListener { @Override public void handleMessage(Message msg) { - switch (msg.what) { - case NO_LOCATION: + if (msg.what == NO_LOCATION) { ExLog.i(getApplicationContext(), TAG, "No Location"); Location location = (Location) msg.obj; if (location == null) { @@ -429,10 +403,6 @@ public class TrackingService extends Service implements LocationListener { } reportGPSQualityBearingAndSpeed(NO_DISTANCE, location.getBearing(), location.getSpeed(), location.getLatitude(), location.getLongitude(), location.getAltitude()); - break; - - default: - super.handleMessage(msg); } } } diff --git a/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml b/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml index d2a046e348b..f19410dc12b 100755 --- a/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml +++ b/mobile/com.sap.sailing.racecommittee.app/AndroidManifest.xml @@ -74,7 +74,8 @@ + android:exported="false" + android:stopWithTask="true"> @@ -84,7 +85,8 @@ + android:exported="false" + android:stopWithTask="true"> diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppConstants.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppConstants.java index 5c71056eb91..df65871744a 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppConstants.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/AppConstants.java @@ -22,8 +22,9 @@ public class AppConstants { private final static String INTENT_ACTION = PACKAGE_NAME + ".action"; public final static String INTENT_ACTION_RESET = INTENT_ACTION + ".reset"; + public final static String INTENT_ACTION_REGISTER_RACE = INTENT_ACTION + ".registerRace"; + public final static String INTENT_ACTION_UNREGISTER_RACE = INTENT_ACTION + ".unregisterRace"; public final static String INTENT_ACTION_CLEAR_RACES = INTENT_ACTION + ".clearRaces"; - public final static String INTENT_ACTION_CLEANUP_RACES = INTENT_ACTION + ".cleanupRaces"; public final static String INTENT_ACTION_ALARM_ACTION = INTENT_ACTION + ".alarmAction"; public final static String INTENT_ACTION_RELOAD_RACES = INTENT_ACTION + ".reloadRaces"; public final static String INTENT_ACTION_START_PROCEDURE_SPECIFIC_ACTION = INTENT_ACTION diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java index 33e1502790c..097d54742f8 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java @@ -1,13 +1,12 @@ package com.sap.sailing.racecommittee.app.data; +import android.content.Context; + import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.racecommittee.app.AppConstants; import com.sap.sailing.racecommittee.app.AppPreferences; import com.sap.sailing.racecommittee.app.services.RaceStateService; -import android.content.Context; -import android.content.Intent; - /** * Base class for all data managers. Use {@link DataManager#create(Context)} for creating your {@link DataManager}. */ @@ -43,30 +42,13 @@ public abstract class DataManager implements ReadonlyDataManager { } /** - * {@link InMemoryDataStore#reset() Resets} the data store properly and, by means of calling - * {@link #unloadAllRaces()}, fires the {@link AppConstants#INTENT_ACTION_CLEAR_RACES} intent which is expected to + * {@link InMemoryDataStore#clearRaces()} ()}, fires the {@link AppConstants#INTENT_ACTION_CLEAR_RACES} intent which is expected to * be handled by the {@link RaceStateService} which responds by unregistering all its races, stopping to listen on * and poll their race logs and by clearing the data store's races collection. + * {@link InMemoryDataStore#reset()} resets the data store properly. */ public void resetAll() { - unloadAllRaces(); + InMemoryDataStore.INSTANCE.clearRaces(); InMemoryDataStore.INSTANCE.reset(); } - - /** - * Properly unloading of all races by first unloading / unregistering them from the race state service. The - * {@link RaceStateService} then in turn clears the races on the data store. - */ - public void unloadAllRaces() { - // It's not needed to call getDataStore().getRaces().clear() because it's already called by the service - // internally. - Intent intent = new Intent(context, RaceStateService.class); - intent.setAction(AppConstants.INTENT_ACTION_CLEAR_RACES); - context.startService(intent); - } - - public void stopService() { - Intent intent = new Intent(context, RaceStateService.class); - context.stopService(intent); - } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java index 05dc2ecdd49..677907fce69 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java @@ -1,9 +1,6 @@ package com.sap.sailing.racecommittee.app.data; -import java.io.Serializable; -import java.util.Collection; -import java.util.Set; -import java.util.UUID; +import android.content.Context; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.base.CourseArea; @@ -14,7 +11,10 @@ import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.racegroup.RaceGroup; import com.sap.sailing.racecommittee.app.domain.ManagedRace; -import android.content.Context; +import java.io.Serializable; +import java.util.Collection; +import java.util.Set; +import java.util.UUID; public interface DataStore { @@ -58,6 +58,8 @@ public interface DataStore { void registerRaces(Collection races); + void clearRaces(); + Collection getMarks(RaceGroup raceGroup); Mark getMark(RaceGroup raceGroup, Serializable id); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java index 317e108b1d1..3bc6c1ad7f3 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java @@ -1,12 +1,7 @@ package com.sap.sailing.racecommittee.app.data; -import java.io.Serializable; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import android.content.Context; +import android.content.Intent; import com.sap.sailing.android.shared.util.CollectionUtils; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; @@ -18,17 +13,20 @@ import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl; import com.sap.sailing.domain.base.racegroup.RaceGroup; +import com.sap.sailing.racecommittee.app.AppConstants; import com.sap.sailing.racecommittee.app.domain.ManagedRace; import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier; import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl; import com.sap.sailing.racecommittee.app.services.RaceStateService; import com.sap.sse.common.Util.Triple; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; public enum InMemoryDataStore implements DataStore { INSTANCE; @@ -43,9 +41,6 @@ public enum InMemoryDataStore implements DataStore { private Serializable eventUUID; private UUID courseAreaId; - private RaceStateService mService; - private boolean mBound; - InMemoryDataStore() { reset(); } @@ -55,10 +50,6 @@ public enum InMemoryDataStore implements DataStore { if (mContext == null) { mContext = context.getApplicationContext(); } - if (!mBound) { - Intent intent = new Intent(mContext, RaceStateService.class); - mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } } @Override @@ -71,11 +62,6 @@ public enum InMemoryDataStore implements DataStore { eventUUID = null; courseAreaId = null; - - if (mContext != null && mBound) { - mContext.unbindService(mConnection); - mBound = false; - } } @Override @@ -339,34 +325,28 @@ public enum InMemoryDataStore implements DataStore { courseAreaId = uuid; } + @Override public void registerRaces(Collection races) { - //TODO Log - if (mBound) { - for (ManagedRace race : races) { - mService.registerRace(race); - } + for (ManagedRace race : races) { + final Intent registerIntent = new Intent(mContext, RaceStateService.class); + registerIntent.setAction(AppConstants.INTENT_ACTION_REGISTER_RACE); + registerIntent.putExtra(AppConstants.INTENT_EXTRA_RACE_ID, race.getId()); + mContext.startService(registerIntent); } } + @Override + public void clearRaces() { + managedRaceById.clear(); + final Intent intent = new Intent(mContext, RaceStateService.class); + intent.setAction(AppConstants.INTENT_ACTION_CLEAR_RACES); + mContext.startService(intent); + } + private void unregisterRace(ManagedRace race) { - if (mBound) { - mService.unregisterRace(race); - } + final Intent intent = new Intent(mContext, RaceStateService.class); + intent.setAction(AppConstants.INTENT_ACTION_UNREGISTER_RACE); + intent.putExtra(AppConstants.INTENT_EXTRA_RACE_ID, race.getId()); + mContext.startService(intent); } - - private ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - //TODO Log - RaceStateService.RaceStateServiceBinder binder = (RaceStateService.RaceStateServiceBinder) service; - mService = binder.getService(); - mBound = true; - } - - @Override - public void onServiceDisconnected(ComponentName name) { - mBound = false; - } - }; } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java index dc16c44fe63..45e5e5b6f77 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java @@ -1,19 +1,18 @@ package com.sap.sailing.racecommittee.app.data.handlers; +import android.content.Context; +import android.content.Intent; + +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed; +import com.sap.sailing.domain.abstractlog.race.state.RaceState; +import com.sap.sailing.racecommittee.app.data.OnlineDataManager; +import com.sap.sailing.racecommittee.app.domain.ManagedRace; +import com.sap.sailing.racecommittee.app.services.RaceStateService; + import java.util.Collection; import java.util.HashSet; import java.util.Set; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed; -import com.sap.sailing.domain.abstractlog.race.state.RaceState; -import com.sap.sailing.racecommittee.app.AppConstants; -import com.sap.sailing.racecommittee.app.data.OnlineDataManager; -import com.sap.sailing.racecommittee.app.domain.ManagedRace; -import com.sap.sailing.racecommittee.app.services.polling.RaceLogPollingService; - -import android.content.Context; -import android.content.Intent; - public class ManagedRacesDataHandler extends DataHandler> { private Context context; @@ -37,14 +36,11 @@ public class ManagedRacesDataHandler extends DataHandler @Override public void onResult(Collection data, boolean isCached) { if (!isCached) { - Set deleteList = new HashSet<>(); - for (ManagedRace race : manager.getDataStore().getRaces()) { - if (!data.contains(race)) { - deleteList.add(new DeleteFromDataStore(context, manager, race)); - } - } - for (DeleteFromDataStore action : deleteList) { - action.run(); + manager.getDataStore().clearRaces(); + if (data.isEmpty()) { + final Intent intent = new Intent(context, RaceStateService.class); + context.stopService(intent); + return; } manager.addRaces(data); calcRaceState(data); @@ -78,27 +74,4 @@ public class ManagedRacesDataHandler extends DataHandler raceStatesWithUnresolvedStartTimes.removeAll(resolved); } while (oldNumberOfRaceStatesWithUnresolvedStartTimes != raceStatesWithUnresolvedStartTimes.size()); } - - private static class DeleteFromDataStore implements Runnable { - - private final Context context; - private final OnlineDataManager manager; - private final ManagedRace race; - - public DeleteFromDataStore(Context context, OnlineDataManager manager, ManagedRace race) { - this.context = context; - this.manager = manager; - this.race = race; - } - - @Override - public void run() { - manager.getDataStore().removeRace(race); - - Intent intent = new Intent(context, RaceLogPollingService.class); - intent.setAction(AppConstants.INTENT_ACTION_POLLING_RACE_REMOVE); - intent.putExtra(AppConstants.INTENT_ACTION_EXTRA, race.getId()); - context.startService(intent); - } - } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java index 26d0f8eb922..1559c8dfe2c 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java @@ -1,12 +1,17 @@ package com.sap.sailing.racecommittee.app.services; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import android.annotation.TargetApi; +import android.app.AlarmManager; +import android.app.Notification; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.Build; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.util.Pair; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.util.NotificationHelper; @@ -21,7 +26,6 @@ import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents; import com.sap.sailing.racecommittee.app.AppConstants; import com.sap.sailing.racecommittee.app.R; import com.sap.sailing.racecommittee.app.data.DataManager; -import com.sap.sailing.racecommittee.app.data.DataStore; import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager; import com.sap.sailing.racecommittee.app.domain.ManagedRace; import com.sap.sailing.racecommittee.app.services.polling.RaceLogPollingService; @@ -32,19 +36,11 @@ import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerialize import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogEventSerializer; import com.sap.sse.common.impl.MillisecondsTimePoint; -import android.annotation.TargetApi; -import android.app.AlarmManager; -import android.app.Notification; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Pair; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; public class RaceStateService extends Service { @@ -59,8 +55,6 @@ public class RaceStateService extends Service { } } - private final IBinder mBinder = new RaceStateServiceBinder(); - private AlarmManager alarmManager; private int alarmManagerRequestCode = 0; @@ -81,8 +75,6 @@ public class RaceStateService extends Service { this.registeredStateEventSchedulers = new HashMap<>(); this.managedIntents = new HashMap<>(); - super.onCreate(); - ExLog.i(this, TAG, "Started."); } @@ -103,7 +95,7 @@ public class RaceStateService extends Service { @Override public IBinder onBind(Intent intent) { - return mBinder; + return null; } @Override @@ -122,17 +114,41 @@ public class RaceStateService extends Service { @Override public void onDestroy() { unregisterAllRaces(); - stopForeground(true); - super.onDestroy(); } - @Override - public void onTaskRemoved(Intent rootIntent) { - super.onTaskRemoved(rootIntent); - unregisterAllRaces(); - stopForeground(true); - stopSelf(); - ExLog.i(this, TAG, "Race State Service is being removed."); + private void handleStartCommand(Intent intent) { + String action = intent.getAction(); + ExLog.i(this, TAG, String.format("Command action '%s' received.", action)); + + if (AppConstants.INTENT_ACTION_CLEAR_RACES.equals(action)) { + handleClearRaces(); + } else { + String id = intent.getStringExtra(AppConstants.INTENT_EXTRA_RACE_ID); + ManagedRace race = dataManager.getDataStore().getRace(id); + if (race == null) { + ExLog.w(this, TAG, "No race for id " + id); + return; + } + + switch (action) { + case AppConstants.INTENT_ACTION_REGISTER_RACE: + registerRace(race); + break; + case AppConstants.INTENT_ACTION_UNREGISTER_RACE: + unregisterRace(race); + break; + + case AppConstants.INTENT_ACTION_ALARM_ACTION: + long timePoint = intent.getLongExtra(AppConstants.INTENT_EXTRA_TIMEPOINT_MILLIS, 0); + String eventName = intent.getStringExtra(AppConstants.INTENT_EXTRA_EVENTNAME); + RaceStateEvent event = new RaceStateEventImpl(new MillisecondsTimePoint(timePoint), + RaceStateEvents.valueOf(eventName)); + ExLog.i(this, TAG, String.format("Processing %s", event.toString())); + race.getState().processStateEvent(event); + clearAlarmByName(race, event.getEventName()); + break; + } + } } private void unregisterAllRaces() { @@ -158,10 +174,9 @@ public class RaceStateService extends Service { managedIntents.clear(); ExLog.i(this, TAG, "All races unregistered."); - stopForeground(true); } - public void unregisterRace(ManagedRace race) { + private void unregisterRace(ManagedRace race) { Intent intent = new Intent(this, RaceLogPollingService.class); intent.setAction(AppConstants.INTENT_ACTION_POLLING_RACE_REMOVE); intent.putExtra(AppConstants.INTENT_ACTION_EXTRA, race.getId()); @@ -196,109 +211,24 @@ public class RaceStateService extends Service { } } - private void handleStartCommand(Intent intent) { - String action = intent.getAction(); - ExLog.i(this, TAG, String.format("Command action '%s' received.", action)); - - if (action != null) { - switch (action) { - case AppConstants.INTENT_ACTION_CLEAR_RACES: - handleClearRaces(); - break; - - case AppConstants.INTENT_ACTION_CLEANUP_RACES: - handleCleanupRaces(); - break; - - default: - String id = intent.getStringExtra(AppConstants.INTENT_EXTRA_RACE_ID); - ManagedRace race = dataManager.getDataStore().getRace(id); - if (race == null) { - ExLog.w(this, TAG, "No race for id " + id); - return; - } - - switch (action) { - case AppConstants.INTENT_ACTION_ALARM_ACTION: - long timePoint = intent.getLongExtra(AppConstants.INTENT_EXTRA_TIMEPOINT_MILLIS, 0); - String eventName = intent.getStringExtra(AppConstants.INTENT_EXTRA_EVENTNAME); - RaceStateEvent event = new RaceStateEventImpl(new MillisecondsTimePoint(timePoint), - RaceStateEvents.valueOf(eventName)); - ExLog.i(this, TAG, String.format("Processing %s", event.toString())); - race.getState().processStateEvent(event); - clearAlarmByName(race, event.getEventName()); - break; - } - } - } - } - private void handleClearRaces() { unregisterAllRaces(); - DataStore dataStore = dataManager.getDataStore(); - dataStore.getRaces().clear(); - dataStore.setEventUUID(null); - dataStore.setCourseAreaId(null); ExLog.i(this, TAG, "handleClearRaces: Cleared all races."); - stopSelf(); - } - - private class RemoveRaceAction implements Runnable { - - private final ManagedRace managedRace; - - /* package */ RemoveRaceAction(@NonNull ManagedRace race) { - managedRace = race; - } - - @Override - public void run() { - unregisterRace(managedRace); - } - } - - private void handleCleanupRaces() { - Set actions = new HashSet<>(); - for (String raceId : managedIntents.keySet()) { - if (!inDataStore(raceId)) { - for (ManagedRace race : registeredLogListeners.keySet()) { - if (race.getId().equals(raceId)) { - actions.add(new RemoveRaceAction(race)); - } - } - } - } - for (RemoveRaceAction action : actions) { - action.run(); - } - updateNotification(); - } - - private boolean inDataStore(String raceId) { - for (ManagedRace race : dataManager.getDataStore().getRaces()) { - if (race.getId().equals(raceId)) { - return true; - } - } - return false; } private void updateNotification() { int numRaces = managedIntents.keySet().size(); String content = getString(R.string.service_text_num_races, numRaces); Notification notification = setupNotification(content); - if (numRaces > 0) { - ExLog.i(this, TAG, "Starting foreground"); - startForeground(NotificationHelper.getNotificationId(), notification); - } + startForeground(NotificationHelper.getNotificationId(), notification); } - public void registerRace(ManagedRace race) { + private void registerRace(ManagedRace race) { ExLog.i(this, TAG, "Trying to register race " + race.getId()); if (!managedIntents.containsKey(race.getId())) { RaceState state = race.getState(); - managedIntents.put(race.getId(), new ArrayList>()); + managedIntents.put(race.getId(), new ArrayList<>()); // Register on event additions... JsonSerializer eventSerializer = RaceLogEventSerializer diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/polling/RaceLogPollingService.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/polling/RaceLogPollingService.java index 18aec93fc62..06935ae4f0c 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/polling/RaceLogPollingService.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/polling/RaceLogPollingService.java @@ -1,12 +1,14 @@ package com.sap.sailing.racecommittee.app.services.polling; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Build; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.text.TextUtils; import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.android.shared.services.sending.MessageSendingService; @@ -18,15 +20,13 @@ import com.sap.sailing.racecommittee.app.domain.ManagedRace; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Build; -import android.os.IBinder; -import android.support.annotation.Nullable; -import android.text.TextUtils; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class RaceLogPollingService extends Service implements AppPreferences.PollingActiveChangedListener, RaceLogPollingTask.PollingResultListener { @@ -60,45 +60,41 @@ public class RaceLogPollingService extends Service ExLog.i(this, TAG, "Restarted"); } else { String action = intent.getAction(); - String extra = null; - if (intent.getExtras() != null) { - extra = intent.getExtras().getString(AppConstants.INTENT_ACTION_EXTRA); - } + String extra = intent.getStringExtra(AppConstants.INTENT_ACTION_EXTRA); switch (action) { - case AppConstants.INTENT_ACTION_POLLING_STOP: - stopSelf(); - break; + case AppConstants.INTENT_ACTION_POLLING_STOP: + stopSelf(startId); + break; - case AppConstants.INTENT_ACTION_POLLING_RACE_ADD: - if (TextUtils.isEmpty(extra)) { - ExLog.i(this, TAG, "INTENT_ACTION_EXTRA was null for " + action); - } else { - registerRace(extra); - } - break; + case AppConstants.INTENT_ACTION_POLLING_RACE_ADD: + if (TextUtils.isEmpty(extra)) { + ExLog.i(this, TAG, "INTENT_ACTION_EXTRA was null for " + action); + } else { + registerRace(extra); + } + break; - case AppConstants.INTENT_ACTION_POLLING_RACE_REMOVE: - if (TextUtils.isEmpty(extra)) { - ExLog.i(this, TAG, "INTENT_ACTION_EXTRA was null for " + action); - } else { - unregisterRace(extra); - } - break; + case AppConstants.INTENT_ACTION_POLLING_RACE_REMOVE: + if (TextUtils.isEmpty(extra)) { + ExLog.i(this, TAG, "INTENT_ACTION_EXTRA was null for " + action); + } else { + unregisterRace(extra); + } + break; - case AppConstants.INTENT_ACTION_POLLING_POLL: - poll(); - break; + case AppConstants.INTENT_ACTION_POLLING_POLL: + poll(); + break; } } - return super.onStartCommand(intent, flags, startId); + // We want this service to continue running until it is explicitly + // stopped, therefore return sticky. + return START_STICKY; } @Override public void onDestroy() { - ExLog.i(this, TAG, "onDestroy"); - stopForeground(true); - stopSelf(); mRaces.clear(); if (mAppPreferences != null) { mAppPreferences.unregisterPollingActiveChangedListener(this); @@ -106,15 +102,6 @@ public class RaceLogPollingService extends Service if (mAlarm != null && mPendingIntent != null) { mAlarm.cancel(mPendingIntent); } - super.onDestroy(); - } - - @Override - public void onTaskRemoved(Intent rootIntent) { - super.onTaskRemoved(rootIntent); - stopForeground(true); - stopSelf(); - ExLog.i(this, TAG, "Race State Service is being removed."); } @Override @@ -200,7 +187,7 @@ public class RaceLogPollingService extends Service List> queries = getPollingQueries(); RaceLogPollingTask task = new RaceLogPollingTask(this, this); @SuppressWarnings("unchecked") - Util.Pair[] param = queries.toArray(new Util.Pair[queries.size()]); + Util.Pair[] param = queries.toArray(new Util.Pair[0]); task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, param); } } @@ -221,7 +208,7 @@ public class RaceLogPollingService extends Service mAlarm.cancel(mPendingIntent); } - if (mAppPreferences.isPollingActive() && mRaces.size() >= 0) { + if (mAppPreferences.isPollingActive() && !mRaces.isEmpty()) { long time = MillisecondsTimePoint.now().asMillis() + (1000 * mAppPreferences.getPollingInterval()); Intent intent = new Intent(this, this.getClass()); intent.setAction(AppConstants.INTENT_ACTION_POLLING_POLL); From 96c17b019b130e9760dcf731715830dec1933f84 Mon Sep 17 00:00:00 2001 From: Robert Benedikt Date: Mon, 10 Aug 2020 15:29:44 +0200 Subject: [PATCH 3/9] fix: stop service when user signs out --- .../racecommittee/app/data/DataManager.java | 5 +- .../racecommittee/app/data/DataStore.java | 8 ++- .../app/data/InMemoryDataStore.java | 50 +++++++++---------- .../handlers/ManagedRacesDataHandler.java | 11 +--- .../app/services/RaceStateService.java | 39 ++++++++------- 5 files changed, 52 insertions(+), 61 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java index 097d54742f8..61311cc9e6e 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataManager.java @@ -14,7 +14,6 @@ public abstract class DataManager implements ReadonlyDataManager { public static ReadonlyDataManager create(Context context) { DataStore dataStore = InMemoryDataStore.INSTANCE; - dataStore.setContext(context); if (AppPreferences.on(context).isOfflineMode()) { return new OfflineDataManager(context, dataStore, dataStore.getDomainFactory()); } @@ -42,13 +41,13 @@ public abstract class DataManager implements ReadonlyDataManager { } /** - * {@link InMemoryDataStore#clearRaces()} ()}, fires the {@link AppConstants#INTENT_ACTION_CLEAR_RACES} intent which is expected to + * {@link InMemoryDataStore#clearRaces(Context)}, fires the {@link AppConstants#INTENT_ACTION_CLEAR_RACES} intent which is expected to * be handled by the {@link RaceStateService} which responds by unregistering all its races, stopping to listen on * and poll their race logs and by clearing the data store's races collection. * {@link InMemoryDataStore#reset()} resets the data store properly. */ public void resetAll() { - InMemoryDataStore.INSTANCE.clearRaces(); + InMemoryDataStore.INSTANCE.clearRaces(context); InMemoryDataStore.INSTANCE.reset(); } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java index 677907fce69..4b0e1777c9e 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/DataStore.java @@ -18,8 +18,6 @@ import java.util.UUID; public interface DataStore { - void setContext(Context context); - void reset(); SharedDomainFactory getDomainFactory(); @@ -46,7 +44,7 @@ public interface DataStore { void addRace(int index, ManagedRace race); - void removeRace(ManagedRace race); + void removeRace(Context context, ManagedRace race); ManagedRace getRace(String id); @@ -56,9 +54,9 @@ public interface DataStore { boolean hasRace(SimpleRaceLogIdentifier id); - void registerRaces(Collection races); + void registerRaces(Context context, Collection races); - void clearRaces(); + void clearRaces(Context context); Collection getMarks(RaceGroup raceGroup); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java index 3bc6c1ad7f3..f9f247b61fd 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/InMemoryDataStore.java @@ -31,7 +31,6 @@ import java.util.UUID; public enum InMemoryDataStore implements DataStore { INSTANCE; - private Context mContext; private LinkedHashMap eventsById; private LinkedHashMap managedRaceById; private LinkedHashMap> marksData; @@ -45,13 +44,6 @@ public enum InMemoryDataStore implements DataStore { reset(); } - @Override - public void setContext(Context context) { - if (mContext == null) { - mContext = context.getApplicationContext(); - } - } - @Override public void reset() { eventsById = new LinkedHashMap<>(); @@ -120,9 +112,12 @@ public enum InMemoryDataStore implements DataStore { @Override public CourseArea getCourseArea(Serializable id) { for (EventBase event : eventsById.values()) { - for (CourseArea courseArea : getCourseAreas(event)) { - if (courseArea.getId().equals(id)) { - return courseArea; + final Collection courseAreas = getCourseAreas(event); + if (courseAreas != null) { + for (CourseArea courseArea : courseAreas) { + if (courseArea.getId().equals(id)) { + return courseArea; + } } } } @@ -132,9 +127,12 @@ public enum InMemoryDataStore implements DataStore { @Override public boolean hasCourseArea(Serializable id) { for (EventBase event : eventsById.values()) { - for (CourseArea courseArea : getCourseAreas(event)) { - if (courseArea.getId().equals(id)) { - return true; + final Collection courseAreas = getCourseAreas(event); + if (courseAreas != null) { + for (CourseArea courseArea : courseAreas) { + if (courseArea.getId().equals(id)) { + return true; + } } } } @@ -192,8 +190,8 @@ public enum InMemoryDataStore implements DataStore { } @Override - public void removeRace(ManagedRace race) { - unregisterRace(race); + public void removeRace(Context context, ManagedRace race) { + unregisterRace(context, race); managedRaceById.remove(convertManagedRaceIdentifierToSimpleRaceLogIdentifier(race.getIdentifier())); } @@ -288,7 +286,7 @@ public enum InMemoryDataStore implements DataStore { @Override public Set getRaceGroups() { - Set raceGroups = new HashSet(); + Set raceGroups = new HashSet<>(); for (ManagedRace race : getRaces()) { raceGroups.add(race.getRaceGroup()); } @@ -326,27 +324,27 @@ public enum InMemoryDataStore implements DataStore { } @Override - public void registerRaces(Collection races) { + public void registerRaces(Context context, Collection races) { for (ManagedRace race : races) { - final Intent registerIntent = new Intent(mContext, RaceStateService.class); + final Intent registerIntent = new Intent(context, RaceStateService.class); registerIntent.setAction(AppConstants.INTENT_ACTION_REGISTER_RACE); registerIntent.putExtra(AppConstants.INTENT_EXTRA_RACE_ID, race.getId()); - mContext.startService(registerIntent); + context.startService(registerIntent); } } @Override - public void clearRaces() { + public void clearRaces(Context context) { managedRaceById.clear(); - final Intent intent = new Intent(mContext, RaceStateService.class); + final Intent intent = new Intent(context, RaceStateService.class); intent.setAction(AppConstants.INTENT_ACTION_CLEAR_RACES); - mContext.startService(intent); + context.startService(intent); } - private void unregisterRace(ManagedRace race) { - final Intent intent = new Intent(mContext, RaceStateService.class); + private void unregisterRace(Context context, ManagedRace race) { + final Intent intent = new Intent(context, RaceStateService.class); intent.setAction(AppConstants.INTENT_ACTION_UNREGISTER_RACE); intent.putExtra(AppConstants.INTENT_EXTRA_RACE_ID, race.getId()); - mContext.startService(intent); + context.startService(intent); } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java index 45e5e5b6f77..db4a698c949 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/handlers/ManagedRacesDataHandler.java @@ -1,13 +1,11 @@ package com.sap.sailing.racecommittee.app.data.handlers; import android.content.Context; -import android.content.Intent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult.ResolutionFailed; import com.sap.sailing.domain.abstractlog.race.state.RaceState; import com.sap.sailing.racecommittee.app.data.OnlineDataManager; import com.sap.sailing.racecommittee.app.domain.ManagedRace; -import com.sap.sailing.racecommittee.app.services.RaceStateService; import java.util.Collection; import java.util.HashSet; @@ -36,15 +34,10 @@ public class ManagedRacesDataHandler extends DataHandler @Override public void onResult(Collection data, boolean isCached) { if (!isCached) { - manager.getDataStore().clearRaces(); - if (data.isEmpty()) { - final Intent intent = new Intent(context, RaceStateService.class); - context.stopService(intent); - return; - } + manager.getDataStore().clearRaces(context); manager.addRaces(data); calcRaceState(data); - manager.getDataStore().registerRaces(data); + manager.getDataStore().registerRaces(context, data); } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java index 1559c8dfe2c..6a905acd236 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/services/RaceStateService.java @@ -7,7 +7,6 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.support.annotation.Nullable; @@ -46,15 +45,6 @@ public class RaceStateService extends Service { private final static String TAG = RaceStateService.class.getName(); - /** - * Binder for this {@link RaceStateService}. - */ - public class RaceStateServiceBinder extends Binder { - public RaceStateService getService() { - return RaceStateService.this; - } - } - private AlarmManager alarmManager; private int alarmManagerRequestCode = 0; @@ -103,7 +93,7 @@ public class RaceStateService extends Service { if (intent == null) { ExLog.i(this, TAG, "Restarted."); } else { - handleStartCommand(intent); + handleStartCommand(intent, startId); } // We want this service to continue running until it is explicitly @@ -113,15 +103,23 @@ public class RaceStateService extends Service { @Override public void onDestroy() { - unregisterAllRaces(); + if (!managedIntents.isEmpty()) { + unregisterAllRaces(); + } + stopForeground(true); } - private void handleStartCommand(Intent intent) { + private void handleStartCommand(Intent intent, int startId) { String action = intent.getAction(); ExLog.i(this, TAG, String.format("Command action '%s' received.", action)); + if (action == null) { + return; + } + if (AppConstants.INTENT_ACTION_CLEAR_RACES.equals(action)) { handleClearRaces(); + stopSelf(startId); } else { String id = intent.getStringExtra(AppConstants.INTENT_EXTRA_RACE_ID); ManagedRace race = dataManager.getDataStore().getRace(id); @@ -272,7 +270,10 @@ public class RaceStateService extends Service { @TargetApi(Build.VERSION_CODES.KITKAT) /* package */ void setAlarm(ManagedRace race, RaceStateEvent event) { PendingIntent intent = createAlarmPendingIntent(race, event); - managedIntents.get(race.getId()).add(Pair.create(intent, event.getEventName())); + final List> intents = managedIntents.get(race.getId()); + if (intents != null) { + intents.add(Pair.create(intent, event.getEventName())); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { alarmManager.setExact(AlarmManager.RTC_WAKEUP, event.getTimePoint().asMillis(), intent); } else { @@ -284,10 +285,12 @@ public class RaceStateService extends Service { /* package */ void clearAlarmByName(ManagedRace race, RaceStateEvents stateEventName) { List> intents = managedIntents.get(race.getId()); Pair toBeRemoved = null; - for (Pair intentPair : intents) { - if (intentPair.second.equals(stateEventName)) { - toBeRemoved = intentPair; - break; + if (intents != null) { + for (Pair intentPair : intents) { + if (intentPair.second.equals(stateEventName)) { + toBeRemoved = intentPair; + break; + } } } if (toBeRemoved != null) { From 90aad259605aa61c560ac0b4c4da430b37ff0f79 Mon Sep 17 00:00:00 2001 From: "service.tip.git" Date: Thu, 20 Aug 2020 15:11:44 +0000 Subject: [PATCH 4/9] [INTERNAL] Translation delivery: commit by LX Lab Change-Id: I36ac6fbbc80c83c81a817eebc6d507d90774d0c5 --- .../SAPTracker/es.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/es.lproj/Localizable.strings | Bin 19728 -> 19742 bytes .../SAPTracker/fr.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/fr.lproj/Localizable.strings | Bin 20620 -> 20634 bytes .../SAPTracker/it.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/it.lproj/Localizable.strings | Bin 19642 -> 19656 bytes .../SAPTracker/ja.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/ja.lproj/Localizable.strings | Bin 15368 -> 15382 bytes .../SAPTracker/pt.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/pt.lproj/Localizable.strings | Bin 19412 -> 19426 bytes .../SAPTracker/ru.lproj/InfoPlist.strings | 6 +----- .../SAPTracker/ru.lproj/Localizable.strings | Bin 18944 -> 18958 bytes .../Sailing_StringMessages_es.properties | 1 + .../Sailing_StringMessages_fr.properties | 1 + .../Sailing_StringMessages_it.properties | 1 + .../Sailing_StringMessages_ja.properties | 1 + .../Sailing_StringMessages_pt.properties | 1 + .../Sailing_StringMessages_ru.properties | 1 + .../Sailing_StringMessages_zh.properties | 1 + .../ui/client/StringMessages_es.properties | 2 +- .../ui/client/StringMessages_it.properties | 2 +- .../ui/client/StringMessages_ru.properties | 2 +- .../ui/client/StringMessages_zh.properties | 2 +- .../ui/client/StringMessages_it.properties | 2 +- 24 files changed, 18 insertions(+), 35 deletions(-) diff --git a/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/InfoPlist.strings b/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/InfoPlist.strings index dd326d34bc3..ef1aa91e709 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/InfoPlist.strings +++ b/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/InfoPlist.strings @@ -1,8 +1,4 @@ -/* InfoPlist.strings - SAPTracker - - Created by Raimund Wege on 04.11.16. - Copyright © 2016 com.sap.sailing. All rights reserved. */ +/* InfoPlist.strings\n SAPTracker\n \n Created by Raimund Wege on 04.11.16.\n Copyright © 2016 com.sap.sailing. All rights reserved. */ "NSLocationAlwaysUsageDescription" = "Para poder realizar el rastreo de toda una carrera, es necesario que su teléfono continúe rastreando cuando apague o bloquee la pantalla, lo que ayuda a ahorrar batería y evita tener que parar el proceso de rastreo de forma involuntaria."; "NSLocationWhenInUseUsageDescription" = "Para poder realizar el rastreo de toda una carrera, es necesario que su teléfono continúe rastreando cuando apague o bloquee la pantalla, lo que ayuda a ahorrar batería y evita tener que parar el proceso de rastreo de forma involuntaria."; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/es.lproj/Localizable.strings index f4c2c786fe26b892a464b768470098ad09e7a76b..c618e30608e0630392cee097e1604c90ab165f8b 100644 GIT binary patch delta 70 zcmbO*i*ep8#tC}NF${SV^<}w%6oUc~g1EtfV9}+e!bqYZ8IX#}jBLV_{cPDbJ1}1G F1^{{^5h?%x delta 44 qcmbO?i*W)F=`nImG?ZoMVo(4=u8EO>K>pfNPAH#&YqKHaTW2xw`m)?Wia`MgLEPX#u;|iKVI)zI3`oV~gUaHY?HK+10YEJf AZ2$lO delta 44 scmbQWkg;bW;{-iMu8D@S>|6{AK*%*QG7!jLTgnOLGjMG-WX$vj0PO7vYXATM diff --git a/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/InfoPlist.strings b/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/InfoPlist.strings index 34c93305755..a959aa61afd 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/InfoPlist.strings +++ b/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/InfoPlist.strings @@ -1,8 +1,4 @@ -/* InfoPlist.strings - SAPTracker - - Created by Raimund Wege on 04.11.16. - Copyright © 2016 com.sap.sailing. All rights reserved. */ +/* InfoPlist.strings\n SAPTracker\n \n Created by Raimund Wege on 04.11.16.\n Copyright © 2016 com.sap.sailing. All rights reserved. */ "NSLocationAlwaysUsageDescription" = "Per tracciare l'intera gara il tuo telefono deve continuare il tracciamento anche quando disattivi o blocchi lo schermo per risparmiare la batteria ed evitare di arrestare involontariamente il processo di tracciamento."; "NSLocationWhenInUseUsageDescription" = "Per tracciare l'intera gara il tuo telefono deve continuare il tracciamento anche quando disattivi o blocchi lo schermo per risparmiare la batteria ed evitare di arrestare involontariamente il processo di tracciamento."; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/it.lproj/Localizable.strings index 959de9374a293f016589000d306d830824937749..96314c662c9e1c46d07f203c63b890c90b492956 100644 GIT binary patch delta 70 zcmdlrlkvn%#tC}NF${SV^<}w%6oUc~g1EtfV9}+e!bqYZ8IX#}h0MZ}H`uUkc3`aX F1^}0m5%d56 delta 44 scmX>xlX2Hf#tC|iToVmt*|``LfRJlqWFU~gwv-dfXW-gw$T-~_0QvI?;Q#;t diff --git a/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/InfoPlist.strings b/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/InfoPlist.strings index 53d83affa8f..308d324df52 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/InfoPlist.strings +++ b/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/InfoPlist.strings @@ -1,8 +1,4 @@ -/* InfoPlist.strings - SAPTracker - - Created by Raimund Wege on 04.11.16. - Copyright © 2016 com.sap.sailing. All rights reserved. */ +/* InfoPlist.strings\n SAPTracker\n \n Created by Raimund Wege on 04.11.16.\n Copyright © 2016 com.sap.sailing. All rights reserved. */ "NSLocationAlwaysUsageDescription" = "レース全体を追跡するには、画面のオフ時またはロック時にも電話で追跡が続行される必要があり、これは電池の節約や追跡プロセスの意図しない停止の回避に役立ちます。"; "NSLocationWhenInUseUsageDescription" = "レース全体を追跡するには、画面のオフ時またはロック時にも電話で追跡が続行される必要があり、これは電池の節約や追跡プロセスの意図しない停止の回避に役立ちます。"; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/ja.lproj/Localizable.strings index f150d48ae336b198d2415e03e2e2f90f0c138fa7..2b460c7032a768ff396d30edce4bfcef336ffb7e 100644 GIT binary patch delta 64 ycmeCEm{u`Ck2!`RZ=${|H;`gb074KqI1ntlv{V>L6eI&uF*#6Obh8cP87lxIv=9ma delta 42 qcmbPM(NQr$kCAJlp)5NWg8~q8O^gf#^4FGfLir3_n++MCS^)st!U=W& diff --git a/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/InfoPlist.strings b/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/InfoPlist.strings index 302f0ffba3a..50289d72d92 100644 --- a/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/InfoPlist.strings +++ b/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/InfoPlist.strings @@ -1,8 +1,4 @@ -/* InfoPlist.strings - SAPTracker - - Created by Raimund Wege on 04.11.16. - Copyright © 2016 com.sap.sailing. All rights reserved. */ +/* InfoPlist.strings\n SAPTracker\n \n Created by Raimund Wege on 04.11.16.\n Copyright © 2016 com.sap.sailing. All rights reserved. */ "NSLocationAlwaysUsageDescription" = "Para rastrear a corrida completa, seu telefone precisa continuar o rastreamento mesmo quando você desativa ou bloqueia a tela, o que ajuda a poupar bateria e evita a paragem acidental do processo de rastreamento."; "NSLocationWhenInUseUsageDescription" = "Para rastrear a corrida completa, seu telefone precisa continuar o rastreamento mesmo quando você desativa ou bloqueia a tela, o que ajuda a poupar bateria e evita a paragem acidental do processo de rastreamento."; diff --git a/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/Localizable.strings b/ios/SAPTracker/src/xcode/SAPTracker/pt.lproj/Localizable.strings index eab9baa81318fe20d0bc4ac8255707228a84ab9d..c45dda2bd3c39a5533a8704ebef53391c7453bad 100644 GIT binary patch delta 69 zcmcaIo$=9h#tC}NF${SV^<}w%6oUc~g1EtfV9}+e!bqYZ8IX#}i5$X{Y}htCFi!CT E0FNROfdBvi delta 44 scmaDfo$<TeOYcG#h?I$AZ~CVSafNrFp?-p2BczgqpR>{E5>6U05e?> Ah5!Hn delta 44 scmeC1!q_l{ae^Kr*F-~Eb}j}5Amo}D83^RBE#-vr8MrnZGT!w70OgwrrT_o{ diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_es.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_es.properties index 270a5396d55..b648f90a8ce 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_es.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_es.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Apéndices de foil FoilingSegmentName=Nombre de apéndice de foil WindFixSailingDomainRetrieverChain=Puntos de viento MarkPassingSailingDomainRetrieverChain=Superaciones de marca +TrackedRaceResultOfCompetitorRetrieverChain=Carreras RaceResultSailingDomainRetrieverChain=Resultados de la carrera RaceOfCompetitorSailingDomainRetrieverChain=Carreras de los competidores ManeuverSailingDomainRetrieverChain=Maniobra diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_fr.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_fr.properties index 1ba52525795..89e6f873dde 100755 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_fr.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_fr.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Tronçons en planing FoilingSegmentName=Nom du tronçon en planing WindFixSailingDomainRetrieverChain=Points vent MarkPassingSailingDomainRetrieverChain=Passages des marques +TrackedRaceResultOfCompetitorRetrieverChain=Courses RaceResultSailingDomainRetrieverChain=Résultats de course RaceOfCompetitorSailingDomainRetrieverChain=Courses des concurrents ManeuverSailingDomainRetrieverChain=Manœuvre diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_it.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_it.properties index a6585a97b28..b6e7d7980b3 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_it.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_it.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Segmenti percorsi su foil FoilingSegmentName=Nome del segmento percorso su foil WindFixSailingDomainRetrieverChain=Punti nave vento MarkPassingSailingDomainRetrieverChain=Passaggi di segnali +TrackedRaceResultOfCompetitorRetrieverChain=Gare RaceResultSailingDomainRetrieverChain=Risultati gara RaceOfCompetitorSailingDomainRetrieverChain=Gare di concorrenti ManeuverSailingDomainRetrieverChain=Manovra diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ja.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ja.properties index 5caf71bb7ab..aac33ebb56b 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ja.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ja.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=フォイリングしたセグメン FoilingSegmentName=フォイリングしたセグメント名 WindFixSailingDomainRetrieverChain=風フィックス MarkPassingSailingDomainRetrieverChain=マーク通過 +TrackedRaceResultOfCompetitorRetrieverChain=レース RaceResultSailingDomainRetrieverChain=レース結果 RaceOfCompetitorSailingDomainRetrieverChain=競技者のレース ManeuverSailingDomainRetrieverChain=マニューバー diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_pt.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_pt.properties index 37e746b7e8a..407c479ec64 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_pt.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_pt.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Segmentos com hidrofólio FoilingSegmentName=Nome do segmento com hidrofólio WindFixSailingDomainRetrieverChain=Pontos fixos de vento MarkPassingSailingDomainRetrieverChain=Passagens na marca +TrackedRaceResultOfCompetitorRetrieverChain=Corridas RaceResultSailingDomainRetrieverChain=Resultados da corrida RaceOfCompetitorSailingDomainRetrieverChain=Corridas de competidores ManeuverSailingDomainRetrieverChain=Manobra diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ru.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ru.properties index 9a4ff656295..c9816e6b229 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ru.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_ru.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Сегменты в крыльево FoilingSegmentName=Имя сегмента в крыльевом режиме WindFixSailingDomainRetrieverChain=Замеры ветра MarkPassingSailingDomainRetrieverChain=Прохождения отметок +TrackedRaceResultOfCompetitorRetrieverChain=Гонки RaceResultSailingDomainRetrieverChain=Результаты гонки RaceOfCompetitorSailingDomainRetrieverChain=Гонки участников ManeuverSailingDomainRetrieverChain=Маневр diff --git a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_zh.properties b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_zh.properties index 3b9137a9bc5..98ff4a27200 100644 --- a/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_zh.properties +++ b/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages_zh.properties @@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=水翼腾空段 FoilingSegmentName=水翼腾空段名称 WindFixSailingDomainRetrieverChain=风力修复 MarkPassingSailingDomainRetrieverChain=绕标 +TrackedRaceResultOfCompetitorRetrieverChain=比赛轮次 RaceResultSailingDomainRetrieverChain=比赛轮次结果 RaceOfCompetitorSailingDomainRetrieverChain=参赛队的比赛轮次 ManeuverSailingDomainRetrieverChain=操作 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties index d2740a8fb7f..af7000643e2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties @@ -532,7 +532,7 @@ actionAddEvent=Añadir evento publicationUrl=URL de publicación suppress=Suprimir isListedOnHomepage=Enumerado en la página de inicio -raceSelection=Selección de carrera +raceSelection=Selección de la carrera unsuppress=Anular la eliminación suppressedCompetitors=Competidores suprimidos mediaPanel=Audio y vídeo diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties index f2c7c7385b3..b8c2d29737d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties @@ -532,7 +532,7 @@ actionAddEvent=Aggiungi evento publicationUrl=URL pubblicazione suppress=Elimina isListedOnHomepage=è elencato nella pagina principale -raceSelection=Selezione della gara +raceSelection=Selezione gara unsuppress=Annulla eliminazione suppressedCompetitors=Concorrenti eliminati mediaPanel=Audio e Video diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index f3c461e4667..ade3570000c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -532,7 +532,7 @@ actionAddEvent=Добавить событие publicationUrl=URL-адрес публикации suppress=Подавлять isListedOnHomepage=Отображается на начальной странице -raceSelection=выбор расы +raceSelection=Выбор гонки unsuppress=Отменить подавление suppressedCompetitors=Подавляемые участники mediaPanel=Аудио и видео diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 231586e3e7f..9cac7192aa8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -532,7 +532,7 @@ actionAddEvent=添加活动 publicationUrl=出版 URL suppress=禁止 isListedOnHomepage=列在主页中 -raceSelection=種族選擇 +raceSelection=竞赛选择 unsuppress=取消禁止 suppressedCompetitors=禁止的参赛队 mediaPanel=音频和视频 diff --git a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties index 57d5291d872..3ab96a8f109 100644 --- a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties +++ b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties @@ -61,7 +61,7 @@ queryBasedOnRetrieverChainCanNotBeApplied=Impossibile eseguire la query in base statisticNotAvailable=Statistica {0} non disponibile. aggregatorNotAvailable=Aggregatore {0} non disponibile. filterDimensionsAreNotAvailable=Le seguenti dimensioni filtro non sono disponibili: {0} -filterValuesOfDimensionAreNotAvailable=I seguenti valori filtro della dimensione {0} non sono disponibili: {1} +filterValuesOfDimensionAreNotAvailable=I seguenti valori filtro della dimensione {1} non sono disponibili: {1} groupingDimensionsAreNotAvailable=Le seguenti dimensioni filtro non sono disponibili: {0} rememberDecisionCanBeChangedInSettings=Ricorda decisione (modificabile nelle impostazioni) changeLossStrategy=Strategia perdita di modifiche From 4a28c9901cb4f2e482e64e6f47172ccdf32329e4 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 28 Aug 2020 19:54:08 +0200 Subject: [PATCH 5/9] ignore Igtimi fixes with null timepoints --- .../domain/igtimiadapter/impl/FixFactory.java | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/FixFactory.java b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/FixFactory.java index 79a83f4a64e..bfb0048afe6 100755 --- a/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/FixFactory.java +++ b/java/com.sap.sailing.domain.igtimiadapter/src/com/sap/sailing/domain/igtimiadapter/impl/FixFactory.java @@ -43,22 +43,24 @@ public class FixFactory { JSONArray timePointsMillis = (JSONArray) fixesJson.get("t"); int fixIndex = 0; for (Object timePointMillis : timePointsMillis) { - TimePoint timePoint = new MillisecondsTimePoint(((Number) timePointMillis).longValue()); - Map valuesPerSubindex = new HashMap<>(); - int i=1; - JSONArray values; - while ((values=(JSONArray) fixesJson.get(""+i)) != null) { - valuesPerSubindex.put(i, values.get(fixIndex)); - i++; - } - Sensor sensor = new SensorImpl(deviceSerialNumber, - fixTypeAndOptionalColonSeparatedSensorsSubId.length < 2 ? 0 - : Long.valueOf(fixTypeAndOptionalColonSeparatedSensorsSubId[1])); - final Type ft = Type.valueOf(fixType); - if (ft != null) { - Fix fix = createFix(sensor, ft, timePoint, valuesPerSubindex); - result.add(fix); - fixIndex++; + if (timePointMillis != null) { + TimePoint timePoint = new MillisecondsTimePoint(((Number) timePointMillis).longValue()); + Map valuesPerSubindex = new HashMap<>(); + int i=1; + JSONArray values; + while ((values=(JSONArray) fixesJson.get(""+i)) != null) { + valuesPerSubindex.put(i, values.get(fixIndex)); + i++; + } + Sensor sensor = new SensorImpl(deviceSerialNumber, + fixTypeAndOptionalColonSeparatedSensorsSubId.length < 2 ? 0 + : Long.valueOf(fixTypeAndOptionalColonSeparatedSensorsSubId[1])); + final Type ft = Type.valueOf(fixType); + if (ft != null) { + Fix fix = createFix(sensor, ft, timePoint, valuesPerSubindex); + result.add(fix); + fixIndex++; + } } } } From f70e0b62f1c684d0087ae6f21d4293480e674e83 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 29 Aug 2020 16:24:36 +0200 Subject: [PATCH 6/9] fixed incorrect placeholder in Italian translation in DataMining module --- .../sap/sse/datamining/ui/client/StringMessages_it.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties index 3ab96a8f109..57d5291d872 100644 --- a/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties +++ b/java/com.sap.sse.datamining.ui/src/main/java/com/sap/sse/datamining/ui/client/StringMessages_it.properties @@ -61,7 +61,7 @@ queryBasedOnRetrieverChainCanNotBeApplied=Impossibile eseguire la query in base statisticNotAvailable=Statistica {0} non disponibile. aggregatorNotAvailable=Aggregatore {0} non disponibile. filterDimensionsAreNotAvailable=Le seguenti dimensioni filtro non sono disponibili: {0} -filterValuesOfDimensionAreNotAvailable=I seguenti valori filtro della dimensione {1} non sono disponibili: {1} +filterValuesOfDimensionAreNotAvailable=I seguenti valori filtro della dimensione {0} non sono disponibili: {1} groupingDimensionsAreNotAvailable=Le seguenti dimensioni filtro non sono disponibili: {0} rememberDecisionCanBeChangedInSettings=Ricorda decisione (modificabile nelle impostazioni) changeLossStrategy=Strategia perdita di modifiche From 76d999c9758e25c75709079b36b4d787d07720ee Mon Sep 17 00:00:00 2001 From: Dennis Aulenbacher Date: Mon, 31 Aug 2020 14:42:01 +0200 Subject: [PATCH 7/9] added eclipse2020-06 pluginInstall script --- .../installPluginsForEclipse2020-06.sh | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 configuration/installPluginsForEclipse2020-06.sh diff --git a/configuration/installPluginsForEclipse2020-06.sh b/configuration/installPluginsForEclipse2020-06.sh new file mode 100644 index 00000000000..0d62f5fe5d1 --- /dev/null +++ b/configuration/installPluginsForEclipse2020-06.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# You need an installation of the 2020-06 release of "Eclipse IDE for Eclipse Committers" matching you OS and JDK (32 vs 64 Bit): +# https://www.eclipse.org/downloads/packages/release/2020-06/r/eclipse-ide-eclipse-committers + +if [[ $1 == "" ]]; then + echo "You need to specify the Eclipse installation directory" + exit 1 +fi + +installPath="$1" + +installPlugins() { + "$installPath/eclipse" -application org.eclipse.equinox.p2.director -noSplash -roaming -repository $1 -installIU $2 + echo "" +} + +updatePlugins() { + "$installPath/eclipse" -application org.eclipse.equinox.p2.director -noSplash -roaming -repository $1 -uninstallIU $2 -installIU $2 + echo "" +} + +uninstallPlugins() { + "$installPath/eclipse" -application org.eclipse.equinox.p2.director -noSplash -roaming -uninstallIU $1 + echo "" +} + +# Not necessary if using Eclipse for JEE developers +echo "Installing webtools (WTP/WST/JPT) and m2e that are required by the GWT plugin..." +installPlugins http://download.eclipse.org/releases/2020-06/ org.eclipse.wst.web_ui.feature.feature.group,org.eclipse.jst.web_ui.feature.feature.group,org.eclipse.wst.xml_ui.feature.feature.group,org.eclipse.jpt.common.feature.feature.group,org.eclipse.jpt.jpa.feature.feature.group,org.eclipse.m2e.feature.feature.group,org.eclipse.m2e.wtp.feature.feature.group + +echo "Installing GWT plugin..." +installPlugins http://storage.googleapis.com/gwt-eclipse-plugin/v3/release com.gwtplugins.eclipse.suite.v3.feature.feature.group + +echo "Installing Mission Control plugin..." +installPlugins http://download.oracle.com/technology/products/missioncontrol/updatesites/base/6.0.0/eclipse com.oracle.jmc.feature.ide.feature.group,com.oracle.jmc.feature.flightrecorder.feature.group,com.oracle.jmc.feature.core.feature.group,com.oracle.jmc.feature.console.feature.group,com.oracle.jmc.feature.core.feature.group,com.oracle.jmc.feature.core.feature.group + +echo "Installing GWT SDM debug bridge..." +installPlugins http://p2.sapsailing.com/p2/sdbg com.github.sdbg.feature.feature.group + +echo "Installing EasyShell..." +installPlugins http://anb0s.github.io/EasyShell de.anbos.eclipse.easyshell.feature.feature.group + +echo "Installing Memory Analyzer..." +installPlugins http://download.eclipse.org/releases/2020-06 org.eclipse.mat.feature.feature.group,org.eclipse.mat.chart.feature.feature.group + +echo "Installing SAP JVM Tools (profiler) ..." +installPlugins https://tools.hana.ondemand.com/oxygen com.sap.jvm.profiling.feature.group + +echo "Installing UMLet ..." +installPlugins https://www.umlet.com/umlet_latest/repository/ umlet-eclipse-feature.feature.group + +echo "Installing javax.xml.bind for news feed polling (see https://stackoverflow.com/questions/52528693/eclipse-internal-error-polling-news-feeds)..." +installPlugins http://download.eclipse.org/tools/orbit/downloads/drops/R20200224183213/repository javax.xml.bind + +echo "Installing Enhanced Class Decompiler" +installPlugins https://ecd-plugin.github.io/update org.sf.feeling.decompiler.feature.group,org.sf.feeling.decompiler.cfr.feature.group,org.sf.feeling.decompiler.jad.feature.group,org.sf.feeling.decompiler.jd.feature.group,org.sf.feeling.decompiler.procyon.feature.group + +echo "Uninstalling Wild Web Developer" +uninstallPlugins org.eclipse.wildwebdeveloper.feature.feature.group + +echo "Installation completed!" From 506160a9180e61f3f6eebcf8e561db605ff35405 Mon Sep 17 00:00:00 2001 From: Udo Wessels Date: Mon, 31 Aug 2020 16:18:37 +0200 Subject: [PATCH 8/9] bug5322: fixed testing: exchange thread sync logic with ExecutionService and Future implementation. The old implementation causes synchronization failures. It was possible to enter the synchronized block of the main thread before coming to the synchronized block of the child thread. Therefore the result was null (after the defined wait). This behavior causes randomly assertion errors while building and testing the application. Added org.objenesis dependency to manifest. This dependency was missing and therefore for local test execution was not possible (Igtimi tests). --- .../declination/impl/DeclinationImporter.java | 47 ++++++++----------- .../META-INF/MANIFEST.MF | 3 +- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationImporter.java b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationImporter.java index c7d978fc894..2faefd7342e 100644 --- a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationImporter.java +++ b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationImporter.java @@ -2,6 +2,11 @@ package com.sap.sailing.declination.impl; import java.io.IOException; import java.text.ParseException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,34 +38,20 @@ public abstract class DeclinationImporter { */ public Declination getDeclination(final Position position, final TimePoint timePoint, long timeoutForOnlineFetchInMilliseconds) throws IOException, ParseException { - final Declination[] result = new Declination[1]; - Thread fetcher = new Thread("Declination fetcher for "+position+"@"+timePoint) { - @Override - public void run() { - try { - Declination fetched = importRecord(position, timePoint); - synchronized (result) { - result[0] = fetched; - result.notifyAll(); - } - } catch (IOException | ParserConfigurationException | SAXException e) { - logger.log(Level.INFO, "Exception while trying to load magnetic declination online", e); - synchronized (result) { - result.notifyAll(); // wake up waiter; no result will show up anymore - } - } - } - }; - fetcher.start(); - synchronized (result) { - if (result[0] == null) { - try { - result.wait(timeoutForOnlineFetchInMilliseconds); - } catch (InterruptedException e) { - // ignore; simply use value from file in this case - } - } + ExecutorService executorService = Executors.newFixedThreadPool(1); + try { + return executorService.submit( + () -> importRecord(position, timePoint) + ).get(timeoutForOnlineFetchInMilliseconds, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + logger.log(Level.INFO, "Timeout while getting declination.", e); + // ignore; simply use value from file in this case + } catch (InterruptedException e) { + logger.log(Level.INFO, "InterruptedException while getting declination", e); + // ignore; simply use value from file in this case + } catch (ExecutionException e) { + logger.log(Level.INFO, "Exception while trying to load magnetic declination online", e); } - return result[0]; + return null; } } diff --git a/java/com.sap.sailing.domain.igtimiadapter.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.igtimiadapter.test/META-INF/MANIFEST.MF index d698ba8aba0..50dcf15136a 100644 --- a/java/com.sap.sailing.domain.igtimiadapter.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.igtimiadapter.test/META-INF/MANIFEST.MF @@ -13,4 +13,5 @@ Require-Bundle: org.junit;bundle-version="4.8.2", com.sap.sse.common, com.sap.sse.security.testsupport, org.mockito.mockito-core;bundle-version="1.10.14", - org.hamcrest;bundle-version="1.1.0" + org.hamcrest;bundle-version="1.1.0", + org.objenesis;bundle-version="2.1.0" From a08ae2261cbb696d99cccbf68c3cd80fac3dcd52 Mon Sep 17 00:00:00 2001 From: Simon Pamies Date: Wed, 2 Sep 2020 14:49:41 +0200 Subject: [PATCH 9/9] Added field trackedRaceUuid to API /v1/api/leaderboardgroups/{name} as per request of TracTrac --- .../racelogtracking/impl/RaceLogRaceTracker.java | 2 +- .../domain/tracking/TrackingConnectorInfo.java | 6 ++++++ .../tracking/impl/TrackingConnectorInfoImpl.java | 15 ++++++++++++++- .../impl/SwissTimingRaceTrackerImpl.java | 2 +- .../impl/SwissTimingReplayToDomainAdapter.java | 2 +- .../tractracadapter/impl/DomainFactoryImpl.java | 2 +- .../tractracadapter/impl/RaceCourseReceiver.java | 2 +- .../TrackingConnectorInfoJsonDeserializer.java | 11 ++++++++++- .../impl/TrackingConnectorInfoJsonSerializer.java | 6 ++++++ .../jaxrs/api/LeaderboardGroupsResource.java | 1 + 10 files changed, 42 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index d476f76c453..5a63de1851c 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -369,7 +369,7 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { params.getDelayToLiveInMillis(), WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, boatClass.getApproximateManeuverDurationInMilliseconds(), null, /*useMarkPassingCalculator*/ true, raceLogResolver, /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), - new TrackingConnectorInfoImpl(TrackingConnectorType.RaceLog, /* webUrl */ null)); + new TrackingConnectorInfoImpl(TrackingConnectorType.RaceLog, /* webUrl */ null, /* uuid */ null)); notifyRaceCreationListeners(); logger.info(String.format("Started tracking race-log race (%s)", raceLog)); // this wakes up all waiting race handles diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/TrackingConnectorInfo.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/TrackingConnectorInfo.java index 936bfa77c91..194b0f6ed90 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/TrackingConnectorInfo.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/TrackingConnectorInfo.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking; import java.io.Serializable; import java.net.URL; +import java.util.UUID; import com.sap.sailing.domain.common.tracking.TrackingConnectorType; @@ -21,4 +22,9 @@ public interface TrackingConnectorInfo extends Serializable { * may be {@code null} if the API of the respective Tracking-Service does not provide a URL; */ URL getWebUrl(); + + /** + * gets a unique identifier for the tracked race matching the one given by the provider + */ + UUID getUuid(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackingConnectorInfoImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackingConnectorInfoImpl.java index 65a8a27434c..3a128baeece 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackingConnectorInfoImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/tracking/impl/TrackingConnectorInfoImpl.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.tracking.impl; import java.net.URL; +import java.util.UUID; import com.sap.sailing.domain.common.tracking.TrackingConnectorType; import com.sap.sailing.domain.tracking.TrackingConnectorInfo; @@ -9,11 +10,13 @@ public class TrackingConnectorInfoImpl implements TrackingConnectorInfo { private static final long serialVersionUID = 7970268841592389145L; private final TrackingConnectorType trackingConnectorType; private final URL webUrl; + private final UUID uuid; - public TrackingConnectorInfoImpl(TrackingConnectorType trackingConnectorType, URL webUrl) { + public TrackingConnectorInfoImpl(TrackingConnectorType trackingConnectorType, URL webUrl, UUID itemUUID) { super(); this.trackingConnectorType = trackingConnectorType; this.webUrl = webUrl; + this.uuid = itemUUID; } public TrackingConnectorType getTrackingConnectorType() { @@ -23,6 +26,10 @@ public class TrackingConnectorInfoImpl implements TrackingConnectorInfo { public URL getWebUrl() { return webUrl; } + + public UUID getUuid() { + return uuid; + } @Override public int hashCode() { @@ -30,6 +37,7 @@ public class TrackingConnectorInfoImpl implements TrackingConnectorInfo { int result = 1; result = prime * result + ((trackingConnectorType == null) ? 0 : trackingConnectorType.hashCode()); result = prime * result + ((webUrl == null) ? 0 : webUrl.hashCode()); + result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); return result; } @@ -52,6 +60,11 @@ public class TrackingConnectorInfoImpl implements TrackingConnectorInfo { return false; } else if (!webUrl.equals(other.webUrl)) return false; + if (uuid == null) { + if (other.uuid != null) + return false; + } else if (!uuid.equals(other.uuid)) + return false; return true; } } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java index e4f8aa67a44..fae5b40e703 100644 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/SwissTimingRaceTrackerImpl.java @@ -540,7 +540,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl } }, useInternalMarkPassingAlgorithm, raceLogResolver, /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), - new TrackingConnectorInfoImpl(TrackingConnectorType.SwissTiming, /*no api connection to query the webUrl*/ null)); + new TrackingConnectorInfoImpl(TrackingConnectorType.SwissTiming, /*no api connection to query the webUrl*/ null, /* uuid */ null)); addUpdateHandlers(); notifyRaceCreationListeners(); logger.info("Created SwissTiming RaceDefinition and TrackedRace for "+race.getName()); diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java index fec9e9f6755..ded5750041e 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java @@ -417,7 +417,7 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), /* raceDefinitionSetToUpdate */ null, useInternalMarkPassingAlgorithm, raceLogResolver, /* Not needed because the RaceTracker is not active on a replica */ Optional.empty(), - new TrackingConnectorInfoImpl(TrackingConnectorType.SwissTiming, /*no api connection to query the webUrl*/ null)); + new TrackingConnectorInfoImpl(TrackingConnectorType.SwissTiming, /*no api connection to query the webUrl*/ null, /* uuid */ null)); trackedRace.onStatusChanged(this, new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0)); TimePoint bestStartTimeKnownSoFar = bestStartTimePerRaceID.get(currentRaceID); if (bestStartTimeKnownSoFar != null) { diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index b499de8dcce..c6084c93569 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -661,7 +661,7 @@ public class DomainFactoryImpl implements DomainFactory { trackedRegatta.getRegatta().addRace(raceDefinition); TrackingConnectorInfo trackingConnectorInfo = null; if (tractracRace != null) { - trackingConnectorInfo = new TrackingConnectorInfoImpl(TrackingConnectorType.TracTrac, tractracRace.getEvent().getWebURL()); + trackingConnectorInfo = new TrackingConnectorInfoImpl(TrackingConnectorType.TracTrac, tractracRace.getEvent().getWebURL(), tractracRace.getId()); } trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, ignoreTracTracMarkPassings, diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java index 366cb2236bd..c1d2dcf89fe 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java @@ -276,7 +276,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue { public static final String FIELD_TRACKING_CONNECTOR_TYPE = "trackingConnectorType"; public static final String FIELD_WEB_URL = "webUrl"; + public static final String FIELD_UUID = "uuid"; @Override public JSONObject serialize(TrackingConnectorInfo trackingConnectorInfo) { @@ -19,6 +21,10 @@ public class TrackingConnectorInfoJsonSerializer implements JsonSerializer