TRACKING APP: Fix bug in transmitting GPSFixes to API, report GPS accurracy to user

This commit is contained in:
Lukas Zielinski committed 2014-11-20 18:00:11 +01:00
1 parent b493f2f642
commit 0b247ae11c
6 files changed
+211 -44

No files matched your search

@@ -68,7 +68,7 @@
android:contentDescription="@string/signal_quality_indicator_view_description"
android:focusable="true"
android:paddingRight="20dp"
app:signalQuality="good" />
app:signalQuality="none" />
<TextView
android:id="@+id/qps_quality"
@@ -18,6 +18,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -47,6 +48,9 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
private boolean locationUpdateRequested = false;
private AppPreferences prefs;
private ScheduledExecutorService scheduler;
private GPSQualityListener gpsQualityListener;
private final IBinder trackingBinder = new TrackingBinder();
private static final String TAG = TrackingService.class.getName();
@@ -124,11 +128,39 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
public void onDisconnected() {
ExLog.i(this, TAG, "LocationClient was disconnected");
}
public void reportGPSQuality( float gpsAccurracy )
{
GPSQuality quality = GPSQuality.noSignal;
if (gpsQualityListener != null)
{
if (gpsAccurracy > 163)
{
quality = GPSQuality.poor;
}
else if (gpsAccurracy > 48)
{
quality = GPSQuality.good;
}
else if (gpsAccurracy < 48)
{
quality = GPSQuality.great;
}
gpsQualityListener.gpsQualityUpdated(quality);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onLocationChanged(Location location) {
reportGPSQuality(location.getAccuracy());
JSONObject json = new JSONObject();
try {
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.DEVICE_UUID,
prefs.getDeviceIdentifier());
@@ -193,7 +225,7 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
@Override
public IBinder onBind(Intent intent) {
return null;
return trackingBinder;
}
@Override
@@ -213,4 +245,45 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(NOTIFICATION_ID, notification);
}
public void registerGPSQualityListener( GPSQualityListener listener )
{
gpsQualityListener = listener;
}
public void unregisterGPSQualityListener()
{
gpsQualityListener = null;
}
public class TrackingBinder extends Binder {
public TrackingService getService() {
return TrackingService.this;
}
}
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 {
public void gpsQualityUpdated( GPSQuality quality );
}
}
@@ -279,7 +279,6 @@ public class TransmittingService extends Service {
sendingAttempted = true;
VolleyHelper.getInstance(this).addRequest(
new JsonObjectRequest(prefs.getServerURL()
+ prefs.getServerGpsFixesPostPath(), requestObject,
@@ -1,32 +1,38 @@
package com.sap.sailing.android.tracking.app.ui.activities;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.os.IBinder;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import com.sap.sailing.android.tracking.app.R;
import com.sap.sailing.android.tracking.app.services.TrackingService;
import com.sap.sailing.android.tracking.app.ui.fragments.HomeFragment;
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.TrackingFragment;
public class TrackingActivity extends BaseActivity {
public class TrackingActivity extends BaseActivity implements GPSQualityListener {
TrackingService trackingService;
boolean trackingServiceBound;
private final static String TAG = TrackingActivity.class.getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Intent intent = getIntent();
setContentView(R.layout.fragment_container);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
@@ -42,6 +48,30 @@ public class TrackingActivity extends BaseActivity {
startTrackingService();
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, TrackingService.class);
bindService(intent, trackingServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (trackingServiceBound) {
trackingService.unregisterGPSQualityListener();
unbindService(trackingServiceConnection);
trackingServiceBound = false;
}
}
@Override
public void gpsQualityUpdated(GPSQuality quality) {
TrackingFragment trackingFragment = (TrackingFragment) getSupportFragmentManager()
.findFragmentById(R.id.content_frame);
trackingFragment.setGPSQuality(quality);
}
private void startTrackingService()
{
Intent intent = new Intent(this, TrackingService.class);
@@ -49,6 +79,7 @@ public class TrackingActivity extends BaseActivity {
startService(intent);
}
@Override
public void onBackPressed() {
TrackingFragment trackingFragment = (TrackingFragment) getSupportFragmentManager()
@@ -56,4 +87,23 @@ public class TrackingActivity extends BaseActivity {
trackingFragment.userTappedBackButton();
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection trackingServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
TrackingBinder binder = (TrackingBinder) service;
trackingService = binder.getService();
trackingServiceBound = true;
trackingService.registerGPSQualityListener(TrackingActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
trackingServiceBound = false;
}
};
}
@@ -160,8 +160,9 @@ public class HomeFragment extends BaseFragment implements
final String server = scheme + "://" + uri.getHost();
final int port = (uri.getPort() == -1) ? 80 : uri.getPort();
final String hostWithPort = server + ":" + port;
prefs.setServerURL(server + ":" + port);
prefs.setServerURL(hostWithPort);
String leaderboardNameFromQR;
try {
@@ -174,13 +175,9 @@ public class HomeFragment extends BaseFragment implements
leaderboardNameFromQR = "";
}
final String competitorId = uri
.getQueryParameter(CheckinHelper.COMPETITOR_ID);
final String checkinURLStr = prefs.getServerURL()
+ prefs.getServerCheckinPath().replace(
"{leaderboard-name}", leaderboardNameFromQR);
final String eventId = uri
.getQueryParameter(CheckinHelper.EVENT_ID);
final String competitorId = uri.getQueryParameter(CheckinHelper.COMPETITOR_ID);
final String checkinURLStr = prefs.getServerURL() + prefs.getServerCheckinPath().replace("{leaderboard-name}", leaderboardNameFromQR);
final String eventId = uri.getQueryParameter(CheckinHelper.EVENT_ID);
final String leaderboardName = leaderboardNameFromQR;
final DeviceIdentifier deviceUuid = new SmartphoneUUIDIdentifierImpl(
@@ -193,12 +190,9 @@ public class HomeFragment extends BaseFragment implements
// 4. Let user confirm that the information is correct
// 5. Checkin
final String getEventUrl = prefs.getServerURL()
+ prefs.getServerEventPath(eventId);
final String getLeaderboardUrl = prefs.getServerURL()
+ prefs.getServerLeaderboardPath(leaderboardName);
final String getCompetitorUrl = prefs.getServerURL()
+ prefs.getServerCompetitorPath(competitorId);
final String getEventUrl = prefs.getServerURL() + prefs.getServerEventPath(eventId);
final String getLeaderboardUrl = prefs.getServerURL() + prefs.getServerLeaderboardPath(leaderboardName);
final String getCompetitorUrl = prefs.getServerURL() + prefs.getServerCompetitorPath(competitorId);
JsonObjectRequest getLeaderboardRequest = new JsonObjectRequest(
getLeaderboardUrl, null, new Listener<JSONObject>() {
@@ -303,7 +297,8 @@ public class HomeFragment extends BaseFragment implements
data.eventStartDateStr = eventStartDateStr;
data.eventEndDateStr = eventEndDateStr;
data.eventFirstImageUrl = eventFirstImageUrl;
data.eventServerUrl = checkinURLStr;
data.eventServerUrl = hostWithPort;
data.checkinURL = checkinURLStr;
data.leaderboardName = leaderboardName;
data.deviceUid = deviceUuid
.getStringRepresentation();
@@ -534,9 +529,9 @@ public class HomeFragment extends BaseFragment implements
JSONObject requestObject = CheckinHelper.getCheckinJson(
checkinData.competitorId, checkinData.deviceUid, "TODO!!",
date.getTime());
JsonObjectRequest checkinRequest = new JsonObjectRequest(
checkinData.eventServerUrl, requestObject,
checkinData.checkinURL, requestObject,
new CheckinListener(checkinData.leaderboardName),
new CheckinErrorListener());
@@ -654,6 +649,7 @@ public class HomeFragment extends BaseFragment implements
public String eventEndDateStr;
public String eventFirstImageUrl;
public String eventServerUrl;
public String checkinURL;
public String competitorDisplayName;
public String competitorId;
public String competitorSailId;
@@ -687,23 +683,14 @@ public class HomeFragment extends BaseFragment implements
Cursor cursor = (Cursor) mAdapter.getItem(position - 1); // -1, because there's a header row
prefs.setServerURL(cursor.getString(cursor
.getColumnIndex(Event.EVENT_SERVER)));
prefs.setServerURL(cursor.getString(cursor.getColumnIndex(Event.EVENT_SERVER)));
String competitorId = cursor.getString(cursor.getColumnIndex("competitor_id"));
String eventServer = cursor.getString(cursor.getColumnIndex("event_server"));
// String competitorId = cursor.getString(cursor.getColumnIndex("competitor_id"));
// String eventServer = cursor.getString(cursor.getColumnIndex("event_server"));
String leaderboardName = cursor.getString(cursor.getColumnIndex("leaderboard_name"));
CheckinData data = new CheckinData();
data.competitorId = competitorId;
data.deviceUid = new SmartphoneUUIDIdentifierImpl(
UUID.fromString(prefs.getDeviceIdentifier()))
.getStringRepresentation();
data.eventServerUrl = eventServer;
data.leaderboardName = leaderboardName;
performAPICheckin(data);
startRegatta(leaderboardName, leaderboardName);
}
}
@@ -1,25 +1,38 @@
package com.sap.sailing.android.tracking.app.ui.fragments;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import com.sap.sailing.android.shared.logging.ExLog;
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.utils.AppPreferences;
import com.sap.sailing.android.tracking.app.views.AutoResizeTextView;
import com.sap.sailing.android.tracking.app.views.SignalQualityIndicatorView;
public class TrackingFragment extends BaseFragment implements OnClickListener {
private TimerRunnable timer;
private AppPreferences prefs;
private long lastGPSQualityUpdate;
private String TAG = TrackingFragment.class.getName();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -77,6 +90,42 @@ public class TrackingFragment extends BaseFragment implements OnClickListener {
textView.setText(getTimeFormatString(diff));
}
/**
* 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.");
}
setGPSQuality(GPSQuality.noSignal);
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@SuppressWarnings("deprecation")
private boolean isLocationEnabled(Context context) {
int locationMode = 0;
String locationProviders;
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();
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
public void userTappedBackButton()
{
showStopTrackingConfirmationDialog();
@@ -114,6 +163,14 @@ public class TrackingFragment extends BaseFragment implements OnClickListener {
return String.format(getResources().getConfiguration().locale, "%02d:%02d:%02d", hours, minutes, seconds);
}
public void setGPSQuality( GPSQuality quality )
{
SignalQualityIndicatorView indicatorView = (SignalQualityIndicatorView) getActivity().findViewById(R.id.qps_quality_indicator);
indicatorView.setSignalQuality( quality.toInt() );
lastGPSQualityUpdate = System.currentTimeMillis();
}
private class TimerRunnable implements Runnable {
public Thread t;
@@ -132,6 +189,7 @@ public class TrackingFragment extends BaseFragment implements OnClickListener {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
checkLastGPSReceived();
updateTimer();
}
});