mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-08 20:12:23 +00:00
Merge branch 'master' into bug5239
This commit is contained in:
commit
f7d4fa34aa
48 files changed
+395
-528
No files matched your search
@@ -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!"
|
||||
@@ -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.";
|
||||
|
||||
Binary file not shown.
@@ -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" = "Pour pouvoir suivre l'intégralité de votre course, votre téléphone doit continuer le suivi même si vous l'éteignez ou verrouillez l'écran (pour économiser de l'énergie). Ainsi, vous évitez un arrêt non voulu du suivi.";
|
||||
|
||||
"NSLocationWhenInUseUsageDescription" = "Pour pouvoir suivre l'intégralité de votre course, votre téléphone doit continuer le suivi même si vous l'éteignez ou verrouillez l'écran (pour économiser de l'énergie). Ainsi, vous évitez un arrêt non voulu du suivi.";
|
||||
|
||||
Binary file not shown.
@@ -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.";
|
||||
|
||||
Binary file not shown.
@@ -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" = "レース全体を追跡するには、画面のオフ時またはロック時にも電話で追跡が続行される必要があり、これは電池の節約や追跡プロセスの意図しない停止の回避に役立ちます。";
|
||||
|
||||
Binary file not shown.
@@ -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.";
|
||||
|
||||
Binary file not shown.
@@ -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" = "Для отслеживания всей гонки ваш телефон должен продолжать отслеживание даже при выключении или блокировке экрана, что помогает экономить заряд аккумулятора и избегать непреднамеренной остановки процесса отслеживания.";
|
||||
|
||||
Binary file not shown.
+1
@@ -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
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=フォイリングしたセグメン
|
||||
FoilingSegmentName=フォイリングしたセグメント名
|
||||
WindFixSailingDomainRetrieverChain=風フィックス
|
||||
MarkPassingSailingDomainRetrieverChain=マーク通過
|
||||
TrackedRaceResultOfCompetitorRetrieverChain=レース
|
||||
RaceResultSailingDomainRetrieverChain=レース結果
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=競技者のレース
|
||||
ManeuverSailingDomainRetrieverChain=マニューバー
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=Сегменты в крыльево
|
||||
FoilingSegmentName=Имя сегмента в крыльевом режиме
|
||||
WindFixSailingDomainRetrieverChain=Замеры ветра
|
||||
MarkPassingSailingDomainRetrieverChain=Прохождения отметок
|
||||
TrackedRaceResultOfCompetitorRetrieverChain=Гонки
|
||||
RaceResultSailingDomainRetrieverChain=Результаты гонки
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Гонки участников
|
||||
ManeuverSailingDomainRetrieverChain=Маневр
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ FoilingSegmentsSailingDomainRetrieverChain=水翼腾空段
|
||||
FoilingSegmentName=水翼腾空段名称
|
||||
WindFixSailingDomainRetrieverChain=风力修复
|
||||
MarkPassingSailingDomainRetrieverChain=绕标
|
||||
TrackedRaceResultOfCompetitorRetrieverChain=比赛轮次
|
||||
RaceResultSailingDomainRetrieverChain=比赛轮次结果
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=参赛队的比赛轮次
|
||||
ManeuverSailingDomainRetrieverChain=操作
|
||||
|
||||
+19
-28
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
+18
-16
@@ -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<Integer, Object> 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<Integer, Object> 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+6
@@ -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();
|
||||
}
|
||||
+14
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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());
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -276,7 +276,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<IControlRoute,
|
||||
raceDefinitionSetToUpdate, useInternalMarkPassingAlgorithm, raceLogResolver,
|
||||
/* ThreadLocalTransporter not needed because the RaceTracker is not active on a replica */ Optional
|
||||
.empty(),
|
||||
new TrackingConnectorInfoImpl(TrackingConnectorType.TracTrac, tractracRace.getEvent().getWebURL()));
|
||||
new TrackingConnectorInfoImpl(TrackingConnectorType.TracTrac, tractracRace.getEvent().getWebURL(), tractracRace.getId()));
|
||||
if (runAfterCreatingTrackedRace != null) {
|
||||
runAfterCreatingTrackedRace.accept(trackedRace);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -532,7 +532,7 @@ actionAddEvent=Добавить событие
|
||||
publicationUrl=URL-адрес публикации
|
||||
suppress=Подавлять
|
||||
isListedOnHomepage=Отображается на начальной странице
|
||||
raceSelection=выбор расы
|
||||
raceSelection=Выбор гонки
|
||||
unsuppress=Отменить подавление
|
||||
suppressedCompetitors=Подавляемые участники
|
||||
mediaPanel=Аудио и видео
|
||||
|
||||
+1
-1
@@ -532,7 +532,7 @@ actionAddEvent=添加活动
|
||||
publicationUrl=出版 URL
|
||||
suppress=禁止
|
||||
isListedOnHomepage=列在主页中
|
||||
raceSelection=種族選擇
|
||||
raceSelection=竞赛选择
|
||||
unsuppress=取消禁止
|
||||
suppressedCompetitors=禁止的参赛队
|
||||
mediaPanel=音频和视频
|
||||
|
||||
+10
-1
@@ -2,6 +2,7 @@ package com.sap.sailing.server.gateway.deserialization.impl;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -28,8 +29,16 @@ public class TrackingConnectorInfoJsonDeserializer implements JsonDeserializer<T
|
||||
logger.log(Level.WARNING, "Error while parsing webUrl of TrackingConnectorInfo", e);
|
||||
webUrl = null;
|
||||
}
|
||||
final String uuidString = (String) object.get(TrackingConnectorInfoJsonSerializer.FIELD_UUID);
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = uuidString == null ? null : UUID.fromString(uuidString);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Error while parsing uuid of TrackingConnectorInfo", e);
|
||||
uuid = null;
|
||||
}
|
||||
final TrackingConnectorInfo trackingConnectorInfo = new TrackingConnectorInfoImpl(trackingConnectorType,
|
||||
webUrl);
|
||||
webUrl, uuid);
|
||||
return trackingConnectorInfo;
|
||||
}
|
||||
}
|
||||
+6
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.server.gateway.serialization.impl;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
@@ -10,6 +11,7 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
public class TrackingConnectorInfoJsonSerializer implements JsonSerializer<TrackingConnectorInfo> {
|
||||
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<Track
|
||||
if (webUrl != null) {
|
||||
result.put(FIELD_WEB_URL, webUrl.toString());
|
||||
}
|
||||
UUID uuid = trackingConnectorInfo.getUuid();
|
||||
if (uuid != null) {
|
||||
result.put(FIELD_UUID, uuid.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+1
@@ -220,6 +220,7 @@ public class LeaderboardGroupsResource extends AbstractSailingServerResource {
|
||||
jsonRaceColumn.put("regattaName",
|
||||
trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
jsonRaceColumn.put("trackedRaceName", trackedRace.getRace().getName());
|
||||
jsonRaceColumn.put("trackedRaceUuid", trackedRace.getTrackingConnectorInfo().getUuid());
|
||||
final JSONObject raceBoardURLsByEventID = new JSONObject();
|
||||
for (Event event : eventsReferencingLeaderboardGroup) {
|
||||
if (Util.containsAny(event.getVenue().getCourseAreas(), leaderboard.getCourseAreas())) {
|
||||
|
||||
+9
-23
@@ -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<Serializable> suppressedMessageIds = new HashSet<Serializable>();
|
||||
private Set<Serializable> suppressedMessageIds = new HashSet<>();
|
||||
|
||||
private APIConnectivityListener apiConnectivityListener;
|
||||
|
||||
@@ -243,24 +243,12 @@ 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.");
|
||||
}
|
||||
|
||||
@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
|
||||
@@ -270,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);
|
||||
}
|
||||
}
|
||||
@@ -444,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&"
|
||||
@@ -453,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -494,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -521,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;
|
||||
}
|
||||
}
|
||||
+30
-75
@@ -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,10 +143,8 @@ 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");
|
||||
showNotification();
|
||||
|
||||
prefs.setTrackerIsTracking(true);
|
||||
prefs.setTrackerIsTrackingCheckinDigest(checkinDigest);
|
||||
@@ -344,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
|
||||
*/
|
||||
@@ -395,20 +369,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;
|
||||
}
|
||||
@@ -435,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) {
|
||||
@@ -444,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
|
||||
<service
|
||||
android:name=".services.polling.RaceLogPollingService"
|
||||
android:exported="false">
|
||||
android:exported="false"
|
||||
android:stopWithTask="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.sap.sailing.racecommittee.app.action.stopPoller" />
|
||||
<action android:name="com.sap.sailing.racecommittee.app.action.addRace" />
|
||||
@@ -84,7 +85,8 @@
|
||||
</service>
|
||||
<service
|
||||
android:name=".services.RaceStateService"
|
||||
android:exported="false">
|
||||
android:exported="false"
|
||||
android:stopWithTask="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.sap.sailing.racecommittee.app.action.startProcedureSpecificAction" />
|
||||
</intent-filter>
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
+5
-24
@@ -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}.
|
||||
*/
|
||||
@@ -15,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());
|
||||
}
|
||||
@@ -43,30 +41,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(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() {
|
||||
unloadAllRaces();
|
||||
InMemoryDataStore.INSTANCE.clearRaces(context);
|
||||
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);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -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,12 +11,13 @@ 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 {
|
||||
|
||||
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,7 +54,9 @@ public interface DataStore {
|
||||
|
||||
boolean hasRace(SimpleRaceLogIdentifier id);
|
||||
|
||||
void registerRaces(Collection<ManagedRace> races);
|
||||
void registerRaces(Context context, Collection<ManagedRace> races);
|
||||
|
||||
void clearRaces(Context context);
|
||||
|
||||
Collection<Mark> getMarks(RaceGroup raceGroup);
|
||||
|
||||
|
||||
+44
-64
@@ -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,22 +13,24 @@ 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;
|
||||
|
||||
private Context mContext;
|
||||
private LinkedHashMap<Serializable, EventBase> eventsById;
|
||||
private LinkedHashMap<SimpleRaceLogIdentifier, ManagedRace> managedRaceById;
|
||||
private LinkedHashMap<RaceGroup, LinkedHashMap<Serializable, Mark>> marksData;
|
||||
@@ -43,22 +40,10 @@ public enum InMemoryDataStore implements DataStore {
|
||||
private Serializable eventUUID;
|
||||
private UUID courseAreaId;
|
||||
|
||||
private RaceStateService mService;
|
||||
private boolean mBound;
|
||||
|
||||
InMemoryDataStore() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
if (mContext == null) {
|
||||
mContext = context.getApplicationContext();
|
||||
}
|
||||
Intent intent = new Intent(mContext, RaceStateService.class);
|
||||
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
eventsById = new LinkedHashMap<>();
|
||||
@@ -69,11 +54,6 @@ public enum InMemoryDataStore implements DataStore {
|
||||
|
||||
eventUUID = null;
|
||||
courseAreaId = null;
|
||||
|
||||
if (mContext != null && mBound) {
|
||||
mContext.unbindService(mConnection);
|
||||
mBound = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,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<CourseArea> courseAreas = getCourseAreas(event);
|
||||
if (courseAreas != null) {
|
||||
for (CourseArea courseArea : courseAreas) {
|
||||
if (courseArea.getId().equals(id)) {
|
||||
return courseArea;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,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<CourseArea> courseAreas = getCourseAreas(event);
|
||||
if (courseAreas != null) {
|
||||
for (CourseArea courseArea : courseAreas) {
|
||||
if (courseArea.getId().equals(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,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()));
|
||||
}
|
||||
|
||||
@@ -300,7 +286,7 @@ public enum InMemoryDataStore implements DataStore {
|
||||
|
||||
@Override
|
||||
public Set<RaceGroup> getRaceGroups() {
|
||||
Set<RaceGroup> raceGroups = new HashSet<RaceGroup>();
|
||||
Set<RaceGroup> raceGroups = new HashSet<>();
|
||||
for (ManagedRace race : getRaces()) {
|
||||
raceGroups.add(race.getRaceGroup());
|
||||
}
|
||||
@@ -337,34 +323,28 @@ public enum InMemoryDataStore implements DataStore {
|
||||
courseAreaId = uuid;
|
||||
}
|
||||
|
||||
public void registerRaces(Collection<ManagedRace> races) {
|
||||
//TODO Log
|
||||
if (mBound) {
|
||||
for (ManagedRace race : races) {
|
||||
mService.registerRace(race);
|
||||
}
|
||||
@Override
|
||||
public void registerRaces(Context context, Collection<ManagedRace> races) {
|
||||
for (ManagedRace race : races) {
|
||||
final Intent registerIntent = new Intent(context, RaceStateService.class);
|
||||
registerIntent.setAction(AppConstants.INTENT_ACTION_REGISTER_RACE);
|
||||
registerIntent.putExtra(AppConstants.INTENT_EXTRA_RACE_ID, race.getId());
|
||||
context.startService(registerIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterRace(ManagedRace race) {
|
||||
if (mBound) {
|
||||
mService.unregisterRace(race);
|
||||
}
|
||||
@Override
|
||||
public void clearRaces(Context context) {
|
||||
managedRaceById.clear();
|
||||
final Intent intent = new Intent(context, RaceStateService.class);
|
||||
intent.setAction(AppConstants.INTENT_ACTION_CLEAR_RACES);
|
||||
context.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;
|
||||
}
|
||||
};
|
||||
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());
|
||||
context.startService(intent);
|
||||
}
|
||||
}
|
||||
+9
-43
@@ -1,19 +1,16 @@
|
||||
package com.sap.sailing.racecommittee.app.data.handlers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
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 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<Collection<ManagedRace>> {
|
||||
|
||||
private Context context;
|
||||
@@ -37,18 +34,10 @@ public class ManagedRacesDataHandler extends DataHandler<Collection<ManagedRace>
|
||||
@Override
|
||||
public void onResult(Collection<ManagedRace> data, boolean isCached) {
|
||||
if (!isCached) {
|
||||
Set<DeleteFromDataStore> 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(context);
|
||||
manager.addRaces(data);
|
||||
calcRaceState(data);
|
||||
manager.getDataStore().registerRaces(data);
|
||||
manager.getDataStore().registerRaces(context, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,27 +67,4 @@ public class ManagedRacesDataHandler extends DataHandler<Collection<ManagedRace>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
-139
@@ -1,12 +1,16 @@
|
||||
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.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 +25,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,35 +35,16 @@ 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 {
|
||||
|
||||
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 final IBinder mBinder = new RaceStateServiceBinder();
|
||||
|
||||
private AlarmManager alarmManager;
|
||||
|
||||
private int alarmManagerRequestCode = 0;
|
||||
@@ -81,10 +65,6 @@ public class RaceStateService extends Service {
|
||||
this.registeredStateEventSchedulers = new HashMap<>();
|
||||
this.managedIntents = new HashMap<>();
|
||||
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = setupNotification(null);
|
||||
startForeground(NotificationHelper.getNotificationId(), notification);
|
||||
ExLog.i(this, TAG, "Started.");
|
||||
}
|
||||
|
||||
@@ -105,7 +85,7 @@ public class RaceStateService extends Service {
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,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
|
||||
@@ -123,18 +103,50 @@ public class RaceStateService extends Service {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
unregisterAllRaces();
|
||||
if (!managedIntents.isEmpty()) {
|
||||
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, 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);
|
||||
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() {
|
||||
@@ -162,7 +174,7 @@ public class RaceStateService extends Service {
|
||||
ExLog.i(this, TAG, "All races unregistered.");
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -178,7 +190,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();
|
||||
@@ -197,91 +209,9 @@ 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<RemoveRaceAction> 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() {
|
||||
@@ -291,12 +221,12 @@ public class RaceStateService extends Service {
|
||||
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<Pair<PendingIntent, RaceStateEvents>>());
|
||||
managedIntents.put(race.getId(), new ArrayList<>());
|
||||
|
||||
// Register on event additions...
|
||||
JsonSerializer<RaceLogEvent> eventSerializer = RaceLogEventSerializer
|
||||
@@ -338,9 +268,12 @@ 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()));
|
||||
final List<Pair<PendingIntent, RaceStateEvents>> 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 {
|
||||
@@ -352,10 +285,12 @@ public class RaceStateService extends Service {
|
||||
/* package */ void clearAlarmByName(ManagedRace race, RaceStateEvents stateEventName) {
|
||||
List<Pair<PendingIntent, RaceStateEvents>> intents = managedIntents.get(race.getId());
|
||||
Pair<PendingIntent, RaceStateEvents> toBeRemoved = null;
|
||||
for (Pair<PendingIntent, RaceStateEvents> intentPair : intents) {
|
||||
if (intentPair.second.equals(stateEventName)) {
|
||||
toBeRemoved = intentPair;
|
||||
break;
|
||||
if (intents != null) {
|
||||
for (Pair<PendingIntent, RaceStateEvents> intentPair : intents) {
|
||||
if (intentPair.second.equals(stateEventName)) {
|
||||
toBeRemoved = intentPair;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toBeRemoved != null) {
|
||||
|
||||
+42
-55
@@ -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<Util.Pair<String, URL>> queries = getPollingQueries();
|
||||
RaceLogPollingTask task = new RaceLogPollingTask(this, this);
|
||||
@SuppressWarnings("unchecked")
|
||||
Util.Pair<String, URL>[] param = queries.toArray(new Util.Pair[queries.size()]);
|
||||
Util.Pair<String, URL>[] 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);
|
||||
|
||||
+7
-7
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user