mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 05:05:31 +00:00
Merge branch 'android_apps_tracking' into android_apps
This commit is contained in:
+5
@@ -44,4 +44,9 @@ public class HttpJsonPostRequest extends HttpRequest {
|
||||
outputStream.write(requestBody.getBytes(Charset.forName("UTF-8")));
|
||||
}
|
||||
}
|
||||
|
||||
public String getRequestBody()
|
||||
{
|
||||
return requestBody;
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -53,6 +53,15 @@ public abstract class HttpRequest {
|
||||
this.isCancelled = false;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public String getUrlAsString()
|
||||
{
|
||||
if (url != null)
|
||||
{
|
||||
return url.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return isCancelled;
|
||||
|
||||
+8
-21
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@@ -12,8 +12,6 @@ import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.utils.ServiceHelper;
|
||||
|
||||
/**
|
||||
* Informs {@link MessageSendingService} whenever connectivity is restored, so that it can start sending
|
||||
@@ -21,7 +19,7 @@ import com.sap.sailing.android.tracking.app.utils.ServiceHelper;
|
||||
*
|
||||
* Register in manifest:
|
||||
* <pre>{@code
|
||||
* <receiver android:name="com.sap.sailing.android.tracking.app.services.sending.ConnectivityChangedReceiver" >
|
||||
* <receiver android:name="com.sap.sailing.android.shared.services.sending.ConnectivityChangedReceiver" >
|
||||
* <intent-filter>
|
||||
* <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
* </intent-filter>
|
||||
@@ -31,29 +29,17 @@ import com.sap.sailing.android.tracking.app.utils.ServiceHelper;
|
||||
public class ConnectivityChangedReceiver extends BroadcastReceiver {
|
||||
|
||||
private final static String TAG = ConnectivityChangedReceiver.class.getName();
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
final NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
|
||||
NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||
if (!networkInfo.isConnected())
|
||||
return;
|
||||
context.startService(MessageSendingService.createSendDelayedIntent(context));
|
||||
|
||||
if (networkInfo == null)
|
||||
{
|
||||
return; // was null when restarted router..
|
||||
}
|
||||
|
||||
if (!networkInfo.isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(context, TAG, "Starting TransmittingService");
|
||||
}
|
||||
|
||||
ServiceHelper.getInstance().startTransmittingService(context);
|
||||
disable(context);
|
||||
}
|
||||
|
||||
@@ -78,4 +64,5 @@ public class ConnectivityChangedReceiver extends BroadcastReceiver {
|
||||
packageManager.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
|
||||
ExLog.w(context, TAG, "Connectivity lost. ConnectivityChangedReceiver enabled");
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -14,7 +14,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract;
|
||||
import com.sap.sailing.android.shared.util.FileHandlerUtils;
|
||||
|
||||
public class MessagePersistenceManager {
|
||||
+1
-2
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -68,5 +68,4 @@ public class MessageSenderTask extends AsyncTask<Intent, Void, Util.Triple<Inten
|
||||
super.onPostExecute(resultTriple);
|
||||
listener.onMessageSent(resultTriple.getA(), resultTriple.getB(), resultTriple.getC());
|
||||
}
|
||||
|
||||
}
|
||||
+107
-24
@@ -1,7 +1,8 @@
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@@ -24,9 +25,9 @@ import android.os.IBinder;
|
||||
|
||||
import com.sap.sailing.android.shared.R;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.services.sending.MessagePersistenceManager.MessageRestorer;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSenderTask.MessageSendingListener;
|
||||
import com.sap.sailing.android.shared.util.PrefUtils;
|
||||
import com.sap.sailing.android.tracking.app.services.sending.MessagePersistenceManager.MessageRestorer;
|
||||
import com.sap.sailing.android.tracking.app.services.sending.MessageSenderTask.MessageSendingListener;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||
|
||||
/**
|
||||
@@ -34,17 +35,16 @@ import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||
* by buffering the messages in a file, so that they can be sent when the connection is
|
||||
* re-established.<br>
|
||||
*
|
||||
* <b>Use in the following way:</b> Add the service declaration to your {@code AndroidManifest.xml}, and also specify
|
||||
* your class implementing the {@link MessagePersistenceManager.MessageRestorer} as a meta-data tag with the key
|
||||
* {@code com.sap.sailing.android.tracking.app..services.sending.messageRestorer}. Also refer to
|
||||
* {@link ConnectivityChangedReceiver}, which has to be registered as well. For example:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* <b>Use in the following way:</b> Add the service declaration to your {@code AndroidManifest.xml},
|
||||
* and also specify your class implementing the {@link MessagePersistenceManager.MessageRestorer}
|
||||
* as a meta-data tag with the key {@code com.sap.sailing.android.shared.services.sending.messageRestorer}.
|
||||
* Also refer to {@link ConnectivityChangedReceiver}, which has to be registered as well.
|
||||
* For example:
|
||||
* <pre>{@code
|
||||
* <service
|
||||
* android:name="com.sap.sailing.android.tracking.app.services.sending.MessageSendingService"
|
||||
* android:name="com.sap.sailing.android.shared.services.sending.MessageSendingService"
|
||||
* android:exported="false" >
|
||||
* <meta-data android:name="com.sap.sailing.android.tracking.app.services.sending.messageRestorer"
|
||||
* <meta-data android:name="com.sap.sailing.android.shared.services.sending.messageRestorer"
|
||||
* android:value="com.sap.sailing.racecommittee.app.services.sending.EventRestorer" />
|
||||
* </service>
|
||||
* }</pre>
|
||||
@@ -55,8 +55,6 @@ import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||
* context.startService(MessageSendingService.createMessageIntent(
|
||||
* context, url, race.getId(), eventId, serializedEventAsJson, callbackClass));
|
||||
* }</pre>
|
||||
*
|
||||
* NOTE: Started using TransmittingService.java, perhaps this class can be dismissed? -LZ
|
||||
*/
|
||||
public class MessageSendingService extends Service implements MessageSendingListener {
|
||||
public final static String URL = "url";
|
||||
@@ -75,6 +73,8 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
|
||||
private Set<Serializable> suppressedMessageIds = new HashSet<Serializable>();
|
||||
|
||||
private APIConnectivityListener apiConnectivityListener;
|
||||
|
||||
public void registerMessageForSuppression(Serializable messageId) {
|
||||
suppressedMessageIds.add(messageId);
|
||||
}
|
||||
@@ -130,7 +130,8 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
serviceLogger.onMessageSentSuccessful();
|
||||
}
|
||||
|
||||
public static Intent createMessageIntent(Context context, String url, Serializable callbackPayload, Serializable messageId, String payload,
|
||||
public static Intent createMessageIntent(Context context, String url,
|
||||
Serializable callbackPayload, Serializable messageId, String payload,
|
||||
Class<? extends ServerReplyCallback> callbackClass) {
|
||||
Intent messageIntent = new Intent(context, MessageSendingService.class);
|
||||
messageIntent.setAction(context.getString(R.string.intent_send_message));
|
||||
@@ -231,6 +232,7 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
persistenceManager.persistIntent(intent);
|
||||
ConnectivityChangedReceiver.enable(this);
|
||||
serviceLogger.onMessageSentFailed();
|
||||
reportApiConnectivity(APIConnectivity.notReachable);
|
||||
} else {
|
||||
sendMessage(intent);
|
||||
}
|
||||
@@ -259,7 +261,7 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
private void sendMessage(Intent intent) {
|
||||
boolean sendingActive = PrefUtils.getBoolean(this, R.string.preference_isSendingActive_key,
|
||||
R.bool.preference_isSendingActive_default);
|
||||
if (! sendingActive) {
|
||||
if (!sendingActive) {
|
||||
ExLog.i(this, TAG, "Sending deactivated. Message will not be sent to server.");
|
||||
} else {
|
||||
Serializable messageId = getMessageId(intent);
|
||||
@@ -275,9 +277,12 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
|
||||
@Override
|
||||
public void onMessageSent(Intent intent, boolean success, InputStream inputStream) {
|
||||
ExLog.i(this, "MS", "on message sent");
|
||||
int resendMillis = PrefUtils.getInt(this, R.string.preference_messageResendIntervalMillis_key,
|
||||
R.integer.preference_messageResendIntervalMillis_default);
|
||||
if (!success) {
|
||||
ExLog.i(this, "MS", "success");
|
||||
reportApiConnectivity(APIConnectivity.transmissionError);
|
||||
ExLog.w(this, TAG, "Error while posting intent to server. Will persist intent...");
|
||||
persistenceManager.persistIntent(intent);
|
||||
if (!isHandlerSet) {
|
||||
@@ -285,8 +290,11 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
handler.postDelayed(delayedCaller, resendMillis); // after 30 sec, try the sending again
|
||||
isHandlerSet = true;
|
||||
}
|
||||
reportUnsentGPSFixesCount();
|
||||
serviceLogger.onMessageSentFailed();
|
||||
} else {
|
||||
ExLog.i(this, "MS", "!success");
|
||||
reportApiConnectivity(APIConnectivity.transmissionSuccess);
|
||||
ExLog.i(this, TAG, "Message successfully sent.");
|
||||
if (persistenceManager.areIntentsDelayed()) {
|
||||
persistenceManager.removeIntent(intent);
|
||||
@@ -308,6 +316,8 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
String raceId = intent.getStringExtra(CALLBACK_PAYLOAD);
|
||||
callback.processResponse(this, inputStream, raceId);
|
||||
}
|
||||
ExLog.i(this, "MS", "report");
|
||||
reportUnsentGPSFixesCount() ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,14 +341,87 @@ public class MessageSendingService extends Service implements MessageSendingList
|
||||
|
||||
public static String getRaceLogEventSendAndReceiveUrl(Context context, final String raceGroupName,
|
||||
final String raceName, final String fleetName) {
|
||||
String url = String.format("%s/sailingserver/rc/racelog?"+
|
||||
RaceLogServletConstants.PARAMS_LEADERBOARD_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_RACE_FLEET_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_CLIENT_UUID+"=%s",
|
||||
PrefUtils.getString(context, R.string.preference_server_url_key, R.string.preference_server_url_default),
|
||||
URLEncoder.encode(raceGroupName),
|
||||
URLEncoder.encode(raceName), URLEncoder.encode(fleetName), uuid);
|
||||
String url = null;
|
||||
try {
|
||||
url = String.format("%s/sailingserver/rc/racelog?"+
|
||||
RaceLogServletConstants.PARAMS_LEADERBOARD_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_RACE_FLEET_NAME+"=%s&"+
|
||||
RaceLogServletConstants.PARAMS_CLIENT_UUID+"=%s",
|
||||
PrefUtils.getString(context, R.string.preference_server_url_key, R.string.preference_server_url_default),
|
||||
URLEncoder.encode(raceGroupName, "UTF-8"),
|
||||
URLEncoder.encode(raceName,"UTF-8"),
|
||||
URLEncoder.encode(fleetName, "UTF-8"), uuid);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
ExLog.e(context, TAG, "UnsupportedEncodingException: " + e.getLocalizedMessage());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for API-connectivity
|
||||
*
|
||||
* @param listener class that wants to be notified of api-connectivity changes
|
||||
*/
|
||||
public void registerAPIConnectivityListener(APIConnectivityListener listener) {
|
||||
apiConnectivityListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for API-connectivity
|
||||
*/
|
||||
public void unregisterAPIConnectivityListener() {
|
||||
apiConnectivityListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for reporting of network connectivity.
|
||||
*/
|
||||
public enum APIConnectivity {
|
||||
notReachable(0),
|
||||
transmissionSuccess(1),
|
||||
transmissionError(2),
|
||||
noAttempt(4);
|
||||
|
||||
private final int apiConnectivity;
|
||||
|
||||
APIConnectivity(int connectivity) {
|
||||
this.apiConnectivity = connectivity;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.apiConnectivity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface for reporting of connectivity and number of
|
||||
* unsent GPS-fixes.
|
||||
*/
|
||||
public interface APIConnectivityListener {
|
||||
public void apiConnectivityUpdated(APIConnectivity apiConnectivity);
|
||||
public void setUnsentGPSFixesCount(int count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report API connectivity to listening activity
|
||||
*
|
||||
* @param apiConnectivity
|
||||
*/
|
||||
private void reportApiConnectivity(APIConnectivity apiConnectivity) {
|
||||
if (apiConnectivityListener != null) {
|
||||
apiConnectivityListener.apiConnectivityUpdated(apiConnectivity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report the number of currently unsent GPS-fixes
|
||||
*
|
||||
* @param unsentGPSFixesCount
|
||||
*/
|
||||
private void reportUnsentGPSFixesCount() {
|
||||
if (apiConnectivityListener != null) {
|
||||
apiConnectivityListener.setUnsentGPSFixesCount(getDelayedIntentsCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.sap.sailing.android.tracking.app.services.sending;
|
||||
package com.sap.sailing.android.shared.services.sending;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
package com.sap.sailing.android.shared.ui.activities;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.sap.sailing.android.shared.R;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.MessageSendingBinder;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.MessageSendingServiceLogger;
|
||||
import com.sap.sailing.android.shared.util.PrefUtils;
|
||||
|
||||
public abstract class SendingServiceAwareActivity extends ResilientActivity {
|
||||
|
||||
private class MessageSendingServiceConnection implements ServiceConnection, MessageSendingServiceLogger {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
MessageSendingBinder binder = (MessageSendingBinder) service;
|
||||
sendingService = binder.getService();
|
||||
boundSendingService = true;
|
||||
sendingService.setMessageSendingServiceLogger(this);
|
||||
updateSendingServiceInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg) {
|
||||
boundSendingService = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageSentSuccessful() {
|
||||
updateSendingServiceInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageSentFailed() {
|
||||
updateSendingServiceInformation();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = SendingServiceAwareActivity.class.getName();
|
||||
|
||||
protected MenuItem menuItemLive;
|
||||
protected int menuItemLiveId = -1;
|
||||
|
||||
protected boolean boundSendingService = false;
|
||||
protected MessageSendingService sendingService;
|
||||
private MessageSendingServiceConnection sendingServiceConnection;
|
||||
|
||||
private String sendingServiceStatus = "";
|
||||
|
||||
public SendingServiceAwareActivity() {
|
||||
this.sendingServiceConnection = new MessageSendingServiceConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Intent intent = new Intent(this, MessageSendingService.class);
|
||||
bindService(intent, sendingServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (boundSendingService) {
|
||||
unbindService(sendingServiceConnection);
|
||||
boundSendingService = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateSendingServiceInformation() {
|
||||
if (menuItemLive == null)
|
||||
return;
|
||||
|
||||
if (!boundSendingService)
|
||||
return;
|
||||
|
||||
int errorCount = this.sendingService.getDelayedIntentsCount();
|
||||
if (errorCount > 0) {
|
||||
menuItemLive.setIcon(R.drawable.ic_menu_share_red);
|
||||
Date lastSuccessfulSend = this.sendingService.getLastSuccessfulSend();
|
||||
sendingServiceStatus = String.format("Currently %d events waiting to be sent.\nLast successful sent was at %s",
|
||||
errorCount, lastSuccessfulSend == null ? "never" : lastSuccessfulSend);
|
||||
} else {
|
||||
menuItemLive.setIcon(R.drawable.ic_menu_share);
|
||||
sendingServiceStatus = String.format("Currently no event waiting to be sent.", errorCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resource ID for the options menu, {@code 0} if none.
|
||||
* The menu item displaying the connection status is added automatically.
|
||||
*/
|
||||
protected abstract int getOptionsMenuResId();
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.options_menu_live_status, menu);
|
||||
menuItemLive = menu.findItem(R.id.options_menu_live);
|
||||
if (getOptionsMenuResId() != 0) {
|
||||
inflater.inflate(getOptionsMenuResId(), menu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (R.id.options_menu_live == item.getItemId()) {
|
||||
ExLog.i(this, TAG, "Clicked LIVE.");
|
||||
Toast.makeText(this, getLiveIconText(), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
updateSendingServiceInformation();
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private String getLiveIconText() {
|
||||
return String.format("Connected to: %s\n%s", PrefUtils.getString(this, R.string.preference_server_url_key,
|
||||
R.string.preference_server_url_default), sendingServiceStatus);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.sap.sailing.android.tracking.app.test;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.utils.DatabaseHelper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
||||
public class DatabaseCallsTest extends ActivityUnitTestCase<Activity> {
|
||||
|
||||
private Intent mStartIntent;
|
||||
|
||||
|
||||
public DatabaseCallsTest() {
|
||||
super(Activity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mStartIntent = new Intent(Intent.ACTION_MAIN);
|
||||
startActivity(mStartIntent, null, null);
|
||||
DatabaseTestHelper.deleteAllEventsFromDB(getActivity());
|
||||
}
|
||||
|
||||
public void testDeleteRegatta()
|
||||
{
|
||||
DatabaseTestHelper.createNewRegattaInDBAndReturnEventRowId(getActivity(), "TEST-EVENT",
|
||||
"123-456-789", "TEST-LEADERBOARD", "TEST-COMPETITOR", "TEST-DIGEST1");
|
||||
|
||||
DatabaseTestHelper.createNewRegattaInDBAndReturnEventRowId(getActivity(), "TEST-EVENT 2",
|
||||
"234-567-890", "TEST-LEADERBOARD 2", "TEST-COMPETITOR 2", "TEST-DIGEST2");
|
||||
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(getActivity(), "TEST-DIGEST1");
|
||||
|
||||
assertEquals(1, DatabaseTestHelper.getNumberOfEventsFromDB(getActivity()));
|
||||
|
||||
//TODO: Continue, ensure context is not null
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+46
-1
@@ -10,8 +10,10 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Competitor;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.EventGpsFixesJoined;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Leaderboard;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.SensorGps;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.GpsFix;
|
||||
|
||||
@@ -98,14 +100,57 @@ public class DatabaseTestHelper {
|
||||
cr.insert(SensorGps.CONTENT_URI, cv);
|
||||
}
|
||||
|
||||
public static long createNewEventInDBAndReturnItsId(Context context, String eventName, String eventId)
|
||||
public static long createNewEventInDBAndReturnItsId(Context context, String eventName, String eventId, String checkinDigest)
|
||||
{
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Event.EVENT_NAME, eventName);
|
||||
cv.put(Event.EVENT_ID, eventId);
|
||||
cv.put(Event.EVENT_SERVER, "127.0.0.1");
|
||||
cv.put(Event.EVENT_CHECKIN_DIGEST, checkinDigest);
|
||||
Uri uri = cr.insert(Event.CONTENT_URI, cv);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
public static long createNewRegattaInDBAndReturnEventRowId(Context context, String eventName,
|
||||
String eventId, String leaderboardName, String competitorName, String checkinDigest) {
|
||||
|
||||
long leaderboardRowId = createNewLeaderboardInDBAndReturnItsId(context, leaderboardName, checkinDigest);
|
||||
long eventRowId = createNewEventInDBAndReturnItsId(context, eventName, eventId, leaderboardRowId, checkinDigest);
|
||||
createNewCompetitorInDBAndReturnItsId(context, competitorName, leaderboardRowId, checkinDigest);
|
||||
|
||||
return eventRowId;
|
||||
}
|
||||
|
||||
private static long createNewEventInDBAndReturnItsId(Context context, String eventName, String eventId, long leaderboardRowId, String checkinDigest)
|
||||
{
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Event.EVENT_NAME, eventName);
|
||||
cv.put(Event.EVENT_ID, eventId);
|
||||
cv.put(Event.EVENT_SERVER, "127.0.0.1");
|
||||
cv.put(Event.EVENT_CHECKIN_DIGEST, checkinDigest);
|
||||
Uri uri = cr.insert(Event.CONTENT_URI, cv);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private static long createNewLeaderboardInDBAndReturnItsId(Context context, String leaderboardName, String checkinDigest)
|
||||
{
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Leaderboard.LEADERBOARD_NAME, leaderboardName);
|
||||
cv.put(Leaderboard.LEADERBOARD_CHECKIN_DIGEST, checkinDigest);
|
||||
Uri uri = cr.insert(Leaderboard.CONTENT_URI, cv);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
|
||||
private static long createNewCompetitorInDBAndReturnItsId(Context context,
|
||||
String competitorDisplayName, long leaderboardRowId, String checkinDigest) {
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Competitor.COMPETITOR_DISPLAY_NAME, competitorDisplayName);
|
||||
cv.put(Competitor.COMPETITOR_CHECKIN_DIGEST, checkinDigest);
|
||||
Uri uri = cr.insert(Competitor.CONTENT_URI, cv);
|
||||
return ContentUris.parseId(uri);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -22,7 +22,7 @@ import com.sap.sailing.android.tracking.app.valueobjects.GpsFix;
|
||||
public class TrackingServiceTest extends ServiceTestCase<TrackingService> {
|
||||
|
||||
static final String TAG = TrackingServiceTest.class.getName();
|
||||
final String eventId = "test123";
|
||||
final String checkinDigest = "testDigest123";
|
||||
long eventRowId;
|
||||
|
||||
private ServiceHelperTestable serviceHelperSpy;
|
||||
@@ -37,8 +37,7 @@ public class TrackingServiceTest extends ServiceTestCase<TrackingService> {
|
||||
System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
|
||||
DatabaseTestHelper.deleteAllGpsFixesFromDB(getContext());
|
||||
DatabaseTestHelper.deleteAllEventsFromDB(getContext());
|
||||
eventRowId = DatabaseTestHelper.createNewEventInDBAndReturnItsId(getContext(), "test123",
|
||||
eventId);
|
||||
eventRowId = DatabaseTestHelper.createNewEventInDBAndReturnItsId(getContext(), "test123", "123-456", checkinDigest);
|
||||
|
||||
serviceHelperSpy = Mockito.mock(ServiceHelperTestable.class);
|
||||
ServiceHelperTestable.injectInstance(serviceHelperSpy);
|
||||
@@ -52,8 +51,7 @@ public class TrackingServiceTest extends ServiceTestCase<TrackingService> {
|
||||
private void startService() {
|
||||
Intent startIntent = new Intent();
|
||||
startIntent.setClass(getContext(), TrackingService.class);
|
||||
startIntent.putExtra(getContext().getString(R.string.tracking_service_event_id_parameter),
|
||||
eventId);
|
||||
startIntent.putExtra(getContext().getString(R.string.tracking_service_checkin_digest_parameter), checkinDigest);
|
||||
startIntent.setAction(getContext().getString(R.string.tracking_service_start));
|
||||
startService(startIntent);
|
||||
}
|
||||
|
||||
+16
-15
@@ -12,13 +12,15 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.test.ServiceTestCase;
|
||||
|
||||
import com.android.volley.Response.ErrorListener;
|
||||
import com.android.volley.Response.Listener;
|
||||
import com.sap.sailing.android.shared.data.http.HttpJsonPostRequest;
|
||||
import com.sap.sailing.android.shared.data.http.HttpRequest;
|
||||
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.TransmittingService;
|
||||
import com.sap.sailing.android.tracking.app.test.extensions.DatabaseHelperTestable;
|
||||
import com.sap.sailing.android.tracking.app.test.extensions.VolleyHelperTestable;
|
||||
import com.sap.sailing.android.tracking.app.test.extensions.NetworkHelperTestable;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperFailureListener;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperSuccessListener;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.GpsFix;
|
||||
|
||||
public class TransmittingServiceTest extends ServiceTestCase<TransmittingService> {
|
||||
@@ -26,7 +28,7 @@ public class TransmittingServiceTest extends ServiceTestCase<TransmittingService
|
||||
static final String TAG = TransmittingServiceTest.class.getName();
|
||||
final String eventId = "test123";
|
||||
|
||||
private VolleyHelperTestable volleyHelperSpy;
|
||||
private NetworkHelperTestable networkHelperSpy;
|
||||
private DatabaseHelperTestable databaseHelperMock;
|
||||
|
||||
public TransmittingServiceTest() {
|
||||
@@ -40,11 +42,10 @@ public class TransmittingServiceTest extends ServiceTestCase<TransmittingService
|
||||
DatabaseTestHelper.deleteAllEventsFromDB(getContext());
|
||||
DatabaseTestHelper.deleteAllGpsFixesFromDB(getContext());
|
||||
|
||||
if (volleyHelperSpy == null)
|
||||
if (networkHelperSpy == null)
|
||||
{
|
||||
VolleyHelperTestable.injectInstance(null, null);
|
||||
volleyHelperSpy = Mockito.spy(new VolleyHelperTestable(getContext()));
|
||||
VolleyHelperTestable.injectInstance(getContext(), volleyHelperSpy);
|
||||
networkHelperSpy = Mockito.spy(new NetworkHelperTestable());
|
||||
NetworkHelperTestable.injectInstance(getContext(), networkHelperSpy);
|
||||
}
|
||||
|
||||
if (databaseHelperMock == null)
|
||||
@@ -71,8 +72,8 @@ public class TransmittingServiceTest extends ServiceTestCase<TransmittingService
|
||||
public void testTransmittingServiceTransmitsGpsFix() throws InterruptedException, JSONException {
|
||||
long timestamp = (new Date()).getTime();
|
||||
|
||||
ArgumentCaptor<JSONObject> jsonObjectCaptor = ArgumentCaptor.forClass(JSONObject.class);
|
||||
ArgumentCaptor<String> urlCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<HttpJsonPostRequest> requestCaptor = ArgumentCaptor.forClass(HttpJsonPostRequest.class);
|
||||
//ArgumentCaptor<String> urlCaptor = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
ArrayList<GpsFix> list = new ArrayList<GpsFix>();
|
||||
GpsFix fix = new GpsFix();
|
||||
@@ -91,12 +92,12 @@ public class TransmittingServiceTest extends ServiceTestCase<TransmittingService
|
||||
startService();
|
||||
|
||||
Thread.sleep(3500);
|
||||
|
||||
Mockito.verify(networkHelperSpy, Mockito.times(1)).executeHttpJsonRequestAsnchronously(requestCaptor.capture(),
|
||||
(NetworkHelperSuccessListener)Mockito.any(), (NetworkHelperFailureListener)Mockito.any());
|
||||
|
||||
Mockito.verify(volleyHelperSpy, Mockito.times(1)).enqueueRequest(
|
||||
urlCaptor.capture(), jsonObjectCaptor.capture(),
|
||||
(Listener<JSONObject>)Mockito.any(), Mockito.any(ErrorListener.class));
|
||||
|
||||
JSONObject json = jsonObjectCaptor.getValue();
|
||||
JSONObject json = new JSONObject(requestCaptor.getValue().getRequestBody());
|
||||
assertEquals(1, json.getJSONArray("fixes").length());
|
||||
|
||||
JSONObject jsonFix = (JSONObject)json.getJSONArray("fixes").get(0);
|
||||
@@ -106,7 +107,7 @@ public class TransmittingServiceTest extends ServiceTestCase<TransmittingService
|
||||
assertEquals(14, jsonFix.getLong("speed"));
|
||||
assertEquals(101.5, jsonFix.getDouble("course"));
|
||||
|
||||
assertEquals("http://127.0.0.1/sailingserver/api/v1/gps_fixes", urlCaptor.getValue());
|
||||
assertEquals("http://127.0.0.1/sailingserver/api/v1/gps_fixes", requestCaptor.getValue().getUrlAsString());
|
||||
shutdownService();
|
||||
}
|
||||
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.sap.sailing.android.tracking.app.test.extensions;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.sap.sailing.android.shared.data.http.HttpJsonPostRequest;
|
||||
|
||||
public class HttpJsonPostRequestTestable extends HttpJsonPostRequest {
|
||||
|
||||
public HttpJsonPostRequestTestable(URL requestUrl, String body, Context context) {
|
||||
super(requestUrl, body, context);
|
||||
}
|
||||
|
||||
public JSONObject getPayloadJSON() throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException, JSONException{
|
||||
Class<?> clazz = getClass().getSuperclass();
|
||||
Field requestBodyField = clazz.getDeclaredField("requestBody");
|
||||
requestBodyField.setAccessible(true);
|
||||
|
||||
return new JSONObject((String)requestBodyField.get(this));
|
||||
}
|
||||
|
||||
public URL getUrl() throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException
|
||||
{
|
||||
Class<?> clazz = getClass().getSuperclass();
|
||||
Field requestBodyField = clazz.getDeclaredField("url");
|
||||
requestBodyField.setAccessible(true);
|
||||
|
||||
return (URL)requestBodyField.get(this);
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.android.tracking.app.test.extensions;
|
||||
|
||||
import android.content.Context;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper;
|
||||
|
||||
public class NetworkHelperTestable extends NetworkHelper {
|
||||
|
||||
public static void injectInstance(Context context, NetworkHelper instance)
|
||||
{
|
||||
mContext = context;
|
||||
mInstance = instance;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.test.extensions;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.utils.VolleyHelper;
|
||||
|
||||
public class VolleyHelperTestable extends VolleyHelper {
|
||||
|
||||
public VolleyHelperTestable(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private static Context mContext;
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public static void injectInstance(Context context, VolleyHelper instance)
|
||||
{
|
||||
mContext = context;
|
||||
mInstance = instance;
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,7 @@
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/com.sap.sailing.domain.common"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/com.sap.sailing.domain"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -79,29 +79,29 @@
|
||||
<activity
|
||||
android:name=".ui.activities.SettingsActivity"
|
||||
android:screenOrientation="unspecified" />
|
||||
<activity android:name="net.hockeyapp.android.UpdateActivity" />
|
||||
<service
|
||||
android:name=".services.TrackingService"
|
||||
android:exported="false"
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/tracking_service" />
|
||||
<service
|
||||
<!-- <service
|
||||
android:name=".services.TransmittingService"
|
||||
android:exported="false"
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/transmitting_service" />
|
||||
<!--
|
||||
android:label="@string/transmitting_service" /> -->
|
||||
|
||||
<service
|
||||
android:name="com.sap.sailing.android.tracking.app.services.sending.MessageSendingService"
|
||||
android:name="com.sap.sailing.android.shared.services.sending.MessageSendingService"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.sap.sailing.android.tracking.app.action.sendSavedIntents" />
|
||||
<action android:name="com.sap.sailing.android.tracking.app.action.sendMessage" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
-->
|
||||
<!--<service android:name=".service.GcmIntentService" />-->
|
||||
|
||||
<receiver android:name="com.sap.sailing.android.tracking.app.services.sending.ConnectivityChangedReceiver" >
|
||||
<receiver android:name="com.sap.sailing.android.shared.services.sending.ConnectivityChangedReceiver" >
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -54,6 +54,8 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "net.hockeyapp.android:HockeySDK:3.5.0"
|
||||
|
||||
/* support libraries */
|
||||
compile "com.android.support:appcompat-v7:21.0.3"
|
||||
|
||||
@@ -62,10 +64,9 @@ dependencies {
|
||||
|
||||
/* local dependencies */
|
||||
compile project(":mobile:com.sap.sailing.android.shared")
|
||||
compile project(":mobile:google-volley_lib")
|
||||
|
||||
/* all local jar-libs */
|
||||
compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
// compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
}
|
||||
|
||||
// Custom tasks
|
||||
|
||||
Binary file not shown.
@@ -7,6 +7,6 @@
|
||||
android:width="1dip"
|
||||
android:color="#ffffff" />
|
||||
|
||||
<corners android:radius="0dip" />
|
||||
<corners android:radius="5dip" />
|
||||
|
||||
</shape>
|
||||
+2
-2
@@ -4,9 +4,9 @@
|
||||
<solid android:color="#00FFFFFF" />
|
||||
|
||||
<stroke
|
||||
android:width="1dip"
|
||||
android:width="0.5dip"
|
||||
android:color="#ffffff" />
|
||||
|
||||
<corners android:radius="0dip" />
|
||||
<corners android:radius="5dip" />
|
||||
|
||||
</shape>
|
||||
@@ -4,8 +4,8 @@
|
||||
<solid android:color="@color/sap_green" />
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="3dip"
|
||||
android:bottomRightRadius="3dip"
|
||||
android:topLeftRadius="3dip"
|
||||
android:topRightRadius="3dip" />
|
||||
android:bottomLeftRadius="5dip"
|
||||
android:bottomRightRadius="5dip"
|
||||
android:topLeftRadius="5dip"
|
||||
android:topRightRadius="5dip" />
|
||||
</shape>
|
||||
@@ -4,8 +4,8 @@
|
||||
<solid android:color="@color/sap_red" />
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="3dip"
|
||||
android:bottomRightRadius="3dip"
|
||||
android:topLeftRadius="3dip"
|
||||
android:topRightRadius="3dip" />
|
||||
android:bottomLeftRadius="5dip"
|
||||
android:bottomRightRadius="5dip"
|
||||
android:topLeftRadius="5dip"
|
||||
android:topRightRadius="5dip" />
|
||||
</shape>
|
||||
@@ -8,9 +8,9 @@
|
||||
android:color="@color/white" />
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="3dip"
|
||||
android:bottomRightRadius="3dip"
|
||||
android:topLeftRadius="3dip"
|
||||
android:topRightRadius="3dip" />
|
||||
android:bottomLeftRadius="5dip"
|
||||
android:bottomRightRadius="5dip"
|
||||
android:topLeftRadius="5dip"
|
||||
android:topRightRadius="5dip" />
|
||||
|
||||
</shape>
|
||||
@@ -4,8 +4,8 @@
|
||||
<solid android:color="@color/sap_yellow" />
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="3dip"
|
||||
android:bottomRightRadius="3dip"
|
||||
android:topLeftRadius="3dip"
|
||||
android:topRightRadius="3dip" />
|
||||
android:bottomLeftRadius="5dip"
|
||||
android:bottomRightRadius="5dip"
|
||||
android:topLeftRadius="5dip"
|
||||
android:topRightRadius="5dip" />
|
||||
</shape>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:custom="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app.views"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/darker_gray" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/compass_bearing_header_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="@string/heading"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="15sp"
|
||||
android:paddingTop="15dp"
|
||||
/>
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/compass_bearing_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
android:layout_centerInParent="true"
|
||||
android:textSize="124sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:custom="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app.views"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/darker_gray" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/speed_header_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sog"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingTop="15dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/speed_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/white"
|
||||
android:text="-"
|
||||
android:textSize="124sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/speed_unit_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/speed_text_view"
|
||||
android:gravity="top|center"
|
||||
android:text="@string/knots"
|
||||
android:textColor="@color/white"
|
||||
android:layout_marginTop="-20dp"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -5,28 +5,27 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/sap_yellow" >
|
||||
android:background="@color/darker_gray" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeTextView
|
||||
<TextView
|
||||
android:id="@+id/compass_bearing_header_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/heading"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="48sp"
|
||||
android:textStyle="bold" />
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="@string/course_over_ground"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="15sp"
|
||||
android:paddingTop="15dp"
|
||||
/>
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeTextView
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/compass_bearing_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_below="@id/compass_bearing_header_text_view"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
android:textColor="@color/black"
|
||||
android:textSize="118sp"
|
||||
android:textStyle="bold" />
|
||||
android:layout_centerInParent="true"
|
||||
android:textSize="124sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -18,17 +18,19 @@
|
||||
android:id="@+id/toolbar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textSize="18sp"/>
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansTextView
|
||||
android:id="@+id/toolbar_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -19,17 +19,19 @@
|
||||
android:id="@+id/toolbar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textSize="18sp" />
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansTextView
|
||||
android:id="@+id/toolbar_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</com.sap.sailing.android.tracking.app.customviews.OpenSansToolbar>
|
||||
|
||||
@@ -62,8 +64,8 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="#00000000"
|
||||
android:paddingBottom="10dp"
|
||||
android:background="@color/black"
|
||||
android:paddingTop="10dp" />
|
||||
|
||||
|
||||
|
||||
@@ -5,28 +5,46 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@color/sap_yellow" >
|
||||
android:background="@color/darker_gray" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeTextView
|
||||
<TextView
|
||||
android:id="@+id/speed_header_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sog"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="48sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeTextView
|
||||
android:id="@+id/speed_text_view"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="14sp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingTop="15dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_below="@id/speed_header_text_view"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
android:textColor="@color/black"
|
||||
android:textSize="108sp"
|
||||
android:textStyle="bold" />
|
||||
android:layout_centerInParent="true"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/speed_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/white"
|
||||
android:text="0"
|
||||
android:textSize="124sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/speed_unit_text_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/speed_text_view"
|
||||
android:gravity="top|center"
|
||||
android:text="@string/knots"
|
||||
android:textColor="@color/white"
|
||||
android:layout_marginTop="-20dp"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -5,15 +5,15 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.sap.sailing.android.tracking.app"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/black" >
|
||||
android:background="@color/darker_gray" >
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_above="@+id/stop_tracking_box"
|
||||
android:baselineAligned="false"
|
||||
android:paddingTop="20sp" >
|
||||
android:paddingTop="15dp" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansTextView
|
||||
android:id="@+id/tracking_time"
|
||||
@@ -23,44 +23,38 @@
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="@string/tracking_time" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeTextView
|
||||
<com.sap.sailing.android.tracking.app.customviews.AutoResizeLightTextView
|
||||
android:id="@+id/tracking_time_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="110dp"
|
||||
android:gravity="center"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:text="00:00:00"
|
||||
android:layout_below="@+id/tracking_time"
|
||||
android:textSize="128sp" />
|
||||
android:gravity="bottom"
|
||||
android:textSize="100sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/stop_tracking_box"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="100dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@color/gray" >
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@color/white_transparent" />
|
||||
android:layout_alignParentBottom="true" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/stop_tracking"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/rounded_btn_red"
|
||||
android:padding="10dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/stop_tracking"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="400dp"
|
||||
android:layout_height="402dp"
|
||||
android:background="@color/black" >
|
||||
|
||||
<ScrollView
|
||||
@@ -142,6 +142,12 @@
|
||||
android:layout_height="1dp"
|
||||
android:layout_below="@id/gps_quality"
|
||||
android:background="@android:color/darker_gray" />
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_below="@id/tracking_status_label"
|
||||
android:background="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</ScrollView>
|
||||
</RelativeLayout>
|
||||
@@ -7,9 +7,11 @@
|
||||
<string name="preference_energy_saving_is_disabled">Aus</string>
|
||||
<string name="prefrence_energy_saving_summary_is_enabled">GPS Updates werden alle 30 Sekunden verschickt.</string>
|
||||
<string name="prefrence_energy_saving_summary_is_disabled">GPS Updates werden alle 3 Sekunden verschickt.</string>
|
||||
<string name="preference_heading_from_magnetic_key_is_enabled">magn.</string>
|
||||
<string name="preference_heading_from_magnetic_key_is_disabled">GPS</string>
|
||||
<string name="preference_heading_from_magnetic_key_summary_is_enabled">Richtung stammt vom Magnetkompass</string>
|
||||
<string name="preference_heading_from_magnetic_key_summary_is_disabled">Richtung stammt vom GPS</string>
|
||||
<string name="preference_heading_from_magnetic_enabled">Richtung</string>
|
||||
</resources>
|
||||
<string name="preference_heading_with_declination_subtracted_key_is_enabled">Ein</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_is_disabled">Aus</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_summary_is_enabled">Anzeige: Magnetkompasskurs ohne Ablenkung</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_summary_is_disabled">Anzeige: Magnetkompasskurs mit Ablenkung</string>
|
||||
<string name="preference_heading_with_declination_subtracted_enabled">Richtung</string>
|
||||
|
||||
|
||||
</resources>
|
||||
@@ -80,9 +80,19 @@
|
||||
<string name="hud_heading_prefix">HDG: </string>
|
||||
<string name="hud_speed_over_ground_prefix">SPD: </string>
|
||||
<string name="heading">Kurs</string>
|
||||
<string name="course_over_ground">Course over Ground</string>
|
||||
<string name="sog">SOG</string>
|
||||
<string name="none">Keine</string>
|
||||
<string name="show_leaderboard">Leaderboard</string>
|
||||
<string name="desc_regatta_user_image">Benutzerdefiniertes Bild für Regatta</string>
|
||||
<string name="desc_add_photo_button">Foto hinzufügen Button</string>
|
||||
<string name="error_play_store_and_scanning_not_available">"PlayStore und BarcodeScanner-App nicht verfügbar."</string>
|
||||
<string name="scanning_cancelled">Scan abgebrochen</string>
|
||||
<string name="error_scanning_qrcode">Fehler beim Scannen des QR-Codes {result-code}</string>
|
||||
<string name="error_invalid_qr_code">Ungültiger QR-Code</string>
|
||||
<string name="error_while_receiving_server_data">Fehler beim Empfang vom Server</string>
|
||||
<string name="info_already_checked_in_this_qr_code">Bereits für diese Regatta eingecheckt</string>
|
||||
<string name="warning">Warnung</string>
|
||||
<string name="gps_turned_off">GPS ist nicht aktiviert. Bitte aktivieren Sie den Standortzugriff (GPS) in Ihren Android-Einstellungen!</string>
|
||||
<string name="knots">Knoten</string>
|
||||
</resources>
|
||||
@@ -4,7 +4,7 @@
|
||||
<string name="notify_user_api_call_failed">Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal.</string>
|
||||
<string name="confirm_data_hello_name">Hallo {full_name}</string>
|
||||
<string name="confirm_data_you_are_signed_in_as_sail_id">Sie sind als {sail_id} gemeldet</string>
|
||||
<string name="confirm_data_is_correct">Stimmt</string>
|
||||
<string name="confirm_data_is_correct">OK</string>
|
||||
<string name="decline_data_is_incorrect">Das bin nicht ich!</string>
|
||||
<string name="notify_user_db_operation_failed">Fehler: Datenbank-Operation ist fehlgeschlagen.</string>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<string name="preference_server_url_default">http://95.85.58.11:8000</string>
|
||||
|
||||
<string name="preference_energy_saving_enabled_key">preferenceEnergySavingEnabled</string>
|
||||
<string name="preference_heading_from_magnetic_key">preferenceHeadingFromMagneticKey</string>
|
||||
<string name="preference_heading_with_declination_subtracted">preferenceHeadingWithDeclinationSubtracted</string>
|
||||
|
||||
<string name="settings_category_energy_saving">Battery Saving</string>
|
||||
<string name="energy_saving_enabled">Save Energy</string>
|
||||
@@ -26,11 +26,12 @@
|
||||
<string name="preference_battery_is_charging">batteryIsCharging</string>
|
||||
<string name="preference_tracking_timer_started">trackingTimerStarted</string>
|
||||
<string name="preference_tracker_is_tracking">trackerIsTracking</string>
|
||||
<string name="preference_tracker_is_tracking_event_id">trackerIsTrackingEventId</string>
|
||||
|
||||
<string name="preference_heading_from_magnetic_key_is_enabled">magn.</string>
|
||||
<string name="preference_heading_from_magnetic_key_is_disabled">GPS</string>
|
||||
<string name="preference_heading_from_magnetic_key_summary_is_enabled">Heading from magnetic compass</string>
|
||||
<string name="preference_heading_from_magnetic_key_summary_is_disabled">Heading from GPS</string>
|
||||
<string name="preference_heading_from_magnetic_enabled">Heading</string>
|
||||
<string name="preference_tracker_is_tracking_checkin_digest">trackerIsTrackingCheckinDigest</string>
|
||||
<string name="preference_last_scanned_qr_code">lastScannedQRCode</string>
|
||||
|
||||
<string name="preference_heading_with_declination_subtracted_key_is_enabled">On</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_is_disabled">Off</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_summary_is_enabled">Display: Course without declination</string>
|
||||
<string name="preference_heading_with_declination_subtracted_key_summary_is_disabled">Display: Course with declination</string>
|
||||
<string name="preference_heading_with_declination_subtracted_enabled">Heading</string>
|
||||
</resources>
|
||||
@@ -35,6 +35,7 @@
|
||||
<string name="competitor_id">CompetitorId</string>
|
||||
<string name="event_id">EventId</string>
|
||||
<string name="leaderboard_name">LeaderboardName</string>
|
||||
<string name="checkin_digest">CheckinDigest</string>
|
||||
<string name="add_team_photo">Add Team Photo</string>
|
||||
<string name="do_you_want_to_choose_existing_img_or_take_a_new_one">Do you want to use an existing image or take a new one?</string>
|
||||
<string name="existing_image">Existing</string>
|
||||
@@ -65,8 +66,17 @@
|
||||
<string name="tracking_colon">Tracking:</string>
|
||||
<string name="regatta_in_progress">The regatta is in progress.</string>
|
||||
<string name="heading">Heading</string>
|
||||
<string name="sog">SOG</string>
|
||||
<string name="course_over_ground">Course over Ground</string>
|
||||
<string name="sog">Speed over Ground</string>
|
||||
<string name="none">None</string>
|
||||
<string name="show_leaderboard">Leader board</string>
|
||||
|
||||
<string name="error_play_store_and_scanning_not_available">"PlayStore and Scanning not available."</string>
|
||||
<string name="scanning_cancelled">Scanning cancelled</string>
|
||||
<string name="error_scanning_qrcode">Error scanning QR-Code {result-code}</string>
|
||||
<string name="error_invalid_qr_code">Invalid QR-Code</string>
|
||||
<string name="error_while_receiving_server_data">Error while receiving server data</string>
|
||||
<string name="info_already_checked_in_this_qr_code">Already checked in to this regatta</string>
|
||||
<string name="warning">Warning</string>
|
||||
<string name="gps_turned_off">GPS is turned off. Please turn on location access (GPS) in your Android Settings!</string>
|
||||
<string name="knots">knots</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="tracking_activity_event_id_parameter">trackingActivityEventId</string>
|
||||
<string name="tracking_activity_checkin_digest_parameter">trackingActivityCheckinDigestParameter</string>
|
||||
</resources>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<string name="notify_user_api_call_failed">An error occurred while contacting the server. Please try again.</string>
|
||||
<string name="confirm_data_hello_name">Hello {full_name}</string>
|
||||
<string name="confirm_data_you_are_signed_in_as_sail_id">You are signing in as {sail_id}</string>
|
||||
<string name="confirm_data_is_correct">Correct</string>
|
||||
<string name="confirm_data_is_correct">OK</string>
|
||||
<string name="decline_data_is_incorrect">That\'s not me!</string>
|
||||
<string name="notify_user_db_operation_failed">Error: Database operation has failed.</string>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<string name="tracking_service_start">tracking_start</string>
|
||||
<string name="tracking_service_stop">tracking_stop</string>
|
||||
<string name="tracking_service_change">tracking_change</string>
|
||||
<string name="tracking_service_event_id_parameter">trackingServiceEventId</string>
|
||||
<string name="tracking_service_checkin_digest_parameter">trackingServiceCheckinDigest</string>
|
||||
<string name="transmitting_service">Transmitting Service</string>
|
||||
<string name="transmitting_service_start">transmitting_start</string>
|
||||
<string name="transmitting_service_stop">transmitting_stop</string>
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/preference_heading_from_magnetic_key"
|
||||
android:switchTextOn="@string/preference_heading_from_magnetic_key_is_enabled"
|
||||
android:switchTextOff="@string/preference_heading_from_magnetic_key_is_disabled"
|
||||
android:summaryOn="@string/preference_heading_from_magnetic_key_summary_is_enabled"
|
||||
android:summaryOff="@string/preference_heading_from_magnetic_key_summary_is_disabled"
|
||||
android:title="@string/preference_heading_from_magnetic_enabled" />
|
||||
android:key="@string/preference_heading_with_declination_subtracted"
|
||||
android:switchTextOn="@string/preference_heading_with_declination_subtracted_key_is_enabled"
|
||||
android:switchTextOff="@string/preference_heading_with_declination_subtracted_key_is_disabled"
|
||||
android:summaryOn="@string/preference_heading_with_declination_subtracted_key_summary_is_enabled"
|
||||
android:summaryOff="@string/preference_heading_with_declination_subtracted_key_summary_is_disabled"
|
||||
android:title="@string/preference_heading_with_declination_subtracted_enabled" />
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sap.sailing.android.tracking.app.customviews;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class AutoResizeLightTextView extends AutoResizeTextView {
|
||||
|
||||
public AutoResizeLightTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public AutoResizeLightTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public AutoResizeLightTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/OpenSans-Light.ttf"));
|
||||
mTextSize = getTextSize();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class AutoResizeTextView extends TextView {
|
||||
|
||||
// Text size that is set from code. This acts as a starting point for
|
||||
// resizing
|
||||
private float mTextSize;
|
||||
protected float mTextSize;
|
||||
|
||||
// Temporary upper bounds on the starting text size
|
||||
private float mMaxTextSize = 0;
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.android.tracking.app.customviews;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class OpenSansLightTextView extends TextView {
|
||||
|
||||
public OpenSansLightTextView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public OpenSansLightTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public OpenSansLightTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/OpenSans-Light.ttf"));
|
||||
}
|
||||
|
||||
}
|
||||
+4
-44
@@ -12,11 +12,12 @@ public class AnalyticsContract {
|
||||
String COMPETITOR_COUNTRY_CODE = "competitor_country_code";
|
||||
String COMPETITOR_NATIONALITY = "competitor_nationality";
|
||||
String COMPETITOR_SAIL_ID = "competitor_sail_id";
|
||||
String COMPETITOR_LEADERBOARD_FK = "leaderboard_id";
|
||||
String COMPETITOR_CHECKIN_DIGEST = "competitor_checkin_digest";
|
||||
}
|
||||
|
||||
interface LeaderboardColumns {
|
||||
String LEADERBOARD_NAME = "leaderboard_name";
|
||||
String LEADERBOARD_CHECKIN_DIGEST = "leaderboard_checkin_digest";
|
||||
}
|
||||
|
||||
interface EventColumns {
|
||||
@@ -26,44 +27,22 @@ public class AnalyticsContract {
|
||||
String EVENT_SERVER = "event_server";
|
||||
String EVENT_IMAGE_URL = "image_url";
|
||||
String EVENT_NAME = "event_name";
|
||||
String EVENT_LEADERBOARD_FK = "leaderboard_id";
|
||||
}
|
||||
|
||||
interface SensorGpsColumns {
|
||||
String GPS_ACCURACY = "gps_accuracy";
|
||||
String GPS_ALTITUDE = "gps_altitude";
|
||||
String GPS_BEARING = "gps_bearing";
|
||||
String GPS_DEVICE = "gps_device";
|
||||
String GPS_LATITUDE = "gps_latitude";
|
||||
String GPS_LONGITUDE = "gps_longitude";
|
||||
String GPS_PROVIDER = "gps_provider";
|
||||
String GPS_SYNCED = "gps_synced";
|
||||
String GPS_SPEED = "gps_speed";
|
||||
String GPS_TIME = "gps_time";
|
||||
String GPS_EVENT_FK = "event_id";
|
||||
String EVENT_CHECKIN_DIGEST = "event_checkin_digest";
|
||||
}
|
||||
|
||||
public static final String CONTENT_AUTHORITY = "com.sap.sailing.android.tracking.app.provider.db";
|
||||
|
||||
public static final Uri BASE_CONTENT_URI = Uri.parse("content://"
|
||||
+ CONTENT_AUTHORITY);
|
||||
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
|
||||
|
||||
private static final String PATH_COMPETITOR = "competitors";
|
||||
private static final String PATH_EVENT = "events";
|
||||
private static final String PATH_LEADERBOARD = "leaderboards";
|
||||
private static final String PATH_SENSOR_GPS = "sensor_gps";
|
||||
|
||||
|
||||
public static class LeaderboardsEventsJoined {
|
||||
public final static Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
|
||||
.appendPath("leaderboards_events_joined").build();
|
||||
}
|
||||
|
||||
public static class EventGpsFixesJoined {
|
||||
public final static Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
|
||||
.appendPath("event_gps_fix_joined").build();
|
||||
}
|
||||
|
||||
public static class EventLeaderboardCompetitorJoined {
|
||||
public final static Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
|
||||
.appendPath("event_leaderboard_competitor_joined")
|
||||
@@ -120,25 +99,6 @@ public class AnalyticsContract {
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorGps implements SensorGpsColumns, BaseColumns {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
|
||||
.appendPath(PATH_SENSOR_GPS).build();
|
||||
|
||||
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
|
||||
+ "/vnd.sap_sailing_analytics.sensor.gps";
|
||||
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
|
||||
+ "/vnd.sap_sailing_analytics.sensor.gps";
|
||||
public static final String DEFAULT_SORT = BaseColumns._ID + " ASC ";
|
||||
|
||||
public static Uri buildSensorGpsUri(String gpsId) {
|
||||
return CONTENT_URI.buildUpon().appendPath(gpsId).build();
|
||||
}
|
||||
|
||||
public static String getGpsId(Uri uri) {
|
||||
return uri.getPathSegments().get(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Leaderboard implements LeaderboardColumns {
|
||||
public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
|
||||
.appendPath(PATH_LEADERBOARD).build();
|
||||
|
||||
+13
-29
@@ -6,10 +6,12 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Competitor;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.CompetitorColumns;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.EventColumns;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Leaderboard;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.LeaderboardColumns;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.SensorGpsColumns;
|
||||
|
||||
public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
|
||||
@@ -26,13 +28,15 @@ public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
String COMPETITORS = "competitors";
|
||||
String EVENTS = "events";
|
||||
String EVENTS_COMPETITORS = "events_competitors";
|
||||
String SENSOR_GPS = "sensor_gps";
|
||||
String LEADERBOARDS = "leaderboards";
|
||||
String EVENTS_JOIN_LEADERBOARDS_JOIN_COMPETITORS = Tables.LEADERBOARDS +
|
||||
" INNER JOIN " + Tables.EVENTS + " ON (" + Tables.LEADERBOARDS + "." + BaseColumns._ID + " = " + Tables.EVENTS + ".leaderboard_id ) " +
|
||||
" INNER JOIN " + Tables.COMPETITORS + " ON (" + Tables.LEADERBOARDS + "."+ BaseColumns._ID + " = " + Tables.COMPETITORS + ".leaderboard_id ) ";
|
||||
String GPS_FIXES_JOIN_EVENTS = "sensor_gps LEFT JOIN events ON sensor_gps.event_id = events._id ";
|
||||
String LEADERBOARDS_JOIN_EVENTS = "events LEFT JOIN leaderboards ON events.leaderboard_id = leaderboards._id ";
|
||||
" INNER JOIN " + Tables.EVENTS + " ON (" + Tables.LEADERBOARDS + "." + Leaderboard.LEADERBOARD_CHECKIN_DIGEST
|
||||
+ " = " + Tables.EVENTS + "." + Event.EVENT_CHECKIN_DIGEST + ") " +
|
||||
" INNER JOIN " + Tables.COMPETITORS + " ON (" + Tables.LEADERBOARDS + "."+ Leaderboard.LEADERBOARD_CHECKIN_DIGEST
|
||||
+ " = " + Tables.COMPETITORS + "." + Competitor.COMPETITOR_CHECKIN_DIGEST + ") ";
|
||||
|
||||
String LEADERBOARDS_JOIN_EVENTS = "events LEFT JOIN leaderboards ON " + Tables.EVENTS + "." + Event.EVENT_CHECKIN_DIGEST
|
||||
+ " = " + Tables.LEADERBOARDS + "." + Leaderboard.LEADERBOARD_CHECKIN_DIGEST;
|
||||
}
|
||||
|
||||
public AnalyticsDatabase(Context context) {
|
||||
@@ -44,6 +48,7 @@ public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + Tables.LEADERBOARDS + " ("
|
||||
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ LeaderboardColumns.LEADERBOARD_CHECKIN_DIGEST + " TEXT, "
|
||||
+ LeaderboardColumns.LEADERBOARD_NAME + " TEXT );");
|
||||
|
||||
db.execSQL("CREATE TABLE " + Tables.COMPETITORS + " ("
|
||||
@@ -53,9 +58,7 @@ public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
+ CompetitorColumns.COMPETITOR_COUNTRY_CODE + " TEXT, "
|
||||
+ CompetitorColumns.COMPETITOR_NATIONALITY + " TEXT, "
|
||||
+ CompetitorColumns.COMPETITOR_SAIL_ID + " TEXT, "
|
||||
+ CompetitorColumns.COMPETITOR_LEADERBOARD_FK + " INTEGER, "
|
||||
+ "FOREIGN KEY (" + CompetitorColumns.COMPETITOR_LEADERBOARD_FK + ") "
|
||||
+ "REFERENCES " + Tables.LEADERBOARDS + "( " + BaseColumns._ID + " ))");
|
||||
+ CompetitorColumns.COMPETITOR_CHECKIN_DIGEST + " TEXT )");
|
||||
|
||||
db.execSQL("CREATE TABLE " + Tables.EVENTS + " ( "
|
||||
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
@@ -65,25 +68,7 @@ public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
+ EventColumns.EVENT_DATE_END + " INTEGER, "
|
||||
+ EventColumns.EVENT_SERVER + " TEXT, "
|
||||
+ EventColumns.EVENT_IMAGE_URL + " TEXT, "
|
||||
+ EventColumns.EVENT_LEADERBOARD_FK + " INTEGER, "
|
||||
+ "FOREIGN KEY (" + EventColumns.EVENT_LEADERBOARD_FK + ") "
|
||||
+ "REFERENCES " + Tables.LEADERBOARDS + "( " + BaseColumns._ID + " ))");
|
||||
|
||||
db.execSQL("CREATE TABLE " + Tables.SENSOR_GPS + " ( "
|
||||
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
+ SensorGpsColumns.GPS_ACCURACY + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_ALTITUDE + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_BEARING + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_DEVICE + " TEXT, "
|
||||
+ SensorGpsColumns.GPS_LATITUDE + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_LONGITUDE + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_PROVIDER + " TEXT, "
|
||||
+ SensorGpsColumns.GPS_SPEED + " DOUBLE, "
|
||||
+ SensorGpsColumns.GPS_SYNCED + " INTEGER DEFAULT 0, "
|
||||
+ SensorGpsColumns.GPS_TIME + " INTEGER, "
|
||||
+ SensorGpsColumns.GPS_EVENT_FK + " INTEGER, "
|
||||
+ "FOREIGN KEY (" + SensorGpsColumns.GPS_EVENT_FK + ") "
|
||||
+ "REFERENCES " + Tables.EVENTS + "( " + EventColumns.EVENT_ID + " ))");
|
||||
+ EventColumns.EVENT_CHECKIN_DIGEST + " TEXT )");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,7 +82,6 @@ public class AnalyticsDatabase extends SQLiteOpenHelper {
|
||||
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Tables.COMPETITORS);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Tables.EVENTS);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Tables.SENSOR_GPS);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Tables.LEADERBOARDS);
|
||||
|
||||
onCreate(db);
|
||||
|
||||
+5
-52
@@ -18,7 +18,6 @@ import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Competitor;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Leaderboard;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.SensorGps;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsDatabase.Tables;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
|
||||
@@ -42,9 +41,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
private static final int MESSAGE = 400;
|
||||
private static final int MESSAGE_ID = 401;
|
||||
|
||||
private static final int SENSOR_GPS = 500;
|
||||
private static final int SENSOR_GPS_ID = 501;
|
||||
|
||||
private static final int EVENT_LEADERBOARD_COMPETITOR_JOINED = 600;
|
||||
|
||||
private static final int EVENT_GPS_FIXES_JOINED = 700;
|
||||
@@ -67,9 +63,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
matcher.addURI(authority, "messages", MESSAGE);
|
||||
matcher.addURI(authority, "messages/#", MESSAGE_ID);
|
||||
|
||||
matcher.addURI(authority, "sensor_gps", SENSOR_GPS);
|
||||
matcher.addURI(authority, "sensor_gps/#", SENSOR_GPS_ID);
|
||||
|
||||
matcher.addURI(authority, "event_leaderboard_competitor_joined", EVENT_LEADERBOARD_COMPETITOR_JOINED);
|
||||
|
||||
matcher.addURI(authority, "event_gps_fix_joined", EVENT_GPS_FIXES_JOINED);
|
||||
@@ -112,12 +105,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
cursor = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
|
||||
return cursor;
|
||||
|
||||
case EVENT_GPS_FIXES_JOINED:
|
||||
SQLiteQueryBuilder eb = new SQLiteQueryBuilder();
|
||||
eb.setTables(Tables.GPS_FIXES_JOIN_EVENTS);
|
||||
cursor = eb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
|
||||
return cursor;
|
||||
|
||||
case LEADERBOARDS_EVENTS_JOINED:
|
||||
SQLiteQueryBuilder el = new SQLiteQueryBuilder();
|
||||
el.setTables(Tables.LEADERBOARDS_JOIN_EVENTS);
|
||||
@@ -161,12 +148,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
case LEADERBOARD_ID:
|
||||
return Leaderboard.CONTENT_ITEM_TYPE;
|
||||
|
||||
case SENSOR_GPS:
|
||||
return SensorGps.CONTENT_TYPE;
|
||||
|
||||
case SENSOR_GPS_ID:
|
||||
return SensorGps.CONTENT_ITEM_TYPE;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown uri: " + uri);
|
||||
}
|
||||
@@ -183,9 +164,9 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
case COMPETITOR:
|
||||
db.insertOrThrow(Tables.COMPETITORS, null, values);
|
||||
long competitorId = db.insertOrThrow(Tables.COMPETITORS, null, values);
|
||||
notifyChange(uri);
|
||||
return Competitor.buildCompetitorUri(values.getAsString(Competitor.COMPETITOR_ID));
|
||||
return Competitor.buildCompetitorUri(String.valueOf(competitorId));
|
||||
|
||||
case EVENT:
|
||||
long eventId = db.insertOrThrow(Tables.EVENTS, null, values);
|
||||
@@ -193,14 +174,9 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
return Event.buildEventUri(String.valueOf(eventId));
|
||||
|
||||
case LEADERBOARD:
|
||||
db.insertOrThrow(Tables.LEADERBOARDS, null, values);
|
||||
long leaderboardId = db.insertOrThrow(Tables.LEADERBOARDS, null, values);
|
||||
notifyChange(uri);
|
||||
return Leaderboard.buildLeaderboardUri(values.getAsString(BaseColumns._ID));
|
||||
|
||||
case SENSOR_GPS:
|
||||
db.insertOrThrow(Tables.SENSOR_GPS, null, values);
|
||||
notifyChange(uri);
|
||||
return SensorGps.buildSensorGpsUri("XX");
|
||||
return Leaderboard.buildLeaderboardUri(String.valueOf(leaderboardId));
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown uri: " + uri);
|
||||
@@ -218,18 +194,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
|
||||
case SENSOR_GPS:
|
||||
int numGpsFixesDeleted = db.delete(Tables.SENSOR_GPS, selection, selectionArgs);
|
||||
notifyChange(uri);
|
||||
return numGpsFixesDeleted;
|
||||
|
||||
case SENSOR_GPS_ID:
|
||||
String idStr = uri.getLastPathSegment();
|
||||
String where = SensorGps._ID + " = " + idStr;
|
||||
int numGpsFixesWithIdDeleted = db.delete(Tables.SENSOR_GPS, where, selectionArgs);
|
||||
notifyChange(uri);
|
||||
return numGpsFixesWithIdDeleted;
|
||||
|
||||
case COMPETITOR:
|
||||
int numCompetitorRowsDeleted = db.delete(Tables.COMPETITORS, selection, selectionArgs);
|
||||
@@ -260,17 +224,9 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
ExLog.i(getContext(), TAG, message);
|
||||
}
|
||||
|
||||
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
//final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
|
||||
|
||||
switch (sUriMatcher.match(uri)) {
|
||||
|
||||
case SENSOR_GPS_ID:
|
||||
String idStr = uri.getLastPathSegment();
|
||||
String where = SensorGps._ID + " = " + idStr;
|
||||
int numRowsAffected = db.update(Tables.SENSOR_GPS, values, where, selectionArgs);
|
||||
notifyChange(uri);
|
||||
return numRowsAffected;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown uri: " + uri);
|
||||
}
|
||||
@@ -308,9 +264,6 @@ public class AnalyticsProvider extends ContentProvider {
|
||||
return builder.table(Tables.EVENTS)
|
||||
.where(Event.EVENT_ID + " = ?", event_id);
|
||||
|
||||
case SENSOR_GPS:
|
||||
return builder.table(Tables.SENSOR_GPS);
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown uri: " + uri);
|
||||
}
|
||||
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.sensors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
|
||||
public class CompassManager implements SensorEventListener {
|
||||
//private final static String TAG = CompassManager.class.getName();
|
||||
|
||||
private static CompassManager mInstance;
|
||||
private Context mContext;
|
||||
|
||||
private SensorManager sensorManager;
|
||||
private Sensor gsensor;
|
||||
private Sensor msensor;
|
||||
private float[] mGravity = new float[3];
|
||||
private float[] mGeomagnetic = new float[3];
|
||||
private float azimuth = 0f;
|
||||
|
||||
private MagneticHeadingListener listener;
|
||||
|
||||
public static synchronized CompassManager getInstance(Context context) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new CompassManager(context);
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
private CompassManager(Context context) {
|
||||
mContext = context;
|
||||
sensorManager = (SensorManager) mContext
|
||||
.getSystemService(Context.SENSOR_SERVICE);
|
||||
gsensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
msensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
|
||||
}
|
||||
|
||||
public void registerListener(MagneticHeadingListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
start();
|
||||
}
|
||||
|
||||
public void unregisterListener()
|
||||
{
|
||||
stop();
|
||||
this.listener = null;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
sensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_GAME);
|
||||
sensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_GAME);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
sensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
final float alpha = 0.97f;
|
||||
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
|
||||
mGravity[0] = alpha * mGravity[0] + (1 - alpha) * event.values[0];
|
||||
mGravity[1] = alpha * mGravity[1] + (1 - alpha) * event.values[1];
|
||||
mGravity[2] = alpha * mGravity[2] + (1 - alpha) * event.values[2];
|
||||
}
|
||||
|
||||
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
|
||||
mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha) * event.values[0];
|
||||
mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha) * event.values[1];
|
||||
mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha) * event.values[2];
|
||||
}
|
||||
|
||||
float R[] = new float[9];
|
||||
float I[] = new float[9];
|
||||
|
||||
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
|
||||
if (success) {
|
||||
float orientation[] = new float[3];
|
||||
SensorManager.getOrientation(R, orientation);
|
||||
azimuth = (float) Math.toDegrees(orientation[0]); // orientation
|
||||
azimuth = (azimuth + 360) % 360;
|
||||
listener.magneticHeadingUpdated(azimuth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public interface MagneticHeadingListener {
|
||||
public void magneticHeadingUpdated(float heading);
|
||||
}
|
||||
}
|
||||
+269
-182
@@ -1,14 +1,22 @@
|
||||
package com.sap.sailing.android.tracking.app.services;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
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.IntentFilter;
|
||||
import android.hardware.GeomagneticField;
|
||||
import android.location.Location;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -16,242 +24,321 @@ import android.os.IBinder;
|
||||
import android.widget.Toast;
|
||||
|
||||
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.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService;
|
||||
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.LaunchActivity;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
import com.sap.sailing.android.tracking.app.utils.DatabaseHelper;
|
||||
import com.sap.sailing.android.tracking.app.utils.ServiceHelper;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.EventInfo;
|
||||
|
||||
public class TrackingService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
|
||||
|
||||
private GoogleApiClient googleApiClient;
|
||||
private LocationRequest locationRequest;
|
||||
private NotificationManager notificationManager;
|
||||
private boolean locationUpdateRequested = false;
|
||||
private AppPreferences prefs;
|
||||
private ScheduledExecutorService scheduler;
|
||||
private GoogleApiClient googleApiClient;
|
||||
private LocationRequest locationRequest;
|
||||
private NotificationManager notificationManager;
|
||||
private boolean locationUpdateRequested = false;
|
||||
private AppPreferences prefs;
|
||||
private ScheduledExecutorService scheduler;
|
||||
|
||||
private GPSQualityListener gpsQualityListener;
|
||||
private final IBinder trackingBinder = new TrackingBinder();
|
||||
private GPSQualityListener gpsQualityListener;
|
||||
private final IBinder trackingBinder = new TrackingBinder();
|
||||
|
||||
private static final String TAG = TrackingService.class.getName();
|
||||
private static final String TAG = TrackingService.class.getName();
|
||||
|
||||
public static final String WEB_SERVICE_PATH = "/sailingserver/api/v1/gps_fixes";
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION_ID = R.string.tracker_started;
|
||||
public static final String WEB_SERVICE_PATH = "/sailingserver/api/v1/gps_fixes";
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION_ID = R.string.tracker_started;
|
||||
|
||||
private final int UPDATE_INTERVAL_DEFAULT = 3000;
|
||||
private final int UPDATE_INTERVAL_POWERSAVE_MODE = 30000;
|
||||
private final float BATTERY_POWER_SAVE_TRESHOLD = 0.2f;
|
||||
|
||||
private String eventId;
|
||||
private long eventRowId;
|
||||
private String checkinDigest;
|
||||
private EventInfo event;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
prefs = new AppPreferences(this);
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
prefs = new AppPreferences(this);
|
||||
|
||||
// http://developer.android.com/training/location/receive-location-updates.html
|
||||
locationRequest = LocationRequest.create();
|
||||
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
||||
locationRequest.setInterval(prefs.getGPSFixInterval());
|
||||
locationRequest.setFastestInterval(prefs.getGPSFixFastestInterval());
|
||||
// http://developer.android.com/training/location/receive-location-updates.html
|
||||
locationRequest = LocationRequest.create();
|
||||
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
||||
locationRequest.setInterval(prefs.getGPSFixInterval());
|
||||
locationRequest.setFastestInterval(prefs.getGPSFixFastestInterval());
|
||||
|
||||
googleApiClient = new GoogleApiClient.Builder(this)
|
||||
googleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addApi(LocationServices.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
.build();
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
}
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
if (intent != null) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Starting Tracking Service with eventId: " + eventId);
|
||||
}
|
||||
if (intent != null) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Starting Tracking Service with checkinDigest: " + checkinDigest);
|
||||
}
|
||||
|
||||
if (intent.getAction() != null) {
|
||||
if (intent.getAction().equals(getString(R.string.tracking_service_stop))) {
|
||||
stopTracking();
|
||||
} else {
|
||||
if (intent.getExtras() != null) {
|
||||
eventId = intent.getExtras().getString(getString(R.string.tracking_service_event_id_parameter));
|
||||
if (intent.getAction() != null) {
|
||||
if (intent.getAction().equals(
|
||||
getString(R.string.tracking_service_stop))) {
|
||||
stopTracking();
|
||||
} else {
|
||||
if (intent.getExtras() != null) {
|
||||
checkinDigest = intent
|
||||
.getExtras()
|
||||
.getString(getString(R.string.tracking_service_checkin_digest_parameter));
|
||||
|
||||
event = DatabaseHelper.getInstance().getEventInfo(this, checkinDigest);
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Starting Tracking Service with checkinDigest: "+ checkinDigest);
|
||||
}
|
||||
|
||||
startTracking();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopTracking();
|
||||
}
|
||||
}
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
eventRowId = DatabaseHelper.getInstance().getRowIdForEventId(this, eventId);
|
||||
public void startTracking() {
|
||||
googleApiClient.connect();
|
||||
locationUpdateRequested = true;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Starting Tracking Service with eventId: " + eventId);
|
||||
ExLog.i(this, TAG, "And with event._id: " + eventRowId);
|
||||
}
|
||||
ExLog.i(this, TAG, "Started Tracking");
|
||||
// showNotification();
|
||||
|
||||
startTracking();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopTracking();
|
||||
}
|
||||
}
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
prefs.setTrackerIsTracking(true);
|
||||
prefs.setTrackerIsTrackingCheckinDigest(checkinDigest);
|
||||
}
|
||||
|
||||
public void startTracking() {
|
||||
googleApiClient.connect();
|
||||
locationUpdateRequested = true;
|
||||
public void stopTracking() {
|
||||
if (googleApiClient.isConnected()) {
|
||||
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
|
||||
}
|
||||
googleApiClient.disconnect();
|
||||
locationUpdateRequested = false;
|
||||
|
||||
ExLog.i(this, TAG, "Started Tracking");
|
||||
// showNotification();
|
||||
if (scheduler != null) {
|
||||
scheduler.shutdown();
|
||||
}
|
||||
|
||||
prefs.setTrackerIsTracking(true);
|
||||
prefs.setTrackerIsTrackingEventId(eventId);
|
||||
}
|
||||
prefs.setTrackerIsTracking(false);
|
||||
prefs.setTrackerIsTrackingCheckinDigest(null);
|
||||
|
||||
public void stopTracking() {
|
||||
if (googleApiClient.isConnected()) {
|
||||
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
|
||||
}
|
||||
googleApiClient.disconnect();
|
||||
locationUpdateRequested = false;
|
||||
stopSelf();
|
||||
ExLog.i(this, TAG, "Stopped Tracking");
|
||||
}
|
||||
|
||||
if (scheduler != null) {
|
||||
scheduler.shutdown();
|
||||
}
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult arg0) {
|
||||
ExLog.e(this, TAG,
|
||||
"Failed to connect to Google Play Services for location updates");
|
||||
}
|
||||
|
||||
prefs.setTrackerIsTracking(false);
|
||||
prefs.setTrackerIsTrackingEventId(null);
|
||||
|
||||
stopSelf();
|
||||
ExLog.i(this, TAG, "Stopped Tracking");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult arg0) {
|
||||
ExLog.e(this, TAG, "Failed to connect to Google Play Services for location updates");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle arg0) {
|
||||
if (locationUpdateRequested) {
|
||||
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onConnected(Bundle arg0) {
|
||||
if (locationUpdateRequested) {
|
||||
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int i) {
|
||||
|
||||
}
|
||||
|
||||
public void reportGPSQualityBearingAndSpeed(float gpsAccurracy, float bearing, float speed) {
|
||||
GPSQuality quality = GPSQuality.noSignal;
|
||||
if (gpsQualityListener != null) {
|
||||
if (gpsAccurracy > 48) {
|
||||
quality = GPSQuality.poor;
|
||||
} else if (gpsAccurracy > 10) {
|
||||
quality = GPSQuality.good;
|
||||
} else if (gpsAccurracy <= 10) {
|
||||
quality = GPSQuality.great;
|
||||
}
|
||||
public void reportGPSQualityBearingAndSpeed(float gpsAccurracy, float bearing, float speed, double latitude, double longitude, double altitude) {
|
||||
|
||||
if (prefs.getDisplayHeadingWithSubtractedDeclination())
|
||||
{
|
||||
GeomagneticField geomagneticField = new GeomagneticField((float)latitude, (float)longitude, (float)altitude, System.currentTimeMillis());
|
||||
bearing = bearing - geomagneticField.getDeclination();
|
||||
}
|
||||
|
||||
GPSQuality quality = GPSQuality.noSignal;
|
||||
if (gpsQualityListener != null) {
|
||||
if (gpsAccurracy > 48) {
|
||||
quality = GPSQuality.poor;
|
||||
} else if (gpsAccurracy > 10) {
|
||||
quality = GPSQuality.good;
|
||||
} else if (gpsAccurracy <= 10) {
|
||||
quality = GPSQuality.great;
|
||||
}
|
||||
|
||||
gpsQualityListener.gpsQualityAndAccurracyUpdated(quality, gpsAccurracy, bearing, speed);
|
||||
}
|
||||
}
|
||||
gpsQualityListener.gpsQualityAndAccurracyUpdated(quality, gpsAccurracy, bearing, speed);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
updateResendIntervalSetting();
|
||||
reportGPSQualityBearingAndSpeed(location.getAccuracy(), location.getBearing(),
|
||||
location.getSpeed(), location.getLatitude(), location.getLongitude(),
|
||||
location.getAltitude());
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
JSONObject fixJson = new JSONObject();
|
||||
|
||||
reportGPSQualityBearingAndSpeed(location.getAccuracy(), location.getBearing(), location.getSpeed());
|
||||
fixJson.put("course", location.getBearing());
|
||||
fixJson.put("timestamp", location.getTime());
|
||||
fixJson.put("speed", location.getSpeed());
|
||||
fixJson.put("longitude", location.getLongitude());
|
||||
fixJson.put("latitude", location.getLatitude());
|
||||
|
||||
DatabaseHelper.getInstance().insertGPSFix(this, location.getLatitude(), location.getLongitude(),
|
||||
location.getSpeed(), location.getBearing(), location.getProvider(), location.getTime(), eventRowId);
|
||||
jsonArray.put(fixJson);
|
||||
|
||||
ensureTransmittingServiceIsRunning();
|
||||
}
|
||||
json.put("fixes", jsonArray);
|
||||
json.put("deviceUuid", prefs.getDeviceIdentifier());
|
||||
|
||||
/**
|
||||
* start transmitting service when a new fix arrives, because it ends itself, if there's no data to send.
|
||||
*/
|
||||
private void ensureTransmittingServiceIsRunning() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "ensureTransmittingServiceIsRunning, starting TransmittingService");
|
||||
}
|
||||
String postUrlStr = event.server + prefs.getServerGpsFixesPostPath();
|
||||
|
||||
ServiceHelper.getInstance().startTransmittingService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return trackingBinder;
|
||||
}
|
||||
startService(MessageSendingService.createMessageIntent(this, postUrlStr,
|
||||
null, UUID.randomUUID(), json.toString(), null));
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopTracking();
|
||||
notificationManager.cancel(NOTIFICATION_ID);
|
||||
Toast.makeText(this, R.string.tracker_stopped, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (JSONException ex) {
|
||||
ExLog.i(this, TAG, "Error while building geolocation json " + ex.getMessage());
|
||||
}
|
||||
|
||||
// DatabaseHelper.getInstance().insertGPSFix(this, location.getLatitude(),
|
||||
// location.getLongitude(), location.getSpeed(),
|
||||
// location.getBearing(), location.getProvider(),
|
||||
// location.getTime(), eventRowId);
|
||||
// ensureTransmittingServiceIsRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update whether message sending service should retry every 3 seconds or
|
||||
* every 30.
|
||||
*/
|
||||
private void updateResendIntervalSetting() {
|
||||
float batteryPct = getBatteryPercentage();
|
||||
boolean batteryIsCharging = prefs.getBatteryIsCharging();
|
||||
|
||||
int updateInterval = UPDATE_INTERVAL_DEFAULT;
|
||||
|
||||
if (prefs.getEnergySavingEnabledByUser() ||
|
||||
(batteryPct < BATTERY_POWER_SAVE_TRESHOLD && !batteryIsCharging)) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "POWER-LEVELS", "in power saving mode");
|
||||
}
|
||||
|
||||
// private void showNotification() {
|
||||
// Intent intent = new Intent(this, RegattaActivity.class);
|
||||
// intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
// | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
// PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
// CharSequence text = getText(R.string.tracker_started);
|
||||
// Notification notification = new NotificationCompat.Builder(this)
|
||||
// .setContentTitle(getText(R.string.app_name))
|
||||
// .setContentText(text).setContentIntent(pi)
|
||||
// .setSmallIcon(R.drawable.icon).build();
|
||||
// notification.flags |= Notification.FLAG_NO_CLEAR;
|
||||
// startForeground(NOTIFICATION_ID, notification);
|
||||
// }
|
||||
updateInterval = UPDATE_INTERVAL_POWERSAVE_MODE;
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "POWER-LEVELS", "in default power mode");
|
||||
}
|
||||
}
|
||||
|
||||
prefs.setMessageResendInterval(updateInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get battery charging level
|
||||
* @return battery charging level in interval [0,1]
|
||||
*/
|
||||
private float getBatteryPercentage() {
|
||||
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
Intent batteryStatus = this.registerReceiver(null, ifilter);
|
||||
|
||||
public void registerGPSQualityListener(GPSQualityListener listener) {
|
||||
gpsQualityListener = listener;
|
||||
}
|
||||
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
|
||||
|
||||
public void unregisterGPSQualityListener() {
|
||||
gpsQualityListener = null;
|
||||
}
|
||||
float batteryPct = level / (float) scale;
|
||||
|
||||
public class TrackingBinder extends Binder {
|
||||
public TrackingService getService() {
|
||||
return TrackingService.this;
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Battery: " + (batteryPct * 100) + "%");
|
||||
}
|
||||
|
||||
public enum GPSQuality {
|
||||
noSignal(0), poor(2), good(3), great(4);
|
||||
return batteryPct;
|
||||
}
|
||||
|
||||
private final int gpsQuality;
|
||||
/**
|
||||
* start transmitting service when a new fix arrives, because it ends
|
||||
* itself, if there's no data to send.
|
||||
*/
|
||||
// private void ensureTransmittingServiceIsRunning() {
|
||||
// if (BuildConfig.DEBUG) {
|
||||
// ExLog.i(this, TAG,
|
||||
// "ensureTransmittingServiceIsRunning, starting TransmittingService");
|
||||
// }
|
||||
//
|
||||
// ServiceHelper.getInstance().startTransmittingService(this);
|
||||
// }
|
||||
|
||||
GPSQuality(int quality) {
|
||||
this.gpsQuality = quality;
|
||||
}
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return trackingBinder;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.gpsQuality;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopTracking();
|
||||
notificationManager.cancel(NOTIFICATION_ID);
|
||||
Toast.makeText(this, R.string.tracker_stopped, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
public interface GPSQualityListener {
|
||||
public void gpsQualityAndAccurracyUpdated(GPSQuality quality, float gpsAccurracy, float gpsBearing,
|
||||
float gpsSpeed);
|
||||
}
|
||||
// private void showNotification() {
|
||||
// Intent intent = new Intent(this, RegattaActivity.class);
|
||||
// intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
// | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
// PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
// CharSequence text = getText(R.string.tracker_started);
|
||||
// Notification notification = new NotificationCompat.Builder(this)
|
||||
// .setContentTitle(getText(R.string.app_name))
|
||||
// .setContentText(text).setContentIntent(pi)
|
||||
// .setSmallIcon(R.drawable.icon).build();
|
||||
// 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 gpsQualityAndAccurracyUpdated(GPSQuality quality, float gpsAccurracy, float gpsBearing, float gpsSpeed);
|
||||
}
|
||||
|
||||
private void showNotification() {
|
||||
CharSequence text = getText(R.string.tracker_started);
|
||||
Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());
|
||||
Intent i = new Intent(this, LaunchActivity.class);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
|
||||
notification.setLatestEventInfo(this, getText(R.string.app_name), text, pi);
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR;
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
-559
@@ -1,559 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.services;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.sap.sailing.android.shared.data.http.HttpJsonPostRequest;
|
||||
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.sending.ConnectivityChangedReceiver;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
import com.sap.sailing.android.tracking.app.utils.DatabaseHelper;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperError;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperFailureListener;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperSuccessListener;
|
||||
import com.sap.sailing.android.tracking.app.utils.UniqueDeviceUuid;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.GpsFix;
|
||||
|
||||
/**
|
||||
* Service that handles sending of GPS-fixes (fixes) to the Sailing-API.
|
||||
*
|
||||
* It checks, after a certain time-interval has passed, if any fixes are
|
||||
* available in the database and attempts to send them batch-wise.
|
||||
*
|
||||
* (There are two strategies for sending, depending on whether tracking is
|
||||
* running. If it's running, only fixes for the current event are being sent. If
|
||||
* not, it tries to send fixes for previous events, as well. Assuming there are
|
||||
* older unsent fixes that for some reason have not been sent.)
|
||||
*
|
||||
* It keeps track of when the last successful sending occurred and, if no new
|
||||
* data is available (i.e., if tracking is disabled), ends itself after a
|
||||
* certain period. It relies on being restarted by the {@link TrackingService}.
|
||||
*
|
||||
* It also ends itself when connectivity is lost. In that case it relies on
|
||||
* being restarted by the {@link ConnectivityChangedReceiver}.
|
||||
*
|
||||
* It switches into a power saving mode, if a certain battery discharge is
|
||||
* reached. It does, however, not do so, if the device is plugged in (= when it
|
||||
* is charging). The power saving mode causes the time-interval between check-
|
||||
* and transmit-cycles to be increased to conserve power.
|
||||
*
|
||||
* @author Lukas Zielinski
|
||||
*
|
||||
*/
|
||||
public class TransmittingService extends Service {
|
||||
|
||||
private static final String TAG = TransmittingService.class.getName();
|
||||
|
||||
private final int UPDATE_BATCH_SIZE = 1000;
|
||||
private final int UPDATE_INTERVAL_DEFAULT = 3000;
|
||||
private final int UPDATE_INTERVAL_POWERSAVE_MODE = 30000;
|
||||
private final long AUTO_END_SERVICE_AFTER_NANO_PASSED = 10000000000L; // 10
|
||||
// sec
|
||||
private final float BATTERY_POWER_SAVE_TRESHOLD = 0.2f;
|
||||
|
||||
private int currentUpdateInterval = UPDATE_INTERVAL_DEFAULT;
|
||||
|
||||
private boolean sendingAttempted = false;
|
||||
private boolean lastTransmissionFailed = false;
|
||||
private long lastTransmissionTimestamp = 0;
|
||||
|
||||
private AppPreferences prefs;
|
||||
private Timer timer;
|
||||
private boolean timerRunning;
|
||||
|
||||
private APIConnectivityListener apiConnectivityListener;
|
||||
private final IBinder transmittingBinder = new TransmittingBinder();
|
||||
|
||||
/**
|
||||
* True if sending, because if sending takes longer a new attempt should not
|
||||
* be made.
|
||||
*/
|
||||
private static boolean currentlySending = false;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
prefs = new AppPreferences(this);
|
||||
|
||||
if (!timerRunning) {
|
||||
startTimer();
|
||||
}
|
||||
|
||||
return transmittingBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
prefs = new AppPreferences(this);
|
||||
|
||||
if (intent != null) {
|
||||
if (intent.getAction() != null) {
|
||||
if (intent.getAction().equals(getString(R.string.transmitting_service_start))) {
|
||||
if (!timerRunning) {
|
||||
startTimer();
|
||||
}
|
||||
} else {
|
||||
stopTimer();
|
||||
}
|
||||
} else {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
timer = new Timer();
|
||||
timer.start();
|
||||
timerRunning = true;
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TIMER", "Background update-timer start");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timerRunning = false;
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TIMER", "Background update-timer stop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void markSuccessfulTransmission() {
|
||||
currentlySending = false;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "markSuccessfulTransmission");
|
||||
}
|
||||
|
||||
lastTransmissionFailed = false;
|
||||
lastTransmissionTimestamp = System.nanoTime();
|
||||
|
||||
reportApiConnectivity(APIConnectivity.reachableTransmissionSuccess);
|
||||
}
|
||||
|
||||
private void markFailedTransmission() {
|
||||
currentlySending = false;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "markFailedTransmission");
|
||||
}
|
||||
|
||||
lastTransmissionFailed = true;
|
||||
lastTransmissionTimestamp = 0;
|
||||
|
||||
if (isConnected()) {
|
||||
reportApiConnectivity(APIConnectivity.reachableTransmissionError);
|
||||
} else {
|
||||
reportApiConnectivity(APIConnectivity.notReachable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If time interval has passed without any transmission, the service can
|
||||
* turn itself off. Same for
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean serviceCanShutItselfDown() {
|
||||
long currentNanoTime = System.nanoTime();
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "serviceCanShutItselfDown?");
|
||||
ExLog.i(this, "TRANSMISSION", "DELTA:" + (currentNanoTime - lastTransmissionTimestamp));
|
||||
}
|
||||
|
||||
// if network is not connected, shutdown. ConnevtivityChangedReceiver
|
||||
// should restart us.
|
||||
if (!isConnected()) {
|
||||
enabledConnectivityReceiver(); // make sure ConnectivityReceiver is
|
||||
// running
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we had a failure, never go to sleep until data is sent
|
||||
// successfully.
|
||||
if (lastTransmissionFailed) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "returning false, have failed transmission");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sendingAttempted) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "returning true, no sending attempt");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentNanoTime - lastTransmissionTimestamp > AUTO_END_SERVICE_AFTER_NANO_PASSED) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "returning true, timeout");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "returning false, don't terminate");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void timerFired() {
|
||||
float batteryPct = getBatteryPercentage();
|
||||
boolean batteryIsCharging = prefs.getBatteryIsCharging();
|
||||
|
||||
if (prefs.getEnergySavingEnabledByUser()
|
||||
|| (batteryPct < BATTERY_POWER_SAVE_TRESHOLD && !batteryIsCharging)) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "POWER-LEVELS", "in power saving mode");
|
||||
}
|
||||
|
||||
currentUpdateInterval = UPDATE_INTERVAL_POWERSAVE_MODE;
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "POWER-LEVELS", "in default power mode");
|
||||
}
|
||||
|
||||
currentUpdateInterval = UPDATE_INTERVAL_DEFAULT;
|
||||
}
|
||||
|
||||
sendFixesToAPI(null);
|
||||
reportUnsentGPSFixesCount(DatabaseHelper.getInstance().getNumberOfUnsentGPSFixes(
|
||||
getBaseContext()));
|
||||
}
|
||||
|
||||
private boolean getTrackingServiceIsCurrentlyTracking() {
|
||||
return prefs.getTrackerIsTracking();
|
||||
}
|
||||
|
||||
private void sendFixesToAPI(List<String> failedHosts) {
|
||||
// first, lets fetch all unsent fixes
|
||||
List<GpsFix> fixes = DatabaseHelper.getInstance().getUnsentFixes(getBaseContext(),
|
||||
failedHosts, UPDATE_BATCH_SIZE);
|
||||
// store ids so we can delete the rows later
|
||||
ArrayList<String> ids = new ArrayList<String>();
|
||||
|
||||
// create JSON
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
String currentEventId = null;
|
||||
String host = null;
|
||||
|
||||
for (GpsFix fix : fixes) {
|
||||
if (currentEventId == null) {
|
||||
currentEventId = fix.eventId;
|
||||
host = fix.host;
|
||||
}
|
||||
|
||||
if (currentEventId.equals(fix.eventId)) {
|
||||
// still have more unsent Gps-Fixes for this event.
|
||||
ids.add(String.valueOf(fix.id));
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("course", fix.course);
|
||||
json.put("timestamp", fix.timestamp);
|
||||
json.put("speed", fix.speed);
|
||||
json.put("longitude", fix.longitude);
|
||||
json.put("latitude", fix.latitude);
|
||||
} catch (JSONException ex) {
|
||||
ExLog.i(this, TAG, "Error while building geolocation json " + ex.getMessage());
|
||||
}
|
||||
|
||||
jsonArray.put(json);
|
||||
} else {
|
||||
// we don't have any more Gps-fixes for this batch, end
|
||||
// collection, proceed with sending.
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (jsonArray.length() > 0) {
|
||||
// send
|
||||
String[] idsArr = new String[ids.size()];
|
||||
|
||||
JSONObject requestObject = new JSONObject();
|
||||
|
||||
try {
|
||||
requestObject.put("deviceUuid", UniqueDeviceUuid.getUniqueId(this));
|
||||
requestObject.put("fixes", jsonArray);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "sending gps fix json: " + requestObject.toString());
|
||||
ExLog.i(this, TAG,
|
||||
"url: " + prefs.getServerURL() + prefs.getServerGpsFixesPostPath());
|
||||
}
|
||||
|
||||
if (host != null) {
|
||||
if (currentlySending == true)
|
||||
{
|
||||
ExLog.w(this, TAG, "Warning, can't send fixes, currentlySending flag is set!");
|
||||
}
|
||||
else
|
||||
{
|
||||
currentlySending = true;
|
||||
sendingAttempted = true; // will be set to false in the listeners
|
||||
|
||||
HttpJsonPostRequest request;
|
||||
try {
|
||||
request = new HttpJsonPostRequest(new URL(host
|
||||
+ prefs.getServerGpsFixesPostPath()), requestObject.toString(), this);
|
||||
|
||||
|
||||
NetworkHelper.getInstance(this).executeHttpJsonRequestAsnchronously(
|
||||
request,
|
||||
new FixSubmitListener(ids.toArray(idsArr)),
|
||||
new FixSubmitErrorListener(host,
|
||||
getTrackingServiceIsCurrentlyTracking(), failedHosts));
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
ExLog.w(this, TAG, "Warning, can't send fixes, MalformedURLException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ExLog.w(this, TAG, "Warning, can't send fixes, host is null!");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (serviceCanShutItselfDown()) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this,
|
||||
TAG,
|
||||
"Nothing to send or timeout occurred, Transmitting Service is stopping timer and terminating itself.");
|
||||
}
|
||||
|
||||
stopTimer();
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a count of ALL unsent GPS-fixes.
|
||||
*
|
||||
* This method is only interested in the GPS-fixes for the currently tracked
|
||||
* event, and needs to find out the id of that event first.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
private float getBatteryPercentage() {
|
||||
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
Intent batteryStatus = this.registerReceiver(null, ifilter);
|
||||
|
||||
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
|
||||
|
||||
float batteryPct = level / (float) scale;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Battery: " + (batteryPct * 100) + "%");
|
||||
}
|
||||
|
||||
return batteryPct;
|
||||
}
|
||||
|
||||
private void deleteSynced(String[] fixIdStrings) {
|
||||
DatabaseHelper.getInstance().deleteGpsFixes(getBaseContext(), fixIdStrings);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if there is network connectivity
|
||||
*
|
||||
* @return connectivity check value
|
||||
*/
|
||||
private boolean isConnected() {
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
|
||||
if (activeNetwork == null) {
|
||||
return false;
|
||||
}
|
||||
return activeNetwork.isConnected();
|
||||
}
|
||||
|
||||
private void enabledConnectivityReceiver() {
|
||||
ConnectivityChangedReceiver.enable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report API connectivity to listening activity
|
||||
*
|
||||
* @param apiConnectivity
|
||||
*/
|
||||
private void reportApiConnectivity(APIConnectivity apiConnectivity) {
|
||||
if (apiConnectivityListener != null) {
|
||||
apiConnectivityListener.apiConnectivityUpdated(apiConnectivity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report the number of currently unsent GPS-fixes
|
||||
*
|
||||
* @param unsentGPSFixesCount
|
||||
*/
|
||||
private void reportUnsentGPSFixesCount(int unsentGPSFixesCount) {
|
||||
if (apiConnectivityListener != null) {
|
||||
apiConnectivityListener.setUnsentGPSFixesCount(unsentGPSFixesCount);
|
||||
}
|
||||
}
|
||||
|
||||
// might need this class in the future:
|
||||
//
|
||||
// private void markAsSynced(String[] fixIdStrings)
|
||||
// {
|
||||
// for (String idStr: fixIdStrings)
|
||||
// {
|
||||
// ContentValues updateValues = new ContentValues();
|
||||
// updateValues.put(SensorGps.GPS_SYNCED, 1);
|
||||
// Uri uri = ContentUris.withAppendedId(SensorGps.CONTENT_URI,
|
||||
// Long.parseLong(idStr));
|
||||
// getContentResolver().update(uri, updateValues, null, null);
|
||||
// }
|
||||
// }
|
||||
|
||||
private class FixSubmitListener implements NetworkHelperSuccessListener {
|
||||
private String[] ids;
|
||||
|
||||
public FixSubmitListener(String[] ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(JSONObject response) {
|
||||
deleteSynced(ids);
|
||||
markSuccessfulTransmission();
|
||||
}
|
||||
}
|
||||
|
||||
private class FixSubmitErrorListener implements NetworkHelperFailureListener {
|
||||
private String host;
|
||||
private List<String> failedHosts;
|
||||
private boolean currentlyTracking = false;
|
||||
|
||||
public FixSubmitErrorListener(String host, boolean currentlyTracking,
|
||||
List<String> failedHosts) {
|
||||
this.failedHosts = failedHosts;
|
||||
this.host = host;
|
||||
this.currentlyTracking = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction(NetworkHelperError error) {
|
||||
markFailedTransmission();
|
||||
ExLog.e(TransmittingService.this, TAG,
|
||||
"Error while sending GPS fix " + error.getMessage());
|
||||
|
||||
if (!currentlyTracking) {
|
||||
if (failedHosts == null) {
|
||||
failedHosts = new ArrayList<String>();
|
||||
failedHosts.add(host);
|
||||
}
|
||||
|
||||
sendFixesToAPI(this.failedHosts);
|
||||
ExLog.i(TransmittingService.this, TAG,
|
||||
"Retrying resend step with this failed hosts list: " + failedHosts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Timer implements Runnable {
|
||||
public Thread t;
|
||||
public volatile boolean endExecution;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!endExecution) {
|
||||
try {
|
||||
Thread.sleep(currentUpdateInterval);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
timerFired();
|
||||
}
|
||||
reportApiConnectivity(APIConnectivity.noAttempt);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
endExecution = false;
|
||||
if (t == null) {
|
||||
t = new Thread(this);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
endExecution = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAPIConnectivityListener(APIConnectivityListener listener) {
|
||||
apiConnectivityListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterAPIConnectivityListener() {
|
||||
apiConnectivityListener = null;
|
||||
}
|
||||
|
||||
public class TransmittingBinder extends Binder {
|
||||
public TransmittingService getService() {
|
||||
return TransmittingService.this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum APIConnectivity {
|
||||
notReachable(0), reachableTransmissionSuccess(1), reachableTransmissionError(2), noAttempt(
|
||||
4);
|
||||
|
||||
private final int apiConnectivity;
|
||||
|
||||
APIConnectivity(int connectivity) {
|
||||
this.apiConnectivity = connectivity;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.apiConnectivity;
|
||||
}
|
||||
}
|
||||
|
||||
public interface APIConnectivityListener {
|
||||
public void apiConnectivityUpdated(APIConnectivity apiConnectivity);
|
||||
|
||||
public void setUnsentGPSFixesCount(int count);
|
||||
}
|
||||
|
||||
}
|
||||
+9
-2
@@ -8,17 +8,19 @@ import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.ui.activities.SendingServiceAwareActivity;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
import com.sap.sailing.android.tracking.app.utils.SqlDebugHelper;
|
||||
|
||||
public class BaseActivity extends ActionBarActivity {
|
||||
import com.sap.sailing.android.shared.ui.activities.SendingServiceAwareActivity;
|
||||
|
||||
public class BaseActivity extends SendingServiceAwareActivity {
|
||||
private static final String TAG = BaseActivity.class.getName();
|
||||
|
||||
protected AppPreferences prefs;
|
||||
@@ -102,4 +104,9 @@ public class BaseActivity extends ActionBarActivity {
|
||||
public void showErrorPopup(int string1Id, int string2Id) {
|
||||
showErrorPopup(getString(string1Id), getString(string2Id));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOptionsMenuResId() {
|
||||
return R.menu.options_menu;
|
||||
}
|
||||
}
|
||||
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.activities;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningServiceInfo;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
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.sending.MessageSendingService;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class LaunchActivity extends BaseActivity {
|
||||
private static int requestCodeQRCode = 42471;
|
||||
private static final String TAG = LaunchActivity.class.getName();
|
||||
private Button toggleTrackingBtn;
|
||||
private boolean isTrackingActive = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.launch_activity);
|
||||
toggleTrackingBtn = (Button) findViewById(R.id.btnToggleTracking);
|
||||
isTrackingActive = isTrackingServiceRunning();
|
||||
updateToggleTrackingBtn();
|
||||
}
|
||||
|
||||
private void updateToggleTrackingBtn() {
|
||||
toggleTrackingBtn.setText(getString(
|
||||
isTrackingActive ? R.string.stop_tracking : R.string.start_tracking));
|
||||
}
|
||||
|
||||
public void onScanQRCodeClicked(View view) {
|
||||
try {
|
||||
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
|
||||
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
|
||||
startActivityForResult(intent, requestCodeQRCode);
|
||||
} catch (Exception e) {
|
||||
Uri marketUri = Uri.parse("market://details?id=com.google.zxing.client.android");
|
||||
Intent marketIntent = new Intent(Intent.ACTION_VIEW,marketUri);
|
||||
startActivity(marketIntent);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ErrorDialogFragment extends DialogFragment {
|
||||
private Dialog dialog;
|
||||
|
||||
public ErrorDialogFragment() {
|
||||
super();
|
||||
dialog = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dialog to display
|
||||
*
|
||||
* @param dialog
|
||||
* An error dialog
|
||||
*/
|
||||
public void setDialog(Dialog dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method must return a Dialog to the DialogFragment.
|
||||
*/
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean googlePLayServicesAvailable() {
|
||||
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
|
||||
|
||||
if (ConnectionResult.SUCCESS == resultCode) {
|
||||
ExLog.i(this, TAG, getString(R.string.play_services_available));
|
||||
return true;
|
||||
} else {
|
||||
// Display an error dialog
|
||||
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
|
||||
if (dialog != null) {
|
||||
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
|
||||
errorFragment.setDialog(dialog);
|
||||
errorFragment.show(getSupportFragmentManager(), TAG);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void onToggleTrackingClicked(View view) {
|
||||
if (googlePLayServicesAvailable()) {
|
||||
if (!isTrackingActive) {
|
||||
Intent startTrackingIntent = new Intent(this, TrackingService.class);
|
||||
getBaseContext().startService(startTrackingIntent);
|
||||
} else {
|
||||
Intent startTrackingIntent = new Intent(this, TrackingService.class);
|
||||
getBaseContext().stopService(startTrackingIntent);
|
||||
}
|
||||
isTrackingActive = !isTrackingActive;
|
||||
updateToggleTrackingBtn();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode != requestCodeQRCode) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String content = data.getStringExtra("SCAN_RESULT");
|
||||
ExLog.i(this, TAG, "Parsing URI: "+content);
|
||||
Uri uri = Uri.parse(content);
|
||||
String server = uri.getScheme() + "://";
|
||||
server += uri.getHost();
|
||||
if (uri.getPort() != -1) {
|
||||
server += ":" + uri.getPort();
|
||||
}
|
||||
prefs.setServerURL(server);
|
||||
|
||||
String leaderboard = uri.getQueryParameter(DeviceMappingConstants.LEADERBOARD_NAME);
|
||||
String competitorIdAsString = uri.getQueryParameter(DeviceMappingConstants.COMPETITOR_ID_AS_STRING);
|
||||
String markIdAsString = uri.getQueryParameter(DeviceMappingConstants.MARK_ID_AS_STRING);
|
||||
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(UUID.fromString(prefs.getDeviceIdentifier()));
|
||||
TimePoint from = MillisecondsTimePoint.now();
|
||||
String itemId = null;
|
||||
String itemType = null;
|
||||
|
||||
JSONObject mappingStart = new JSONObject();
|
||||
try {
|
||||
mappingStart.put(DeviceMappingConstants.DEVICE_UUID, device.getStringRepresentation());
|
||||
mappingStart.put(DeviceMappingConstants.FROM_MILLIS, from.asMillis());
|
||||
mappingStart.put(DeviceMappingConstants.DEVICE_TYPE, "android");
|
||||
if (competitorIdAsString != null) {
|
||||
mappingStart.put(DeviceMappingConstants.PUSH_DEVICE_ID, "<push_device_id_not_known_on_android>");
|
||||
mappingStart.put(DeviceMappingConstants.COMPETITOR_ID_AS_STRING, competitorIdAsString);
|
||||
itemType = "competitor";
|
||||
} else if (markIdAsString != null) {
|
||||
mappingStart.put(DeviceMappingConstants.MARK_ID_AS_STRING, markIdAsString);
|
||||
itemType = "mark";
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
//deserializing the competitor/mark on the server would fail if the idAsString were used
|
||||
ExLog.e(this, TAG, "Found non-UUID as mapped item id - can only deal with UUIDs: " + itemId);
|
||||
Toast.makeText(this, "Did not get a UUID as item ID: " + itemId, Toast.LENGTH_LONG).show(); // FIXME i18n
|
||||
} catch (JSONException e) {
|
||||
ExLog.e(this, TAG, "Internal error trying to register device: " + e.getMessage());
|
||||
Toast.makeText(this, "Internal error trying to register device : " + e.getMessage(), Toast.LENGTH_LONG).show(); // FIXME i18n
|
||||
}
|
||||
String postCheckinUrl = getPostCheckinUrl(server, leaderboard);
|
||||
startService(MessageSendingService.createMessageIntent(this, postCheckinUrl, /* callbackPayload */ null,
|
||||
UUID.randomUUID(), mappingStart.toString(), /* callbackClass */ null));
|
||||
ExLog.i(this, TAG, "Created mapping event");
|
||||
Toast.makeText(this, "Successfully created mapping between device and " + itemType, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(this, "Error scanning QRCode (" + resultCode + ")", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private String getPostCheckinUrl(String serverBaseUrl, String leaderboardName) {
|
||||
return serverBaseUrl+"/sailingserver/api/v1/leaderboards/"+Uri.encode(leaderboardName)+"/device_mappings/start";
|
||||
}
|
||||
|
||||
//FIXME: currently duplicate code with racecommitte app (GeneralPreferenceFragment), refactor once maven build is available and thus update mechanism can be created for tracking app see bugs 2398 2399
|
||||
protected String getServerUrl(URL apkUrl) {
|
||||
String protocol = apkUrl.getProtocol();
|
||||
String host = apkUrl.getHost();
|
||||
String port = apkUrl.getPort() == -1 ? "" : ":" + apkUrl.getPort();
|
||||
return protocol + "://" + host + port;
|
||||
}
|
||||
|
||||
// approach with static member on TrackingService class did not work
|
||||
// this is not a really good approach in my opinion either, but simple
|
||||
private boolean isTrackingServiceRunning() {
|
||||
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
||||
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (TrackingService.class.getName().equals(service.service.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+23
-11
@@ -64,13 +64,11 @@ public class RegattaActivity extends BaseActivity {
|
||||
competitor = new CompetitorInfo();
|
||||
leaderboard = new LeaderboardInfo();
|
||||
|
||||
String leaderboardName = intent.getStringExtra(getString(R.string.leaderboard_name));
|
||||
String eventId = intent.getStringExtra(getString(R.string.event_id));
|
||||
String competitorId = intent.getStringExtra(getString(R.string.competitor_id));
|
||||
String checkinDigest = intent.getStringExtra(getString(R.string.checkin_digest));
|
||||
|
||||
competitor = DatabaseHelper.getInstance().getCompetitor(this, competitorId);
|
||||
event = DatabaseHelper.getInstance().getEventInfo(this, eventId);
|
||||
leaderboard = DatabaseHelper.getInstance().getLeaderboard(this, leaderboardName);
|
||||
competitor = DatabaseHelper.getInstance().getCompetitor(this, checkinDigest);
|
||||
event = DatabaseHelper.getInstance().getEventInfo(this, checkinDigest);
|
||||
leaderboard = DatabaseHelper.getInstance().getLeaderboard(this, checkinDigest);
|
||||
|
||||
setContentView(R.layout.fragment_container);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
@@ -83,12 +81,22 @@ public class RegattaActivity extends BaseActivity {
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
toolbar.setNavigationIcon(R.drawable.sap_logo_64_sq);
|
||||
toolbar.setPadding(20, 0, 0, 0);
|
||||
getSupportActionBar().setTitle(leaderboardName);
|
||||
getSupportActionBar().setTitle(leaderboard.name);
|
||||
getSupportActionBar().setSubtitle(event.name);
|
||||
}
|
||||
|
||||
replaceFragment(R.id.content_frame, new RegattaFragment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (prefs.getTrackerIsTracking())
|
||||
{
|
||||
String checkinDigest = prefs.getTrackerIsTrackingCheckinDigest();
|
||||
startTrackingActivity(checkinDigest);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
@@ -223,7 +231,6 @@ public class RegattaActivity extends BaseActivity {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
System.out.println("*** STORE IMAGE: " + image +", FILENAME: " + fileName);
|
||||
FileOutputStream fos = new FileOutputStream(pictureFile);
|
||||
image.compress(Bitmap.CompressFormat.PNG, 90, fos);
|
||||
fos.close();
|
||||
@@ -386,7 +393,7 @@ public class RegattaActivity extends BaseActivity {
|
||||
*/
|
||||
public void checkout()
|
||||
{
|
||||
final String checkoutURLStr = prefs.getServerURL()
|
||||
final String checkoutURLStr = event.server
|
||||
+ prefs.getServerCheckoutPath().replace("{leaderboard-name}",
|
||||
Uri.encode(leaderboard.name));
|
||||
|
||||
@@ -411,8 +418,7 @@ public class RegattaActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
public void performAction(JSONObject response) {
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(
|
||||
RegattaActivity.this, event, competitor, leaderboard);
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(RegattaActivity.this, event.checkinDigest);
|
||||
deleteImageFile(getLeaderboardImageFileName(leaderboard.name));
|
||||
dismissProgressDialog();
|
||||
finish();
|
||||
@@ -444,4 +450,10 @@ public class RegattaActivity extends BaseActivity {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
private void startTrackingActivity(String checkinDigest) {
|
||||
Intent intent = new Intent(this, TrackingActivity.class);
|
||||
intent.putExtra(getString(R.string.tracking_activity_checkin_digest_parameter), checkinDigest);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
+40
-14
@@ -1,15 +1,18 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.activities;
|
||||
|
||||
import net.hockeyapp.android.CrashManager;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
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.ui.fragments.HomeFragment;
|
||||
import com.sap.sailing.android.tracking.app.utils.ServiceHelper;
|
||||
|
||||
public class StartActivity extends BaseActivity {
|
||||
|
||||
@@ -35,9 +38,22 @@ public class StartActivity extends BaseActivity {
|
||||
replaceFragment(R.id.content_frame, new HomeFragment());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
checkForCrashes();
|
||||
//checkForUpdates();
|
||||
|
||||
int googleServicesResultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
|
||||
if (googleServicesResultCode != ConnectionResult.SUCCESS)
|
||||
{
|
||||
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(googleServicesResultCode, this, 0);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// get url if launched via url intent-filter
|
||||
@@ -47,8 +63,7 @@ public class StartActivity extends BaseActivity {
|
||||
|
||||
if (urlStr != null) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG,
|
||||
"Matched URL, handling scanned or matched URL.");
|
||||
ExLog.i(this, TAG, "Matched URL, handling scanned or matched URL.");
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(urlStr);
|
||||
@@ -58,23 +73,34 @@ public class StartActivity extends BaseActivity {
|
||||
|
||||
homeFragment.handleScannedOrUrlMatchedUri(uri);
|
||||
}
|
||||
|
||||
// start transmitting service that will henceforth run in the background
|
||||
ServiceHelper.getInstance().startTransmittingService(this);
|
||||
|
||||
intent.setData(null);
|
||||
|
||||
if (prefs.getTrackerIsTracking())
|
||||
{
|
||||
String eventId = prefs.getTrackerIsTrackingEventId();
|
||||
startTrackingActivity(eventId);
|
||||
String checkinDigest = prefs.getTrackerIsTrackingCheckinDigest();
|
||||
startRegatta(checkinDigest);
|
||||
}
|
||||
}
|
||||
|
||||
private void startTrackingActivity(String eventId) {
|
||||
Intent intent = new Intent(this, TrackingActivity.class);
|
||||
intent.putExtra(getString(R.string.tracking_activity_event_id_parameter), eventId);
|
||||
startActivity(intent);
|
||||
|
||||
/**
|
||||
* Hockeyapp integration method.
|
||||
*/
|
||||
private void checkForCrashes() {
|
||||
CrashManager.register(this, "060ff0c8a907638e3b31d3146091c87b");
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Hockeyapp integration method.
|
||||
// */
|
||||
// private void checkForUpdates() {
|
||||
// // TODO: Remove this for store builds!
|
||||
// UpdateManager.register(this, "060ff0c8a907638e3b31d3146091c87b");
|
||||
// }
|
||||
|
||||
private void startRegatta(String checkinDigest) {
|
||||
Intent intent = new Intent(this, RegattaActivity.class);
|
||||
intent.putExtra(getString(R.string.checkin_digest), checkinDigest);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
+42
-68
@@ -6,6 +6,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -17,18 +18,16 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
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.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.sensors.CompassManager;
|
||||
import com.sap.sailing.android.tracking.app.sensors.CompassManager.MagneticHeadingListener;
|
||||
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.services.TransmittingService;
|
||||
import com.sap.sailing.android.tracking.app.services.TransmittingService.APIConnectivity;
|
||||
import com.sap.sailing.android.tracking.app.services.TransmittingService.APIConnectivityListener;
|
||||
import com.sap.sailing.android.tracking.app.services.TransmittingService.TransmittingBinder;
|
||||
import com.sap.sailing.android.tracking.app.ui.fragments.CompassFragment;
|
||||
import com.sap.sailing.android.tracking.app.ui.fragments.SpeedFragment;
|
||||
import com.sap.sailing.android.tracking.app.ui.fragments.StopTrackingButtonFragment;
|
||||
@@ -40,13 +39,13 @@ import com.sap.sailing.android.tracking.app.valueobjects.EventInfo;
|
||||
import com.viewpagerindicator.CirclePageIndicator;
|
||||
|
||||
public class TrackingActivity extends BaseActivity implements GPSQualityListener,
|
||||
APIConnectivityListener, MagneticHeadingListener {
|
||||
APIConnectivityListener {
|
||||
|
||||
TrackingService trackingService;
|
||||
boolean trackingServiceBound;
|
||||
|
||||
TransmittingService transmittingService;
|
||||
boolean transmittingServiceBound;
|
||||
MessageSendingService messageSendingService;
|
||||
boolean messageSendingServiceBound;
|
||||
|
||||
private final static String TAG = TrackingActivity.class.getName();
|
||||
private final static String SIS_TRACKING_FRAGMENT = "savedInstanceTrackingFragment";
|
||||
@@ -56,11 +55,11 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
|
||||
private ViewPager mPager;
|
||||
private ScreenSlidePagerAdapter mPagerAdapter;
|
||||
|
||||
private String eventId;
|
||||
private AppPreferences prefs;
|
||||
|
||||
private TrackingFragment trackingFragment;
|
||||
|
||||
private String checkinDigest;
|
||||
|
||||
private TrackingFragment trackingFragment;
|
||||
private TimerRunnable timer;
|
||||
|
||||
private int lastViewPagerItem;
|
||||
@@ -72,18 +71,16 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
* Thus they are cached here and the fragments can pick
|
||||
* them up.
|
||||
*/
|
||||
public String lastSpeedIndicatorText = "";
|
||||
public String lastCompassIndicatorText = "";
|
||||
public String lastSpeedIndicatorText = "-";
|
||||
public String lastCompassIndicatorText = "-°";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
prefs = new AppPreferences(this);
|
||||
|
||||
Intent intent = getIntent();
|
||||
eventId = intent.getExtras().getString(
|
||||
getString(R.string.tracking_activity_event_id_parameter));
|
||||
|
||||
checkinDigest = getIntent().getExtras().getString(getString(R.string.tracking_activity_checkin_digest_parameter));
|
||||
|
||||
setContentView(R.layout.fragment_hud_container);
|
||||
|
||||
@@ -96,7 +93,7 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
}
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
EventInfo eventInfo = DatabaseHelper.getInstance().getEventInfoWithLeaderboard(this, eventId);
|
||||
EventInfo eventInfo = DatabaseHelper.getInstance().getEventInfoWithLeaderboardAndCompetitor(this, checkinDigest);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
toolbar.setNavigationIcon(R.drawable.sap_logo_64_sq);
|
||||
@@ -124,8 +121,8 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
}
|
||||
|
||||
lastViewPagerItem = savedInstanceState.getInt(SIS_LAST_VIEWPAGER_ITEM);
|
||||
lastSpeedIndicatorText = savedInstanceState.getString(SIS_LAST_SPEED_TEXT);
|
||||
lastCompassIndicatorText = savedInstanceState.getString(SIS_LAST_COMPASS_TEXT);
|
||||
lastSpeedIndicatorText = savedInstanceState.getString(SIS_LAST_SPEED_TEXT, "-");
|
||||
lastCompassIndicatorText = savedInstanceState.getString(SIS_LAST_COMPASS_TEXT, "-°");
|
||||
} else {
|
||||
trackingFragment = new TrackingFragment();
|
||||
}
|
||||
@@ -150,7 +147,7 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
});
|
||||
|
||||
replaceFragment(R.id.tracking_linear_layout, trackingFragment);
|
||||
ServiceHelper.getInstance().startTrackingService(this, eventId);
|
||||
ServiceHelper.getInstance().startTrackingService(this, checkinDigest);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,17 +164,16 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Intent transmittingServiceIntent = new Intent(this, TransmittingService.class);
|
||||
bindService(transmittingServiceIntent, transmittingServiceConnection,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
Intent messageSendingServiceIntent = new Intent(this, MessageSendingService.class);
|
||||
bindService(messageSendingServiceIntent, messageSendingServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
Intent trackingServiceIntent = new Intent(this, TrackingService.class);
|
||||
bindService(trackingServiceIntent, trackingServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (trackingServiceBound) {
|
||||
trackingService.unregisterGPSQualityListener();
|
||||
@@ -189,11 +185,11 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
}
|
||||
}
|
||||
|
||||
if (transmittingServiceBound) {
|
||||
transmittingService.unregisterAPIConnectivityListener();
|
||||
unbindService(transmittingServiceConnection);
|
||||
if (messageSendingServiceBound) {
|
||||
messageSendingService.unregisterAPIConnectivityListener();
|
||||
unbindService(messageSendingServiceConnection);
|
||||
|
||||
transmittingServiceBound = false;
|
||||
messageSendingServiceBound = false;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Unbound transmitting Service");
|
||||
@@ -204,7 +200,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
CompassManager.getInstance(this).unregisterListener();
|
||||
timer.stop();
|
||||
|
||||
mPager = (ViewPager) findViewById(R.id.pager);
|
||||
@@ -215,10 +210,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (prefs.getHeadingFromMagneticSensorPreferred()) {
|
||||
CompassManager.getInstance(this).registerListener(this);
|
||||
}
|
||||
|
||||
timer = new TimerRunnable();
|
||||
timer.start();
|
||||
|
||||
@@ -229,6 +220,13 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
|
||||
mPager.setAdapter(mPagerAdapter);
|
||||
mPager.setCurrentItem(lastViewPagerItem);
|
||||
|
||||
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
|
||||
boolean gpsEnabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
|
||||
if (gpsEnabled == false)
|
||||
{
|
||||
showErrorPopup(R.string.warning, R.string.gps_turned_off);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -270,24 +268,24 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
}
|
||||
|
||||
/** Defines callbacks for service binding, passed to bindService() */
|
||||
private ServiceConnection transmittingServiceConnection = new ServiceConnection() {
|
||||
private ServiceConnection messageSendingServiceConnection = new ServiceConnection() {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// We've bound to LocalService, cast the IBinder and get
|
||||
// LocalService instance
|
||||
TransmittingBinder binder = (TransmittingBinder) service;
|
||||
transmittingService = binder.getService();
|
||||
transmittingServiceBound = true;
|
||||
transmittingService.registerAPIConnectivityListener(TrackingActivity.this);
|
||||
MessageSendingBinder binder = (MessageSendingBinder) service;
|
||||
messageSendingService = binder.getService();
|
||||
messageSendingServiceBound = true;
|
||||
messageSendingService.registerAPIConnectivityListener(TrackingActivity.this);
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(TrackingActivity.this, TAG, "connected to transmitting service");
|
||||
ExLog.i(TrackingActivity.this, TAG, "connected to message sending service");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
transmittingServiceBound = false;
|
||||
messageSendingServiceBound = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -312,30 +310,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
trackingServiceBound = false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void magneticHeadingUpdated(float heading) {
|
||||
// HudFragment hudFragment = (HudFragment)
|
||||
// getSupportFragmentManager().findFragmentById(R.id.hud_content_frame);
|
||||
if (prefs.getHeadingFromMagneticSensorPreferred()) {
|
||||
if (mPager.getCurrentItem() == ScreenSlidePagerAdapter.VIEW_PAGER_FRAGMENT_COMPASS) {
|
||||
|
||||
ScreenSlidePagerAdapter viewPagerAdapter = getViewPagerAdapter();
|
||||
if (viewPagerAdapter != null) {
|
||||
CompassFragment compassFragment = viewPagerAdapter.getCompassFragment();
|
||||
if (compassFragment != null && compassFragment.isAdded()) {
|
||||
compassFragment.setBearing(heading);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG,
|
||||
"Received magnet compass update, even though prefs say get from GPS. Unregistering listener.");
|
||||
}
|
||||
CompassManager.getInstance(this).unregisterListener();
|
||||
}
|
||||
}
|
||||
|
||||
private ScreenSlidePagerAdapter getViewPagerAdapter() {
|
||||
return (ScreenSlidePagerAdapter) mPager.getAdapter();
|
||||
|
||||
+98
-94
@@ -4,6 +4,7 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -35,29 +36,24 @@ import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.Response.ErrorListener;
|
||||
import com.android.volley.Response.Listener;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.sap.sailing.android.shared.data.http.HttpGetRequest;
|
||||
import com.sap.sailing.android.shared.data.http.HttpJsonPostRequest;
|
||||
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.adapter.RegattaAdapter;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.RegattaActivity;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.StartActivity;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
import com.sap.sailing.android.tracking.app.utils.CheckinHelper;
|
||||
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.utils.JsonObjectOrStatusOnlyRequest;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperError;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperFailureListener;
|
||||
import com.sap.sailing.android.tracking.app.utils.NetworkHelper.NetworkHelperSuccessListener;
|
||||
import com.sap.sailing.android.tracking.app.utils.UniqueDeviceUuid;
|
||||
import com.sap.sailing.android.tracking.app.utils.VolleyHelper;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.CheckinData;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
@@ -66,7 +62,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
LoaderCallbacks<Cursor> {
|
||||
|
||||
private final static String TAG = HomeFragment.class.getName();
|
||||
private final static String REQUEST_TAG = "request_homefragment";
|
||||
private final static int REGATTA_LOADER = 1;
|
||||
|
||||
private AppPreferences prefs;
|
||||
@@ -93,7 +88,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
if (noQrCodeButton != null) {
|
||||
noQrCodeButton.setOnClickListener(new ClickListener());
|
||||
}
|
||||
|
||||
|
||||
ListView listView = (ListView) view.findViewById(R.id.listRegatta);
|
||||
if (listView != null) {
|
||||
@@ -114,7 +108,13 @@ public class HomeFragment extends BaseFragment implements
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getLoaderManager().restartLoader(REGATTA_LOADER, null, this);
|
||||
|
||||
String lastQRCode = prefs.getLastScannedQRCode();
|
||||
if (lastQRCode != null) {
|
||||
handleQRCode(lastQRCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void showNoQRCodeMessage()
|
||||
{
|
||||
@@ -139,7 +139,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
startActivity(marketIntent);
|
||||
} else {
|
||||
Toast.makeText(getActivity(),
|
||||
"PlayStore and Scanning not available.",
|
||||
getString(R.string.error_play_store_and_scanning_not_available),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
return false;
|
||||
@@ -150,20 +150,24 @@ public class HomeFragment extends BaseFragment implements
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String scanResult = data.getStringExtra("SCAN_RESULT");
|
||||
|
||||
ExLog.i(getActivity(), TAG, "Parsing URI: " + scanResult);
|
||||
Uri uri = Uri.parse(scanResult);
|
||||
handleScannedOrUrlMatchedUri(uri);
|
||||
|
||||
prefs.setLastScannedQRCode(scanResult);
|
||||
// handleQRCode is called in onResume()
|
||||
} else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
Toast.makeText(getActivity(), "Scanning canceled",
|
||||
Toast.makeText(getActivity(), getString(R.string.scanning_cancelled),
|
||||
Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
String templateString = getString(R.string.error_scanning_qrcode);
|
||||
Toast.makeText(getActivity(),
|
||||
"Error scanning QRCode (" + resultCode + ")",
|
||||
templateString.replace("{result-code}", String.valueOf(resultCode)),
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleQRCode(String qrCode) {
|
||||
ExLog.i(getActivity(), TAG, "Parsing URI: " + qrCode);
|
||||
Uri uri = Uri.parse(qrCode);
|
||||
handleScannedOrUrlMatchedUri(uri);
|
||||
}
|
||||
|
||||
public void handleScannedOrUrlMatchedUri(Uri uri) {
|
||||
// TODO: assuming scheme is http, is this valid?
|
||||
@@ -172,12 +176,11 @@ public class HomeFragment extends BaseFragment implements
|
||||
scheme = "http";
|
||||
}
|
||||
|
||||
final String uriStr = uri.toString();
|
||||
final String server = scheme + "://" + uri.getHost();
|
||||
final int port = (uri.getPort() == -1) ? 80 : uri.getPort();
|
||||
final String hostWithPort = server + ":" + port;
|
||||
|
||||
prefs.setServerURL(hostWithPort);
|
||||
|
||||
String leaderboardNameFromQR;
|
||||
try {
|
||||
leaderboardNameFromQR = URLEncoder.encode(uri.getQueryParameter(CheckinHelper.LEADERBOARD_NAME),"UTF-8").replace("+", "%20");
|
||||
@@ -186,12 +189,12 @@ public class HomeFragment extends BaseFragment implements
|
||||
leaderboardNameFromQR = "";
|
||||
} catch (NullPointerException e) {
|
||||
ExLog.e(getActivity(), TAG, "Invalid Barcode (no leaderboard-name set): " + e.getMessage());
|
||||
Toast.makeText(this.getActivity(), "Invalid QR Code", Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this.getActivity(), getString(R.string.error_invalid_qr_code), Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
final String competitorId = uri.getQueryParameter(CheckinHelper.COMPETITOR_ID);
|
||||
final String checkinURLStr = prefs.getServerURL()
|
||||
final String checkinURLStr = hostWithPort
|
||||
+ prefs.getServerCheckinPath().replace("{leaderboard-name}",
|
||||
leaderboardNameFromQR);
|
||||
final String eventId = uri.getQueryParameter(CheckinHelper.EVENT_ID);
|
||||
@@ -209,9 +212,9 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
final StartActivity startActivity = (StartActivity)getActivity();
|
||||
|
||||
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 = hostWithPort + prefs.getServerEventPath(eventId);
|
||||
final String getLeaderboardUrl = hostWithPort + prefs.getServerLeaderboardPath(leaderboardName);
|
||||
final String getCompetitorUrl = hostWithPort + prefs.getServerCompetitorPath(competitorId);
|
||||
|
||||
startActivity.showProgressDialog(R.string.please_wait, R.string.getting_leaderboard);
|
||||
|
||||
@@ -354,6 +357,27 @@ public class HomeFragment extends BaseFragment implements
|
||||
data.leaderboardName = leaderboardName;
|
||||
data.deviceUid = deviceUuid
|
||||
.getStringRepresentation();
|
||||
try {
|
||||
data.setCheckinDigestFromString(uriStr);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
ExLog.e(getActivity(),
|
||||
TAG,
|
||||
"Failed to get generate digest of qr-code string ("
|
||||
+ uriStr + "). "
|
||||
+ e.getMessage());
|
||||
startActivity.dismissProgressDialog();
|
||||
displayAPIErrorRecommendRetry();
|
||||
return;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
ExLog.e(getActivity(),
|
||||
TAG,
|
||||
"Failed to get generate digest of qr-code string ("
|
||||
+ uriStr + "). "
|
||||
+ e.getMessage());
|
||||
startActivity.dismissProgressDialog();
|
||||
displayAPIErrorRecommendRetry();
|
||||
return;
|
||||
}
|
||||
|
||||
displayUserConfirmationScreen(data);
|
||||
|
||||
@@ -419,12 +443,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
VolleyHelper.getInstance(getActivity()).cancelRequest(REQUEST_TAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a confirmation-dialog in which the user confirms his full name
|
||||
* and sail-id.
|
||||
@@ -446,6 +464,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
clearScannedQRCodeInPrefs();
|
||||
checkInWithAPIAndDisplayTrackingActivity(checkinData);
|
||||
}
|
||||
|
||||
@@ -454,15 +473,18 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
clearScannedQRCodeInPrefs();
|
||||
dialog.cancel();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
AlertDialog alert = builder.create();
|
||||
alert.show();
|
||||
}
|
||||
|
||||
private void clearScannedQRCodeInPrefs() {
|
||||
prefs.setLastScannedQRCode(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a checkin request and launch RegattaAcitivity afterwards
|
||||
@@ -471,14 +493,16 @@ public class HomeFragment extends BaseFragment implements
|
||||
*
|
||||
* @param deviceMappingData
|
||||
*/
|
||||
private void checkInWithAPIAndDisplayTrackingActivity(
|
||||
CheckinData checkinData) {
|
||||
if (DatabaseHelper.getInstance().eventLeaderboardCompetitorCombnationAvailable(
|
||||
getActivity(), checkinData.eventId, checkinData.leaderboardName, checkinData.competitorId)) {
|
||||
private void checkInWithAPIAndDisplayTrackingActivity(CheckinData checkinData) {
|
||||
if (DatabaseHelper.getInstance().eventLeaderboardCompetitorCombnationAvailable(getActivity(), checkinData.checkinDigest)) {
|
||||
|
||||
try {
|
||||
DatabaseHelper.getInstance().storeCheckinRow(getActivity(), checkinData.getEvent(),
|
||||
checkinData.getCompetitor(), checkinData.getLeaderboard());
|
||||
DatabaseHelper.getInstance().storeCheckinRow(
|
||||
getActivity(),
|
||||
checkinData.getEvent(),
|
||||
checkinData.getCompetitor(),
|
||||
checkinData.getLeaderboard());
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
} catch (GeneralDatabaseHelperException e) {
|
||||
ExLog.e(getActivity(), TAG, "Batch insert failed: " + e.getMessage());
|
||||
@@ -492,6 +516,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
} 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();
|
||||
}
|
||||
|
||||
performAPICheckin(checkinData);
|
||||
@@ -509,21 +534,23 @@ public class HomeFragment extends BaseFragment implements
|
||||
startActivity.showProgressDialog(R.string.please_wait, R.string.checking_in);
|
||||
|
||||
try {
|
||||
JSONObject requestObject = CheckinHelper.getCheckinJson(
|
||||
checkinData.competitorId, checkinData.deviceUid, "TODO!!",
|
||||
date.getTime());
|
||||
JSONObject requestObject = CheckinHelper.getCheckinJson(checkinData.competitorId,
|
||||
checkinData.deviceUid, "TODO!!", date.getTime());
|
||||
|
||||
JsonObjectOrStatusOnlyRequest checkinRequest = new JsonObjectOrStatusOnlyRequest(checkinData.checkinURL,
|
||||
requestObject, new CheckinListener(checkinData.leaderboardName,
|
||||
checkinData.eventId, checkinData.competitorId),
|
||||
new CheckinErrorListener(checkinData.leaderboardName, checkinData.eventId,
|
||||
checkinData.competitorId));
|
||||
|
||||
VolleyHelper.getInstance(getActivity()).addRequest(checkinRequest);
|
||||
HttpJsonPostRequest request = new HttpJsonPostRequest(new URL(checkinData.checkinURL),
|
||||
requestObject.toString(), getActivity());
|
||||
|
||||
NetworkHelper.getInstance(getActivity()).executeHttpJsonRequestAsnchronously(
|
||||
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 generate checkin JSON: " + e.getMessage());
|
||||
"Failed to perform checkin, MalformedURLException: " + e.getMessage());
|
||||
displayAPIErrorRecommendRetry();
|
||||
}
|
||||
}
|
||||
@@ -573,14 +600,11 @@ public class HomeFragment extends BaseFragment implements
|
||||
/**
|
||||
* Start regatta activity.
|
||||
*
|
||||
* @param regattaName
|
||||
* @param eventName
|
||||
* @param checkinDigest
|
||||
*/
|
||||
private void startRegatta(String leaderboardName, String eventId, String competitorId) {
|
||||
private void startRegatta(String checkinDigest) {
|
||||
Intent intent = new Intent(getActivity(), RegattaActivity.class);
|
||||
intent.putExtra(getString(R.string.leaderboard_name), leaderboardName);
|
||||
intent.putExtra(getString(R.string.event_id), eventId);
|
||||
intent.putExtra(getString(R.string.competitor_id), competitorId);
|
||||
intent.putExtra(getString(R.string.checkin_digest), checkinDigest);
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
@@ -589,6 +613,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
switch (loaderId) {
|
||||
case REGATTA_LOADER:
|
||||
String[] projection = new String[] {
|
||||
"events.event_checkin_digest",
|
||||
"events.event_id",
|
||||
"events._id", "events.event_name", "events.event_server",
|
||||
"competitors.competitor_display_name",
|
||||
@@ -656,76 +681,55 @@ public class HomeFragment extends BaseFragment implements
|
||||
return;
|
||||
}
|
||||
|
||||
Cursor cursor = (Cursor) adapter.getItem(position - 1); // -1,
|
||||
// because
|
||||
// there's
|
||||
// a
|
||||
// header
|
||||
// row
|
||||
|
||||
|
||||
prefs.setServerURL(cursor.getString(cursor.getColumnIndex(Event.EVENT_SERVER)));
|
||||
// -1, because there's a header row
|
||||
Cursor cursor = (Cursor) adapter.getItem(position - 1);
|
||||
|
||||
String leaderboardName = cursor.getString(cursor.getColumnIndex("leaderboard_name"));
|
||||
String competitorId = cursor.getString(cursor.getColumnIndex("competitor_id"));
|
||||
String eventId = cursor.getString(cursor.getColumnIndex("event_id"));
|
||||
|
||||
startRegatta(leaderboardName, eventId, competitorId);
|
||||
String checkinDigest = cursor.getString(cursor.getColumnIndex("event_checkin_digest"));
|
||||
startRegatta(checkinDigest);
|
||||
}
|
||||
}
|
||||
|
||||
private class CheckinListener implements Listener<JSONObject> {
|
||||
private class CheckinListener implements NetworkHelperSuccessListener {
|
||||
|
||||
public String leaderboardName;
|
||||
public String eventId;
|
||||
public String competitorId;
|
||||
public String checkinDigest;
|
||||
|
||||
public CheckinListener(String leaderboardName, String eventId, String competitorId) {
|
||||
this.leaderboardName = leaderboardName;
|
||||
this.eventId = eventId;
|
||||
this.competitorId = competitorId;
|
||||
public CheckinListener(String checkinDigest) {
|
||||
this.checkinDigest = checkinDigest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
public void performAction(JSONObject response) {
|
||||
StartActivity startActivity = (StartActivity)getActivity();
|
||||
startActivity.dismissProgressDialog();
|
||||
|
||||
startRegatta(leaderboardName, eventId, competitorId);
|
||||
startRegatta(checkinDigest);
|
||||
}
|
||||
}
|
||||
|
||||
private class CheckinErrorListener implements ErrorListener {
|
||||
private class CheckinErrorListener implements NetworkHelperFailureListener {
|
||||
|
||||
public String leaderboardName;
|
||||
public String eventId;
|
||||
public String competitorId;
|
||||
public String checkinDigest;
|
||||
|
||||
public CheckinErrorListener(String leaderboardName, String eventId, String competitorId) {
|
||||
this.leaderboardName = leaderboardName;
|
||||
this.eventId = eventId;
|
||||
this.competitorId = competitorId;
|
||||
public CheckinErrorListener(String checkinDigest) {
|
||||
this.checkinDigest = checkinDigest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error.getMessage() != null)
|
||||
public void performAction(NetworkHelperError e) {
|
||||
if (e.getMessage() != null)
|
||||
{
|
||||
ExLog.e(getActivity(), TAG, error.getMessage().toString());
|
||||
ExLog.e(getActivity(), TAG, e.getMessage().toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
ExLog.e(getActivity(), TAG, "Unknown Error");
|
||||
}
|
||||
|
||||
|
||||
StartActivity startActivity = (StartActivity)getActivity();
|
||||
startActivity.dismissProgressDialog();
|
||||
startActivity.showErrorPopup(R.string.error, R.string.error_could_not_complete_operation_on_server_try_again);
|
||||
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(getActivity(), eventId, leaderboardName, competitorId);
|
||||
|
||||
Toast.makeText(getActivity(), "Error while receiving server data", Toast.LENGTH_LONG).show();
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(getActivity(), checkinDigest);
|
||||
Toast.makeText(getActivity(), getString(R.string.error_while_receiving_server_data), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.method.MovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
|
||||
public class HudFragment extends BaseFragment {
|
||||
|
||||
private static final String TAG = HudFragment.class.getName();
|
||||
|
||||
private float maxTranslateY;
|
||||
private float minTranslateY;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
// View view = inflater.inflate(R.layout.fragment_hud, container, false);
|
||||
//
|
||||
// FrameLayout layout = (FrameLayout)getActivity().findViewById(R.id.hud_content_frame);
|
||||
// layout.setOnTouchListener(new OverlayOnTouchListener());
|
||||
//
|
||||
// return view;
|
||||
}
|
||||
|
||||
public void setHeading(float heading)
|
||||
{
|
||||
TextView headingLabel = (TextView)getActivity().findViewById(R.id.hud_hdg_label);
|
||||
headingLabel.setText(getString(R.string.hud_heading_prefix) + String.valueOf(Math.round(heading)) + "°");
|
||||
}
|
||||
|
||||
public void setSpeedOverGround(float speedInMetersPerSeconds)
|
||||
{
|
||||
float speedInKnots = speedInMetersPerSeconds * 1.9438444924574f;
|
||||
TextView speedLabel = (TextView)getActivity().findViewById(R.id.hud_speed_label);
|
||||
speedLabel.setText(getString(R.string.hud_speed_over_ground_prefix) + String.valueOf(speedInKnots) + "kn");
|
||||
}
|
||||
|
||||
/**
|
||||
* called from activity
|
||||
*/
|
||||
public void layoutOverlay() {
|
||||
// FrameLayout layout = (FrameLayout)getActivity().findViewById(R.id.hud_content_frame);
|
||||
// maxTranslateY = layout.getHeight()- dpToPx(40);
|
||||
//
|
||||
// View modeLabel = (View)getActivity().findViewById(R.id.mode_label);
|
||||
// float heightOfOneDataRow = modeLabel.getHeight();
|
||||
// minTranslateY = layout.getTranslationY() + (heightOfOneDataRow * 2);
|
||||
//
|
||||
// layout.setTranslationY(maxTranslateY);
|
||||
}
|
||||
|
||||
class OverlayOnTouchListener implements OnTouchListener {
|
||||
private int yDelta;
|
||||
private int lastTranslation;
|
||||
boolean isUp = false;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
// if (view.getId() != R.id.hud_content_frame) return false;
|
||||
|
||||
final int y = (int) event.getRawY();
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int newTranslation = y - yDelta;
|
||||
|
||||
if (newTranslation > lastTranslation)
|
||||
{
|
||||
animateDown(view);
|
||||
}
|
||||
else
|
||||
{
|
||||
animateUp(view);
|
||||
}
|
||||
|
||||
|
||||
lastTranslation = newTranslation;
|
||||
// if (newTranslation >= minTranslateY && newTranslation < maxTranslateY)
|
||||
// {
|
||||
// view.setTranslationY(newTranslation);
|
||||
// }
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
// int treshold = Math.round((maxTranslateY - minTranslateY) / 2);
|
||||
// if (lastTranslation < treshold) {
|
||||
// animateUp(view);
|
||||
// } else {
|
||||
// animateDown(view);
|
||||
// }
|
||||
//
|
||||
// long eventDuration =
|
||||
// android.os.SystemClock.elapsedRealtime()
|
||||
// - event.getDownTime();
|
||||
//
|
||||
// if (eventDuration < 200) {
|
||||
// view.performClick();
|
||||
// if (!isUp)
|
||||
// {
|
||||
// animateUp(view);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
yDelta = y - (int)Math.round(view.getTranslationY());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateUp(View view) {
|
||||
view.animate().translationY(minTranslateY).setDuration(100)
|
||||
.setInterpolator(new LinearInterpolator()).start();
|
||||
|
||||
lastTranslation = (int) minTranslateY;
|
||||
isUp = true;
|
||||
}
|
||||
|
||||
private void animateDown(View view) {
|
||||
view.animate().translationY(maxTranslateY).setDuration(500)
|
||||
.setInterpolator(new BounceInterpolator()).start();
|
||||
|
||||
lastTranslation = (int) maxTranslateY;
|
||||
isUp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-5
@@ -29,7 +29,6 @@ import android.widget.TextView;
|
||||
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.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.LeaderboardWebViewActivity;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.RegattaActivity;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
@@ -44,7 +43,6 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
private final String CAMERA_TEMP_FILE = "cameraTempFile";
|
||||
|
||||
|
||||
private boolean showingThankYouNote;
|
||||
|
||||
private TimerRunnable timer;
|
||||
@@ -323,9 +321,8 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
private void startTrackingActivity() {
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
Intent intent = new Intent(getActivity(), TrackingActivity.class);
|
||||
intent.putExtra(
|
||||
getString(R.string.tracking_activity_event_id_parameter),
|
||||
regattaActivity.event.id);
|
||||
String checkinDigest = regattaActivity.event.checkinDigest;
|
||||
intent.putExtra(getString(R.string.tracking_activity_checkin_digest_parameter), checkinDigest);
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ public class SpeedFragment extends BaseFragment {
|
||||
String formattedSpeed = df.format(speedInKnots);
|
||||
|
||||
TextView speedText = (TextView) getActivity().findViewById(R.id.speed_text_view);
|
||||
speedText.setText(formattedSpeed + "kn");
|
||||
speedText.setText(formattedSpeed);
|
||||
TrackingActivity activity = (TrackingActivity) getActivity();
|
||||
|
||||
if (activity != null) {
|
||||
@@ -53,7 +53,7 @@ public class SpeedFragment extends BaseFragment {
|
||||
if (activity != null) {
|
||||
speedText.setText(activity.lastSpeedIndicatorText);
|
||||
} else {
|
||||
speedText.setText("");
|
||||
speedText.setText("0");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-18
@@ -15,11 +15,11 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.services.sending.MessageSendingService.APIConnectivity;
|
||||
import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.customviews.SignalQualityIndicatorView;
|
||||
import com.sap.sailing.android.tracking.app.services.TrackingService.GPSQuality;
|
||||
import com.sap.sailing.android.tracking.app.services.TransmittingService.APIConnectivity;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
import com.sap.sailing.android.tracking.app.utils.AppPreferences;
|
||||
|
||||
@@ -143,7 +143,7 @@ public class TrackingFragment extends BaseFragment {
|
||||
TextView textView = (TextView) getActivity().findViewById(
|
||||
R.id.mode);
|
||||
|
||||
if (apiConnectivity == APIConnectivity.reachableTransmissionSuccess) {
|
||||
if (apiConnectivity == APIConnectivity.transmissionSuccess) {
|
||||
if (prefs.getEnergySavingEnabledByUser()) {
|
||||
textView.setText(getString(R.string.tracking_mode_battery_saving));
|
||||
textView.setTextColor(Color
|
||||
@@ -158,7 +158,7 @@ public class TrackingFragment extends BaseFragment {
|
||||
textView.setText(getString(R.string.tracking_mode_offline));
|
||||
textView.setTextColor(Color
|
||||
.parseColor(getString(R.color.sap_green)));
|
||||
} else if (apiConnectivity == APIConnectivity.reachableTransmissionError) {
|
||||
} else if (apiConnectivity == APIConnectivity.transmissionError) {
|
||||
textView.setText(getString(R.string.tracking_mode_api_error));
|
||||
textView.setTextColor(Color
|
||||
.parseColor(getString(R.color.sap_red)));
|
||||
@@ -218,7 +218,6 @@ public class TrackingFragment extends BaseFragment {
|
||||
if (isAdded())
|
||||
{
|
||||
Activity activity = getActivity();
|
||||
System.out.println("ACTIVITY: " + activity);
|
||||
SignalQualityIndicatorView indicatorView = (SignalQualityIndicatorView) activity.findViewById(R.id.gps_quality_indicator);
|
||||
indicatorView.setSignalQuality( quality.toInt() );
|
||||
|
||||
@@ -232,22 +231,19 @@ public class TrackingFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
public void setUnsentGPSFixesCount(final int count) {
|
||||
if (isAdded()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TextView unsentGpsFixesTextView = (TextView) getActivity()
|
||||
.findViewById(R.id.tracking_unsent_fixes);
|
||||
if (count == 0)
|
||||
{
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isAdded()) {
|
||||
TextView unsentGpsFixesTextView = (TextView) getActivity().findViewById(
|
||||
R.id.tracking_unsent_fixes);
|
||||
if (count == 0) {
|
||||
unsentGpsFixesTextView.setText(getString(R.string.none));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsentGpsFixesTextView.setText(String.valueOf(count));
|
||||
} else {
|
||||
unsentGpsFixesTextView.setText(String.valueOf(count));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+21
-14
@@ -30,10 +30,6 @@ public class AppPreferences {
|
||||
return DeviceIdentifier;
|
||||
}
|
||||
|
||||
public String getServerURL() {
|
||||
return PrefUtils.getString(context, R.string.preference_server_url_key, R.string.preference_server_url_default);
|
||||
}
|
||||
|
||||
public String getServerGpsFixesPostPath() {
|
||||
return PrefUtils.getString(context, R.string.preference_server_gps_fixes_post_path, R.string.preference_server_gps_fixes_post_path);
|
||||
}
|
||||
@@ -70,10 +66,6 @@ public class AppPreferences {
|
||||
return value == null ? -1 : Integer.valueOf(value);
|
||||
}
|
||||
|
||||
public void setServerURL(String serverUrl) {
|
||||
preferences.edit().putString(context.getString(R.string.preference_server_url_key), serverUrl).apply();
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return PrefUtils.getString(context, R.string.preference_eventid_key, R.string.preference_eventid_default);
|
||||
}
|
||||
@@ -104,8 +96,8 @@ public class AppPreferences {
|
||||
return preferences.getBoolean(context.getString(R.string.preference_energy_saving_enabled_key), false);
|
||||
}
|
||||
|
||||
public boolean getHeadingFromMagneticSensorPreferred() {
|
||||
return preferences.getBoolean(context.getString(R.string.preference_heading_from_magnetic_key), true);
|
||||
public boolean getDisplayHeadingWithSubtractedDeclination() {
|
||||
return preferences.getBoolean(context.getString(R.string.preference_heading_with_declination_subtracted_enabled), true);
|
||||
}
|
||||
|
||||
public void setTrackingTimerStarted(long milliseconds)
|
||||
@@ -128,18 +120,33 @@ public class AppPreferences {
|
||||
return preferences.getBoolean(context.getString(R.string.preference_tracker_is_tracking), false);
|
||||
}
|
||||
|
||||
public void setTrackerIsTrackingEventId(String eventId)
|
||||
public void setTrackerIsTrackingCheckinDigest(String checkinDigest)
|
||||
{
|
||||
preferences.edit().putString(context.getString(R.string.preference_tracker_is_tracking_event_id), eventId).commit();
|
||||
preferences.edit().putString(context.getString(R.string.preference_tracker_is_tracking_checkin_digest), checkinDigest).commit();
|
||||
}
|
||||
|
||||
public String getTrackerIsTrackingEventId()
|
||||
public String getTrackerIsTrackingCheckinDigest()
|
||||
{
|
||||
return preferences.getString(context.getString(R.string.preference_tracker_is_tracking_event_id), null);
|
||||
return preferences.getString(context.getString(R.string.preference_tracker_is_tracking_checkin_digest), null);
|
||||
}
|
||||
|
||||
public static boolean getPrintDatabaseOperationDebugMessages()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getLastScannedQRCode()
|
||||
{
|
||||
return preferences.getString(context.getString(R.string.preference_last_scanned_qr_code), null);
|
||||
}
|
||||
|
||||
public void setLastScannedQRCode(String lastQRCode)
|
||||
{
|
||||
preferences.edit().putString(context.getString(R.string.preference_last_scanned_qr_code), lastQRCode).commit();
|
||||
}
|
||||
|
||||
public void setMessageResendInterval(int interval)
|
||||
{
|
||||
preferences.edit().putInt(context.getString(R.string.preference_messageResendIntervalMillis_key), interval).commit();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class CheckinHelper {
|
||||
public static final String LEADERBOARD_NAME = "leaderboard_name";
|
||||
public static final String COMPETITOR_ID = "competitor_id";
|
||||
public static final String LEADERBOARD_NAME = "leaderboardName";
|
||||
public static final String COMPETITOR_ID = "competitorId";
|
||||
public static final String EVENT_ID = "event_id";
|
||||
|
||||
public static JSONObject getCheckinJson(String competitorId, String deviceUuid, String pushDeviceId, long fromMillis) throws JSONException
|
||||
|
||||
+139
-196
@@ -1,16 +1,13 @@
|
||||
package com.sap.sailing.android.tracking.app.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.BaseColumns;
|
||||
|
||||
@@ -19,13 +16,10 @@ import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Competitor;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.EventGpsFixesJoined;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.EventLeaderboardCompetitorJoined;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Leaderboard;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.LeaderboardsEventsJoined;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.SensorGps;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.CompetitorInfo;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.EventInfo;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.GpsFix;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.LeaderboardInfo;
|
||||
|
||||
public class DatabaseHelper {
|
||||
@@ -43,168 +37,83 @@ public class DatabaseHelper {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public List<GpsFix> getUnsentFixes(Context context, List<String> failedHosts, int updateBatchSize) {
|
||||
String selectionClause = SensorGps.GPS_SYNCED + " = 0";
|
||||
String projectionClauseStr = "events._id as _eid,sensor_gps.gps_time,sensor_gps.gps_latitude,"
|
||||
+ "sensor_gps.gps_longitude,sensor_gps.gps_speed,sensor_gps.gps_bearing,sensor_gps.gps_synced,"
|
||||
+ "events.event_server,sensor_gps._id as _gid";
|
||||
String[] projectionClause = projectionClauseStr.split(",");
|
||||
String sortAndLimitClause = SensorGps.GPS_TIME + " DESC LIMIT "
|
||||
+ updateBatchSize;
|
||||
|
||||
if (failedHosts != null) {
|
||||
if (failedHosts.size() > 0) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("( ");
|
||||
|
||||
for (String failedHost : failedHosts) {
|
||||
buf.append("\"" + failedHost + "\",");
|
||||
}
|
||||
|
||||
// remove the last comma
|
||||
buf.setLength(buf.length() - 1);
|
||||
buf.append(" )");
|
||||
|
||||
selectionClause += " AND " + Event.EVENT_SERVER + " NOT IN "
|
||||
+ buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<GpsFix> list = new ArrayList<GpsFix>();
|
||||
Cursor cur = context.getContentResolver().query(
|
||||
EventGpsFixesJoined.CONTENT_URI, projectionClause,
|
||||
selectionClause, null, sortAndLimitClause);
|
||||
while (cur.moveToNext()) {
|
||||
|
||||
GpsFix gpsFix = new GpsFix();
|
||||
|
||||
gpsFix.id = cur.getInt(cur.getColumnIndex("_gid"));
|
||||
gpsFix.timestamp = cur.getLong(cur.getColumnIndex(SensorGps.GPS_TIME));
|
||||
gpsFix.latitude = cur.getDouble(cur.getColumnIndex(SensorGps.GPS_LATITUDE));
|
||||
gpsFix.longitude = cur.getDouble(cur.getColumnIndex(SensorGps.GPS_LONGITUDE));
|
||||
gpsFix.speed = cur.getDouble(cur.getColumnIndex(SensorGps.GPS_SPEED));
|
||||
gpsFix.course = cur.getDouble(cur.getColumnIndex(SensorGps.GPS_BEARING));
|
||||
gpsFix.synced = cur.getInt(cur.getColumnIndex(SensorGps.GPS_SYNCED));
|
||||
gpsFix.host = cur.getString(cur.getColumnIndex(Event.EVENT_SERVER));
|
||||
gpsFix.eventId = cur.getString(cur.getColumnIndex("_eid"));
|
||||
|
||||
list.add(gpsFix);
|
||||
|
||||
if (list.size() >= updateBatchSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cur.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
public int getNumberOfUnsentGPSFixes(Context context)
|
||||
{
|
||||
String selectionClause = SensorGps.GPS_SYNCED + " = 0";
|
||||
String sortAndLimitClause = SensorGps.GPS_TIME + " DESC LIMIT 1";
|
||||
|
||||
int eventId = -1;
|
||||
|
||||
Cursor cur = context.getContentResolver().query(
|
||||
EventGpsFixesJoined.CONTENT_URI,
|
||||
new String[] { "events._id as _eid" },
|
||||
selectionClause,
|
||||
null,
|
||||
sortAndLimitClause);
|
||||
|
||||
while (cur.moveToNext()) {
|
||||
eventId = cur.getInt(0);
|
||||
}
|
||||
|
||||
cur.close();
|
||||
|
||||
if (eventId == -1)
|
||||
{
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
ExLog.i(context, TAG, "no event id, reporting 0 gps-fixes.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String selectionClause2 = "events._id = " + eventId;
|
||||
Cursor countCursor = context.getContentResolver().query(
|
||||
EventGpsFixesJoined.CONTENT_URI,
|
||||
new String[] { "count(*) AS count" }, selectionClause2, null, null);
|
||||
|
||||
countCursor.moveToFirst();
|
||||
int count = countCursor.getInt(0);
|
||||
countCursor.close();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public int deleteGpsFixes(Context context, String[] fixIdStrings)
|
||||
{
|
||||
int numDeleted = 0;
|
||||
for (String idStr: fixIdStrings)
|
||||
{
|
||||
ContentValues updateValues = new ContentValues();
|
||||
updateValues.put(SensorGps.GPS_SYNCED, 1);
|
||||
Uri uri = ContentUris.withAppendedId(SensorGps.CONTENT_URI, Long.parseLong(idStr));
|
||||
numDeleted = context.getContentResolver().delete(uri, null, null);
|
||||
}
|
||||
|
||||
return numDeleted;
|
||||
}
|
||||
|
||||
public long getRowIdForEventId(Context context, String eventId)
|
||||
public long getEventRowIdForCheckinDigest(Context context, String checkinDigest)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
Cursor cursor = cr.query(Event.CONTENT_URI, null, "event_id = \"" + eventId + "\"", null, null);
|
||||
Cursor cursor = cr.query(Event.CONTENT_URI, null, Event.EVENT_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null, null);
|
||||
cursor.moveToFirst();
|
||||
result = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void insertGPSFix(Context context, double lat, double lon, double speed,
|
||||
double bearing, String provider, long timestamp, long eventRowId) {
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues cv = new ContentValues();
|
||||
|
||||
cv.put(SensorGps.GPS_LATITUDE, lat);
|
||||
cv.put(SensorGps.GPS_LONGITUDE, lon);
|
||||
cv.put(SensorGps.GPS_PROVIDER, provider);
|
||||
cv.put(SensorGps.GPS_SPEED, speed);
|
||||
cv.put(SensorGps.GPS_TIME, timestamp);
|
||||
cv.put(SensorGps.GPS_BEARING, bearing);
|
||||
cv.put(SensorGps.GPS_EVENT_FK, eventRowId);
|
||||
|
||||
cr.insert(SensorGps.CONTENT_URI, cv);
|
||||
}
|
||||
// public EventInfo getEventInfoWithLeaderboard(Context context, String eventId) {
|
||||
// EventInfo result = new EventInfo();
|
||||
//
|
||||
// ContentResolver cr = context.getContentResolver();
|
||||
// String projectionStr = "events._id,leaderboards.leaderboard_name,events.event_name";
|
||||
// String[] projection = projectionStr.split(",");
|
||||
// Cursor cursor = cr.query(LeaderboardsEventsJoined.CONTENT_URI, projection, "events.event_id = \"" + eventId + "\"", null, null);
|
||||
// if (cursor.moveToFirst())
|
||||
// {
|
||||
// result.name = cursor.getString(cursor.getColumnIndex("event_name"));
|
||||
// result.leaderboardName = cursor.getString(cursor.getColumnIndex("leaderboard_name"));
|
||||
// }
|
||||
//
|
||||
// cursor.close();
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public EventInfo getEventInfoWithLeaderboard(Context context, String eventId) {
|
||||
public EventInfo getEventInfoWithLeaderboardAndCompetitor(Context context, String checkinDigest) {
|
||||
EventInfo result = new EventInfo();
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
String projectionStr = "events._id,leaderboards.leaderboard_name,events.event_name";
|
||||
String[] projection = projectionStr.split(",");
|
||||
Cursor cursor = cr.query(LeaderboardsEventsJoined.CONTENT_URI, projection, "events.event_id = \"" + eventId + "\"", null, null);
|
||||
if (cursor.moveToFirst())
|
||||
String projectionStr = "events._id ,leaderboards.leaderboard_name, events.event_id,"
|
||||
+ " events.event_name, competitors.competitor_id";
|
||||
String[] projection = projectionStr.split(",");
|
||||
Cursor cursor = cr
|
||||
.query(EventLeaderboardCompetitorJoined.CONTENT_URI, projection, "events."
|
||||
+ Event.EVENT_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null, null);
|
||||
if (cursor.moveToFirst())
|
||||
{
|
||||
result.name = cursor.getString(cursor.getColumnIndex("event_name"));
|
||||
result.leaderboardName = cursor.getString(cursor.getColumnIndex("leaderboard_name"));
|
||||
result.competitorId = cursor.getString(cursor.getColumnIndex("competitor_id"));
|
||||
result.id = cursor.getString(cursor.getColumnIndex("event_id"));
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public EventInfo getEventInfo(Context context, String eventId) {
|
||||
// public EventInfo getEventInfoWithLeaderboardAndCompetitor(Context context, String eventId) {
|
||||
// EventInfo result = new EventInfo();
|
||||
//
|
||||
// ContentResolver cr = context.getContentResolver();
|
||||
// String projectionStr = "events._id,leaderboards.leaderboard_name,events.event_name, competitors.competitor_id";
|
||||
// String[] projection = projectionStr.split(",");
|
||||
// Cursor cursor = cr.query(EventLeaderboardCompetitorJoined.CONTENT_URI, projection, "events.event_id = \"" + eventId + "\"", null, null);
|
||||
// if (cursor.moveToFirst())
|
||||
// {
|
||||
// result.name = cursor.getString(cursor.getColumnIndex("event_name"));
|
||||
// result.leaderboardName = cursor.getString(cursor.getColumnIndex("leaderboard_name"));
|
||||
// result.competitorId = cursor.getString(cursor.getColumnIndex("competitor_id"));
|
||||
// }
|
||||
//
|
||||
// cursor.close();
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
|
||||
public EventInfo getEventInfo(Context context, String checkinDigest) {
|
||||
EventInfo event = new EventInfo();
|
||||
event.id = eventId;
|
||||
event.checkinDigest = checkinDigest;
|
||||
|
||||
Cursor cursor = context.getContentResolver().query(Event.CONTENT_URI,
|
||||
null, "event_id = \"" + eventId + "\"", null, null);
|
||||
null, Event.EVENT_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null, null);
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
event.name = cursor.getString(cursor.getColumnIndex(Event.EVENT_NAME));
|
||||
@@ -213,37 +122,76 @@ public class DatabaseHelper {
|
||||
event.endMillis = cursor.getLong(cursor.getColumnIndex(Event.EVENT_DATE_END));
|
||||
event.server = cursor.getString(cursor.getColumnIndex(Event.EVENT_SERVER));
|
||||
event.rowId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||
event.id = cursor.getString(cursor.getColumnIndex(Event.EVENT_ID));
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return event;
|
||||
}
|
||||
|
||||
public CompetitorInfo getCompetitor(Context context, String competitorId)
|
||||
// public CompetitorInfo getCompetitor(Context context, String competitorId)
|
||||
// {
|
||||
// CompetitorInfo competitor = new CompetitorInfo();
|
||||
// competitor.id = competitorId;
|
||||
//
|
||||
// Cursor cursor = context.getContentResolver().query(Competitor.CONTENT_URI, null, "competitor_id = \"" + competitorId + "\"", null, null);
|
||||
// if (cursor.moveToFirst()) {
|
||||
// competitor.name = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_DISPLAY_NAME));
|
||||
// competitor.countryCode = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_COUNTRY_CODE));
|
||||
// competitor.sailId = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_SAIL_ID));
|
||||
// competitor.rowId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||
// }
|
||||
//
|
||||
// cursor.close();
|
||||
// return competitor;
|
||||
// }
|
||||
|
||||
public CompetitorInfo getCompetitor(Context context, String checkinDigest)
|
||||
{
|
||||
CompetitorInfo competitor = new CompetitorInfo();
|
||||
competitor.id = competitorId;
|
||||
competitor.checkinDigest = checkinDigest;
|
||||
|
||||
Cursor cursor = context.getContentResolver().query(Competitor.CONTENT_URI, null, "competitor_id = \"" + competitorId + "\"", null, null);
|
||||
Cursor cursor = context.getContentResolver().query(Competitor.CONTENT_URI, null, Competitor.COMPETITOR_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null, null);
|
||||
if (cursor.moveToFirst()) {
|
||||
competitor.name = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_DISPLAY_NAME));
|
||||
competitor.countryCode = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_COUNTRY_CODE));
|
||||
competitor.sailId = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_SAIL_ID));
|
||||
competitor.rowId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||
competitor.id = cursor.getString(cursor.getColumnIndex(Competitor.COMPETITOR_CHECKIN_DIGEST));
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return competitor;
|
||||
}
|
||||
|
||||
public LeaderboardInfo getLeaderboard(Context context, String leaderboardName)
|
||||
// public LeaderboardInfo getLeaderboard(Context context, String leaderboardName)
|
||||
// {
|
||||
// LeaderboardInfo leaderboard = new LeaderboardInfo();
|
||||
// leaderboard.name = leaderboardName;
|
||||
//
|
||||
// Cursor lc = context.getContentResolver().query(Leaderboard.CONTENT_URI, null, "leaderboard_name = \"" + leaderboardName + "\"", null, null);
|
||||
// if (lc.moveToFirst()) {
|
||||
// leaderboard.rowId = lc.getInt(lc.getColumnIndex(BaseColumns._ID));
|
||||
// leaderboard.checkinDigest = lc.getString(lc.getColumnIndex(Leaderboard.LEADERBOARD_CHECKIN_DIGEST));
|
||||
// }
|
||||
//
|
||||
// lc.close();
|
||||
//
|
||||
// return leaderboard;
|
||||
// }
|
||||
|
||||
public LeaderboardInfo getLeaderboard(Context context, String checkinDigest)
|
||||
{
|
||||
LeaderboardInfo leaderboard = new LeaderboardInfo();
|
||||
leaderboard.name = leaderboardName;
|
||||
leaderboard.checkinDigest = checkinDigest;
|
||||
|
||||
Cursor lc = context.getContentResolver().query(Leaderboard.CONTENT_URI, null, "leaderboard_name = \"" + leaderboardName + "\"", null, null);
|
||||
Cursor lc = context.getContentResolver().query(
|
||||
Leaderboard.CONTENT_URI,
|
||||
null,
|
||||
Leaderboard.LEADERBOARD_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null, null);
|
||||
if (lc.moveToFirst()) {
|
||||
leaderboard.rowId = lc.getInt(lc.getColumnIndex(BaseColumns._ID));
|
||||
leaderboard.name = lc.getString(lc.getColumnIndex(Leaderboard.LEADERBOARD_NAME));
|
||||
}
|
||||
|
||||
lc.close();
|
||||
@@ -251,29 +199,29 @@ public class DatabaseHelper {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
public void deleteRegattaFromDatabase(Context context, String eventId, String competitorId, String leaderboardName)
|
||||
{
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
|
||||
int d1 = cr.delete(Event.CONTENT_URI, Event.EVENT_ID + " = \"" + eventId + "\"", null);
|
||||
int d2 = cr.delete(Competitor.CONTENT_URI, Competitor.COMPETITOR_ID + " = \"" + competitorId + "\"", null);
|
||||
int d3 = cr.delete(Leaderboard.CONTENT_URI, Leaderboard.LEADERBOARD_NAME + " = \"" + leaderboardName + "\"", null);
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
ExLog.i(context, TAG, "Checkout, number of events deleted: " + d1);
|
||||
ExLog.i(context, TAG, "Checkout, number of competitors deleted: " + d2);
|
||||
ExLog.i(context, TAG, "Checkout, number of leaderbards deleted: " + d3);
|
||||
}
|
||||
}
|
||||
// public void deleteRegattaFromDatabase(Context context, String eventId, String competitorId, String leaderboardName)
|
||||
// {
|
||||
// ContentResolver cr = context.getContentResolver();
|
||||
//
|
||||
// int d1 = cr.delete(Event.CONTENT_URI, Event.EVENT_ID + " = \"" + eventId + "\"", null);
|
||||
// int d2 = cr.delete(Competitor.CONTENT_URI, Competitor.COMPETITOR_ID + " = \"" + competitorId + "\"", null);
|
||||
// int d3 = cr.delete(Leaderboard.CONTENT_URI, Leaderboard.LEADERBOARD_NAME + " = \"" + leaderboardName + "\"", null);
|
||||
//
|
||||
// if (BuildConfig.DEBUG)
|
||||
// {
|
||||
// ExLog.i(context, TAG, "Checkout, number of events deleted: " + d1);
|
||||
// ExLog.i(context, TAG, "Checkout, number of competitors deleted: " + d2);
|
||||
// ExLog.i(context, TAG, "Checkout, number of leaderbards deleted: " + d3);
|
||||
// }
|
||||
// }
|
||||
|
||||
public void deleteRegattaFromDatabase(Context context, EventInfo event, CompetitorInfo competitor, LeaderboardInfo leaderboard)
|
||||
public void deleteRegattaFromDatabase(Context context, String checkinDigest)
|
||||
{
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
|
||||
int d1 = cr.delete(Event.CONTENT_URI, BaseColumns._ID + " = " + event.rowId, null);
|
||||
int d2 = cr.delete(Competitor.CONTENT_URI, BaseColumns._ID + " = " + competitor.rowId, null);
|
||||
int d3 = cr.delete(Leaderboard.CONTENT_URI, BaseColumns._ID + " = " + leaderboard.rowId, null);
|
||||
int d1 = cr.delete(Event.CONTENT_URI, Event.EVENT_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null);
|
||||
int d2 = cr.delete(Competitor.CONTENT_URI, Competitor.COMPETITOR_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null);
|
||||
int d3 = cr.delete(Leaderboard.CONTENT_URI, Leaderboard.LEADERBOARD_CHECKIN_DIGEST + " = \"" + checkinDigest + "\"", null);
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
@@ -284,7 +232,8 @@ public class DatabaseHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to check in to a race.
|
||||
* When checking in, store info on the event, the competitor and the leaderboard
|
||||
* in the database.
|
||||
*
|
||||
* @param context
|
||||
* @param event
|
||||
@@ -298,27 +247,16 @@ public class DatabaseHelper {
|
||||
public void storeCheckinRow(Context context, EventInfo event, CompetitorInfo competitor,
|
||||
LeaderboardInfo leaderboard) throws GeneralDatabaseHelperException {
|
||||
|
||||
// inserting leaderboard first in order to get the ID.
|
||||
// This should be atomic, but couldn't get withValueBackReference to
|
||||
// work yet.
|
||||
// inserting leaderboard first
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
|
||||
ContentValues clv = new ContentValues();
|
||||
clv.put(Leaderboard.LEADERBOARD_NAME, leaderboard.name);
|
||||
clv.put(Leaderboard.LEADERBOARD_CHECKIN_DIGEST, leaderboard.checkinDigest);
|
||||
cr.insert(Leaderboard.CONTENT_URI, clv);
|
||||
|
||||
Cursor cur = cr.query(Leaderboard.CONTENT_URI, null, null, null, null);
|
||||
long lastLeaderboardId = 0;
|
||||
|
||||
if (cur.moveToLast()) {
|
||||
lastLeaderboardId = cur.getLong(cur.getColumnIndex(BaseColumns._ID));
|
||||
}
|
||||
|
||||
cur.close();
|
||||
|
||||
// now, with the leaderboard id, insert event and competitor
|
||||
// todo: fix this so its atomic.
|
||||
|
||||
// now insert event
|
||||
|
||||
ArrayList<ContentProviderOperation> opList = new ArrayList<ContentProviderOperation>();
|
||||
|
||||
@@ -329,9 +267,11 @@ public class DatabaseHelper {
|
||||
cev.put(Event.EVENT_DATE_END, event.endMillis);
|
||||
cev.put(Event.EVENT_SERVER, event.server);
|
||||
cev.put(Event.EVENT_IMAGE_URL, event.imageUrl);
|
||||
cev.put(Event.EVENT_LEADERBOARD_FK, lastLeaderboardId);
|
||||
cev.put(Event.EVENT_CHECKIN_DIGEST, event.checkinDigest);
|
||||
|
||||
opList.add(ContentProviderOperation.newInsert(Event.CONTENT_URI).withValues(cev).build());
|
||||
|
||||
// competitor
|
||||
|
||||
ContentValues ccv = new ContentValues();
|
||||
|
||||
@@ -340,7 +280,7 @@ public class DatabaseHelper {
|
||||
ccv.put(Competitor.COMPETITOR_ID, competitor.id);
|
||||
ccv.put(Competitor.COMPETITOR_NATIONALITY, competitor.nationality);
|
||||
ccv.put(Competitor.COMPETITOR_SAIL_ID, competitor.sailId);
|
||||
ccv.put(Competitor.COMPETITOR_LEADERBOARD_FK, lastLeaderboardId);
|
||||
ccv.put(Competitor.COMPETITOR_CHECKIN_DIGEST, competitor.checkinDigest);
|
||||
|
||||
opList.add(ContentProviderOperation.newInsert(Competitor.CONTENT_URI).withValues(ccv).build());
|
||||
|
||||
@@ -354,26 +294,29 @@ public class DatabaseHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the combination of eventId, leaderboardName and
|
||||
* competitorId does not exist in the DB.
|
||||
* Return true if the combination of event, leaderboard and
|
||||
* competitor does not exist in the DB. (based on the digest of the checkin-
|
||||
* url obtained from the QR-code.)
|
||||
*
|
||||
* @param eventId
|
||||
* @param checkinDigest SHA-256 digest of QR-code string
|
||||
* @param leaderboardName
|
||||
* @param competitorId
|
||||
* @return
|
||||
*/
|
||||
public boolean eventLeaderboardCompetitorCombnationAvailable(Context context,
|
||||
String eventId, String leaderboardName, String competitorId) {
|
||||
public boolean eventLeaderboardCompetitorCombnationAvailable(Context context, String checkinDigest) {
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
String sel = "leaderboards.leaderboard_name = \"" + leaderboardName
|
||||
+ "\" AND competitors.competitor_id = \"" + competitorId
|
||||
+ "\" AND events.event_id = \"" + eventId + "\"";
|
||||
String sel = "leaderboards.leaderboard_checkin_digest = \"" + checkinDigest
|
||||
+ "\" AND competitors.competitor_checkin_digest = \"" + checkinDigest
|
||||
+ "\" AND events.event_checkin_digest = \"" + checkinDigest + "\"";
|
||||
|
||||
int count = cr.query(
|
||||
Cursor cursor = cr.query(
|
||||
AnalyticsContract.EventLeaderboardCompetitorJoined.CONTENT_URI,
|
||||
null, sel, null, null).getCount();
|
||||
|
||||
null, sel, null, null);
|
||||
|
||||
int count = cursor.getCount();
|
||||
|
||||
cursor.close();
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.utils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.android.volley.NetworkResponse;
|
||||
import com.android.volley.ParseError;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.Response.ErrorListener;
|
||||
import com.android.volley.Response.Listener;
|
||||
import com.android.volley.toolbox.HttpHeaderParser;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
|
||||
public class JsonObjectOrStatusOnlyRequest extends JsonObjectRequest {
|
||||
|
||||
public JsonObjectOrStatusOnlyRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener,
|
||||
ErrorListener errorListener) {
|
||||
super(url, jsonRequest, listener, errorListener);
|
||||
}
|
||||
|
||||
public JsonObjectOrStatusOnlyRequest(int method, String url, JSONObject jsonRequest,
|
||||
Listener<JSONObject> listener, ErrorListener errorListener) {
|
||||
super(method, url, jsonRequest, listener, errorListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
|
||||
try {
|
||||
String jsonString = new String(response.data,
|
||||
HttpHeaderParser.parseCharset(response.headers));
|
||||
// here's the new code, if jsonString.length() == 0 don't parse
|
||||
if (jsonString.length() == 0) {
|
||||
return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
|
||||
}
|
||||
// end of patch
|
||||
return Response.success(new JSONObject(jsonString),
|
||||
HttpHeaderParser.parseCacheHeaders(response));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return Response.error(new ParseError(e));
|
||||
} catch (JSONException je) {
|
||||
|
||||
return Response.error(new ParseError(je));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+6
-5
@@ -18,15 +18,16 @@ public class NetworkHelper {
|
||||
|
||||
private final static String TAG = NetworkHelper.class.getName();
|
||||
|
||||
static NetworkHelper mInstance;
|
||||
static Context mContext;
|
||||
protected static NetworkHelper mInstance;
|
||||
protected static Context mContext;
|
||||
|
||||
public static NetworkHelper getInstance(Context context) {
|
||||
if (mInstance == null)
|
||||
{
|
||||
mInstance = new NetworkHelper();
|
||||
mContext = context;
|
||||
mContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
@@ -38,7 +39,7 @@ public class NetworkHelper {
|
||||
NetworkHelperSuccessListener successListener, NetworkHelperFailureListener failureListener) {
|
||||
|
||||
NetworkRequestTask task = new NetworkRequestTask(successListener, failureListener);
|
||||
task.execute(request);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, request);
|
||||
}
|
||||
|
||||
private class NetworkRequestTask extends AsyncTask<HttpRequest, Void, Void>
|
||||
@@ -65,7 +66,7 @@ public class NetworkHelper {
|
||||
String responseStr = readStream(stream);
|
||||
|
||||
response = null;
|
||||
|
||||
|
||||
if (responseStr.length() > 0) {
|
||||
response = new JSONObject(responseStr);
|
||||
}
|
||||
|
||||
+5
-17
@@ -5,7 +5,6 @@ import android.content.Intent;
|
||||
|
||||
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.TransmittingService;
|
||||
|
||||
/**
|
||||
* Helper class that starts services.
|
||||
@@ -14,7 +13,7 @@ import com.sap.sailing.android.tracking.app.services.TransmittingService;
|
||||
*/
|
||||
public class ServiceHelper {
|
||||
|
||||
private final static String TAG = ServiceHelper.class.getName();
|
||||
//private final static String TAG = ServiceHelper.class.getName();
|
||||
|
||||
protected static ServiceHelper mInstance;
|
||||
|
||||
@@ -24,28 +23,17 @@ public class ServiceHelper {
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start transmitting service. It should be run at least once when the app
|
||||
* starts for the first time, and every time, when a tracking gps-fix is
|
||||
* stored, to ensure it gets sent to the API-server.
|
||||
*/
|
||||
public void startTransmittingService(Context context) {
|
||||
Intent intent = new Intent(context, TransmittingService.class);
|
||||
intent.setAction(context.getString(R.string.transmitting_service_start));
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start tracking service with a given eventId. The eventId is used to determine
|
||||
* Start tracking service with a given checkinDigest. The checkinDigest is used to determine
|
||||
* the event from the database in order to set the host-address correctly.
|
||||
* @param eventId id of the event (not the row-id)
|
||||
* @param checkinDigest of the event
|
||||
*/
|
||||
public void startTrackingService(Context context, String eventId)
|
||||
public void startTrackingService(Context context, String checkinDigest)
|
||||
{
|
||||
Intent intent = new Intent(context, TrackingService.class);
|
||||
intent.setAction(context.getString(R.string.tracking_service_start));
|
||||
intent.putExtra(context.getString(R.string.tracking_service_event_id_parameter), eventId);
|
||||
intent.putExtra(context.getString(R.string.tracking_service_checkin_digest_parameter), checkinDigest);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -9,7 +9,6 @@ import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Competitor;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Event;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.Leaderboard;
|
||||
import com.sap.sailing.android.tracking.app.provider.AnalyticsContract.SensorGps;
|
||||
|
||||
public class SqlDebugHelper {
|
||||
|
||||
@@ -28,6 +27,7 @@ public class SqlDebugHelper {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("_ID: " + c1.getString(c1.getColumnIndex(BaseColumns._ID)) + ", ");
|
||||
sb.append("NAME: " + c1.getString(c1.getColumnIndex(Leaderboard.LEADERBOARD_NAME)) + "\n");
|
||||
sb.append("DIGEST: " + c1.getString(c1.getColumnIndex(Leaderboard.LEADERBOARD_CHECKIN_DIGEST)) + "\n");
|
||||
ExLog.w(context, TAG, "Leaderboard: " + sb.toString());
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class SqlDebugHelper {
|
||||
sb.append("DATE END: " + c2.getString(c2.getColumnIndex(Event.EVENT_DATE_END)) + ", ");
|
||||
sb.append("IMAGE-URL: " + c2.getString(c2.getColumnIndex(Event.EVENT_IMAGE_URL)) + ", ");
|
||||
sb.append("SERVER: " + c2.getString(c2.getColumnIndex(Event.EVENT_SERVER)) + "\n");
|
||||
sb.append("DIGEST: " + c2.getString(c2.getColumnIndex(Event.EVENT_CHECKIN_DIGEST)) + "\n");
|
||||
|
||||
ExLog.w(context, TAG, "Event: " + sb.toString());
|
||||
}
|
||||
@@ -66,15 +67,13 @@ public class SqlDebugHelper {
|
||||
sb.append("NATIONALITY: " + c3.getString(c3.getColumnIndex(Competitor.COMPETITOR_NATIONALITY)) + ", ");
|
||||
sb.append("COUNTRY CODE: " + c3.getString(c3.getColumnIndex(Competitor.COMPETITOR_COUNTRY_CODE)) + ", ");
|
||||
sb.append("SAIL-ID: " + c3.getString(c3.getColumnIndex(Competitor.COMPETITOR_SAIL_ID)) + "\n");
|
||||
sb.append("DIGEST: " + c3.getString(c3.getColumnIndex(Competitor.COMPETITOR_CHECKIN_DIGEST)) + "\n");
|
||||
|
||||
ExLog.w(context, TAG, "Competitor: " + sb.toString());
|
||||
}
|
||||
|
||||
c3.close();
|
||||
|
||||
Cursor c4 = cr.query(SensorGps.CONTENT_URI, null, null, null, null);
|
||||
|
||||
ExLog.w(context, TAG, "--- NUMBER OF GPS FIXES IN DB: " + c4.getCount());
|
||||
ExLog.w(context, TAG, "--- END OF SQL PRINTOUT" );
|
||||
}
|
||||
}
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
package com.sap.sailing.android.tracking.app.utils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response.ErrorListener;
|
||||
import com.android.volley.Response.Listener;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
public class VolleyHelper extends Application {
|
||||
|
||||
private static final String TAG = VolleyHelper.class.getName();
|
||||
|
||||
private RequestQueue mRequestQueue;
|
||||
private Context mContext;
|
||||
|
||||
protected static VolleyHelper mInstance;
|
||||
|
||||
protected VolleyHelper(Context context){
|
||||
super();
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static synchronized VolleyHelper getInstance(Context context) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new VolleyHelper(context);
|
||||
}
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public RequestQueue getRequestQueue() {
|
||||
if (mRequestQueue == null) {
|
||||
mRequestQueue = Volley.newRequestQueue(mContext);
|
||||
}
|
||||
|
||||
return mRequestQueue;
|
||||
}
|
||||
|
||||
public <T> void enqueueRequest(String urlStr, JSONObject requestJsonObject,
|
||||
Listener<JSONObject> listener, ErrorListener errorListener) {
|
||||
addRequest(new JsonObjectOrStatusOnlyRequest(urlStr, requestJsonObject, listener,
|
||||
errorListener));
|
||||
}
|
||||
|
||||
public <T> void addRequest(Request<T> request) {
|
||||
addRequest(request, TAG);
|
||||
}
|
||||
|
||||
public <T> void addRequest(Request<T> request, Object tag) {
|
||||
request.setTag((tag == null) ? TAG : tag);
|
||||
getRequestQueue().add(request);
|
||||
}
|
||||
|
||||
public void cancelRequest(Object tag) {
|
||||
if (mRequestQueue != null) {
|
||||
mRequestQueue.cancelAll((tag == null) ? TAG : tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -1,5 +1,9 @@
|
||||
package com.sap.sailing.android.tracking.app.valueobjects;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class CheckinData {
|
||||
// public String gcmId;
|
||||
public String leaderboardName;
|
||||
@@ -16,6 +20,17 @@ public class CheckinData {
|
||||
public String competitorNationality;
|
||||
public String competitorCountryCode;
|
||||
public String deviceUid;
|
||||
public String checkinDigest;
|
||||
|
||||
public void setCheckinDigestFromString(String checkinString) throws UnsupportedEncodingException, NoSuchAlgorithmException
|
||||
{
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
md.update(checkinString.getBytes("UTF-8"));
|
||||
byte[] digest = md.digest();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (byte byt : digest) buf.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1));
|
||||
checkinDigest = buf.toString();
|
||||
}
|
||||
|
||||
public EventInfo getEvent()
|
||||
{
|
||||
@@ -26,6 +41,7 @@ public class CheckinData {
|
||||
event.endMillis = Long.parseLong(eventEndDateStr);
|
||||
event.imageUrl = eventFirstImageUrl;
|
||||
event.server = eventServerUrl;
|
||||
event.checkinDigest = checkinDigest;
|
||||
return event;
|
||||
}
|
||||
|
||||
@@ -33,6 +49,7 @@ public class CheckinData {
|
||||
{
|
||||
LeaderboardInfo leaderboard = new LeaderboardInfo();
|
||||
leaderboard.name = leaderboardName;
|
||||
leaderboard.checkinDigest = checkinDigest;
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@@ -44,6 +61,7 @@ public class CheckinData {
|
||||
competitor.sailId = competitorSailId;
|
||||
competitor.nationality = competitorNationality;
|
||||
competitor.countryCode = competitorCountryCode;
|
||||
competitor.checkinDigest = checkinDigest;
|
||||
return competitor;
|
||||
}
|
||||
}
|
||||
+1
@@ -7,6 +7,7 @@ public class CompetitorInfo {
|
||||
public String countryCode;
|
||||
public String nationality;
|
||||
public String sailId;
|
||||
public String checkinDigest;
|
||||
public int rowId;
|
||||
|
||||
}
|
||||
+5
-1
@@ -5,18 +5,22 @@ public class EventInfo {
|
||||
public String id;
|
||||
public String name;
|
||||
public String leaderboardName; // when using join-query
|
||||
public String competitorId; // when using join-query
|
||||
public String imageUrl;
|
||||
public long startMillis;
|
||||
public long endMillis;
|
||||
public int rowId;
|
||||
public String checkinDigest;
|
||||
public String server;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "eventName: " + name + ", leaderboardName: "
|
||||
+ leaderboardName + ", eventImageUrl: " + imageUrl
|
||||
+ leaderboardName + ", competitorId: " + competitorId
|
||||
+ ", eventImageUrl: " + imageUrl
|
||||
+ ", eventStartMillis: " + startMillis
|
||||
+ ", eventEndMillis: " + endMillis + ", eventRowId: "
|
||||
+ ", checkinDigest: " + checkinDigest
|
||||
+ rowId + ", server: " + server;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -3,5 +3,6 @@ package com.sap.sailing.android.tracking.app.valueobjects;
|
||||
public class LeaderboardInfo {
|
||||
|
||||
public String name;
|
||||
public String checkinDigest;
|
||||
public int rowId;
|
||||
}
|
||||
|
||||
+1
-1
@@ -199,7 +199,7 @@ public class CirclePageIndicator extends View implements PageIndicator {
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mViewPager == null) {
|
||||
if (mViewPager == null || mViewPager.getAdapter() == null) {
|
||||
return;
|
||||
}
|
||||
final int count = mViewPager.getAdapter().getCount();
|
||||
|
||||
@@ -9,6 +9,3 @@ include ":java:com.sap.sse.datamining.shared"
|
||||
include ":mobile:com.sap.sailing.android.shared"
|
||||
include ":mobile:com.sap.sailing.android.tracking.app"
|
||||
include ":mobile:com.sap.sailing.racecommittee.app"
|
||||
|
||||
/* to be removed later */
|
||||
include ":mobile:google-volley_lib"
|
||||
|
||||
Reference in New Issue
Block a user