mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-25 05:23:51 +00:00
Merge branch 'ubilabs--rcapp--bug-3010'
This commit is contained in:
commit
442a10799b
9 files changed
+531
-548
No files matched your search
@@ -10,7 +10,7 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/header"
|
||||
android:id="@+id/header_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/selector_header_height"
|
||||
android:background="?sap_gray">
|
||||
@@ -54,8 +54,9 @@
|
||||
android:src="?wind_on"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:id="@+id/header_text"
|
||||
android:drawableLeft="?chevron_left_24dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
@@ -65,28 +66,18 @@
|
||||
android:layout_marginStart="@dimen/default_margin"
|
||||
android:layout_toLeftOf="@id/wind_off"
|
||||
android:layout_toStartOf="@id/wind_off"
|
||||
android:orientation="horizontal">
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:text="@string/wind"
|
||||
android:textAppearance="?textNormal" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/header_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="?chevron_left_24dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/wind"
|
||||
android:textAppearance="?textNormal"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/content_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/header"
|
||||
android:layout_below="@id/header_layout"
|
||||
android:background="?sap_gray_black_30"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/default_padding"
|
||||
@@ -140,10 +131,11 @@
|
||||
android:visibility="visible"/>
|
||||
|
||||
<com.sap.sailing.racecommittee.app.ui.views.CompassView
|
||||
android:id="@+id/compassView"
|
||||
android:id="@+id/compass_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
@@ -175,9 +167,14 @@
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_map"
|
||||
android:id="@+id/layout_position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/default_margin"
|
||||
android:layout_marginLeft="@dimen/default_margin"
|
||||
android:layout_marginRight="@dimen/default_margin"
|
||||
android:layout_marginStart="@dimen/default_margin"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/position_header"
|
||||
@@ -189,77 +186,119 @@
|
||||
android:textAppearance="?textSmall"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/position_header">
|
||||
android:layout_below="@+id/position_header">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/windMap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:layout="@layout/welcome"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/address"
|
||||
<TextView
|
||||
android:id="@+id/position_latitude"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/default_margin"
|
||||
android:background="?white"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
android:text="@string/wind_latitude"
|
||||
android:textAppearance="?textSmall"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/address_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="@dimen/default_padding_half"
|
||||
android:src="?search_24dp_invert"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/address_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/default_margin_half"
|
||||
android:layout_marginStart="@dimen/default_margin_half"
|
||||
android:layout_toLeftOf="@id/address_search"
|
||||
android:layout_toStartOf="@id/address_search"
|
||||
android:hint="@string/wind_address_hint"
|
||||
android:padding="@dimen/default_padding_half"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?textNormal"
|
||||
android:textColor="?white_invert"
|
||||
android:textColorHint="?sap_light_gray"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dark_layer"
|
||||
<TextView
|
||||
android:id="@+id/position_longitude"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/default_margin"
|
||||
android:layout_below="@+id/position_latitude"
|
||||
android:text="@string/wind_longitude"
|
||||
android:textAppearance="?textSmall"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/constant_black_transparent"/>
|
||||
<TextView
|
||||
android:id="@+id/position_accuracy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/default_margin"
|
||||
android:layout_below="@+id/position_longitude"
|
||||
android:text="@string/wind_accuracy"
|
||||
android:textAppearance="?textSmall"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/position_show"
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/position_accuracy"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/wind_map_button_show"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/enter_position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="@drawable/button_border_light"
|
||||
android:padding="@dimen/default_padding"
|
||||
android:text="@string/wind_enter_position"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?textNormal"
|
||||
android:textColor="?white"/>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/map_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/content_layout"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/web_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<!-- the following layout is for a future implementation -->
|
||||
<!--<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Overall"/>
|
||||
|
||||
<Button
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="#1"/>
|
||||
|
||||
<Button
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="#2"/>
|
||||
|
||||
<Button
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="#3"/>
|
||||
|
||||
</LinearLayout>-->
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/position_hide"
|
||||
style="?attr/buttonSolidNormal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginRight="@dimen/wind_hide_button_right_margin"
|
||||
android:layout_marginEnd="@dimen/wind_hide_button_right_margin"
|
||||
android:layout_marginTop="@dimen/wind_hide_button_top_margin"
|
||||
android:text="@string/wind_map_button_hide"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
@@ -427,5 +427,11 @@
|
||||
<string name="error_finishing_time">Die ausgewählte Zeit is vor dem Rennstart. Bitte überprüfe die Uhrzeit.</string>
|
||||
<string name="error_time_in_future">Die ausgewählte Zeit liegt in der Zukunft. Bitte überprüfe die Uhrzeit.</string>
|
||||
<string name="error_wrong_race_state">Der RaceState hat nicht den korrekten Status (benötigt: %1$s - aktuell: %2$s)</string>
|
||||
<string name="wind_map_button_show">Windkarte</string>
|
||||
<string name="wind_map_button_hide">Schließen</string>
|
||||
<string name="wind_latitude">Breite</string>
|
||||
<string name="wind_longitude">Länge</string>
|
||||
<string name="wind_accuracy">Genauigkeit</string>
|
||||
<string name="wind_accuracy_ago">alt</string>
|
||||
|
||||
</resources>
|
||||
@@ -48,5 +48,8 @@
|
||||
|
||||
<dimen name="bigger_over_flow_width">64dp</dimen>
|
||||
<dimen name="bigger_over_flow_height">32dp</dimen>
|
||||
|
||||
<dimen name="wind_hide_button_right_margin">76dp</dimen>
|
||||
<dimen name="wind_hide_button_top_margin">20dp</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -447,5 +447,11 @@
|
||||
<string name="error_finishing_time">The selected time is before the race start.</string>
|
||||
<string name="error_time_in_future">The given time is in future. Please recheck the time.</string>
|
||||
<string name="error_wrong_race_state">The RaceState isn\'t in the correct state (needed: %1$s - current: %2$s)</string>
|
||||
<string name="wind_map_button_show">Wind Map</string>
|
||||
<string name="wind_map_button_hide">Hide</string>
|
||||
<string name="wind_latitude">Latitude</string>
|
||||
<string name="wind_longitude">Longitude</string>
|
||||
<string name="wind_accuracy">Accuracy</string>
|
||||
<string name="wind_accuracy_ago">ago</string>
|
||||
|
||||
</resources>
|
||||
+3
@@ -72,4 +72,7 @@ public class AppConstants {
|
||||
public final static String INTENT_ACTION_SHOW_SUMMARY_CONTENT = PACKAGE_NAME + ".action.show.summary";
|
||||
|
||||
public final static String INTENT_ACTION_SHOW_PROTEST = PACKAGE_NAME + ".action.show.protest";
|
||||
|
||||
public final static String INTENT_ACTION_IS_TRACKING = PACKAGE_NAME + "action.is.tracking";
|
||||
public final static String INTENT_ACTION_IS_TRACKING_EXTRA = PACKAGE_NAME + "action.is.tracking.extra";
|
||||
}
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class RaceTimeChangeFragment extends BaseFragment implements View.OnClick
|
||||
|
||||
case FINISHING_TIME_MODE:
|
||||
start.setTime(getRaceState().getStartTime().asDate());
|
||||
mPastDays = TimeUtils.daysBetween(calendar, start);
|
||||
mPastDays = TimeUtils.daysBetween(start, calendar);
|
||||
finished.setTime(getRaceState().getFinishedTime().asDate());
|
||||
mFutureDays = TimeUtils.daysBetween(finished, calendar);
|
||||
break;
|
||||
|
||||
+257
-466
@@ -1,33 +1,27 @@
|
||||
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.location.Location;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.*;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
|
||||
import com.google.android.gms.maps.GoogleMap.OnMarkerDragListener;
|
||||
import com.google.android.gms.maps.OnMapReadyCallback;
|
||||
import com.google.android.gms.maps.UiSettings;
|
||||
import com.google.android.gms.maps.model.LatLng;
|
||||
import com.google.android.gms.maps.model.Marker;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
@@ -41,71 +35,61 @@ import com.sap.sailing.racecommittee.app.AppConstants;
|
||||
import com.sap.sailing.racecommittee.app.R;
|
||||
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
|
||||
import com.sap.sailing.racecommittee.app.services.polling.RacePositionsPoller;
|
||||
import com.sap.sailing.racecommittee.app.ui.fragments.maps.WindMap;
|
||||
import com.sap.sailing.racecommittee.app.ui.utils.OnRaceUpdatedListener;
|
||||
import com.sap.sailing.racecommittee.app.ui.views.CompassView;
|
||||
import com.sap.sailing.racecommittee.app.ui.views.CompassView.CompassDirectionListener;
|
||||
import com.sap.sailing.racecommittee.app.utils.ThemeHelper;
|
||||
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
|
||||
import com.sap.sailing.racecommittee.app.utils.WindHelper;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WindFragment extends BaseFragment
|
||||
implements CompassDirectionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener,
|
||||
OnClickListener, OnMarkerDragListener, OnMapClickListener, OnRaceUpdatedListener, TextView.OnEditorActionListener, OnMapReadyCallback,
|
||||
WindMap.OnResumeCallback {
|
||||
implements CompassDirectionListener,
|
||||
GoogleApiClient.ConnectionCallbacks,
|
||||
GoogleApiClient.OnConnectionFailedListener,
|
||||
LocationListener,
|
||||
OnRaceUpdatedListener {
|
||||
|
||||
private final static String TAG = WindFragment.class.getName();
|
||||
private final static String START_MODE = "startMode";
|
||||
private final static int FIVE_SEC = 5000;
|
||||
private final static int EVERY_POSITION_CHANGE = 0;
|
||||
private final static long ONE_SEC = 1000;
|
||||
private final static long FIVE_SEC = 5000;
|
||||
private final static long EVERY_POSITION_CHANGE = 0;
|
||||
private final static int MIN_KTS = 3;
|
||||
private final static int MAX_KTS = 30;
|
||||
private final static float MAX_LOCATION_DRIFT_IN_METER = 25f; // 25 meter
|
||||
private final static long MAX_LOCATION_DRIFT_IN_MILLIS = 8 * 60 * 60 * 1000; // 8 hours
|
||||
|
||||
private Context mContext;
|
||||
private View mHeaderLayout;
|
||||
private View mContentLayout;
|
||||
private View mMapLayout;
|
||||
|
||||
private View mHeader;
|
||||
private View mLayoutDirection;
|
||||
private View mLayoutSpeed;
|
||||
private View mLayoutAddress;
|
||||
private View mPositionHeader;
|
||||
private View mDarkLayer;
|
||||
private View mWindOn;
|
||||
private View mWindOff;
|
||||
private View mAddressSearch;
|
||||
private View mSetData;
|
||||
private View mSetPosition;
|
||||
|
||||
private CompassView mCompassView;
|
||||
private NumberPicker mWindSpeed;
|
||||
private Button mEnterPosition;
|
||||
private EditText mAddressInput;
|
||||
private TextView mWindSensor;
|
||||
|
||||
private WindMap mWindMap;
|
||||
private GoogleMap mGoogleMap;
|
||||
private TextView mHeaderText;
|
||||
private TextView mHeaderWindSensor;
|
||||
// private View mWindOn;
|
||||
// private View mWindOff;
|
||||
private Button mContentSetData;
|
||||
private CompassView mContentCompassView;
|
||||
private NumberPicker mContentWindSpeed;
|
||||
private TextView mContentLatitude;
|
||||
private TextView mContentLongitude;
|
||||
private TextView mContentAccuracy;
|
||||
private Button mContentMapShow;
|
||||
private WebView mMapWebView;
|
||||
private Button mMapHide;
|
||||
|
||||
private GoogleApiClient apiClient;
|
||||
private LocationRequest locationRequest;
|
||||
private Location mCurrentLocation;
|
||||
|
||||
private Handler mRefreshUIHandler;
|
||||
private Runnable mRefreshUIRunnable;
|
||||
|
||||
private RacePositionsPoller positionPoller;
|
||||
|
||||
// stuff to save during rotation/ ect
|
||||
private boolean bigMap = false;
|
||||
|
||||
public WindFragment() {
|
||||
}
|
||||
|
||||
public static WindFragment newInstance(int startMode) {
|
||||
WindFragment fragment = new WindFragment();
|
||||
Bundle args = new Bundle();
|
||||
@@ -114,20 +98,13 @@ public class WindFragment extends BaseFragment
|
||||
return fragment;
|
||||
}
|
||||
|
||||
protected static float round(float number, int precision) {
|
||||
BigDecimal decimal = new BigDecimal(number);
|
||||
BigDecimal round = decimal.setScale(precision, BigDecimal.ROUND_UP);
|
||||
return round.floatValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the string array that represents the numbers in the windspeed numberpicker
|
||||
* creates the string array that represents the numbers in the wind speed number picker
|
||||
*
|
||||
* @return
|
||||
* @return numbers for wind speed number picker
|
||||
*/
|
||||
private String[] generateNumbers() {
|
||||
ArrayList<String> numbers = new ArrayList<>();
|
||||
|
||||
for (float i = MIN_KTS; i <= MAX_KTS; i += .5f) {
|
||||
numbers.add(String.format("%.1f %s", i, getString(R.string.wind_kn)));
|
||||
}
|
||||
@@ -138,126 +115,196 @@ public class WindFragment extends BaseFragment
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
apiClient = new GoogleApiClient.Builder(getActivity()).addApi(LocationServices.API).addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this).build();
|
||||
// initialize the googleApiClient for location requests
|
||||
apiClient = new GoogleApiClient.Builder(getActivity()).addApi(LocationServices.API).build();
|
||||
|
||||
// create runnable for ui refreshing
|
||||
mRefreshUIRunnable = createUIRefreshRunnable();
|
||||
|
||||
//register receiver to be notified if race is tracked
|
||||
IntentFilter filter = new IntentFilter(AppConstants.INTENT_ACTION_IS_TRACKING);
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(new IsTrackedReceiver(), filter);
|
||||
}
|
||||
|
||||
private Runnable createUIRefreshRunnable() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshUI();
|
||||
mRefreshUIHandler.postDelayed(this, ONE_SEC);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* refresh location data labels and highlight missing or inaccuracy gps data
|
||||
* disable mContentSetData button if gps data is missing or inaccurate
|
||||
*/
|
||||
private void refreshUI() {
|
||||
if (mCurrentLocation != null) {
|
||||
double latitude = mCurrentLocation.getLatitude();
|
||||
double longitude = mCurrentLocation.getLongitude();
|
||||
float accuracy = mCurrentLocation.getAccuracy();
|
||||
long timeDifference = System.currentTimeMillis() - mCurrentLocation.getTime();
|
||||
mContentLatitude.setText(String.format("%s: %.5f", getString(R.string.wind_latitude), latitude));
|
||||
mContentLatitude.setTextColor(Color.BLACK);
|
||||
mContentLongitude.setText(String.format("%s: %.5f", getString(R.string.wind_longitude), longitude));
|
||||
mContentLongitude.setTextColor(Color.BLACK);
|
||||
String timeFormatted = TimeUtils.formatTimeAgo(timeDifference) + " " + getString(R.string.wind_accuracy_ago);
|
||||
mContentAccuracy.setText(String.format("%s: ~%.0fm\n(%s)", getString(R.string.wind_accuracy), mCurrentLocation.getAccuracy(), timeFormatted));
|
||||
mContentSetData.setEnabled(timeDifference <= MAX_LOCATION_DRIFT_IN_MILLIS && accuracy <= MAX_LOCATION_DRIFT_IN_METER);
|
||||
|
||||
// highlight accuracy problem if location is invalid
|
||||
mContentAccuracy.setTextColor(mContentSetData.isEnabled() ? Color.BLACK : Color.RED);
|
||||
} else {
|
||||
mContentSetData.setEnabled(false);
|
||||
|
||||
// highlight location problem if no location is available
|
||||
mContentLatitude.setTextColor(Color.RED);
|
||||
mContentLongitude.setTextColor(Color.RED);
|
||||
mContentAccuracy.setTextColor(Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View layout = inflater.inflate(R.layout.wind_view, container, false);
|
||||
|
||||
mContext = inflater.getContext();
|
||||
// the fragment is divided into three layouts
|
||||
// header layout is optional and is used for back navigation
|
||||
// content layout holds wind direction, wind speed and location controls
|
||||
// map layout holds a lazy web view for map presentation
|
||||
mHeaderLayout = layout.findViewById(R.id.header_layout);
|
||||
mContentLayout = layout.findViewById(R.id.content_layout);
|
||||
mMapLayout = layout.findViewById(R.id.map_layout);
|
||||
|
||||
mHeader = layout.findViewById(R.id.header_text);
|
||||
mDarkLayer = layout.findViewById(R.id.dark_layer);
|
||||
mLayoutDirection = layout.findViewById(R.id.layout_direction);
|
||||
mLayoutSpeed = layout.findViewById(R.id.layout_speed);
|
||||
mLayoutAddress = layout.findViewById(R.id.address);
|
||||
mPositionHeader = layout.findViewById(R.id.position_header);
|
||||
mHeaderText = (TextView) layout.findViewById(R.id.header_text);
|
||||
mHeaderWindSensor = (TextView) layout.findViewById(R.id.wind_sensor);
|
||||
// disabled, because of bug #2871
|
||||
// mWindOff = layout.findViewById(R.id.wind_off);
|
||||
// mWindOn = layout.findViewById(R.id.wind_on);
|
||||
mAddressSearch = layout.findViewById(R.id.address_search);
|
||||
mSetData = layout.findViewById(R.id.set_data);
|
||||
mSetPosition = layout.findViewById(R.id.set_position);
|
||||
|
||||
mCompassView = (CompassView) layout.findViewById(R.id.compassView);
|
||||
mWindSpeed = (NumberPicker) layout.findViewById(R.id.wind_speed);
|
||||
mAddressInput = (EditText) layout.findViewById(R.id.address_input);
|
||||
mWindSensor = (TextView) layout.findViewById(R.id.wind_sensor);
|
||||
|
||||
mEnterPosition = (Button) layout.findViewById(R.id.enter_position);
|
||||
// mWindOff = layout.findViewById(R.id.wind_off);
|
||||
// mWindOn = layout.findViewById(R.id.wind_on);
|
||||
mContentSetData = (Button) layout.findViewById(R.id.set_data);
|
||||
mContentCompassView = (CompassView) layout.findViewById(R.id.compass_view);
|
||||
mContentWindSpeed = (NumberPicker) layout.findViewById(R.id.wind_speed);
|
||||
mContentLatitude = (TextView) layout.findViewById(R.id.position_latitude);
|
||||
mContentLongitude = (TextView) layout.findViewById(R.id.position_longitude);
|
||||
mContentAccuracy = (TextView) layout.findViewById(R.id.position_accuracy);
|
||||
mContentMapShow = (Button) layout.findViewById(R.id.position_show);
|
||||
mMapWebView = (WebView) layout.findViewById(R.id.web_view);
|
||||
mMapHide = (Button) layout.findViewById(R.id.position_hide);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
initialMapFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
if (getArguments() != null) {
|
||||
switch (getArguments().getInt(START_MODE, 0)) {
|
||||
case 1:
|
||||
if (getView() != null) {
|
||||
View header = getView().findViewById(R.id.header);
|
||||
header.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mWindSensor != null && getRace() != null && getRaceState() != null && getRaceState().getWindFix() != null) {
|
||||
if (mHeaderWindSensor != null && getRace() != null && getRaceState() != null && getRaceState().getWindFix() != null) {
|
||||
String sensorData = getString(R.string.wind_sensor);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm", getResources().getConfiguration().locale);
|
||||
Wind wind = getRaceState().getWindFix();
|
||||
sensorData = sensorData.replace("#AT#", dateFormat.format(wind.getTimePoint().asDate()));
|
||||
sensorData = sensorData.replace("#FROM#", String.format("%.0f", wind.getFrom().getDegrees()));
|
||||
sensorData = sensorData.replace("#SPEED#", String.format("%.1f", wind.getKnots()));
|
||||
mWindSensor.setText(sensorData);
|
||||
mHeaderWindSensor.setText(sensorData);
|
||||
}
|
||||
|
||||
setupButtons();
|
||||
setupWindSpeedPicker();
|
||||
showElements(true);
|
||||
setupLayouts(false);
|
||||
}
|
||||
|
||||
setInstanceState(savedInstanceState);
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
mRefreshUIHandler = new Handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* starts the googleApiClient to get location updates
|
||||
*/
|
||||
public void setupLocationClient() {
|
||||
private void tearUpApiClient() {
|
||||
locationRequest = LocationRequest.create();
|
||||
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
||||
locationRequest.setInterval(FIVE_SEC);
|
||||
locationRequest.setFastestInterval(EVERY_POSITION_CHANGE);
|
||||
apiClient.registerConnectionCallbacks(this);
|
||||
apiClient.registerConnectionFailedListener(this);
|
||||
apiClient.connect();
|
||||
}
|
||||
|
||||
private void tearDownApiClient() {
|
||||
apiClient.unregisterConnectionFailedListener(this);
|
||||
apiClient.unregisterConnectionCallbacks(this);
|
||||
apiClient.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the polling for buoy data to the polled races, also registers a callback
|
||||
*/
|
||||
private void tearUpPositionPoller() {
|
||||
positionPoller = new RacePositionsPoller(getActivity());
|
||||
positionPoller.register(getRace(), this);
|
||||
ExLog.i(getActivity(), TAG, "registering race " + getRace().getRaceName());
|
||||
}
|
||||
|
||||
private void tearDownPositionPoller() {
|
||||
positionPoller.unregisterAllAndStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* configures all the buttons in the view
|
||||
*/
|
||||
public void setupButtons() {
|
||||
if (mHeader != null) {
|
||||
mHeader.setOnClickListener(this);
|
||||
if (mHeaderText != null) {
|
||||
mHeaderText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openMainScheduleFragment();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mEnterPosition != null) {
|
||||
mEnterPosition.setOnClickListener(this);
|
||||
if (mContentSetData != null) {
|
||||
mContentSetData.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onSendClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mAddressInput != null) {
|
||||
mAddressInput.setOnEditorActionListener(this);
|
||||
if (mContentMapShow != null) {
|
||||
// disable functionality at first. will be enabled after contacting the server if race is tracked
|
||||
mContentMapShow.setEnabled(false);
|
||||
mContentMapShow.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setupLayouts(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mAddressSearch != null) {
|
||||
mAddressSearch.setOnClickListener(this);
|
||||
}
|
||||
if (mSetData != null) {
|
||||
mSetData.setOnClickListener(this);
|
||||
}
|
||||
if (mSetPosition != null) {
|
||||
mSetPosition.setOnClickListener(this);
|
||||
if (mMapHide != null) {
|
||||
mMapHide.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setupLayouts(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* configures the windspeedpicker views and attaches all relevant listener functions to them
|
||||
* configures the wind speed picker views and attaches all relevant listener functions to them
|
||||
*/
|
||||
public void setupWindSpeedPicker() {
|
||||
String nums[] = generateNumbers();
|
||||
ThemeHelper.setPickerTextColor(getActivity(), mWindSpeed, ThemeHelper.getColor(getActivity(), R.attr.white));
|
||||
mWindSpeed.setMaxValue(nums.length - 1);
|
||||
mWindSpeed.setMinValue(0);
|
||||
mWindSpeed.setWrapSelectorWheel(false);
|
||||
mWindSpeed.setDisplayedValues(nums);
|
||||
mWindSpeed.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
|
||||
ThemeHelper.setPickerTextColor(getActivity(), mContentWindSpeed, ThemeHelper.getColor(getActivity(), R.attr.white));
|
||||
mContentWindSpeed.setMaxValue(nums.length - 1);
|
||||
mContentWindSpeed.setMinValue(0);
|
||||
mContentWindSpeed.setWrapSelectorWheel(false);
|
||||
mContentWindSpeed.setDisplayedValues(nums);
|
||||
mContentWindSpeed.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
|
||||
|
||||
double enteredWindSpeed = preferences.getWindSpeed();
|
||||
double enteredWindBearingFrom = preferences.getWindBearingFromDirection();
|
||||
@@ -270,67 +317,66 @@ public class WindFragment extends BaseFragment
|
||||
}
|
||||
}
|
||||
|
||||
mCompassView.setDirection((float) enteredWindBearingFrom);
|
||||
mWindSpeed.setValue(((int) ((enteredWindSpeed - MIN_KTS) * 2)));
|
||||
mContentCompassView.setDirection((float) enteredWindBearingFrom);
|
||||
mContentWindSpeed.setValue(((int) ((enteredWindSpeed - MIN_KTS) * 2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the polling for buoy data to the polled races, also registers a callback
|
||||
*/
|
||||
public void setupPositionPoller() {
|
||||
positionPoller = new RacePositionsPoller(getActivity());
|
||||
positionPoller.register(getRace(), this);
|
||||
ExLog.i(getActivity(), TAG, "registering race " + getRace().getRaceName());
|
||||
}
|
||||
|
||||
/**
|
||||
* function to restore the instanceState via savedInstanceState bundle
|
||||
*
|
||||
* @param savedInstanceState said bundle
|
||||
*/
|
||||
public void setInstanceState(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
bigMap = savedInstanceState.getBoolean("bigMap", false);
|
||||
double markerLat = savedInstanceState.getDouble("markerLat", -1);
|
||||
|
||||
if (bigMap) {
|
||||
showBigMap();
|
||||
if (mWindMap != null && savedInstanceState.getDouble("lat", -1) != -1) {
|
||||
mWindMap.centerMap(savedInstanceState.getDouble("lat"), savedInstanceState.getDouble("lng"), savedInstanceState.getFloat("zoom"));
|
||||
if (markerLat != -1) {
|
||||
mWindMap.movePositionMarker(new LatLng(markerLat, savedInstanceState.getDouble("markerLng")));
|
||||
}
|
||||
}
|
||||
// the map view needs java script
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private void setupLayouts(boolean showMap) {
|
||||
if (mHeaderLayout != null) {
|
||||
if (getArguments() != null && getArguments().getInt(START_MODE, 0) == 1) {
|
||||
mHeaderLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
mHeaderLayout.setVisibility(showMap ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
if (mContentLayout != null) {
|
||||
mContentLayout.setVisibility(showMap ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
if (mMapLayout != null) {
|
||||
WebSettings settings = mMapWebView.getSettings();
|
||||
if (showMap) {
|
||||
settings.setJavaScriptEnabled(true);
|
||||
loadRaceMap(true, false, false, true);
|
||||
mMapLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
settings.setJavaScriptEnabled(false);
|
||||
mMapLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadRaceMap(boolean showWindCharts, boolean showStreamlets, boolean showSimulation, boolean showMapControls) {
|
||||
ManagedRace race = getRace();
|
||||
if (race != null) {
|
||||
// build complete race map url
|
||||
String mapUrl = WindHelper.generateMapURL(getActivity(), race, showWindCharts, showStreamlets, showSimulation, showMapControls);
|
||||
mMapWebView.loadUrl(mapUrl);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
mCompassView.setDirectionListener(this);
|
||||
mContentCompassView.setDirectionListener(this);
|
||||
|
||||
// start ui refreshing
|
||||
if (mRefreshUIHandler != null) {
|
||||
mRefreshUIHandler.postDelayed(mRefreshUIRunnable, ONE_SEC);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (apiClient.isConnected()) {
|
||||
apiClient.unregisterConnectionFailedListener(this);
|
||||
apiClient.unregisterConnectionCallbacks(this);
|
||||
}
|
||||
apiClient.disconnect();
|
||||
|
||||
positionPoller.unregisterAllAndStop();
|
||||
|
||||
Fragment fragment = getFragmentManager().findFragmentById(R.id.windMap);
|
||||
|
||||
if (fragment != null) {
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
transaction.remove(fragment);
|
||||
transaction.commit();
|
||||
}
|
||||
// disconnect googleApiClient and unregister position poller
|
||||
tearDownApiClient();
|
||||
tearDownPositionPoller();
|
||||
|
||||
sendIntent(AppConstants.INTENT_ACTION_TIME_SHOW);
|
||||
}
|
||||
@@ -339,63 +385,23 @@ public class WindFragment extends BaseFragment
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
setupPositionPoller();
|
||||
setupLocationClient();
|
||||
initialMapFragment();
|
||||
// connect googleApiClient and register position poller
|
||||
tearUpApiClient();
|
||||
tearUpPositionPoller();
|
||||
|
||||
// Contact server and ask if race is tracked and map is allowed to show.
|
||||
WindHelper.isTrackedRace(getActivity(), getRace());
|
||||
|
||||
sendIntent(AppConstants.INTENT_ACTION_TIME_HIDE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
outState.putBoolean("bigMap", bigMap);
|
||||
if (mWindMap != null) {
|
||||
if (mGoogleMap != null) {
|
||||
outState.putDouble("lat", mGoogleMap.getCameraPosition().target.latitude);
|
||||
outState.putDouble("lng", mGoogleMap.getCameraPosition().target.longitude);
|
||||
outState.putFloat("zoom", mGoogleMap.getCameraPosition().zoom);
|
||||
}
|
||||
if (mWindMap.windMarker != null) {
|
||||
outState.putDouble("markerLat", mWindMap.windMarker.getPosition().latitude);
|
||||
outState.putDouble("markerLng", mWindMap.windMarker.getPosition().longitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.header_text:
|
||||
if (bigMap) {
|
||||
showElements(true);
|
||||
bigMap = false;
|
||||
} else {
|
||||
openMainScheduleFragment();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.enter_position:
|
||||
showBigMap();
|
||||
break;
|
||||
|
||||
case R.id.address_search:
|
||||
if (mAddressInput != null) {
|
||||
new GeoCodeTask().execute("" + mAddressInput.getText());
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.set_data: {
|
||||
onSendClick();
|
||||
break;
|
||||
}
|
||||
case R.id.set_position: {
|
||||
onPositionSetClick();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
// stop ui refreshing
|
||||
if (mRefreshUIHandler != null) {
|
||||
mRefreshUIHandler.removeCallbacks(mRefreshUIRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,160 +423,19 @@ public class WindFragment extends BaseFragment
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the boat position for later sendage of the entered windData
|
||||
*/
|
||||
private void onPositionSetClick() {
|
||||
bigMap = false;
|
||||
|
||||
if (mWindMap != null && mWindMap.windMarker != null && mGoogleMap != null) {
|
||||
mGoogleMap.getUiSettings().setAllGesturesEnabled(false);
|
||||
mCurrentLocation = new Location("manual");
|
||||
mCurrentLocation.setLatitude(mWindMap.windMarker.getPosition().latitude);
|
||||
mCurrentLocation.setLongitude(mWindMap.windMarker.getPosition().longitude);
|
||||
preferences.setWindPosition(mWindMap.windMarker.getPosition());
|
||||
mWindMap.windMarker.setDraggable(false);
|
||||
mWindMap.centerMap(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
|
||||
}
|
||||
showElements(true);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
private void initialMapFragment() {
|
||||
mWindMap = WindMap.newInstance(mContext, this);
|
||||
FragmentManager manager;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
manager = getChildFragmentManager();
|
||||
} else {
|
||||
manager = getFragmentManager();
|
||||
}
|
||||
if (manager.findFragmentByTag("googleMap") == null) {
|
||||
FragmentTransaction ft = manager.beginTransaction();
|
||||
ft.replace(R.id.windMap, mWindMap, "googleMap").commit();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
manager.executePendingTransactions();
|
||||
mWindMap.getMapAsync(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* expands the windMap , hides views where the map is supposed to go
|
||||
*/
|
||||
private void showBigMap() {
|
||||
showElements(false);
|
||||
if (mWindMap != null && mGoogleMap != null) {
|
||||
mGoogleMap.getUiSettings().setAllGesturesEnabled(true);
|
||||
if (mWindMap.windMarker != null) {
|
||||
mWindMap.windMarker.setDraggable(true);
|
||||
}
|
||||
}
|
||||
bigMap = true;
|
||||
}
|
||||
|
||||
private void showElements(boolean show) {
|
||||
if (mSetData != null) {
|
||||
mSetData.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
|
||||
mSetData
|
||||
.setEnabled(mWindMap != null && mWindMap.windMarker != null && mWindMap.windMarker.getPosition() != null && mCurrentLocation != null);
|
||||
}
|
||||
if (mSetPosition != null) {
|
||||
mSetPosition.setVisibility(show ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
if (mLayoutDirection != null) {
|
||||
mLayoutDirection.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mLayoutSpeed != null) {
|
||||
mLayoutSpeed.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mPositionHeader != null) {
|
||||
mPositionHeader.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mDarkLayer != null) {
|
||||
mDarkLayer.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mLayoutAddress != null) {
|
||||
mLayoutAddress.setVisibility(show ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setWind(boolean on) {
|
||||
if (mWindOn != null) {
|
||||
mWindOn.setVisibility(on ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
if (mWindOff != null) {
|
||||
mWindOff.setVisibility(!on ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
// private void setWind(boolean on) {
|
||||
// if (mWindOn != null) {
|
||||
// mWindOn.setVisibility(on ? View.VISIBLE : View.GONE);
|
||||
// }
|
||||
// if (mWindOff != null) {
|
||||
// mWindOff.setVisibility(!on ? View.VISIBLE : View.GONE);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
mCurrentLocation = location;
|
||||
if (mWindMap != null) {
|
||||
mWindMap.centerMap(location.getLatitude(), location.getLongitude());
|
||||
|
||||
if (mGoogleMap != null) {
|
||||
UiSettings uiSettings = mGoogleMap.getUiSettings();
|
||||
if (uiSettings != null) {
|
||||
uiSettings.setAllGesturesEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
mWindMap.addAccuracyCircle(location);
|
||||
if (mWindMap.windMarker != null) {
|
||||
mWindMap.windMarker.setDraggable(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mDarkLayer != null) {
|
||||
mDarkLayer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
setWind(true);
|
||||
showElements(true);
|
||||
if (mDarkLayer != null) {
|
||||
mDarkLayer.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function gets called after inputting the location where you want to the map to zoom to
|
||||
*
|
||||
* @param v the view where the location was entered
|
||||
*/
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
switch (actionId) {
|
||||
case EditorInfo.IME_ACTION_DONE:
|
||||
new GeoCodeTask().execute("" + v.getText());
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMarkerDragStart(Marker arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMarkerDragEnd(Marker marker) {
|
||||
mCurrentLocation = new Location("manual");
|
||||
mCurrentLocation.setLatitude(marker.getPosition().latitude);
|
||||
mCurrentLocation.setLongitude(marker.getPosition().longitude);
|
||||
preferences.setWindPosition(marker.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMarkerDrag(Marker arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapClick(LatLng arg0) {
|
||||
if (bigMap && mWindMap != null) {
|
||||
mWindMap.movePositionMarker(arg0);
|
||||
}
|
||||
refreshUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -585,18 +450,21 @@ public class WindFragment extends BaseFragment
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int i) {
|
||||
|
||||
LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDirectionChanged(float degree) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnRaceUpdated(ManagedRace race) {
|
||||
}
|
||||
|
||||
private Wind getResultingWindFix() throws NumberFormatException {
|
||||
Position currentPosition = new DegreePosition(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
|
||||
double windSpeed = mWindSpeed.getValue() / 2 + MIN_KTS;
|
||||
double windBearing = mCompassView.getDirection();
|
||||
double windSpeed = mContentWindSpeed.getValue() / 2 + MIN_KTS;
|
||||
double windBearing = mContentCompassView.getDirection();
|
||||
Bearing bearing_from = new DegreeBearingImpl(windBearing);
|
||||
SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(windSpeed, bearing_from.reverse());
|
||||
return new WindImpl(currentPosition, MillisecondsTimePoint.now(), speedBearing);
|
||||
@@ -613,90 +481,13 @@ public class WindFragment extends BaseFragment
|
||||
preferences.setWindSpeed(wind.getKnots());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void OnRaceUpdated(ManagedRace race) {
|
||||
if (mWindMap != null) {
|
||||
mWindMap.onMapDataUpdated(race.getMapMarkers());
|
||||
}
|
||||
}
|
||||
private class IsTrackedReceiver extends BroadcastReceiver {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onMapReady(GoogleMap map) {
|
||||
mGoogleMap = map;
|
||||
|
||||
if (mWindMap != null && mGoogleMap != null) {
|
||||
mWindMap.setMap(mGoogleMap);
|
||||
mGoogleMap.setOnMapClickListener(this);
|
||||
mGoogleMap.setOnMarkerDragListener(this);
|
||||
UiSettings uiSettings = mGoogleMap.getUiSettings();
|
||||
uiSettings.setAllGesturesEnabled(false);
|
||||
uiSettings.setCompassEnabled(false);
|
||||
uiSettings.setMapToolbarEnabled(false);
|
||||
// mWindMap.setData(mapItems);
|
||||
|
||||
// center the map
|
||||
LatLng enteredWindLocation = preferences.getWindPosition();
|
||||
if (enteredWindLocation.latitude != 0 && enteredWindLocation.longitude != 0) {
|
||||
mWindMap.movePositionMarker(enteredWindLocation);
|
||||
mWindMap.centerMap(enteredWindLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterResumed() {
|
||||
mWindMap.getMapAsync(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Async call to googles geocoder web api
|
||||
*/
|
||||
private class GeoCodeTask extends AsyncTask<String, String, JSONObject> {
|
||||
String location = "";
|
||||
|
||||
protected JSONObject doInBackground(String... urls) {
|
||||
location = urls[0];
|
||||
StringBuilder responseBody = new StringBuilder();
|
||||
JSONObject locJSON = null;
|
||||
try {
|
||||
URL website = new URL(getString(R.string.url_google_geocoder) + URLEncoder.encode(location, "UTF-8")
|
||||
+ getString(R.string.urlpart_google_geocoder_sensor));
|
||||
ExLog.i(getActivity(), TAG, website.toString());
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) website.openConnection();
|
||||
BufferedReader in;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
responseBody.append(line);
|
||||
}
|
||||
JSONObject jObject = new JSONObject(responseBody + "");
|
||||
locJSON = jObject.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location");
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ExLog.ex(WindFragment.this.getActivity(), TAG, e);
|
||||
}
|
||||
|
||||
return (locJSON);
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
mContentMapShow.setEnabled(intent.getBooleanExtra(AppConstants.INTENT_ACTION_IS_TRACKING_EXTRA, false));
|
||||
}
|
||||
|
||||
protected void onPostExecute(JSONObject locJSON) {
|
||||
if (locJSON == null) {
|
||||
ExLog.i(getActivity(), TAG, "No Location found for " + location);
|
||||
Toast.makeText(getActivity(), R.string.no_location_found, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ExLog.i(getActivity(), TAG, "Location found for " + location + ": " + locJSON.getDouble("lat") + "," + locJSON.getDouble("lng"));
|
||||
if (mWindMap != null) {
|
||||
mWindMap.centerMap(locJSON.getDouble("lat"), locJSON.getDouble("lng"));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
ExLog.ex(WindFragment.this.getActivity(), TAG, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -12,6 +12,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class TimeUtils {
|
||||
|
||||
@@ -76,6 +77,21 @@ public class TimeUtils {
|
||||
return formatDuration(secondsTillStart, emptyHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats milliseconds to a string like: 01h23'45''
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String formatTimeAgo(long milliseconds) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
calendar.setTimeInMillis(milliseconds);
|
||||
String hours = String.format("%02d", calendar.get(Calendar.HOUR)) + "h";
|
||||
String minutes = String.format("%02d", calendar.get(Calendar.MINUTE)) + "'";
|
||||
String seconds = String.format("%02d", calendar.get(Calendar.SECOND)) + "''";
|
||||
return hours + minutes + seconds;
|
||||
}
|
||||
|
||||
public static String calcDuration(Calendar from, Calendar to) {
|
||||
String retValue;
|
||||
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
package com.sap.sailing.racecommittee.app.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
import com.sap.sailing.android.shared.data.http.HttpGetRequest;
|
||||
import com.sap.sailing.android.shared.util.NetworkHelper;
|
||||
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
|
||||
import com.sap.sailing.racecommittee.app.AppConstants;
|
||||
import com.sap.sailing.racecommittee.app.AppPreferences;
|
||||
import com.sap.sailing.racecommittee.app.data.DataManager;
|
||||
import com.sap.sailing.racecommittee.app.data.DataStore;
|
||||
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
|
||||
import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl;
|
||||
import com.sap.sse.common.Util;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class WindHelper {
|
||||
private static String TAG = WindHelper.class.getName();
|
||||
private final static String GWT_MAP_AND_WIND_CHART_HTML = "gwt/EmbeddedMapAndWindChart.html";
|
||||
|
||||
public static void isTrackedRace(final Context context, final ManagedRace race){
|
||||
try {
|
||||
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(race.getId());
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getBaseUrl(context));
|
||||
builder.append("/sailingserver/api/v1/events/");
|
||||
builder.append(getEventId(context));
|
||||
builder.append("/racestates");
|
||||
builder.append("?filterByLeaderboard=" + triple.getA());
|
||||
|
||||
URL serverUrl = new URL(builder.toString());
|
||||
|
||||
HttpGetRequest request = new HttpGetRequest(serverUrl, context);
|
||||
NetworkHelper.getInstance(context).executeHttpJsonRequestAsnchronously(request, new NetworkHelper.NetworkHelperSuccessListener() {
|
||||
@Override
|
||||
public void performAction(JSONObject response) {
|
||||
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(context);
|
||||
Intent notifyTrackedIntent = new Intent();
|
||||
notifyTrackedIntent.putExtra(AppConstants.INTENT_ACTION_IS_TRACKING_EXTRA, checkResponseForTracking(response, race));
|
||||
notifyTrackedIntent.setAction(AppConstants.INTENT_ACTION_IS_TRACKING);
|
||||
manager.sendBroadcast(notifyTrackedIntent);
|
||||
}
|
||||
}, new NetworkHelper.NetworkHelperFailureListener() {
|
||||
@Override
|
||||
public void performAction(NetworkHelper.NetworkHelperError e) {
|
||||
Log.e(TAG, "Failed to contact server: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (MalformedURLException e){
|
||||
Log.e(TAG, "Failed to generate url for server call: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static String getBaseUrl(Context context){
|
||||
return AppPreferences.on(context).getServerBaseURL();
|
||||
}
|
||||
|
||||
private static String getEventId(Context context){
|
||||
DataStore dataStore = DataManager.create(context).getDataStore();
|
||||
return "" + dataStore.getEventUUID();
|
||||
}
|
||||
|
||||
private static boolean checkResponseForTracking(JSONObject response, ManagedRace race){
|
||||
boolean isTracked = false;
|
||||
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(race.getId());
|
||||
try {
|
||||
JSONArray raceStates = response.getJSONArray("raceStates");
|
||||
for(int index = 0; index < raceStates.length(); index++){
|
||||
JSONObject raceState = raceStates.getJSONObject(index);
|
||||
String leaderboardName = raceState.getString("leaderboardName");
|
||||
String fleetName = raceState.getString("fleetName");
|
||||
String raceName = raceState.getString("raceName");
|
||||
boolean matchingLeaderboardName = leaderboardName != null && leaderboardName.equals(triple.getA());
|
||||
boolean matchingFleetName = fleetName != null && fleetName.equals(triple.getC());
|
||||
boolean matchingRaceName = raceName != null && raceName.equals(race.getRaceName());
|
||||
if (matchingLeaderboardName && matchingFleetName && matchingRaceName){
|
||||
String trackedRaceId = raceState.getString("trackedRaceId");
|
||||
if (trackedRaceId != null){
|
||||
isTracked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Failed to parse contents of the server response: " + e.getMessage());
|
||||
}
|
||||
return isTracked;
|
||||
}
|
||||
|
||||
public static String generateMapURL(Context context, ManagedRace race ,boolean showWindCharts, boolean showStreamlets, boolean showSimulation, boolean showMapControls){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// get simple race log identifier
|
||||
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(race.getId());
|
||||
SimpleRaceLogIdentifier identifier = new SimpleRaceLogIdentifierImpl(triple.getA(), triple.getB(), triple.getC());
|
||||
|
||||
builder.append(getBaseUrl(context));
|
||||
builder.append(GWT_MAP_AND_WIND_CHART_HTML);
|
||||
builder.append("?regattaLikeName=" + identifier.getRegattaLikeParentName());
|
||||
builder.append("&raceColumnName=" + identifier.getRaceColumnName());
|
||||
builder.append("&fleetName=" + identifier.getFleetName());
|
||||
builder.append("&eventId=" + getEventId(context));
|
||||
builder.append("&viewShowWindChart=" + showWindCharts);
|
||||
builder.append("&viewShowStreamlets=" + showStreamlets);
|
||||
builder.append("&viewShowSimulation=" + showSimulation);
|
||||
builder.append("&viewShowMapControls=" + showMapControls);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user