Get mark from server

This commit is contained in:
Bennet Brunsen
2016-07-05 15:02:39 +02:00
parent 3e15a023b6
commit 5674a1538f
7 changed files with 190 additions and 80 deletions
@@ -8,4 +8,5 @@
<string name="preference_server_competitor_path" translatable="false">/sailingserver/api/v1/competitors/{competitor_id}</string>
<string name="preference_server_team_info_path" translatable="false">/sailingserver/api/v1/competitors/{competitor_id}/team</string>
<string name="preference_server_team_image_upload_path" translatable="false">/sailingserver/api/v1/competitors/{competitor_id}/team/image</string>
<string name="preferece_server_mark_path" translatable="false">/sailingserver/api/v1/leaderboards/{leaderboardName}/marks/{markId}</string>
</resources>
@@ -4,7 +4,6 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import android.widget.AdapterView;
import org.json.JSONException;
import org.json.JSONObject;
@@ -21,8 +20,9 @@ import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.Toast;
@@ -46,6 +46,7 @@ import com.sap.sailing.android.tracking.app.utils.DatabaseHelper;
import com.sap.sailing.android.tracking.app.utils.DatabaseHelper.GeneralDatabaseHelperException;
import com.sap.sailing.android.tracking.app.valueobjects.CheckinData;
import com.sap.sailing.android.tracking.app.valueobjects.CompetitorCheckinData;
import com.sap.sailing.android.tracking.app.valueobjects.MarkCheckinData;
import com.sap.sailing.android.ui.fragments.AbstractHomeFragment;
public class HomeFragment extends AbstractHomeFragment implements LoaderCallbacks<Cursor> {
@@ -87,18 +88,18 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
/**
* Perform a checkin request and launch RegattaAcitivity afterwards
* <p/>
* TODO: Google Cloud Messaging token?
*
* @param deviceMappingData
*/
private void checkInWithAPIAndDisplayTrackingActivity(CompetitorCheckinData checkinData) {
if (DatabaseHelper.getInstance().eventLeaderboardCompetitorCombinationAvailable(getActivity(),
checkinData.checkinDigest)) {
private void checkInWithAPIAndDisplayTrackingActivity(CheckinData checkinData) {
if (DatabaseHelper.getInstance().eventLeaderboardCompetitorCombinationAvailable(getActivity(), checkinData.checkinDigest)) {
try {
DatabaseHelper.getInstance().storeCheckinRow(getActivity(), checkinData.getEvent(),
checkinData.getCompetitor(), checkinData.getLeaderboard(), checkinData.getCheckinUrl());
if (checkinData instanceof CompetitorCheckinData) {
CompetitorCheckinData competitorCheckinData = (CompetitorCheckinData) checkinData;
DatabaseHelper.getInstance()
.storeCheckinRow(getActivity(), competitorCheckinData.getEvent(), competitorCheckinData.getCompetitor(),
competitorCheckinData.getLeaderboard(), competitorCheckinData.getCheckinUrl());
} else if (checkinData instanceof MarkCheckinData) {
// TODO: handle database for mark
}
adapter.notifyDataSetChanged();
} catch (GeneralDatabaseHelperException e) {
ExLog.e(getActivity(), TAG, "Batch insert failed: " + e.getMessage());
@@ -111,8 +112,7 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
}
} else {
ExLog.w(getActivity(), TAG, "Combination of eventId, leaderboardName and competitorId already exists!");
Toast.makeText(getActivity(), getString(R.string.info_already_checked_in_this_qr_code), Toast.LENGTH_LONG)
.show();
Toast.makeText(getActivity(), getString(R.string.info_already_checked_in_this_qr_code), Toast.LENGTH_LONG).show();
}
performAPICheckin(checkinData);
}
@@ -123,26 +123,30 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
* @param checkinData
*/
private void performAPICheckin(CheckinData checkinData) {
if (checkinData instanceof CompetitorCheckinData) {
CompetitorCheckinData competitorCheckinData = (CompetitorCheckinData) checkinData;
Date date = new Date();
StartActivity startActivity = (StartActivity) getActivity();
startActivity.showProgressDialog(R.string.please_wait, R.string.checking_in);
try {
JSONObject requestObject = CheckinHelper.getCheckinJson(competitorCheckinData.competitorId, competitorCheckinData.deviceUid,
"TODO push device ID!!", date.getTime());
HttpJsonPostRequest request = new HttpJsonPostRequest(getActivity(), new URL(competitorCheckinData.checkinURL),
requestObject.toString());
NetworkHelper.getInstance(getActivity())
.executeHttpJsonRequestAsync(request, new CheckinListener(competitorCheckinData.checkinDigest),
new CheckinErrorListener(competitorCheckinData.checkinDigest));
} catch (JSONException e) {
ExLog.e(getActivity(), TAG, "Failed to generate checkin JSON: " + e.getMessage());
displayAPIErrorRecommendRetry();
} catch (MalformedURLException e) {
ExLog.e(getActivity(), TAG, "Failed to perform checkin, MalformedURLException: " + e.getMessage());
displayAPIErrorRecommendRetry();
Date date = new Date();
StartActivity startActivity = (StartActivity) getActivity();
startActivity.showProgressDialog(R.string.please_wait, R.string.checking_in);
try {
JSONObject requestObject = null;
if (checkinData instanceof CompetitorCheckinData) {
CompetitorCheckinData competitorCheckinData = (CompetitorCheckinData) checkinData;
requestObject = CheckinHelper
.getCompetitorCheckinJson(competitorCheckinData.competitorId, competitorCheckinData.deviceUid, "TODO push device ID!!", date
.getTime());
} else if (checkinData instanceof MarkCheckinData) {
MarkCheckinData markCheckinData = (MarkCheckinData) checkinData;
requestObject = CheckinHelper
.getMarkCheckinJson(markCheckinData.getMark().getId().toString(), markCheckinData.deviceUid, "TODO push device ID!!", date.getTime());
}
HttpJsonPostRequest request = new HttpJsonPostRequest(getActivity(), new URL(checkinData.checkinURL), requestObject.toString());
NetworkHelper.getInstance(getActivity())
.executeHttpJsonRequestAsync(request, new CheckinListener(checkinData.checkinDigest), new CheckinErrorListener(checkinData.checkinDigest));
} catch (JSONException e) {
ExLog.e(getActivity(), TAG, "Failed to generate checkin JSON: " + e.getMessage());
displayAPIErrorRecommendRetry();
} catch (MalformedURLException e) {
ExLog.e(getActivity(), TAG, "Failed to perform checkin, MalformedURLException: " + e.getMessage());
displayAPIErrorRecommendRetry();
}
}
@@ -155,17 +159,13 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
/**
* Display a confirmation-dialog in which the user confirms his full name and sail-id.
*
* @param checkinData
*/
@Override
public void displayUserConfirmationScreen(final BaseCheckinData data) {
if (data instanceof CompetitorCheckinData) {
CompetitorCheckinData checkinData = (CompetitorCheckinData) data;
String message1 = getString(R.string.confirm_data_hello_name)
.replace("{full_name}", checkinData.competitorName);
String message2 = getString(R.string.confirm_data_you_are_signed_in_as_sail_id).replace("{sail_id}",
checkinData.competitorSailId);
final CompetitorCheckinData checkinData = (CompetitorCheckinData) data;
String message1 = getString(R.string.confirm_data_hello_name).replace("{full_name}", checkinData.competitorName);
String message2 = getString(R.string.confirm_data_you_are_signed_in_as_sail_id).replace("{sail_id}", checkinData.competitorSailId);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(message1 + "\n\n" + message2);
@@ -174,7 +174,7 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
@Override
public void onClick(DialogInterface dialog, int which) {
clearScannedQRCodeInPrefs();
checkInWithAPIAndDisplayTrackingActivity((CompetitorCheckinData) data);
checkInWithAPIAndDisplayTrackingActivity(checkinData);
}
}).setNegativeButton(R.string.decline_data_is_incorrect, new DialogInterface.OnClickListener() {
@Override
@@ -185,6 +185,10 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
});
AlertDialog alert = builder.create();
alert.show();
} else if (data instanceof MarkCheckinData) {
MarkCheckinData checkinData = (MarkCheckinData) data;
clearScannedQRCodeInPrefs();
checkInWithAPIAndDisplayTrackingActivity(checkinData);
}
}
@@ -202,48 +206,47 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
switch (loaderId) {
case REGATTA_LOADER:
String[] projection = new String[] { AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_CHECKIN_DIGEST,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event._ID,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_NAME,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_SERVER,
AnalyticsContract.PATH_LEADERBOARD + "." + AnalyticsContract.Leaderboard.LEADERBOARD_NAME};
return new CursorLoader(getActivity(), AnalyticsContract.EventLeaderboardCompetitorJoined.CONTENT_URI,
projection, null, null, null);
case REGATTA_LOADER:
String[] projection = new String[] { AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_CHECKIN_DIGEST,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event._ID,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_NAME,
AnalyticsContract.PATH_EVENT + "." + AnalyticsContract.Event.EVENT_SERVER,
AnalyticsContract.PATH_LEADERBOARD + "." + AnalyticsContract.Leaderboard.LEADERBOARD_NAME };
return new CursorLoader(getActivity(), AnalyticsContract.EventLeaderboardCompetitorJoined.CONTENT_URI, projection, null, null, null);
default:
return null;
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
case REGATTA_LOADER:
adapter.changeCursor(cursor);
break;
case REGATTA_LOADER:
adapter.changeCursor(cursor);
break;
default:
break;
default:
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case REGATTA_LOADER:
adapter.changeCursor(null);
break;
case REGATTA_LOADER:
adapter.changeCursor(null);
break;
default:
break;
default:
break;
}
}
private boolean showDeleteConfirmationDialog(int position) {
// -1, because there's a header row
Cursor cursor = (Cursor) adapter.getItem(position - 1);
final String checkinDigest = cursor.getString(cursor.getColumnIndex("event_checkin_digest"));
final String checkinDigest = cursor.getString(cursor.getColumnIndex(AnalyticsContract.Event.EVENT_CHECKIN_DIGEST));
DatabaseHelper.getInstance().getEventInfo(getActivity(), checkinDigest);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.Base_Theme_AppCompat_Dialog_Alert);
builder.setMessage(getString(R.string.confirm_delete_checkin));
@@ -309,6 +312,7 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
public void performAction(JSONObject response) {
StartActivity startActivity = (StartActivity) getActivity();
startActivity.dismissProgressDialog();
// TODO: Start MarkActivity
startRegatta(checkinDigest);
}
}
@@ -331,12 +335,10 @@ public class HomeFragment extends AbstractHomeFragment implements LoaderCallback
StartActivity startActivity = (StartActivity) getActivity();
startActivity.dismissProgressDialog();
startActivity.showErrorPopup(R.string.error,
R.string.error_could_not_complete_operation_on_server_try_again);
startActivity.showErrorPopup(R.string.error, R.string.error_could_not_complete_operation_on_server_try_again);
DatabaseHelper.getInstance().deleteRegattaFromDatabase(getActivity(), checkinDigest);
Toast.makeText(getActivity(), getString(R.string.error_while_receiving_server_data), Toast.LENGTH_LONG)
.show();
Toast.makeText(getActivity(), getString(R.string.error_while_receiving_server_data), Toast.LENGTH_LONG).show();
}
}
@@ -1,15 +1,14 @@
package com.sap.sailing.android.tracking.app.utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.sap.sailing.android.shared.util.PrefUtils;
import com.sap.sailing.android.tracking.app.R;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import android.content.Context;
import android.content.SharedPreferences;
import com.sap.sailing.android.shared.util.BaseAppPreferences;
import com.sap.sailing.android.shared.util.PrefUtils;
import com.sap.sailing.android.tracking.app.R;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
@@ -68,6 +67,11 @@ public class AppPreferences extends BaseAppPreferences {
competitorId);
}
public String getServerMarkPath(String leaderboardName, String markId) {
String path = context.getString(R.string.preferece_server_mark_path);
return path.replace("{leaderboard_name}", leaderboardName).replace("{markId}", markId);
}
public int getGPSFixInterval() {
// EditTextPreference saves value as string, even if android:inputType="number" is set
String value = PrefUtils.getString(context, R.string.preference_gps_fix_interval_ms_key,
@@ -3,18 +3,32 @@ package com.sap.sailing.android.tracking.app.utils;
import org.json.JSONException;
import org.json.JSONObject;
import android.support.annotation.NonNull;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
public class CheckinHelper {
public static JSONObject getCheckinJson(String competitorId, String deviceUuid, String pushDeviceId, long fromMillis)
public static JSONObject getCompetitorCheckinJson(String competitorId, String deviceUuid, String pushDeviceId, long fromMillis)
throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put(DeviceMappingConstants.JSON_COMPETITOR_ID_AS_STRING, competitorId);
// TODO alternatively map device to a mark, providing a mark_id; see also LeaderboardsResource.postCheckin
return getBaseCheckinJsom(deviceUuid, pushDeviceId, fromMillis, jsonObject);
}
@NonNull
private static JSONObject getBaseCheckinJsom(String deviceUuid, String pushDeviceId, long fromMillis, JSONObject jsonObject)
throws JSONException {
jsonObject.put(DeviceMappingConstants.JSON_DEVICE_TYPE, "android");
jsonObject.put(DeviceMappingConstants.JSON_DEVICE_UUID, deviceUuid);
jsonObject.put(DeviceMappingConstants.JSON_PUSH_DEVICE_ID, pushDeviceId);
jsonObject.put(DeviceMappingConstants.JSON_FROM_MILLIS, fromMillis);
return jsonObject;
}
public static JSONObject getMarkCheckinJson(String markId, String deviceUuid, String pushDeviceId, long fromMillis)
throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put(DeviceMappingConstants.JSON_MARK_ID_AS_STRING, markId);
return getBaseCheckinJsom(deviceUuid, pushDeviceId, fromMillis, jsonObject);
}
}
@@ -22,6 +22,7 @@ import com.sap.sailing.android.shared.data.BaseCheckinData;
import com.sap.sailing.android.shared.data.http.HttpGetRequest;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.android.shared.ui.activities.CheckinDataActivity;
import com.sap.sailing.android.shared.util.JsonHelper;
import com.sap.sailing.android.shared.util.NetworkHelper;
import com.sap.sailing.android.shared.util.UniqueDeviceUuid;
import com.sap.sailing.android.tracking.app.R;
@@ -35,11 +36,13 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
import com.sap.sailing.domain.base.EventBase;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl;
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants;
import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer;
@@ -99,10 +102,14 @@ public class CheckinManager {
competitorUrlData.competitorId = uri.getQueryParameter(DeviceMappingConstants.URL_COMPETITOR_ID_AS_STRING);
competitorUrlData.competitorUrl = competitorUrlData.hostWithPort + prefs.getServerCompetitorPath(competitorUrlData.competitorId);
urlData = competitorUrlData;
} else {
// TODO alternatively consider a mark_id
} else if (parameterNames.contains(DeviceMappingConstants.URL_MARK_ID_AS_STRING)) {
MarkUrlData markUrlData = new MarkUrlData(server, port);
markUrlData.setMarkId(uri.getQueryParameter(DeviceMappingConstants.URL_MARK_ID_AS_STRING));
markUrlData.setMarkUrl(markUrlData.hostWithPort + prefs.getServerMarkPath(leaderboardNameFromQR, markUrlData.getMarkId()));
urlData = markUrlData;
} else {
ExLog.e(activity, TAG, "Neither mark nor competitor checkin");
exception = new Exception();
}
urlData.uriStr = uri.toString();
urlData.checkinURLStr = urlData.hostWithPort + prefs.getServerCheckinPath().replace("{leaderboard-name}", leaderboardNameFromQR);
@@ -193,16 +200,25 @@ public class CheckinManager {
}
if (urlData instanceof CompetitorUrlData) {
CompetitorUrlData competitorUrlData = (CompetitorUrlData) urlData;
HttpGetRequest getCompetitorRequest;
try {
getCompetitorRequest = new HttpGetRequest(new URL(competitorUrlData.competitorUrl), activity);
HttpGetRequest getCompetitorRequest = new HttpGetRequest(new URL(competitorUrlData.competitorUrl), activity);
getCompetitorFromServer(getCompetitorRequest, competitorUrlData);
} catch (MalformedURLException e2) {
ExLog.e(activity, TAG, "Error: Failed to perform checking due to a MalformedURLException: " + e2.getMessage());
handleApiError();
}
} else if (urlData instanceof MarkUrlData) {
MarkUrlData markUrlData = (MarkUrlData) urlData;
try {
HttpGetRequest getMarkRequest = new HttpGetRequest(new URL(markUrlData.getMarkUrl()), activity);
getMarkFromServer(getMarkRequest, markUrlData);
} catch (MalformedURLException exception) {
ExLog.e(activity, TAG, "Error: Failed to perform checking due to a MalformedURLException: " + exception.getMessage());
handleApiError();
}
}
}
}, new NetworkHelper.NetworkHelperFailureListener() {
@@ -243,12 +259,44 @@ public class CheckinManager {
});
}
private void getMarkFromServer(HttpGetRequest getMarkRequest, final MarkUrlData urlData) {
NetworkHelper.getInstance(activity)
.executeHttpJsonRequestAsync(getMarkRequest, new NetworkHelper.NetworkHelperSuccessListener() {
@Override
public void performAction(JSONObject response) {
try {
org.json.simple.JSONObject simpleMark;
simpleMark = JsonHelper.convertToSimple(response);
MarkDeserializer markDeserializer = new MarkDeserializer(new SharedDomainFactoryImpl(null));
Mark mark = markDeserializer.deserialize(simpleMark);
urlData.setMark(mark);
} catch (ParseException|JsonDeserializationException e) {
ExLog.e(activity, TAG, "Failed to deserialize mark");
if (activity != null) {
activity.dismissProgressDialog();
displayAPIErrorRecommendRetry();
}
return;
}
saveCheckinDataAndNotifyListeners(urlData);
}
}, new NetworkHelper.NetworkHelperFailureListener() {
@Override
public void performAction(NetworkHelper.NetworkHelperError e) {
ExLog.e(activity, TAG, "Failed to get mark from server: " + e.getMessage());
if (activity != null) {
activity.dismissProgressDialog();
displayAPIErrorRecommendRetry();
}
}
});
}
private void saveCheckinDataAndNotifyListeners(UrlData urlData) {
CheckinData data;
if (urlData instanceof CompetitorUrlData) {
CompetitorUrlData competitorUrlData = (CompetitorUrlData) urlData;
CompetitorCheckinData competitorCheckinData = new CompetitorCheckinData(competitorUrlData);
data = competitorCheckinData;
data = new CompetitorCheckinData(competitorUrlData);
} else {
MarkUrlData markUrlData = (MarkUrlData) urlData;
data = new MarkCheckinData(markUrlData);
@@ -1,8 +1,17 @@
package com.sap.sailing.android.tracking.app.valueobjects;
import com.sap.sailing.domain.base.Mark;
public class MarkCheckinData extends CheckinData {
public Mark mark;
public MarkCheckinData(MarkUrlData markUrlData) {
super(markUrlData);
mark = markUrlData.getMark();
}
public Mark getMark() {
return mark;
}
}
@@ -1,8 +1,40 @@
package com.sap.sailing.android.tracking.app.valueobjects;
import com.sap.sailing.domain.base.Mark;
public class MarkUrlData extends UrlData {
private String markId;
private String markUrl;
private Mark mark;
public MarkUrlData(String server, int port) {
super(server, port);
}
public String getMarkId() {
return markId;
}
public void setMarkId(String markId) {
this.markId = markId;
}
public String getMarkUrl() {
return markUrl;
}
public void setMarkUrl(String markUrl) {
this.markUrl = markUrl;
}
public Mark getMark() {
return mark;
}
public void setMark(Mark mark) {
this.mark = mark;
}
}