mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-25 05:23:51 +00:00
Merge branch 'master' into bug3529
This commit is contained in:
commit
756c6741e8
29 files changed
+690
-641
No files matched your search
+1
-1
@@ -9,7 +9,7 @@
|
||||
<!-- Website header-->
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<div class="{local_res.css.siteheader_logo} {res.mediaCss.small2} {res.mediaCss.medium2} {res.mediaCss.large3} {res.mediaCss.columns}">
|
||||
<a href="http://sapsponsorships.com">
|
||||
<a href="https://www.sap.com/sponsorships">
|
||||
<img src="images/home/logo-small@2x.png" alt="{i18n.headerLogo}" class="{local_res.css.siteheader_logo_image}"></img>
|
||||
<p class="{local_res.css.siteheader_logo_title}">
|
||||
<ui:text from='{i18n.headerLogo}' />
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<header class="{local_res.css.header} {res.mediaCss.small12} {res.mediaCss.columns}">
|
||||
<div class="{local_res.css.header_logo}">
|
||||
<a href="http://sapsponsorships.com" title="SAP sponsorships">
|
||||
<a href="https://www.sap.com/sponsorships" title="SAP sponsorships">
|
||||
<img src="images/mobile/logo-small@2x.png" alt="{i18n.headerLogo}" class="{local_res.css.header_logo_image}"></img>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class LogoAndTitlePanel extends FlowPanel implements RequiresResize {
|
||||
lastIsSmallWidth = windowSizeDetector.isSmallWidth();
|
||||
sapLogo = new Anchor(new SafeHtmlBuilder().appendHtmlConstant(
|
||||
"<img class=\"linkNoBorder\" src=\"/gwt/images/sap_66_transparent.png\"/>").toSafeHtml());
|
||||
sapLogo.setHref("http://www.sap.com");
|
||||
sapLogo.setHref("https://www.sap.com/sponsorships");
|
||||
sapLogo.addStyleName("sapLogo");
|
||||
this.add(sapLogo);
|
||||
renderUI();
|
||||
|
||||
+1
-1
@@ -2770,7 +2770,7 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
|
||||
sapLogo.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
Window.open("http://www.sap.com", "_blank", null);
|
||||
Window.open("https://www.sap.com/sponsorships", "_blank", null);
|
||||
}
|
||||
});
|
||||
sapLogo.setStyleName("raceBoard-Logo");
|
||||
|
||||
+5
@@ -4,6 +4,11 @@
|
||||
<div id="mainContent">
|
||||
<h4 class="articleHeadline">What's New - SAP Sail InSight (Android)</h4>
|
||||
<div class="innerContent">
|
||||
<h5 class="articleSubheadline">November 2016</h5>
|
||||
<ul class="bulletList">
|
||||
<li>Improved tracking status and accuracy reporting</li>
|
||||
</ul>
|
||||
|
||||
<h5 class="articleSubheadline">October 2016</h5>
|
||||
<ul class="bulletList">
|
||||
<li>Improved tracking reliability and accuracy,
|
||||
|
||||
@@ -57,4 +57,7 @@
|
||||
<string name="footer_text">Mehr Informationen auf</string>
|
||||
<string name="footer_text_link">https://www.sapsailing.com</string>
|
||||
|
||||
<string name="yesterday">Gestern</string>
|
||||
<string name="today">Heute</string>
|
||||
<string name="tomorrow">Morgen</string>
|
||||
</resources>
|
||||
@@ -63,4 +63,9 @@
|
||||
|
||||
<color name="normal_button">#f3f3f3</color>
|
||||
<color name="normal_button_pressed">#bfbfbf</color>
|
||||
|
||||
<color name="signal_great">#8ab54e</color>
|
||||
<color name="signal_good">@color/sap_yellow</color>
|
||||
<color name="signal_poor">@color/sap_red</color>
|
||||
<color name="signal_none">#455B27</color>
|
||||
</resources>
|
||||
@@ -53,4 +53,6 @@
|
||||
<dimen name="highlight_text_size">21sp</dimen>
|
||||
<dimen name="list_header_text_size">18sp</dimen>
|
||||
|
||||
<dimen name="default_padding_half">12dp</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -81,4 +81,10 @@
|
||||
<string name="footer_text">More information on</string>
|
||||
<string name="footer_text_link">https://www.sapsailing.com</string>
|
||||
|
||||
<string name="yesterday">Yesterday</string>
|
||||
<string name="today">Today</string>
|
||||
<string name="tomorrow">Tomorrow</string>
|
||||
<string name="time_ago" translatable="false">%1$dh %2$02d\' %3$02d\"</string>
|
||||
<string name="date_short" translatable="false">yyyy-MM-dd</string>
|
||||
|
||||
</resources>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.sap.sailing.android.shared.ui.customviews;
|
||||
|
||||
public enum GPSQuality {
|
||||
noSignal(0), poor(2), good(3), great(4);
|
||||
|
||||
private final int mQuality;
|
||||
|
||||
GPSQuality(int quality) {
|
||||
mQuality = quality;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.mQuality;
|
||||
}
|
||||
|
||||
public static GPSQuality getValue(int value) {
|
||||
GPSQuality result = null;
|
||||
for (GPSQuality item : GPSQuality.values()) {
|
||||
if (item.toInt() == value) {
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+81
-56
@@ -3,7 +3,6 @@ package com.sap.sailing.android.shared.ui.customviews;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.text.TextUtils;
|
||||
@@ -14,17 +13,19 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import com.sap.sailing.android.shared.R;
|
||||
|
||||
/**
|
||||
* Draws one vertical indicator that can is filled green up to a point, depending on the value passed for
|
||||
* signal-quality;
|
||||
* Draws one vertical indicator that is colored depending on the signal quality
|
||||
*
|
||||
* @author Lukas Zielinski
|
||||
* @author Peter Siegmund
|
||||
*/
|
||||
public class SignalQualityIndicatorView extends View {
|
||||
|
||||
private int signalQuality;
|
||||
private GPSQuality mSignalQuality;
|
||||
|
||||
private Paint paint;
|
||||
private Paint paintDark;
|
||||
private Paint paintNone;
|
||||
private Paint paintPoor;
|
||||
private Paint paintGood;
|
||||
private Paint paintGreat;
|
||||
|
||||
private float height;
|
||||
private float width;
|
||||
@@ -35,7 +36,10 @@ public class SignalQualityIndicatorView extends View {
|
||||
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SignalQualityIndicatorView, 0, 0);
|
||||
try {
|
||||
signalQuality = a.getInteger(R.styleable.SignalQualityIndicatorView_signalQuality, 0);
|
||||
mSignalQuality = GPSQuality.getValue(a.getInteger(R.styleable.SignalQualityIndicatorView_signalQuality, 0));
|
||||
if (mSignalQuality == null) {
|
||||
mSignalQuality = GPSQuality.noSignal;
|
||||
}
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
@@ -44,52 +48,69 @@ public class SignalQualityIndicatorView extends View {
|
||||
initPaint();
|
||||
}
|
||||
|
||||
public Integer getSignalQuality() {
|
||||
return signalQuality;
|
||||
public int getSignalQuality() {
|
||||
return mSignalQuality.toInt();
|
||||
}
|
||||
|
||||
private void setAccessibilityString() {
|
||||
if (this.signalQuality == 2) {
|
||||
this.setContentDescription(getContext().getString(R.string.signal_accuracy_indicator_view_description)
|
||||
+ getContext().getString(R.string.poor));
|
||||
} else if (this.signalQuality == 3) {
|
||||
this.setContentDescription(getContext().getString(R.string.signal_accuracy_indicator_view_description)
|
||||
+ getContext().getString(R.string.good));
|
||||
} else if (this.signalQuality == 4) {
|
||||
this.setContentDescription(getContext().getString(R.string.signal_accuracy_indicator_view_description)
|
||||
+ getContext().getString(R.string.great));
|
||||
} else {
|
||||
this.setContentDescription(getContext().getString(R.string.signal_accuracy_indicator_view_description)
|
||||
+ getContext().getString(R.string.no_signal));
|
||||
String desc = getContext().getString(R.string.signal_accuracy_indicator_view_description) + " ";
|
||||
switch (mSignalQuality) {
|
||||
case poor:
|
||||
desc += getContext().getString(R.string.poor);
|
||||
break;
|
||||
|
||||
case good:
|
||||
desc += getContext().getString(R.string.good);
|
||||
break;
|
||||
|
||||
case great:
|
||||
desc += getContext().getString(R.string.great);
|
||||
break;
|
||||
|
||||
default:
|
||||
desc += getContext().getString(R.string.no_signal);
|
||||
|
||||
}
|
||||
setContentDescription(desc);
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(Color.parseColor("#8ab54e"));
|
||||
paintDark = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paintDark.setColor(Color.parseColor("#455B27"));
|
||||
paintNone = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paintNone.setColor(getResources().getColor(R.color.signal_none));
|
||||
paintPoor = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paintPoor.setColor(getResources().getColor(R.color.signal_poor));
|
||||
paintGood = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paintGood.setColor(getResources().getColor(R.color.signal_good));
|
||||
paintGreat = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paintGreat.setColor(getResources().getColor(R.color.signal_great));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
float boxHeight = this.height / 4;
|
||||
|
||||
// first draw gray background
|
||||
Paint paint;
|
||||
switch (mSignalQuality) {
|
||||
case poor:
|
||||
paint = paintPoor;
|
||||
break;
|
||||
|
||||
case good:
|
||||
paint = paintGood;
|
||||
break;
|
||||
|
||||
case great:
|
||||
paint = paintGreat;
|
||||
break;
|
||||
|
||||
default:
|
||||
paint = paintNone;
|
||||
}
|
||||
|
||||
rect.top = 0;
|
||||
rect.left = 0;
|
||||
rect.right = (int) this.width;
|
||||
rect.bottom = (int) this.height;
|
||||
canvas.drawRect(rect, paintDark);
|
||||
|
||||
// then draw green box on top
|
||||
|
||||
rect.top = (int) (this.height - (signalQuality * boxHeight));
|
||||
rect.left = 0;
|
||||
rect.right = (int) this.width;
|
||||
rect.bottom = (int) this.height;
|
||||
canvas.drawRect(rect, paint);
|
||||
}
|
||||
|
||||
@@ -116,24 +137,17 @@ public class SignalQualityIndicatorView extends View {
|
||||
/**
|
||||
* Must be 0,2,3 or 4, otherwise 1 will be set
|
||||
*
|
||||
* @param signalQuality
|
||||
* @param signalQuality the new signal quality
|
||||
*/
|
||||
public void setSignalQuality(Integer signalQuality) {
|
||||
Integer previousSingalQuality = this.signalQuality;
|
||||
public void setSignalQuality(GPSQuality signalQuality) {
|
||||
GPSQuality previousSignalQuality = mSignalQuality;
|
||||
|
||||
if (signalQuality == 0) {
|
||||
this.signalQuality = 0;
|
||||
} else if (signalQuality == 2) {
|
||||
this.signalQuality = 2;
|
||||
} else if (signalQuality == 3) {
|
||||
this.signalQuality = 3;
|
||||
} else if (signalQuality == 4) {
|
||||
this.signalQuality = 4;
|
||||
} else {
|
||||
this.signalQuality = 0;
|
||||
mSignalQuality = signalQuality;
|
||||
if (mSignalQuality == null) {
|
||||
mSignalQuality = GPSQuality.noSignal;
|
||||
}
|
||||
|
||||
if (this.signalQuality != previousSingalQuality) {
|
||||
if (mSignalQuality != previousSignalQuality) {
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
|
||||
}
|
||||
|
||||
@@ -155,13 +169,24 @@ public class SignalQualityIndicatorView extends View {
|
||||
* generate some accessibility info
|
||||
*/
|
||||
public String getAccessibilityText() {
|
||||
if (this.signalQuality == 2)
|
||||
return "poor signal quality";
|
||||
if (this.signalQuality == 3)
|
||||
return "good signal quality";
|
||||
if (this.signalQuality == 4)
|
||||
return "great signal quality";
|
||||
return "no signal";
|
||||
String result;
|
||||
switch (mSignalQuality) {
|
||||
case poor:
|
||||
result = "poor signal quality";
|
||||
break;
|
||||
|
||||
case good:
|
||||
result = "good signal quality";
|
||||
break;
|
||||
|
||||
case great:
|
||||
result = "great signal quality";
|
||||
break;
|
||||
|
||||
default:
|
||||
result = "no signal";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Executable
+230
@@ -0,0 +1,230 @@
|
||||
package com.sap.sailing.android.shared.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.sap.sailing.android.shared.R;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.View;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
protected TimeUtils() {
|
||||
// only static methods
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time to 'kk:mm:ss'.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint) {
|
||||
return formatTime(timePoint, "kk:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time with the help of {@link DateFormat}.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
* @param format format as defined by {@link DateFormat}
|
||||
* @return timestamp formatted as {@link String}
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint, String format) {
|
||||
return DateFormat.format(format, timePoint.asDate()).toString();
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint) {
|
||||
return formatDuration(now, timePoint, true);
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint, boolean inclSign) {
|
||||
String duration;
|
||||
if (timePoint.after(now)) {
|
||||
String sign = (inclSign) ? "-" : "";
|
||||
duration = sign + TimeUtils.formatDurationUntil(timePoint.minus(now.asMillis()).asMillis(), false);
|
||||
} else {
|
||||
duration = TimeUtils.formatDurationSince(now.minus(timePoint.asMillis()).asMillis(), false);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds) {
|
||||
return formatDurationSince(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.floor(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds) {
|
||||
return formatDurationUntil(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.ceil(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats milliseconds to a string like: 01h 23'45"
|
||||
*/
|
||||
public static String formatTimeAgo(Context context, long milliseconds) {
|
||||
Calendar time = Calendar.getInstance();
|
||||
time.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
time.setTimeInMillis(milliseconds);
|
||||
return context.getString(R.string.time_ago, time.get(Calendar.HOUR_OF_DAY), time.get(Calendar.MINUTE), time.get(Calendar.SECOND));
|
||||
}
|
||||
|
||||
public static String calcDuration(Calendar from, Calendar to) {
|
||||
String retValue;
|
||||
|
||||
long millis = to.getTimeInMillis() - from.getTimeInMillis();
|
||||
|
||||
long min = millis / (1000 * 60);
|
||||
long sec = (millis - (min * 60 * 1000)) / 1000;
|
||||
|
||||
retValue = String.valueOf(sec) + "\"";
|
||||
if (retValue.length() == 2) {
|
||||
retValue = "0" + retValue;
|
||||
}
|
||||
if (min > 0) {
|
||||
retValue = String.valueOf(min) + "' " + retValue;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public static Calendar floorTime(Calendar calendar) {
|
||||
if (calendar == null) {
|
||||
calendar = Calendar.getInstance();
|
||||
}
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static int daysBetween(Calendar day1, Calendar day2) {
|
||||
Calendar dayOne = (Calendar) day1.clone();
|
||||
Calendar dayTwo = (Calendar) day2.clone();
|
||||
|
||||
if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) {
|
||||
return dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR);
|
||||
} else {
|
||||
if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) {
|
||||
//swap them
|
||||
Calendar temp = dayOne;
|
||||
dayOne = dayTwo;
|
||||
dayTwo = temp;
|
||||
}
|
||||
int extraDays = 0;
|
||||
|
||||
while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) {
|
||||
dayOne.add(Calendar.YEAR, -1);
|
||||
// getActualMaximum() important for leap years
|
||||
extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOne.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDuration(int secondsTillStart, boolean emptyHours) {
|
||||
int hours = secondsTillStart / 3600;
|
||||
int minutes = (secondsTillStart % 3600) / 60;
|
||||
int seconds = (secondsTillStart % 60);
|
||||
boolean negative = (hours < 0 || minutes < 0 || seconds < 0);
|
||||
String timePattern = ((negative) ? "-" : "") + "%s%s:%s";
|
||||
String secondsString = seconds < 10 ? "0" + Math.abs(seconds) : "" + Math.abs(seconds);
|
||||
String minutesString = minutes < 10 ? "0" + Math.abs(minutes) : "" + Math.abs(minutes);
|
||||
String hoursString = hours < 10 ? "0" + Math.abs(hours) : "" + Math.abs(hours);
|
||||
hoursString = !emptyHours && hoursString.equals("00") ? "" : hoursString + ":";
|
||||
return String.format(timePattern, hoursString, minutesString, secondsString);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays) {
|
||||
initDatePicker(context, datePicker, time, pastDays, futureDays, true);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays, boolean useWords) {
|
||||
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance();
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(time.getTime());
|
||||
// Past
|
||||
calendar.add(Calendar.DAY_OF_MONTH, pastDays);
|
||||
for (int i = pastDays; i < -1; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
if (useWords) {
|
||||
dates.add(context.getString(R.string.yesterday));
|
||||
dates.add(context.getString(R.string.today));
|
||||
dates.add(context.getString(R.string.tomorrow));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 3);
|
||||
} else {
|
||||
for (int i = (pastDays == 0 ? pastDays : -1); i < (futureDays < 2 ? futureDays + 1 : 2); i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
}
|
||||
// Future
|
||||
for (int i = 2; i <= futureDays; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
datePicker.setDisplayedValues(dates.toArray(new String[dates.size()]));
|
||||
datePicker.setMinValue(0);
|
||||
datePicker.setMaxValue(dates.size() - 1);
|
||||
datePicker.setWrapSelectorWheel(false);
|
||||
datePicker.setValue(TimeUtils.daysBetween(calendar, Calendar.getInstance()) + Math.abs(pastDays));
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
TextView date = new TextView(context);
|
||||
date.setText(dateFormat.format(calendar.getTime()));
|
||||
int padding = context.getResources().getDimensionPixelSize(R.dimen.default_padding_half);
|
||||
date.setPadding(padding, padding, padding, padding);
|
||||
date.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
datePicker.getLayoutParams().width = date.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<String> getDates(Context context, TimePoint start, TimePoint end) {
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
SimpleDateFormat simpleFormat = new SimpleDateFormat(context.getString(R.string.date_short), Locale.US);
|
||||
Calendar startDate = Calendar.getInstance();
|
||||
Calendar endDate = (Calendar) startDate.clone();
|
||||
startDate.setTime(start.asDate());
|
||||
endDate.setTime(end.asDate());
|
||||
int dayDiff = daysBetween(endDate, startDate);
|
||||
for (int i = 0; i <= dayDiff; i++) {
|
||||
dates.add(simpleFormat.format(startDate.getTime()));
|
||||
startDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
return dates;
|
||||
}
|
||||
|
||||
public static TimePoint getTime(TimePicker timePicker) {
|
||||
return getTime(timePicker, null);
|
||||
}
|
||||
|
||||
public static TimePoint getTime(TimePicker timePicker, @Nullable NumberPicker secondPicker) {
|
||||
Calendar time = Calendar.getInstance();
|
||||
time.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
|
||||
time.set(Calendar.MINUTE, timePicker.getCurrentMinute());
|
||||
time.set(Calendar.SECOND, secondPicker == null ? 0 : secondPicker.getValue());
|
||||
time.set(Calendar.MILLISECOND, 0);
|
||||
return new MillisecondsTimePoint(time.getTime());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@ public class UniqueDeviceUuid {
|
||||
|
||||
private static String mDeviceId;
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
@SuppressLint("ApplySharedPref")
|
||||
public synchronized static String getUniqueId(Context context) {
|
||||
if (mDeviceId == null) {
|
||||
SharedPreferences preferences = context.getSharedPreferences(FILENAME, Context.MODE_PRIVATE);
|
||||
|
||||
@@ -128,15 +128,6 @@
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".receiver.GcmBroadcastReceiver"
|
||||
android:permission="com.google.android.c2dm.permission.SEND">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
|
||||
|
||||
<category android:name="com.sap.sailing.android.tracking.app"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".receiver.PowerConnectionReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
|
||||
@@ -301,7 +301,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/days"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/white"/>
|
||||
</LinearLayout>
|
||||
@@ -332,7 +331,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/hours"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/white"/>
|
||||
</LinearLayout>
|
||||
@@ -363,7 +361,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/minutes"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/white"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -305,7 +305,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/days"
|
||||
android:textColor="@color/fiori_text_color"
|
||||
android:textSize="@dimen/default_text_size"/>
|
||||
|
||||
@@ -343,7 +342,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/hours"
|
||||
android:textColor="@color/fiori_text_color"
|
||||
android:textSize="@dimen/default_text_size"/>
|
||||
</LinearLayout>
|
||||
@@ -380,7 +378,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/minutes"
|
||||
android:textColor="@color/fiori_text_color"
|
||||
android:textSize="@dimen/default_text_size"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<string name="please_confirm">Bitte bestätigen</string>
|
||||
<string name="do_you_really_want_to_stop_tracking">Soll das Tracking wirklich beendet werden?</string>
|
||||
<string name="tracking_status_tracking">Tracking läuft</string>
|
||||
<string name="tracking_status_no_gps_signal">Kein GPS Signal!</string>
|
||||
<string name="tracking_mode_offline">Offline</string>
|
||||
<string name="tracking_status_no_gps_signal">Keine GPS Änderungen oder Signal!</string>
|
||||
<string name="tracking_mode_no_attempt">Initialisierung</string>
|
||||
<string name="tracking_mode">Modus</string>
|
||||
<string name="tracking_mode_live">Live</string>
|
||||
<string name="tracking_mode_battery_saving">Energie sparen</string>
|
||||
@@ -44,12 +44,18 @@
|
||||
<string name="error_could_not_complete_operation_on_server_try_again">Konnte Operation nicht durchführen. Bitte versuchen Sie es noch einmal.</string>
|
||||
<string name="error_sending_team_image_to_server">Fehler: Konnte Team-Foto nicht an den server senden.</string>
|
||||
<string name="regatta_starts_in">Regatta beginnt in:</string>
|
||||
<string name="hours">Stunden</string>
|
||||
<string name="minute">Minute</string>
|
||||
<string name="minutes">Minuten</string>
|
||||
<string name="days">Tage</string>
|
||||
<string name="hour">Stunde</string>
|
||||
<string name="day">Tag</string>
|
||||
<plurals name="hour">
|
||||
<item quantity="one">Stunde</item>
|
||||
<item quantity="other">Stunden</item>
|
||||
</plurals>
|
||||
<plurals name="minute">
|
||||
<item quantity="one">Minute</item>
|
||||
<item quantity="other">Minuten</item>
|
||||
</plurals>
|
||||
<plurals name="day">
|
||||
<item quantity="one">Tag</item>
|
||||
<item quantity="other">Tage</item>
|
||||
</plurals>
|
||||
<string name="please_listen_to_announcements">Bitte achten Sie auf die Durchsagen</string>
|
||||
<string name="no_qr_code">Sie haben keinen QR-Code?</string>
|
||||
<string name="scan_qr">QR-Code scannen</string>
|
||||
|
||||
@@ -35,12 +35,18 @@
|
||||
<string name="error_could_not_complete_operation_on_server_try_again">Could not complete operation on server. Please try again.</string>
|
||||
<string name="error_sending_team_image_to_server">Error: Could not send team image to server.</string>
|
||||
<string name="regatta_starts_in">Regatta starts in:</string>
|
||||
<string name="hours">Hours</string>
|
||||
<string name="minutes">Minutes</string>
|
||||
<string name="days">Days</string>
|
||||
<string name="hour">Hour</string>
|
||||
<string name="minute">Minute</string>
|
||||
<string name="day">Day</string>
|
||||
<plurals name="hour">
|
||||
<item quantity="one">Hour</item>
|
||||
<item quantity="other">Hours</item>
|
||||
</plurals>
|
||||
<plurals name="minute">
|
||||
<item quantity="one">Minute</item>
|
||||
<item quantity="other">Minutes</item>
|
||||
</plurals>
|
||||
<plurals name="day">
|
||||
<item quantity="one">Day</item>
|
||||
<item quantity="other">Days</item>
|
||||
</plurals>
|
||||
<string name="please_listen_to_announcements">Please listen to announcements</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="thank_you_you_successfully_participated">Thank you! You have successfully taken part in the regatta.\n\nYour SAP Sailing Team</string>
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
<string name="tracking_unsent_fixes">Unsent Messages</string>
|
||||
<string name="tracking_mode_caching">Offline</string>
|
||||
<string name="tracking_mode_api_error">API-Error</string>
|
||||
<string name="tracking_mode_offline">Offline</string>
|
||||
<string name="tracking_mode_no_attempt">Initialise</string>
|
||||
<string name="tracking_time">Tracking Time</string>
|
||||
<string name="tracking_status" translatable="false">Status</string>
|
||||
<string name="tracking_status_tracking">Tracking</string>
|
||||
<string name="tracking_status_no_gps_signal">No GPS Signal!</string>
|
||||
<string name="tracking_status_no_gps_signal">No GPS Changes or Signal!</string>
|
||||
<string name="desc_regatta_user_image">Regatta User Image</string>
|
||||
<string name="desc_add_photo_button">Add Photo Button</string>
|
||||
<string name="tracking_status_gps_found">GPS signal found!</string>
|
||||
|
||||
+109
-72
@@ -1,5 +1,7 @@
|
||||
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;
|
||||
@@ -10,10 +12,33 @@ import java.util.UUID;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
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.support.v4.app.NotificationCompat;
|
||||
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.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
@@ -25,26 +50,19 @@ import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.FlatSmartphoneUuidAndGPSFixMovingJsonSerializer;
|
||||
import com.sap.sse.common.Duration;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.hardware.GeomagneticField;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.widget.Toast;
|
||||
public class TrackingService extends Service implements LocationListener {
|
||||
|
||||
public class TrackingService extends Service implements android.location.LocationListener {
|
||||
private static final String TAG = TrackingService.class.getName();
|
||||
private static final String THREAD_NAME = "Location WatchDog";
|
||||
|
||||
private static final int NO_LOCATION = 0;
|
||||
private static final long NO_LOCATION_CHECK = Duration.ONE_SECOND.times(5).asMillis();
|
||||
|
||||
private static final int POOR_DISTANCE = 48;
|
||||
private static final int GREAT_DISTANCE = 10;
|
||||
private static final int NO_DISTANCE = 0;
|
||||
|
||||
private NotificationManager notificationManager;
|
||||
private AppPreferences prefs;
|
||||
@@ -52,8 +70,6 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
private GPSQualityListener gpsQualityListener;
|
||||
private final IBinder trackingBinder = new TrackingBinder();
|
||||
|
||||
private static final String TAG = TrackingService.class.getName();
|
||||
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION_ID = R.string.tracker_started;
|
||||
@@ -61,12 +77,12 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
public final static int UPDATE_INTERVAL_IN_MILLIS_DEFAULT = 1000;
|
||||
public final static String GPS_DISABLED_MESSAGE = "gpsDisabled";
|
||||
private float minLocationUpdateDistanceInMeters = 0f;
|
||||
private boolean initialLocation;
|
||||
|
||||
private String checkinDigest;
|
||||
private EventInfo event;
|
||||
|
||||
protected LocationManager locationManager;
|
||||
private LocationManager locationManager;
|
||||
private LocationWatchDog locationWatchDog;
|
||||
|
||||
/**
|
||||
* Must be synchronized upon while modifying the {@link #timerForDelayingSendingMessages} field
|
||||
@@ -79,7 +95,7 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
* {@link #locationsQueuedBasedOnSendingInterval} after the send interval, and the next message sending intent
|
||||
* arriving can be forwarded to the sending service immediately, with the timer being started immediately afterwards
|
||||
* to delay the sending of messages arriving later until the resend interval has expired. If not {@code null},
|
||||
* messages that arrive in {@link #enqueueForSending(String, JSONObject)} will be appended to
|
||||
* messages that arrive in {@link #enqueueForSending(String, Location)} will be appended to
|
||||
* {@link #locationsQueuedBasedOnSendingInterval}.
|
||||
* <p>
|
||||
*
|
||||
@@ -111,12 +127,8 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
locationsQueuedBasedOnSendingInterval = new LinkedHashMap<>();
|
||||
prefs = new AppPreferences(this);
|
||||
|
||||
initialLocation = true;
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +171,18 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
|
||||
prefs.setTrackerIsTracking(true);
|
||||
prefs.setTrackerIsTrackingCheckinDigest(checkinDigest);
|
||||
|
||||
if (locationWatchDog == null) {
|
||||
// create new Location WatchDog
|
||||
HandlerThread thread = new HandlerThread(THREAD_NAME, THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
locationWatchDog = new LocationWatchDog(thread.getLooper());
|
||||
|
||||
// start WatchDog
|
||||
Message msg = locationWatchDog.obtainMessage(NO_LOCATION);
|
||||
msg.obj = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||
locationWatchDog.sendMessageDelayed(msg, NO_LOCATION_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopTracking() {
|
||||
@@ -167,6 +191,12 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
prefs.setTrackerIsTracking(false);
|
||||
prefs.setTrackerIsTrackingCheckinDigest(null);
|
||||
|
||||
if (locationWatchDog != null) {
|
||||
// stop the Location WatchDog
|
||||
locationWatchDog.getLooper().quit();
|
||||
locationWatchDog = null;
|
||||
}
|
||||
|
||||
stopSelf();
|
||||
ExLog.i(this, TAG, "Stopped Tracking");
|
||||
}
|
||||
@@ -190,13 +220,15 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
bearingImpl.add(new DegreeBearingImpl(- geomagneticField.getDeclination()));
|
||||
}
|
||||
|
||||
GPSQuality quality = GPSQuality.noSignal;
|
||||
if (gpsQualityListener != null) {
|
||||
if (gpsAccuracy > 48) {
|
||||
GPSQuality quality = GPSQuality.noSignal;
|
||||
if (gpsAccuracy <= NO_DISTANCE) {
|
||||
quality = GPSQuality.noSignal;
|
||||
} else if (gpsAccuracy > POOR_DISTANCE) {
|
||||
quality = GPSQuality.poor;
|
||||
} else if (gpsAccuracy > 10) {
|
||||
} else if (gpsAccuracy > GREAT_DISTANCE) {
|
||||
quality = GPSQuality.good;
|
||||
} else if (gpsAccuracy <= 10) {
|
||||
} else if (gpsAccuracy <= GREAT_DISTANCE) {
|
||||
quality = GPSQuality.great;
|
||||
}
|
||||
|
||||
@@ -204,7 +236,6 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
private JSONObject createJsonLocationFix(Location location) throws JSONException {
|
||||
JSONObject fixJson = new JSONObject();
|
||||
fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.BEARING_DEG, location.getBearing());
|
||||
@@ -214,7 +245,7 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
fixJson.put(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.LAT_DEG, location.getLatitude());
|
||||
return fixJson;
|
||||
}
|
||||
|
||||
|
||||
private JSONArray createJsonLocationFixes(Iterable<Location> locations) throws JSONException {
|
||||
final JSONArray fixesAsJson = new JSONArray();
|
||||
for (final Location location : locations) {
|
||||
@@ -302,16 +333,7 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void storeInitialTrackingTimestamp() {
|
||||
if (prefs.getTrackingTimerStarted() == 0) {
|
||||
prefs.setTrackingTimerStarted(System.currentTimeMillis());
|
||||
}
|
||||
initialLocation = false;
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return trackingBinder;
|
||||
@@ -329,13 +351,18 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
if (initialLocation) {
|
||||
storeInitialTrackingTimestamp();
|
||||
}
|
||||
reportGPSQualityBearingAndSpeed(location.getAccuracy(), location.getBearing(), location.getSpeed(),
|
||||
location.getLatitude(), location.getLongitude(), location.getAltitude());
|
||||
final String postUrlStr = event.server + prefs.getServerGpsFixesPostPath();
|
||||
enqueueForSending(postUrlStr, location);
|
||||
|
||||
// clear message queue
|
||||
locationWatchDog.removeMessages(NO_LOCATION);
|
||||
|
||||
// add new message with last location
|
||||
Message msg = locationWatchDog.obtainMessage(NO_LOCATION);
|
||||
msg.obj = location;
|
||||
locationWatchDog.sendMessageDelayed(msg, NO_LOCATION_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,16 +384,17 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
}
|
||||
|
||||
private void showNotification() {
|
||||
Intent intent = new Intent(this, TrackingActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
Notification notification = new NotificationCompat.Builder(this)
|
||||
.setContentTitle(getText(R.string.app_name))
|
||||
.setContentText(getString(R.string.tracking_notification_text, event.name)).setContentIntent(pi)
|
||||
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
|
||||
.setSmallIcon(R.drawable.ic_directions_boat)
|
||||
.setOngoing(true).build();
|
||||
Intent intent = new Intent(this, TrackingActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
Notification notification = new NotificationCompat.Builder(this)
|
||||
.setContentTitle(getText(R.string.app_name))
|
||||
.setContentText(getString(R.string.tracking_notification_text, event.name))
|
||||
.setContentIntent(pi)
|
||||
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
|
||||
.setSmallIcon(R.drawable.ic_directions_boat)
|
||||
.setOngoing(true)
|
||||
.build();
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
}
|
||||
|
||||
@@ -384,23 +412,32 @@ public class TrackingService extends Service implements android.location.Locati
|
||||
}
|
||||
}
|
||||
|
||||
public enum GPSQuality {
|
||||
noSignal(0), poor(2), good(3), great(4);
|
||||
|
||||
private final int gpsQuality;
|
||||
|
||||
GPSQuality(int quality) {
|
||||
this.gpsQuality = quality;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.gpsQuality;
|
||||
}
|
||||
}
|
||||
|
||||
public interface GPSQualityListener {
|
||||
void gpsQualityAndAccuracyUpdated(GPSQuality quality, float gpsAccurracy, Bearing gpsBearing,
|
||||
Speed gpsSpeed);
|
||||
void gpsQualityAndAccuracyUpdated(GPSQuality quality, float accuracy, Bearing bearing, Speed speed);
|
||||
}
|
||||
|
||||
private class LocationWatchDog extends Handler {
|
||||
|
||||
LocationWatchDog(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case NO_LOCATION:
|
||||
ExLog.i(getApplicationContext(), TAG, "No Location");
|
||||
Location location = (Location) msg.obj;
|
||||
if (location == null) {
|
||||
location = new Location(LocationManager.GPS_PROVIDER);
|
||||
}
|
||||
reportGPSQualityBearingAndSpeed(NO_DISTANCE, location.getBearing(), location.getSpeed(),
|
||||
location.getLatitude(), location.getLongitude(), location.getAltitude());
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-96
@@ -17,7 +17,6 @@ import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.shared.data.LeaderboardInfo;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
@@ -25,10 +24,10 @@ import com.sap.sailing.android.shared.services.sending.MessageSendingService;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.APIConnectivity;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.APIConnectivityListener;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.MessageSendingBinder;
|
||||
import com.sap.sailing.android.shared.ui.customviews.GPSQuality;
|
||||
import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService.GPSQuality;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService.GPSQualityListener;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService.TrackingBinder;
|
||||
import com.sap.sailing.android.tracking.app.ui.fragments.CompassFragment;
|
||||
@@ -45,18 +44,17 @@ import com.viewpagerindicator.CirclePageIndicator;
|
||||
|
||||
public class TrackingActivity extends BaseActivity implements GPSQualityListener, APIConnectivityListener {
|
||||
|
||||
TrackingService trackingService;
|
||||
private TrackingService trackingService;
|
||||
private boolean trackingServiceBound;
|
||||
private boolean gpsReceived;
|
||||
|
||||
MessageSendingService messageSendingService;
|
||||
private MessageSendingService messageSendingService;
|
||||
boolean messageSendingServiceBound;
|
||||
|
||||
private final static String TAG = TrackingActivity.class.getName();
|
||||
private final static String SIS_TRACKING_FRAGMENT = "savedInstanceTrackingFragment";
|
||||
private final static String SIS_LAST_VIEWPAGER_ITEM = "instanceStateLastViewPagerItem";
|
||||
private final static String SIS_LAST_SPEED_TEXT = "instanceStateLastSpeedText";
|
||||
private final static String SIS_LAST_COMPASS_TEXT = "instanceStateLastCompassText";
|
||||
private final static String SIS_TRACKING_FRAGMENT = "trackingFragment";
|
||||
private final static String SIS_LAST_VIEWPAGER_ITEM = "lastViewPagerItem";
|
||||
private final static String SIS_LAST_SPEED_TEXT = "lastSpeedText";
|
||||
private final static String SIS_LAST_COMPASS_TEXT = "lastCompassText";
|
||||
|
||||
private ViewPager mPager;
|
||||
private ScreenSlidePagerAdapter mPagerAdapter;
|
||||
@@ -65,7 +63,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
private String checkinDigest;
|
||||
|
||||
private TrackingFragment trackingFragment;
|
||||
private TimerRunnable timer;
|
||||
|
||||
private int lastViewPagerItem;
|
||||
|
||||
@@ -217,7 +214,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
timer.stop();
|
||||
|
||||
mPager = (ViewPager) findViewById(R.id.pager);
|
||||
mPager.setAdapter(null);
|
||||
@@ -227,39 +223,38 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
timer = new TimerRunnable();
|
||||
Thread thread = new Thread(timer);
|
||||
thread.start();
|
||||
|
||||
if (mPagerAdapter == null) {
|
||||
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
|
||||
}
|
||||
|
||||
mPager.setAdapter(mPagerAdapter);
|
||||
mPager.setCurrentItem(lastViewPagerItem);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gpsQualityAndAccuracyUpdated(GPSQuality quality, float gpsAccurracy, Bearing bearing, Speed speed) {
|
||||
if (trackingFragment.isAdded()) {
|
||||
trackingFragment.setGPSQualityAndAcurracy(quality, gpsAccurracy);
|
||||
}
|
||||
public void gpsQualityAndAccuracyUpdated(final GPSQuality quality, final float accuracy, final Bearing bearing, final Speed speed) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (trackingFragment.isAdded()) {
|
||||
trackingFragment.setGPSQualityAndAccuracy(quality, accuracy);
|
||||
}
|
||||
|
||||
ScreenSlidePagerAdapter viewPagerAdapter = getViewPagerAdapter();
|
||||
ScreenSlidePagerAdapter viewPagerAdapter = getViewPagerAdapter();
|
||||
|
||||
if (viewPagerAdapter != null) {
|
||||
SpeedFragment speedFragment = viewPagerAdapter.getSpeedFragment();
|
||||
if (speedFragment != null && speedFragment.isAdded()) {
|
||||
speedFragment.setSpeed(speed);
|
||||
if (viewPagerAdapter != null) {
|
||||
SpeedFragment speedFragment = viewPagerAdapter.getSpeedFragment();
|
||||
if (speedFragment != null && speedFragment.isAdded()) {
|
||||
speedFragment.setSpeed(speed);
|
||||
}
|
||||
|
||||
CompassFragment compassFragment = viewPagerAdapter.getCompassFragment();
|
||||
if (compassFragment != null && compassFragment.isAdded()) {
|
||||
compassFragment.setBearing(bearing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompassFragment compassFragment = viewPagerAdapter.getCompassFragment();
|
||||
if (compassFragment != null && compassFragment.isAdded()) {
|
||||
compassFragment.setBearing(bearing);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -401,68 +396,4 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
ServiceHelper.getInstance().stopTrackingService(this);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI with a string containing the time since tracking started, e.g. 01:22:45
|
||||
*/
|
||||
public void updateTimer() {
|
||||
long trackingTimerStarted = prefs.getTrackingTimerStarted();
|
||||
if (trackingTimerStarted > 0) {
|
||||
hideWaitForGPSText();
|
||||
long diff = System.currentTimeMillis() - trackingTimerStarted;
|
||||
TextView textView = (TextView) findViewById(R.id.tracking_time_label);
|
||||
if (textView != null) {
|
||||
textView.setText(getTimeFormatString(diff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideWaitForGPSText() {
|
||||
if (!gpsReceived) {
|
||||
View waitForGPSLabel = findViewById(R.id.wait_for_gps);
|
||||
if (waitForGPSLabel != null) {
|
||||
waitForGPSLabel.setVisibility(View.GONE);
|
||||
gpsReceived = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getTimeFormatString(long milliseconds) {
|
||||
int seconds = (int) (milliseconds / 1000) % 60;
|
||||
int minutes = (int) ((milliseconds / (1000 * 60)) % 60);
|
||||
int hours = (int) ((milliseconds / (1000 * 60 * 60)) % 24);
|
||||
|
||||
return String.format(getResources().getConfiguration().locale, "%02d:%02d:%02d", hours, minutes, seconds);
|
||||
}
|
||||
|
||||
private class TimerRunnable implements Runnable {
|
||||
|
||||
private boolean running;
|
||||
|
||||
TimerRunnable() {
|
||||
running = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (running) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackingFragment.checkLastGPSReceived();
|
||||
updateTimer();
|
||||
}
|
||||
});
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
ExLog.e(TrackingActivity.this, TAG, "Interrupted sleep");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-18
@@ -37,6 +37,7 @@ import com.sap.sailing.android.tracking.app.ui.activities.RegattaActivity;
|
||||
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.valueobjects.EventInfo;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
@@ -56,6 +57,7 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View view = inflater.inflate(R.layout.fragment_regatta, container, false);
|
||||
|
||||
Button startTrackingButton = (Button) view.findViewById(R.id.start_tracking);
|
||||
@@ -333,6 +335,7 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
}
|
||||
|
||||
private void startTrackingActivity() {
|
||||
prefs.setTrackingTimerStarted(MillisecondsTimePoint.now().asMillis());
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
Intent intent = new Intent(getActivity(), TrackingActivity.class);
|
||||
String checkinDigest = regattaActivity.event.checkinDigest;
|
||||
@@ -370,27 +373,13 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
TextView hoursTextViewLabel = (TextView) getActivity().findViewById(R.id.starts_in_hours_label);
|
||||
TextView minutesTextViewLabel = (TextView) getActivity().findViewById(R.id.starts_in_minutes_label);
|
||||
|
||||
daysTextViewLabel.setText(getResources().getQuantityText(R.plurals.day, days));
|
||||
hoursTextViewLabel.setText(getResources().getQuantityText(R.plurals.hour, hours));
|
||||
minutesTextViewLabel.setText(getResources().getQuantityText(R.plurals.minute, minutes));
|
||||
|
||||
daysTextView.setText(String.format("%02d", days));
|
||||
hoursTextView.setText(String.format("%02d", hours));
|
||||
minutesTextView.setText(String.format("%02d", minutes));
|
||||
|
||||
if (days == 1) {
|
||||
daysTextViewLabel.setText(R.string.day);
|
||||
} else {
|
||||
daysTextViewLabel.setText(R.string.days);
|
||||
}
|
||||
|
||||
if (hours == 1) {
|
||||
hoursTextViewLabel.setText(R.string.hour);
|
||||
} else {
|
||||
hoursTextViewLabel.setText(R.string.hours);
|
||||
}
|
||||
|
||||
if (minutes == 1) {
|
||||
minutesTextViewLabel.setText(R.string.minute);
|
||||
} else {
|
||||
minutesTextViewLabel.setText(R.string.minutes);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFragmentWatcher(FragmentWatcher fWatcher) {
|
||||
|
||||
+66
-105
@@ -1,11 +1,11 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
@@ -14,40 +14,51 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.APIConnectivity;
|
||||
import com.sap.sailing.android.shared.ui.customviews.GPSQuality;
|
||||
import com.sap.sailing.android.shared.ui.customviews.SignalQualityIndicatorView;
|
||||
import com.sap.sailing.android.shared.util.LocationHelper;
|
||||
import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService.GPSQuality;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
|
||||
public class TrackingFragment extends BaseFragment {
|
||||
|
||||
static final String SIS_MODE = "instanceStateMode";
|
||||
static final String SIS_STATUS = "instanceStateStatus";
|
||||
static final String SIS_GPS_QUALITY = "instanceStateGpsQuality";
|
||||
static final String SIS_GPS_ACCURACY = "instanceStateGpsAccuracy";
|
||||
static final String SIS_GPS_UNSENT_FIXES = "instanceStateGpsUnsentFixes";
|
||||
static final String SIS_MODE = "mode";
|
||||
static final String SIS_STATUS = "status";
|
||||
static final String SIS_GPS_ACCURACY = "gpsAccuracy";
|
||||
static final String SIS_GPS_UNSENT_FIXES = "gpsUnsentFixes";
|
||||
|
||||
private long lastGPSQualityUpdate;
|
||||
private BroadcastReceiver gpsDisabledReceiver;
|
||||
private Toast gpsToast;
|
||||
private boolean gpsFound = true;
|
||||
|
||||
private String TAG = TrackingFragment.class.getName();
|
||||
private TextView modeText;
|
||||
private TextView statusText;
|
||||
private TextView accuracyText;
|
||||
private TextView unsentFixesText;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_tracking, container, false);
|
||||
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.fragment_tracking, container, false);
|
||||
prefs = new AppPreferences(getActivity());
|
||||
return view;
|
||||
|
||||
modeText = (TextView) layout.findViewById(R.id.mode);
|
||||
statusText = (TextView) layout.findViewById(R.id.tracking_status);
|
||||
accuracyText = (TextView) layout.findViewById(R.id.gps_accuracy_label);
|
||||
unsentFixesText = (TextView) layout.findViewById(R.id.tracking_unsent_fixes);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
modeText.setText(savedInstanceState.getString(SIS_MODE));
|
||||
statusText.setText(savedInstanceState.getString(SIS_STATUS));
|
||||
accuracyText.setText(savedInstanceState.getString(SIS_GPS_ACCURACY));
|
||||
unsentFixesText.setText(savedInstanceState.getString(SIS_GPS_UNSENT_FIXES));
|
||||
} else {
|
||||
//initially set quality to "No GPS" on start tracking
|
||||
updateTrackingStatus(GPSQuality.noSignal);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,62 +86,20 @@ public class TrackingFragment extends BaseFragment {
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
getActivity().unregisterReceiver(gpsDisabledReceiver);
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
TextView modeText = (TextView) getActivity().findViewById(R.id.mode);
|
||||
TextView statusText = (TextView) getActivity().findViewById(R.id.tracking_status);
|
||||
SignalQualityIndicatorView qualityIndicator = (SignalQualityIndicatorView) getActivity().findViewById(
|
||||
R.id.gps_quality_indicator);
|
||||
TextView accuracyText = (TextView) getActivity().findViewById(R.id.gps_accuracy_label);
|
||||
TextView unsentFixesText = (TextView) getActivity().findViewById(R.id.tracking_unsent_fixes);
|
||||
|
||||
modeText.setText(savedInstanceState.getString(SIS_MODE));
|
||||
statusText.setText(savedInstanceState.getString(SIS_STATUS));
|
||||
qualityIndicator.setSignalQuality(savedInstanceState.getInt(SIS_GPS_QUALITY));
|
||||
accuracyText.setText(savedInstanceState.getString(SIS_GPS_ACCURACY));
|
||||
unsentFixesText.setText(savedInstanceState.getString(SIS_GPS_UNSENT_FIXES));
|
||||
} else {
|
||||
//initially set quality to "No GPS" on start tracking
|
||||
updateTrackingStatus(GPSQuality.noSignal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
TextView modeText = (TextView) getActivity().findViewById(R.id.mode);
|
||||
TextView statusText = (TextView) getActivity().findViewById(R.id.tracking_status);
|
||||
SignalQualityIndicatorView qualityIndicator = (SignalQualityIndicatorView) getActivity().findViewById(
|
||||
R.id.gps_quality_indicator);
|
||||
TextView accuracyText = (TextView) getActivity().findViewById(R.id.gps_accuracy_label);
|
||||
TextView unsentFixesText = (TextView) getActivity().findViewById(R.id.tracking_unsent_fixes);
|
||||
|
||||
outState.putString(SIS_MODE, modeText.getText().toString());
|
||||
outState.putString(SIS_STATUS, statusText.getText().toString());
|
||||
outState.putInt(SIS_GPS_QUALITY, qualityIndicator.getSignalQuality());
|
||||
outState.putString(SIS_GPS_ACCURACY, accuracyText.getText().toString());
|
||||
outState.putString(SIS_GPS_UNSENT_FIXES, unsentFixesText.getText().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* If last GPS update is too long ago, let's assume there's no signal and set quality to .noSignal
|
||||
*/
|
||||
public void checkLastGPSReceived() {
|
||||
if (System.currentTimeMillis() - lastGPSQualityUpdate > 3000 && !isLocationEnabled(getActivity())) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(getActivity(), TAG,
|
||||
"Setting GPS Quality to 0 because timeout occurred and location is reported as disabled.");
|
||||
}
|
||||
setGPSQualityAndAcurracy(GPSQuality.noSignal, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tracking status string in UI
|
||||
*
|
||||
@@ -138,55 +107,44 @@ public class TrackingFragment extends BaseFragment {
|
||||
*/
|
||||
public void updateTrackingStatus(GPSQuality quality) {
|
||||
if (isAdded()) {
|
||||
TextView textView = (TextView) getActivity().findViewById(R.id.tracking_status);
|
||||
if (quality == GPSQuality.noSignal) {
|
||||
textView.setText(getString(R.string.tracking_status_no_gps_signal));
|
||||
textView.setTextColor(getResources().getColor(R.color.sap_red));
|
||||
//either GPS has been found before or tracking just started (but is not available now) --> show noGPS Toast
|
||||
if (gpsFound || gpsToast == null) {
|
||||
gpsToast = Toast.makeText(getActivity(),getString(R.string.tracking_status_no_gps_signal), Toast.LENGTH_LONG);
|
||||
gpsToast.show();
|
||||
gpsFound = false;
|
||||
}
|
||||
statusText.setText(getString(R.string.tracking_status_no_gps_signal));
|
||||
statusText.setTextColor(getResources().getColor(R.color.sap_red));
|
||||
} else {
|
||||
textView.setText(getString(R.string.tracking_status_tracking));
|
||||
textView.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
if (gpsToast == null) {
|
||||
gpsToast.cancel();
|
||||
}
|
||||
//GPS was lost before but is available again now --> show gpsFound toast
|
||||
if (!gpsFound) {
|
||||
gpsToast = Toast.makeText(getActivity(),getString(R.string.tracking_status_gps_found), Toast.LENGTH_SHORT);
|
||||
gpsToast.show();
|
||||
gpsFound = true;
|
||||
}
|
||||
statusText.setText(getString(R.string.tracking_status_tracking));
|
||||
statusText.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI and tell user if app is caching or sending fixes to api
|
||||
*
|
||||
* @param apiConnectivity
|
||||
*/
|
||||
public void setAPIConnectivityStatus(final APIConnectivity apiConnectivity) {
|
||||
if (isAdded()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TextView textView = (TextView) getActivity().findViewById(R.id.mode);
|
||||
if (apiConnectivity == APIConnectivity.transmissionSuccess) {
|
||||
textView.setText(getString(R.string.tracking_mode_live));
|
||||
textView.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
} else if (apiConnectivity == APIConnectivity.noAttempt) {
|
||||
textView.setText(getString(R.string.tracking_mode_offline));
|
||||
textView.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
} else if (apiConnectivity == APIConnectivity.transmissionError) {
|
||||
textView.setText(getString(R.string.tracking_mode_api_error));
|
||||
textView.setTextColor(getResources().getColor(R.color.sap_red));
|
||||
} else {
|
||||
textView.setText(getString(R.string.tracking_mode_caching));
|
||||
textView.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
switch (apiConnectivity) {
|
||||
case transmissionSuccess:
|
||||
modeText.setText(getString(R.string.tracking_mode_live));
|
||||
modeText.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
break;
|
||||
|
||||
case noAttempt:
|
||||
modeText.setText(getString(R.string.tracking_mode_no_attempt));
|
||||
modeText.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
break;
|
||||
|
||||
case transmissionError:
|
||||
modeText.setText(getString(R.string.tracking_mode_api_error));
|
||||
modeText.setTextColor(getResources().getColor(R.color.sap_red));
|
||||
break;
|
||||
|
||||
default:
|
||||
modeText.setText(getString(R.string.tracking_mode_caching));
|
||||
modeText.setTextColor(getResources().getColor(R.color.fiori_text_color));
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -209,7 +167,6 @@ public class TrackingFragment extends BaseFragment {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
|
||||
|
||||
} catch (SettingNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -219,7 +176,7 @@ public class TrackingFragment extends BaseFragment {
|
||||
} else {
|
||||
locationProviders = Settings.Secure.getString(context.getContentResolver(),
|
||||
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
|
||||
return locationProviders.contains("gps");
|
||||
return locationProviders.contains(LocationManager.GPS_PROVIDER);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
@@ -231,15 +188,19 @@ public class TrackingFragment extends BaseFragment {
|
||||
activity.showStopTrackingConfirmationDialog();
|
||||
}
|
||||
|
||||
public void setGPSQualityAndAcurracy(GPSQuality quality, float gpsAccurracy) {
|
||||
public void setGPSQualityAndAccuracy(GPSQuality quality, float accuracy) {
|
||||
if (isAdded()) {
|
||||
Activity activity = getActivity();
|
||||
SignalQualityIndicatorView indicatorView = (SignalQualityIndicatorView) activity.findViewById(R.id.gps_quality_indicator);
|
||||
indicatorView.setSignalQuality(quality.toInt());
|
||||
TextView accuracyTextView = (TextView) getActivity().findViewById(R.id.gps_accuracy_label);
|
||||
accuracyTextView.setText("~ " + String.valueOf(Math.round(gpsAccurracy)) + " m");
|
||||
updateTrackingStatus(quality);
|
||||
lastGPSQualityUpdate = System.currentTimeMillis();
|
||||
View layout = getView();
|
||||
if (layout != null) {
|
||||
SignalQualityIndicatorView indicatorView = (SignalQualityIndicatorView) layout.findViewById(R.id.gps_quality_indicator);
|
||||
indicatorView.setSignalQuality(quality);
|
||||
updateTrackingStatus(quality);
|
||||
if (quality != GPSQuality.noSignal) {
|
||||
accuracyText.setText("~ " + Math.round(accuracy) + " m");
|
||||
} else {
|
||||
accuracyText.setText(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+84
-15
@@ -1,51 +1,120 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.shared.util.LocationHelper;
|
||||
import com.sap.sailing.android.shared.util.TimeUtils;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class TrackingTimeFragment extends BaseFragment {
|
||||
|
||||
private final static String SIS_TRACKING_TIMER = "savedInstanceTrackingTimer";
|
||||
private static final String SIS_TRACKING_TIMER = "trackingTimer";
|
||||
private static final String THREAD_NAME = "Tracking Timer";
|
||||
|
||||
private static final int TIMER_SET = 0;
|
||||
private static final long TIMER_DELAY = Duration.ONE_SECOND.asMillis();
|
||||
|
||||
private TextView timerView;
|
||||
private TextView noGPSView;
|
||||
|
||||
private Handler handler;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_time, container, false);
|
||||
timerView = (TextView) view.findViewById(R.id.tracking_time_label);
|
||||
noGPSView = (TextView) view.findViewById(R.id.wait_for_gps);
|
||||
return view;
|
||||
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.fragment_time, container, false);
|
||||
timerView = (TextView) layout.findViewById(R.id.tracking_time_label);
|
||||
noGPSView = (TextView) layout.findViewById(R.id.wait_for_gps);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
timerView.setText(savedInstanceState.getString(SIS_TRACKING_TIMER));
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (LocationHelper.isGPSEnabled(getActivity())) {
|
||||
noGPSView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (timerView != null) {
|
||||
outState.putString(SIS_TRACKING_TIMER, timerView.getText().toString());
|
||||
}
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
HandlerThread thread = new HandlerThread(THREAD_NAME, THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
handler = new TimerHandler(thread.getLooper(), getActivity(), timerView);
|
||||
handler.sendEmptyMessageDelayed(TIMER_SET, TIMER_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (savedInstanceState != null && timerView != null) {
|
||||
timerView.setText(savedInstanceState.getString(SIS_TRACKING_TIMER));
|
||||
handler.getLooper().quit();
|
||||
handler.removeMessages(TIMER_SET);
|
||||
handler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putString(SIS_TRACKING_TIMER, timerView.getText().toString());
|
||||
}
|
||||
|
||||
private static class TimerHandler extends Handler {
|
||||
|
||||
private AppPreferences prefs;
|
||||
private TextView timer;
|
||||
|
||||
TimerHandler(Looper looper, Context context, TextView timer) {
|
||||
super(looper);
|
||||
this.prefs = new AppPreferences(context);
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case TIMER_SET:
|
||||
final long trackingTimerStarted = prefs.getTrackingTimerStarted();
|
||||
if (trackingTimerStarted > 0) {
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
if (timer != null) {
|
||||
timer.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
timer.setText(TimeUtils.formatDurationSince(now.minus(trackingTimerStarted).asMillis()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
sendEmptyMessageDelayed(TIMER_SET, TIMER_DELAY);
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-18
@@ -33,6 +33,7 @@ import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkInfo;
|
||||
import com.sap.sailing.android.buoy.positioning.app.valueobjects.MarkPingInfo;
|
||||
import com.sap.sailing.android.shared.data.LeaderboardInfo;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.ui.customviews.GPSQuality;
|
||||
import com.sap.sailing.android.shared.ui.customviews.SignalQualityIndicatorView;
|
||||
import com.sap.sailing.android.shared.util.LocationHelper;
|
||||
import com.sap.sailing.android.shared.util.ViewHelper;
|
||||
@@ -74,7 +75,7 @@ public class BuoyFragment extends BaseFragment
|
||||
setUpSetPositionButton(layout, clickListener);
|
||||
|
||||
signalQualityIndicatorView = ViewHelper.get(layout, R.id.signal_quality_indicator);
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal.toInt());
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal);
|
||||
|
||||
mReceiver = new IntentReceiver();
|
||||
mBroadcastManager = LocalBroadcastManager.getInstance(inflater.getContext());
|
||||
@@ -101,7 +102,7 @@ public class BuoyFragment extends BaseFragment
|
||||
mapFragment.getMap().setMapType(GoogleMap.MAP_TYPE_SATELLITE);
|
||||
initialLocationUpdate = true;
|
||||
MarkInfo mark = positioningActivity.getMarkInfo();
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal.toInt());
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal);
|
||||
if (mark != null) {
|
||||
setUpTextUI(lastKnownLocation);
|
||||
GoogleMap map = mapFragment.getMap();
|
||||
@@ -217,7 +218,7 @@ public class BuoyFragment extends BaseFragment
|
||||
//provider (GPS) disabled by the user while tracking
|
||||
disablePositionButton();
|
||||
setUpTextUI(null);
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal.toInt());
|
||||
signalQualityIndicatorView.setSignalQuality(GPSQuality.noSignal);
|
||||
|
||||
LocationHelper.showNoGPSError(getActivity(), getString(R.string.enable_gps));
|
||||
}
|
||||
@@ -257,7 +258,7 @@ public class BuoyFragment extends BaseFragment
|
||||
} else if (gpsAccuracy <= 10) {
|
||||
quality = GPSQuality.great;
|
||||
}
|
||||
signalQualityIndicatorView.setSignalQuality(quality.toInt());
|
||||
signalQualityIndicatorView.setSignalQuality(quality);
|
||||
}
|
||||
|
||||
private void handleSuccessfulResponse() {
|
||||
@@ -268,20 +269,6 @@ public class BuoyFragment extends BaseFragment
|
||||
pingListener = listener;
|
||||
}
|
||||
|
||||
private enum GPSQuality {
|
||||
noSignal(0), poor(2), good(3), great(4);
|
||||
|
||||
private final int gpsQuality;
|
||||
|
||||
GPSQuality(int quality) {
|
||||
this.gpsQuality = quality;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.gpsQuality;
|
||||
}
|
||||
}
|
||||
|
||||
public interface pingListener {
|
||||
void updatePing();
|
||||
}
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
<string name="race_list_filter_show_active">Aktive Rennen</string>
|
||||
<string name="race_reset_time_schedule_race">Rennen planen</string>
|
||||
<string name="race_reset_time_startmode_starttime">Startmodus und Startzeit setzen</string>
|
||||
<string name="today">Heute</string>
|
||||
<string name="start">Startzeit des Rennens setzen</string>
|
||||
<string name="nationality">Nationalität</string>
|
||||
<string name="number">Nummer</string>
|
||||
@@ -340,7 +339,6 @@
|
||||
<string name="race_set_time">Zeit setzen</string>
|
||||
<string name="race_start_time_in">-%s</string>
|
||||
<string name="race_start_time_ago">%s</string>
|
||||
<string name="tomorrow">Morgen</string>
|
||||
<string name="race_begin_finish_header">Beginn des Zieleinlaufs</string>
|
||||
<string name="race_begin_finish_current">Aktuelle Zeit</string>
|
||||
<string name="race_begin_finish_custom">Individuelle Zeit</string>
|
||||
@@ -431,7 +429,6 @@
|
||||
<string name="author_type_officer_finish">Zielschiff-Wettfahrtleiter</string>
|
||||
<string name="author_type_shore_control">Regattaleitung an Land</string>
|
||||
<string name="author_viewer">Demo-Modus</string>
|
||||
<string name="yesterday">Gestern</string>
|
||||
<string name="change_proceed">fortfahren</string>
|
||||
<string name="change_cancel">Abbrechen</string>
|
||||
<string name="change_message">Nach den Wettfahrtregeln sind diese Daten im aktuellen Rennenstatus nicht veränderbar.\nSie könnten jedoch die falschen Eingaben korrigieren.</string>
|
||||
|
||||
@@ -184,8 +184,6 @@
|
||||
<string name="race_list_filter_show_active">Show active</string>
|
||||
<string name="race_reset_time_schedule_race">Schedule race</string>
|
||||
<string name="race_reset_time_startmode_starttime">Select start mode and start time</string>
|
||||
<string name="today">Today</string>
|
||||
<string name="tomorrow">Tomorrow</string>
|
||||
<string name="start">Set start time</string>
|
||||
<string name="nationality">Nationality</string>
|
||||
<string name="number">Number</string>
|
||||
@@ -456,7 +454,6 @@
|
||||
<string name="author_type_officer_finish">Race Officer on Finish Vessel</string>
|
||||
<string name="author_type_shore_control">Shore Control</string>
|
||||
<string name="author_viewer">Viewer</string>
|
||||
<string name="yesterday">Yesterday</string>
|
||||
<string name="change_proceed">Proceed</string>
|
||||
<string name="change_cancel">Cancel</string>
|
||||
<string name="change_message">According to the race rules this data is not changeable in the current\nrace state. You may proceed nevertheless to correct wrong inputs.</string>
|
||||
@@ -492,7 +489,6 @@
|
||||
<string name="longitude_value" translatable="false">%.5f</string>
|
||||
<string name="accuracy_value" translatable="false"><![CDATA[~ %.0fm]]></string>
|
||||
<string name="accuracy_timestamp">(since %s)</string>
|
||||
<string name="time_ago" translatable="false">%1$dh %2$02d\' %3$02d\"</string>
|
||||
<string name="prev_course">Previous Course</string>
|
||||
<string name="layout_course">Course Layout</string>
|
||||
<string name="wind_degree">°</string>
|
||||
@@ -531,7 +527,6 @@
|
||||
<string name="preference_heading_with_declination_subtracted_summary_is_disabled">North-based</string>
|
||||
<string name="preference_heading_with_declination_subtracted_enabled">Heading</string>
|
||||
<string name="finishing_date">Finishing Date</string>
|
||||
<string name="date_short" translatable="false">yyyy-MM-dd</string>
|
||||
<string-array name="sort_by_values">
|
||||
<item>by Sail Id</item>
|
||||
<item>by Name</item>
|
||||
|
||||
Regular → Executable
File mode changed.
+1
-217
@@ -1,205 +1,17 @@
|
||||
package com.sap.sailing.racecommittee.app.utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.View;
|
||||
import android.widget.NumberPicker;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
import com.sap.sailing.android.shared.util.ViewHelper;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
private TimeUtils() {
|
||||
// only static methods
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time to 'kk:mm:ss'.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint) {
|
||||
return formatTime(timePoint, "kk:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats your time with the help of {@link DateFormat}.
|
||||
*
|
||||
* @param timePoint timestamp to format
|
||||
* @param format format as defined by {@link DateFormat}
|
||||
* @return timestamp formatted as {@link String}
|
||||
*/
|
||||
public static String formatTime(TimePoint timePoint, String format) {
|
||||
return DateFormat.format(format, timePoint.asDate()).toString();
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint) {
|
||||
return formatDuration(now, timePoint, true);
|
||||
}
|
||||
|
||||
public static String formatDuration(TimePoint now, TimePoint timePoint, boolean inclSign) {
|
||||
String duration;
|
||||
if (timePoint.after(now)) {
|
||||
String sign = (inclSign) ? "-" : "";
|
||||
duration = sign + TimeUtils.formatDurationUntil(timePoint.minus(now.asMillis()).asMillis(), false);
|
||||
} else {
|
||||
duration = TimeUtils.formatDurationSince(now.minus(timePoint.asMillis()).asMillis(), false);
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds) {
|
||||
return formatDurationSince(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationSince(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.floor(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds) {
|
||||
return formatDurationUntil(milliseconds, true);
|
||||
}
|
||||
|
||||
public static String formatDurationUntil(long milliseconds, boolean emptyHours) {
|
||||
int secondsTillStart = (int) Math.ceil(milliseconds / 1000f);
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats milliseconds to a string like: 01h 23'45"
|
||||
*/
|
||||
public static String formatTimeAgo(Context context, long milliseconds) {
|
||||
Calendar time = Calendar.getInstance();
|
||||
time.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
time.setTimeInMillis(milliseconds);
|
||||
return context.getString(R.string.time_ago, time.get(Calendar.HOUR_OF_DAY), time.get(Calendar.MINUTE), time.get(Calendar.SECOND));
|
||||
}
|
||||
|
||||
public static String calcDuration(Calendar from, Calendar to) {
|
||||
String retValue;
|
||||
|
||||
long millis = to.getTimeInMillis() - from.getTimeInMillis();
|
||||
|
||||
long min = millis / (1000 * 60);
|
||||
long sec = (millis - (min * 60 * 1000)) / 1000;
|
||||
|
||||
retValue = String.valueOf(sec) + "\"";
|
||||
if (retValue.length() == 2) {
|
||||
retValue = "0" + retValue;
|
||||
}
|
||||
if (min > 0) {
|
||||
retValue = String.valueOf(min) + "' " + retValue;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
public static Calendar floorTime(Calendar calendar) {
|
||||
if (calendar == null) {
|
||||
calendar = Calendar.getInstance();
|
||||
}
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static int daysBetween(Calendar day1, Calendar day2) {
|
||||
Calendar dayOne = (Calendar) day1.clone();
|
||||
Calendar dayTwo = (Calendar) day2.clone();
|
||||
|
||||
if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) {
|
||||
return dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR);
|
||||
} else {
|
||||
if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) {
|
||||
//swap them
|
||||
Calendar temp = dayOne;
|
||||
dayOne = dayTwo;
|
||||
dayTwo = temp;
|
||||
}
|
||||
int extraDays = 0;
|
||||
|
||||
while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) {
|
||||
dayOne.add(Calendar.YEAR, -1);
|
||||
// getActualMaximum() important for leap years
|
||||
extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOne.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDuration(int secondsTillStart, boolean emptyHours) {
|
||||
int hours = secondsTillStart / 3600;
|
||||
int minutes = (secondsTillStart % 3600) / 60;
|
||||
int seconds = (secondsTillStart % 60);
|
||||
boolean negative = (hours < 0 || minutes < 0 || seconds < 0);
|
||||
String timePattern = ((negative) ? "-" : "") + "%s%s:%s";
|
||||
String secondsString = seconds < 10 ? "0" + Math.abs(seconds) : "" + Math.abs(seconds);
|
||||
String minutesString = minutes < 10 ? "0" + Math.abs(minutes) : "" + Math.abs(minutes);
|
||||
String hoursString = hours < 10 ? "0" + Math.abs(hours) : "" + Math.abs(hours);
|
||||
hoursString = !emptyHours && hoursString.equals("00") ? "" : hoursString + ":";
|
||||
return String.format(timePattern, hoursString, minutesString, secondsString);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays) {
|
||||
initDatePicker(context, datePicker, time, pastDays, futureDays, true);
|
||||
}
|
||||
|
||||
public static void initDatePicker(Context context, NumberPicker datePicker, Calendar time, int pastDays, int futureDays, boolean useWords) {
|
||||
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance();
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(time.getTime());
|
||||
// Past
|
||||
calendar.add(Calendar.DAY_OF_MONTH, pastDays);
|
||||
for (int i = pastDays; i < -1; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
if (useWords) {
|
||||
dates.add(context.getString(R.string.yesterday));
|
||||
dates.add(context.getString(R.string.today));
|
||||
dates.add(context.getString(R.string.tomorrow));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 3);
|
||||
} else {
|
||||
for (int i = (pastDays == 0 ? pastDays : -1); i < (futureDays < 2 ? futureDays + 1 : 2); i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
}
|
||||
// Future
|
||||
for (int i = 2; i <= futureDays; i++) {
|
||||
dates.add(dateFormat.format(calendar.getTime()));
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
datePicker.setDisplayedValues(dates.toArray(new String[dates.size()]));
|
||||
datePicker.setMinValue(0);
|
||||
datePicker.setMaxValue(dates.size() - 1);
|
||||
datePicker.setWrapSelectorWheel(false);
|
||||
datePicker.setValue(TimeUtils.daysBetween(calendar, Calendar.getInstance()) + Math.abs(pastDays));
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
TextView date = new TextView(context);
|
||||
date.setText(dateFormat.format(calendar.getTime()));
|
||||
int padding = context.getResources().getDimensionPixelSize(R.dimen.default_padding_half);
|
||||
date.setPadding(padding, padding, padding, padding);
|
||||
date.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
datePicker.getLayoutParams().width = date.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
public class TimeUtils extends com.sap.sailing.android.shared.util.TimeUtils {
|
||||
|
||||
public static void initTimePickerWithSeconds(Context context, final Calendar time, @Nullable final TimePicker timePicker, @Nullable NumberPicker secondPicker) {
|
||||
int textColor = ThemeHelper.getColor(context, R.attr.white);
|
||||
@@ -242,32 +54,4 @@ public class TimeUtils {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<String> getDates(Context context, TimePoint start, TimePoint end) {
|
||||
ArrayList<String> dates = new ArrayList<>();
|
||||
SimpleDateFormat simpleFormat = new SimpleDateFormat(context.getString(R.string.date_short), Locale.US);
|
||||
Calendar startDate = Calendar.getInstance();
|
||||
Calendar endDate = (Calendar) startDate.clone();
|
||||
startDate.setTime(start.asDate());
|
||||
endDate.setTime(end.asDate());
|
||||
int dayDiff = daysBetween(endDate, startDate);
|
||||
for (int i = 0; i <= dayDiff; i++) {
|
||||
dates.add(simpleFormat.format(startDate.getTime()));
|
||||
startDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
return dates;
|
||||
}
|
||||
|
||||
public static TimePoint getTime(TimePicker timePicker) {
|
||||
return getTime(timePicker, null);
|
||||
}
|
||||
|
||||
public static TimePoint getTime(TimePicker timePicker, @Nullable NumberPicker secondPicker) {
|
||||
Calendar time = Calendar.getInstance();
|
||||
time.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
|
||||
time.set(Calendar.MINUTE, timePicker.getCurrentMinute());
|
||||
time.set(Calendar.SECOND, secondPicker == null ? 0 : secondPicker.getValue());
|
||||
time.set(Calendar.MILLISECOND, 0);
|
||||
return new MillisecondsTimePoint(time.getTime());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user