mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-27 06:17:27 +00:00
Merge branch 'android_apps' of ssh://sapsailing.com/home/trac/git into android_apps
This commit is contained in:
commit
9d5fa2efe1
23 files changed
+1477
-604
No files matched your search
+67
@@ -0,0 +1,67 @@
|
||||
package com.sap.sailing.android.tracking.app.test;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.CheckinData;
|
||||
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.LeaderboardInfo;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class CheckinDataTest extends TestCase {
|
||||
|
||||
private CheckinData checkinData;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
checkinData = new CheckinData();
|
||||
|
||||
checkinData.leaderboardName = "lt";
|
||||
checkinData.eventId = "et";
|
||||
checkinData.eventName = "ent";
|
||||
checkinData.eventStartDateStr = "123";
|
||||
checkinData.eventEndDateStr = "456";
|
||||
checkinData.eventFirstImageUrl = "http://1.2.3.4/test.png";
|
||||
checkinData.eventServerUrl = "http://5.6.7.8";
|
||||
checkinData.checkinURL = "http://9.1.2.3/checkin";
|
||||
checkinData.competitorCountryCode = "DE";
|
||||
checkinData.competitorName = "cn";
|
||||
checkinData.competitorNationality = "GER";
|
||||
checkinData.competitorSailId = "SAIL 1";
|
||||
checkinData.competitorId = "1-2-3-4";
|
||||
checkinData.deviceUid = "0011223344";
|
||||
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testGetEvent()
|
||||
{
|
||||
EventInfo event = checkinData.getEvent();
|
||||
assertEquals("et", event.id);
|
||||
assertEquals("ent", event.name);
|
||||
assertEquals(123, event.startMillis);
|
||||
assertEquals(456, event.endMillis);
|
||||
assertEquals("http://1.2.3.4/test.png", event.imageUrl);
|
||||
assertEquals("http://5.6.7.8", event.server);
|
||||
}
|
||||
|
||||
public void testGetCompetitor()
|
||||
{
|
||||
CompetitorInfo competitor = checkinData.getCompetitor();
|
||||
assertEquals("DE", competitor.countryCode);
|
||||
assertEquals("cn", competitor.name);
|
||||
assertEquals("GER", competitor.nationality);
|
||||
assertEquals("SAIL 1", competitor.sailId);
|
||||
assertEquals("1-2-3-4", competitor.id);
|
||||
}
|
||||
|
||||
public void testGetLeaderboard()
|
||||
{
|
||||
LeaderboardInfo leaderboard = checkinData.getLeaderboard();
|
||||
assertEquals("lt", leaderboard.name);
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,14 @@
|
||||
<data android:scheme="comsapsailingtracker" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.activities.LeaderboardWebViewActivity"
|
||||
android:label="@string/title_activity_webview"
|
||||
android:screenOrientation="unspecified" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.activities.LeaderboardWebViewActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.activities.RegattaActivity"
|
||||
android:label="@string/title_activity_regatta"
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left"
|
||||
android:padding="0dp"
|
||||
android:padding="5dp"
|
||||
android:text="@string/thank_you_you_successfully_participated"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold" />
|
||||
@@ -302,18 +302,40 @@
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@color/white_transparent" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/start_tracking"
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="@drawable/rounded_btn_green"
|
||||
android:padding="10dp"
|
||||
android:text="@string/start_tracking"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
android:layout_below="@id/white_bar"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/show_leaderboards_button"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="@drawable/rounded_btn_yellow"
|
||||
android:padding="5dp"
|
||||
android:text="@string/show_leaderboard"
|
||||
android:textAllCaps="true"
|
||||
android:layout_weight="0.50"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/start_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_weight="0.50"
|
||||
android:background="@drawable/rounded_btn_green"
|
||||
android:padding="5dp"
|
||||
android:text="@string/start_tracking"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<WebView
|
||||
android:id="@+id/web_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -287,19 +287,41 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@color/white_transparent" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/start_tracking"
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="@drawable/rounded_btn_green"
|
||||
android:padding="10dp"
|
||||
android:text="@string/start_tracking"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
android:layout_below="@id/white_bar"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/show_leaderboards_button"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="@drawable/rounded_btn_yellow"
|
||||
android:padding="10dp"
|
||||
android:text="@string/show_leaderboard"
|
||||
android:textAllCaps="true"
|
||||
android:layout_weight="0.50"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.sap.sailing.android.tracking.app.customviews.OpenSansButton
|
||||
android:id="@+id/start_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_weight="0.50"
|
||||
android:background="@drawable/rounded_btn_green"
|
||||
android:padding="10dp"
|
||||
android:text="@string/start_tracking"
|
||||
android:textAllCaps="true"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="scan_race_barcode">Scan Race Barcode</string>
|
||||
<string name="gps_fix_interval">GPS Fix Interval</string>
|
||||
<string name="title_activity_regatta">Regatta</string>
|
||||
<string name="title_activity_webview">Leaderboard</string>
|
||||
<string name="title_activity_start">GPS Tracker einstellen</string>
|
||||
<string name="title_activity_tracking">Tracking</string>
|
||||
<string name="hello_world">Hello wörld!</string>
|
||||
@@ -81,4 +82,5 @@
|
||||
<string name="heading">Kurs</string>
|
||||
<string name="sog">SOG</string>
|
||||
<string name="none">Keine</string>
|
||||
<string name="show_leaderboard">Leaderboard</string>
|
||||
</resources>
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="scan_race_barcode">Scan Race Barcode</string>
|
||||
<string name="gps_fix_interval">GPS fix interval</string>
|
||||
<string name="title_activity_regatta">Regatta</string>
|
||||
<string name="title_activity_webview">Leader board</string>
|
||||
<string name="title_activity_start">Setup GPS-Tracker</string>
|
||||
<string name="title_activity_tracking">Tracking</string>
|
||||
<string name="hello_world">Hello world!</string>
|
||||
@@ -68,5 +69,6 @@
|
||||
<string name="heading">Heading</string>
|
||||
<string name="sog">SOG</string>
|
||||
<string name="none">None</string>
|
||||
<string name="show_leaderboard">Leader board</string>
|
||||
|
||||
</resources>
|
||||
+3
-3
@@ -151,11 +151,11 @@ public class TrackingService extends Service implements ConnectionCallbacks,
|
||||
GPSQuality quality = GPSQuality.noSignal;
|
||||
|
||||
if (gpsQualityListener != null) {
|
||||
if (gpsAccurracy > 163) {
|
||||
if (gpsAccurracy > 48) {
|
||||
quality = GPSQuality.poor;
|
||||
} else if (gpsAccurracy > 48) {
|
||||
} else if (gpsAccurracy > 10) {
|
||||
quality = GPSQuality.good;
|
||||
} else if (gpsAccurracy < 48) {
|
||||
} else if (gpsAccurracy <= 10) {
|
||||
quality = GPSQuality.great;
|
||||
}
|
||||
|
||||
|
||||
+287
-304
@@ -34,87 +34,92 @@ 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.
|
||||
* 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.)
|
||||
* (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 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 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.
|
||||
* 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 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();
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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();
|
||||
if (!timerRunning) {
|
||||
startTimer();
|
||||
}
|
||||
} else {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
|
||||
private void startTimer() {
|
||||
timer = new Timer();
|
||||
timer.start();
|
||||
@@ -122,168 +127,151 @@ public class TransmittingService extends Service {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TIMER", "Background update-timer start");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
if (timer != null)
|
||||
{
|
||||
timer.stop();
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
timerRunning = false;
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TIMER", "Background update-timer stop");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void markSuccessfulTransmission()
|
||||
{
|
||||
|
||||
private void markSuccessfulTransmission() {
|
||||
currentlySending = false;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "markSuccessfulTransmission");
|
||||
}
|
||||
|
||||
|
||||
lastTransmissionFailed = false;
|
||||
lastTransmissionTimestamp = System.nanoTime();
|
||||
|
||||
|
||||
reportApiConnectivity(APIConnectivity.reachableTransmissionSuccess);
|
||||
}
|
||||
|
||||
private void markFailedTransmission()
|
||||
{
|
||||
|
||||
private void markFailedTransmission() {
|
||||
currentlySending = false;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "markFailedTransmission");
|
||||
}
|
||||
|
||||
|
||||
lastTransmissionFailed = true;
|
||||
lastTransmissionTimestamp = 0;
|
||||
|
||||
if (isConnected())
|
||||
{
|
||||
|
||||
if (isConnected()) {
|
||||
reportApiConnectivity(APIConnectivity.reachableTransmissionError);
|
||||
} else {
|
||||
reportApiConnectivity(APIConnectivity.notReachable);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportApiConnectivity(APIConnectivity.notReachable);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If time interval has passed without any transmission, the service can turn
|
||||
* itself off. Same for
|
||||
* If time interval has passed without any transmission, the service can
|
||||
* turn itself off. Same for
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean serviceCanShutItselfDown()
|
||||
{
|
||||
private boolean serviceCanShutItselfDown() {
|
||||
long currentNanoTime = System.nanoTime();
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
|
||||
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
|
||||
|
||||
// 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");
|
||||
|
||||
// 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");
|
||||
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "TRANSMISSION", "returning false, don't terminate");
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void timerFired()
|
||||
{
|
||||
|
||||
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");
|
||||
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");
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, "POWER-LEVELS", "in default power mode");
|
||||
}
|
||||
|
||||
|
||||
currentUpdateInterval = UPDATE_INTERVAL_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
sendFixesToAPI(null);
|
||||
reportUnsentGPSFixesCount(DatabaseHelper.getInstance().getNumberOfUnsentGPSFixes(getBaseContext()));
|
||||
reportUnsentGPSFixesCount(DatabaseHelper.getInstance().getNumberOfUnsentGPSFixes(
|
||||
getBaseContext()));
|
||||
}
|
||||
|
||||
private boolean getTrackingServiceIsCurrentlyTracking()
|
||||
{
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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));
|
||||
@@ -296,8 +284,7 @@ public class TransmittingService extends Service {
|
||||
json.put("longitude", fix.longitude);
|
||||
json.put("latitude", fix.latitude);
|
||||
} catch (JSONException ex) {
|
||||
ExLog.i(this, TAG, "Error while building geolocation json "
|
||||
+ ex.getMessage());
|
||||
ExLog.i(this, TAG, "Error while building geolocation json " + ex.getMessage());
|
||||
}
|
||||
|
||||
jsonArray.put(json);
|
||||
@@ -306,197 +293,198 @@ public class TransmittingService extends Service {
|
||||
// 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());
|
||||
ExLog.i(this, TAG,
|
||||
"url: " + prefs.getServerURL() + prefs.getServerGpsFixesPostPath());
|
||||
}
|
||||
|
||||
if (host != null)
|
||||
{
|
||||
sendingAttempted = true;
|
||||
|
||||
JsonObjectOrStatusOnlyRequest request = new JsonObjectOrStatusOnlyRequest(host
|
||||
+ prefs.getServerGpsFixesPostPath(), requestObject, new FixSubmitListener(
|
||||
ids.toArray(idsArr)), new FixSubmitErrorListener(host,
|
||||
getTrackingServiceIsCurrentlyTracking(), failedHosts));
|
||||
|
||||
VolleyHelper.getInstance(this).addRequest(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
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
|
||||
JsonObjectOrStatusOnlyRequest request = new JsonObjectOrStatusOnlyRequest(host
|
||||
+ prefs.getServerGpsFixesPostPath(), requestObject,
|
||||
new FixSubmitListener(ids.toArray(idsArr)), new FixSubmitErrorListener(
|
||||
host, getTrackingServiceIsCurrentlyTracking(), failedHosts));
|
||||
|
||||
VolleyHelper.getInstance(this).addRequest(request);
|
||||
}
|
||||
} else {
|
||||
ExLog.w(this, TAG, "Warning, can't send fixes, host is null!");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
if (serviceCanShutItselfDown())
|
||||
{
|
||||
|
||||
if (serviceCanShutItselfDown()) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Nothing to send or timeout occurred, Transmitting Service is stopping timer and terminating itself.");
|
||||
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.
|
||||
* 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()
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
float batteryPct = level / (float) scale;
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(this, TAG, "Battery: " + (batteryPct * 100) + "%");
|
||||
}
|
||||
|
||||
|
||||
return batteryPct;
|
||||
}
|
||||
|
||||
private void deleteSynced(String[] fixIdStrings)
|
||||
{
|
||||
|
||||
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);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
* 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 Listener<JSONObject> {
|
||||
|
||||
private String[] ids;
|
||||
private String[] ids;
|
||||
|
||||
public FixSubmitListener(String[] ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
deleteSynced(ids);
|
||||
markSuccessfulTransmission();
|
||||
//markAsSynced(ids);
|
||||
}
|
||||
}
|
||||
|
||||
private class FixSubmitErrorListener implements ErrorListener {
|
||||
|
||||
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;
|
||||
public FixSubmitListener(String[] ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
deleteSynced(ids);
|
||||
markSuccessfulTransmission();
|
||||
// markAsSynced(ids);
|
||||
}
|
||||
}
|
||||
|
||||
private class FixSubmitErrorListener implements ErrorListener {
|
||||
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 onErrorResponse(VolleyError 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) {
|
||||
@@ -505,7 +493,7 @@ public class TransmittingService extends Service {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
timerFired();
|
||||
}
|
||||
reportApiConnectivity(APIConnectivity.noAttempt);
|
||||
@@ -518,50 +506,45 @@ public class TransmittingService extends Service {
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void stop() {
|
||||
endExecution = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerAPIConnectivityListener( APIConnectivityListener listener )
|
||||
{
|
||||
|
||||
public void registerAPIConnectivityListener(APIConnectivityListener listener) {
|
||||
apiConnectivityListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterAPIConnectivityListener()
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
notReachable(0), reachableTransmissionSuccess(1), reachableTransmissionError(2), noAttempt(
|
||||
4);
|
||||
|
||||
private final int apiConnectivity;
|
||||
|
||||
APIConnectivity(int connectivity)
|
||||
{
|
||||
|
||||
APIConnectivity(int connectivity) {
|
||||
this.apiConnectivity = connectivity;
|
||||
}
|
||||
|
||||
public int toInt()
|
||||
{
|
||||
|
||||
public int toInt() {
|
||||
return this.apiConnectivity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface APIConnectivityListener {
|
||||
public void apiConnectivityUpdated( APIConnectivity apiConnectivity );
|
||||
public void setUnsentGPSFixesCount( int count );
|
||||
public void apiConnectivityUpdated(APIConnectivity apiConnectivity);
|
||||
|
||||
public void setUnsentGPSFixesCount(int count);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.ui.fragments.LeaderboardFragment;
|
||||
|
||||
public class LeaderboardWebViewActivity extends BaseActivity {
|
||||
|
||||
public final static String LEADERBOARD_EXTRA_SERVER_URL = "leaderboardExtraServerUrl";
|
||||
public final static String LEADERBOARD_EXTRA_EVENT_ID = "leaderboardExtraEventId";
|
||||
public final static String LEADERBOARD_EXTRA_LEADERBOARD_NAME = "leaderboardExtraLeaderboardName";
|
||||
|
||||
public String serverUrl;
|
||||
public String eventId;
|
||||
public String leaderboardName;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
serverUrl = intent.getStringExtra(LEADERBOARD_EXTRA_SERVER_URL);
|
||||
eventId = intent.getStringExtra(LEADERBOARD_EXTRA_EVENT_ID);
|
||||
leaderboardName = intent.getStringExtra(LEADERBOARD_EXTRA_LEADERBOARD_NAME);
|
||||
|
||||
setContentView(R.layout.fragment_container);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
if (toolbar != null) {
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
|
||||
}
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
toolbar.setNavigationIcon(R.drawable.sap_logo_64_sq);
|
||||
toolbar.setPadding(20, 0, 0, 0);
|
||||
getSupportActionBar().setTitle(getString(R.string.title_activity_webview));
|
||||
}
|
||||
|
||||
replaceFragment(R.id.content_frame, new LeaderboardFragment());
|
||||
}
|
||||
}
|
||||
+76
-45
@@ -45,10 +45,11 @@ import com.sap.sailing.android.tracking.app.valueobjects.LeaderboardInfo;
|
||||
public class RegattaActivity extends BaseActivity {
|
||||
|
||||
private final static String TAG = RegattaActivity.class.getName();
|
||||
private final static String LEADERBOARD_IMAGE_FILENAME_PREFIX = "leaderboardImage_";
|
||||
|
||||
private EventInfo event;
|
||||
private CompetitorInfo competitor;
|
||||
private LeaderboardInfo leaderboard;
|
||||
public EventInfo event;
|
||||
public CompetitorInfo competitor;
|
||||
public LeaderboardInfo leaderboard;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -85,7 +86,6 @@ public class RegattaActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
replaceFragment(R.id.content_frame, new RegattaFragment());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,10 +102,6 @@ public class RegattaActivity extends BaseActivity {
|
||||
ExLog.i(this, TAG, "Clicked SETTINGS.");
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
return true;
|
||||
// case R.id.options_menu_info:
|
||||
// ExLog.i(this, TAG, "Clicked INFO.");
|
||||
// startActivity(new Intent(this, SystemInformationActivity.class));
|
||||
// return true;
|
||||
case R.id.options_menu_checkout:
|
||||
ExLog.i(this, TAG, "Clicked CHECKOUT.");
|
||||
checkout();
|
||||
@@ -153,21 +149,22 @@ public class RegattaActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
getRegattaFragment().setChangePhotoButtonHidden(true);
|
||||
ExLog.w(this, TAG, "Event Image URL: " + event.imageUrl);
|
||||
|
||||
if (event.imageUrl != null)
|
||||
ImageView imageView = (ImageView) findViewById(R.id.userImage);
|
||||
Bitmap storedImage = getStoredImage(getLeaderboardImageFileName(leaderboard.name));
|
||||
|
||||
if (storedImage == null)
|
||||
{
|
||||
ImageView imageView = (ImageView) findViewById(R.id.userImage);
|
||||
Bitmap storedImage = getStoredImage();
|
||||
if (storedImage != null)
|
||||
{
|
||||
imageView.setImageBitmap(storedImage);
|
||||
userImageUpdated();
|
||||
}
|
||||
else
|
||||
{
|
||||
new DownloadImageTask(imageView).execute(event.imageUrl);
|
||||
}
|
||||
|
||||
if (event.imageUrl != null)
|
||||
{
|
||||
new DownloadImageTask(imageView).execute(event.imageUrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imageView.setImageBitmap(storedImage);
|
||||
userImageUpdated();
|
||||
}
|
||||
|
||||
super.onResume();
|
||||
@@ -177,9 +174,9 @@ public class RegattaActivity extends BaseActivity {
|
||||
*
|
||||
* @param bitmap
|
||||
*/
|
||||
public void updatePictureChosenByUser(final Bitmap bitmap)
|
||||
public void updateLeaderboardPictureChosenByUser(final Bitmap bitmap)
|
||||
{
|
||||
storeImage(bitmap);
|
||||
storeImage(bitmap, getLeaderboardImageFileName(leaderboard.name));
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
@@ -196,8 +193,8 @@ public class RegattaActivity extends BaseActivity {
|
||||
* Store image for quicker retrieval later.
|
||||
* @param images
|
||||
*/
|
||||
private void storeImage(Bitmap image) {
|
||||
File pictureFile = getMediaFile();
|
||||
private void storeImage(Bitmap image, String fileName) {
|
||||
File pictureFile = getImageFile(fileName);
|
||||
if (pictureFile == null) {
|
||||
Log.d(TAG,
|
||||
"Error creating media file, check storage permissions: ");// e.getMessage());
|
||||
@@ -215,12 +212,12 @@ public class RegattaActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get leaderboard image if there's one saved.
|
||||
* Get stored image if there's one saved.
|
||||
* @return
|
||||
*/
|
||||
private Bitmap getStoredImage()
|
||||
private Bitmap getStoredImage(String fileName)
|
||||
{
|
||||
File pictureFile = getMediaFile();
|
||||
File pictureFile = getImageFile(fileName);
|
||||
if (pictureFile == null)
|
||||
{
|
||||
return null;
|
||||
@@ -228,21 +225,44 @@ public class RegattaActivity extends BaseActivity {
|
||||
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
Bitmap image = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(),
|
||||
options);
|
||||
Bitmap image = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
// private File getMediaFile(){
|
||||
//
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get Path for cached leaderbaord image.
|
||||
* @return
|
||||
*/
|
||||
private File getMediaFile(){
|
||||
public File getImageFile(String fileName) {
|
||||
|
||||
File mediaStorageDir;
|
||||
File mediaStorageDir = getMediaStorageDir();
|
||||
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment
|
||||
.getExternalStorageState())) {
|
||||
File mediaFile;
|
||||
String mImageName="MI_"+ fileName +".png";
|
||||
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
|
||||
return mediaFile;
|
||||
}
|
||||
|
||||
public void deleteImageFile(String fileName) {
|
||||
File mediaStorageDir = getMediaStorageDir();
|
||||
|
||||
File mediaFile;
|
||||
String mImageName = "MI_" + fileName + ".png";
|
||||
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
|
||||
|
||||
mediaFile.delete();
|
||||
}
|
||||
|
||||
public File getMediaStorageDir() {
|
||||
File mediaStorageDir;
|
||||
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
mediaStorageDir = new File(
|
||||
Environment.getExternalStorageDirectory()
|
||||
+ "/Android/data/"
|
||||
@@ -257,12 +277,9 @@ public class RegattaActivity extends BaseActivity {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
File mediaFile;
|
||||
String mImageName="MI_"+ leaderboard.name +".png";
|
||||
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
|
||||
return mediaFile;
|
||||
}
|
||||
|
||||
return mediaStorageDir;
|
||||
}
|
||||
|
||||
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
|
||||
ImageView bmImage;
|
||||
@@ -274,6 +291,7 @@ public class RegattaActivity extends BaseActivity {
|
||||
protected Bitmap doInBackground(String... urls) {
|
||||
String urldisplay = urls[0];
|
||||
Bitmap mIcon11 = null;
|
||||
|
||||
try {
|
||||
InputStream in = new java.net.URL(urldisplay).openStream();
|
||||
mIcon11 = BitmapFactory.decodeStream(in);
|
||||
@@ -285,11 +303,15 @@ public class RegattaActivity extends BaseActivity {
|
||||
|
||||
protected void onPostExecute(Bitmap result) {
|
||||
bmImage.setImageBitmap(result);
|
||||
storeImage(result);
|
||||
storeImage(result, getLeaderboardImageFileName(leaderboard.name));
|
||||
userImageUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private String getLeaderboardImageFileName(String leaderboardName) {
|
||||
return LEADERBOARD_IMAGE_FILENAME_PREFIX + leaderboardName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out from regatta;
|
||||
*/
|
||||
@@ -320,6 +342,7 @@ public class RegattaActivity extends BaseActivity {
|
||||
public void onResponse(JSONObject response) {
|
||||
DatabaseHelper.getInstance().deleteRegattaFromDatabase(
|
||||
RegattaActivity.this, event, competitor, leaderboard);
|
||||
deleteImageFile(getLeaderboardImageFileName(leaderboard.name));
|
||||
dismissProgressDialog();
|
||||
finish();
|
||||
}
|
||||
@@ -331,15 +354,23 @@ public class RegattaActivity extends BaseActivity {
|
||||
showErrorPopup(
|
||||
R.string.error,
|
||||
R.string.error_could_not_complete_operation_on_server_try_again);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
VolleyHelper.getInstance(this).addRequest(checkoutRequest);
|
||||
}
|
||||
|
||||
public EventInfo getEvent()
|
||||
{
|
||||
return event;
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
RegattaFragment fragment = (RegattaFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame);
|
||||
|
||||
if (fragment.isShowingBigCheckoutButton())
|
||||
{
|
||||
//do nothing, user must checkout himself at this point.
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
-29
@@ -14,9 +14,7 @@ import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.BuildConfig;
|
||||
@@ -52,6 +50,9 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
|
||||
private final static String TAG = TrackingActivity.class.getName();
|
||||
private final static String SIS_TRACKING_FRAGMENT = "savedInstanceTrackingFragment";
|
||||
private final static String SIS_LAST_VIEWPAGER_ITEM = "instanceStateLastViewPagerItem";
|
||||
private final static String SIS_LAST_SPEED_TEXT = "instanceStateLastSpeedText";
|
||||
private final static String SIS_LAST_COMPASS_TEXT = "instanceStateLastCompassText";
|
||||
|
||||
private ViewPager mPager;
|
||||
private ScreenSlidePagerAdapter mPagerAdapter;
|
||||
@@ -59,9 +60,20 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
private String eventId;
|
||||
private AppPreferences prefs;
|
||||
|
||||
private TrackingFragment trackingFragment;
|
||||
|
||||
private TrackingFragment trackingFragment;
|
||||
private TimerRunnable timer;
|
||||
|
||||
private int lastViewPagerItem;
|
||||
|
||||
/**
|
||||
* This isn't nice. The callbacks for fragments inside a
|
||||
* view pager are unreliable, but I want the values
|
||||
* to be displayed immediately after device rotation.
|
||||
* Thus they are cached here and the fragments can pick
|
||||
* them up.
|
||||
*/
|
||||
public String lastSpeedIndicatorText = "";
|
||||
public String lastCompassIndicatorText = "";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -101,12 +113,8 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
|
||||
}
|
||||
mPager.setAdapter(mPagerAdapter);
|
||||
mPager.setOffscreenPageLimit(3);
|
||||
mPager.setOffscreenPageLimit(0);
|
||||
|
||||
// ok, here be dragons.
|
||||
// however, I haven't found out how the ViewPager retains and dismisses fragments, so I check for every case.
|
||||
// The easy way (if savedInstanceState != null) takeFromBundle(); doesn't work, since only some fragments are
|
||||
// saved to the bundle it seems.
|
||||
if (savedInstanceState != null) {
|
||||
Fragment tFragment = getSupportFragmentManager().getFragment(savedInstanceState, SIS_TRACKING_FRAGMENT);
|
||||
if (tFragment != null) {
|
||||
@@ -114,6 +122,10 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
} else {
|
||||
trackingFragment = new TrackingFragment();
|
||||
}
|
||||
|
||||
lastViewPagerItem = savedInstanceState.getInt(SIS_LAST_VIEWPAGER_ITEM);
|
||||
lastSpeedIndicatorText = savedInstanceState.getString(SIS_LAST_SPEED_TEXT);
|
||||
lastCompassIndicatorText = savedInstanceState.getString(SIS_LAST_COMPASS_TEXT);
|
||||
} else {
|
||||
trackingFragment = new TrackingFragment();
|
||||
}
|
||||
@@ -125,6 +137,7 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int arg0) {
|
||||
lastViewPagerItem = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,23 +153,17 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
ServiceHelper.getInstance().startTrackingService(this, eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
// HudFragment hudFragment = (HudFragment)
|
||||
// getSupportFragmentManager().findFragmentById(R.id.hud_content_frame);
|
||||
// hudFragment.layoutOverlay();
|
||||
//
|
||||
// hudFragment.setSpeedOverGround(0);
|
||||
// hudFragment.setHeading(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(SIS_LAST_VIEWPAGER_ITEM, lastViewPagerItem);
|
||||
outState.putString(SIS_LAST_SPEED_TEXT, lastSpeedIndicatorText);
|
||||
outState.putString(SIS_LAST_COMPASS_TEXT, lastCompassIndicatorText);
|
||||
|
||||
if (trackingFragment.isAdded()) {
|
||||
getSupportFragmentManager().putFragment(outState, SIS_TRACKING_FRAGMENT, trackingFragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,7 +226,9 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
{
|
||||
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
|
||||
}
|
||||
|
||||
mPager.setAdapter(mPagerAdapter);
|
||||
mPager.setCurrentItem(lastViewPagerItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -367,14 +376,6 @@ public class TrackingActivity extends BaseActivity implements GPSQualityListener
|
||||
return 3;
|
||||
}
|
||||
|
||||
// public StopTrackingButtonFragment getStopTrackingButtonFragment() {
|
||||
// if (stbFragment != null && stbFragment.isAdded())
|
||||
// {
|
||||
// return stbFragment;
|
||||
// }
|
||||
// else return null;
|
||||
// }
|
||||
|
||||
public CompassFragment getCompassFragment() {
|
||||
if (cFragment != null && cFragment.isAdded())
|
||||
{
|
||||
|
||||
+15
-17
@@ -7,11 +7,11 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
|
||||
public class CompassFragment extends BaseFragment {
|
||||
|
||||
private String TAG = CompassFragment.class.getName();
|
||||
private final String SIS_HEADING_TEXTIVEW = "CompassFragmentHeadingTextView";
|
||||
//private String TAG = CompassFragment.class.getName();
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
@@ -25,6 +25,12 @@ public class CompassFragment extends BaseFragment {
|
||||
{
|
||||
TextView headingText = (TextView) getActivity().findViewById(R.id.compass_bearing_text_view);
|
||||
headingText.setText(String.valueOf(Math.round(heading)) + "°");
|
||||
|
||||
TrackingActivity activity = (TrackingActivity) getActivity();
|
||||
|
||||
if (activity != null) {
|
||||
activity.lastCompassIndicatorText = headingText.getText().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,20 +38,12 @@ public class CompassFragment extends BaseFragment {
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
TextView headingText = (TextView)getActivity().findViewById(R.id.compass_bearing_text_view);
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
headingText.setText(savedInstanceState.getString(SIS_HEADING_TEXTIVEW));
|
||||
|
||||
TrackingActivity activity = (TrackingActivity) getActivity();
|
||||
if (activity != null) {
|
||||
headingText.setText(activity.lastCompassIndicatorText);
|
||||
} else {
|
||||
headingText.setText("");
|
||||
}
|
||||
else
|
||||
{
|
||||
headingText.setText("---°");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
TextView headingText = (TextView)getActivity().findViewById(R.id.compass_bearing_text_view);
|
||||
outState.putString(SIS_HEADING_TEXTIVEW, headingText.getText().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-127
@@ -2,7 +2,6 @@ package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -14,19 +13,13 @@ import org.json.JSONObject;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.BaseColumns;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
@@ -49,17 +42,17 @@ 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.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.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.UniqueDeviceUuid;
|
||||
import com.sap.sailing.android.tracking.app.utils.VolleyHelper;
|
||||
import com.sap.sailing.android.tracking.app.valueobjects.CheckinData;
|
||||
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelog.tracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
|
||||
@@ -83,8 +76,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
prefs = new AppPreferences(getActivity());
|
||||
|
||||
getActivity().getContentResolver();
|
||||
|
||||
View view = inflater.inflate(R.layout.fragment_home, container, false);
|
||||
|
||||
Button scanButton = (Button) view.findViewById(R.id.scanQr);
|
||||
@@ -103,8 +94,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
listView.addHeaderView(inflater.inflate(
|
||||
R.layout.regatta_listview_header, null));
|
||||
|
||||
adapter = new RegattaAdapter(getActivity(),
|
||||
R.layout.ragatta_listview_row, null, 0);
|
||||
adapter = new RegattaAdapter(getActivity(), R.layout.ragatta_listview_row, null, 0);
|
||||
listView.setAdapter(adapter);
|
||||
listView.setOnItemClickListener(new ItemClickListener());
|
||||
}
|
||||
@@ -184,17 +174,13 @@ public class HomeFragment extends BaseFragment implements
|
||||
|
||||
String leaderboardNameFromQR;
|
||||
try {
|
||||
leaderboardNameFromQR = URLEncoder.encode(
|
||||
uri.getQueryParameter(CheckinHelper.LEADERBOARD_NAME),
|
||||
"UTF-8").replace("+", "%20");
|
||||
leaderboardNameFromQR = URLEncoder.encode(uri.getQueryParameter(CheckinHelper.LEADERBOARD_NAME),"UTF-8").replace("+", "%20");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
ExLog.e(getActivity(), TAG, "Failed to encode leaderboard name: "
|
||||
+ e.getMessage());
|
||||
ExLog.e(getActivity(), TAG, "Failed to encode leaderboard name: " + e.getMessage());
|
||||
leaderboardNameFromQR = "";
|
||||
}
|
||||
|
||||
final String competitorId = uri
|
||||
.getQueryParameter(CheckinHelper.COMPETITOR_ID);
|
||||
final String competitorId = uri.getQueryParameter(CheckinHelper.COMPETITOR_ID);
|
||||
final String checkinURLStr = prefs.getServerURL()
|
||||
+ prefs.getServerCheckinPath().replace("{leaderboard-name}",
|
||||
leaderboardNameFromQR);
|
||||
@@ -435,30 +421,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
alert.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the combination of eventId, leaderboardName and
|
||||
* competitorId does not exist in the DB.
|
||||
*
|
||||
* @param eventId
|
||||
* @param leaderboardName
|
||||
* @param competitorId
|
||||
* @return
|
||||
*/
|
||||
private boolean eventLeaderboardCompetitorCombnationAvailable(
|
||||
String eventId, String leaderboardName, String competitorId) {
|
||||
|
||||
ContentResolver cr = getActivity().getContentResolver();
|
||||
String sel = "leaderboards.leaderboard_name = \"" + leaderboardName
|
||||
+ "\" AND competitors.competitor_id = \"" + competitorId
|
||||
+ "\" AND events.event_id = \"" + eventId + "\"";
|
||||
|
||||
int count = cr.query(
|
||||
AnalyticsContract.EventLeaderboardCompetitorJoined.CONTENT_URI,
|
||||
null, sel, null, null).getCount();
|
||||
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a checkin request and launch RegattaAcitivity afterwards
|
||||
*
|
||||
@@ -468,74 +430,21 @@ public class HomeFragment extends BaseFragment implements
|
||||
*/
|
||||
private void checkInWithAPIAndDisplayTrackingActivity(
|
||||
CheckinData checkinData) {
|
||||
if (eventLeaderboardCompetitorCombnationAvailable(checkinData.eventId,
|
||||
checkinData.leaderboardName, checkinData.competitorId)) {
|
||||
|
||||
// inserting leaderboard first in order to get the ID.
|
||||
// This should be atomic, but couldn't get withValueBackReference to
|
||||
// work yet.
|
||||
|
||||
ContentResolver cr = getActivity().getContentResolver();
|
||||
|
||||
ContentValues clv = new ContentValues();
|
||||
clv.put(Leaderboard.LEADERBOARD_NAME, checkinData.leaderboardName);
|
||||
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.
|
||||
|
||||
ArrayList<ContentProviderOperation> opList = new ArrayList<ContentProviderOperation>();
|
||||
|
||||
ContentValues cev = new ContentValues();
|
||||
cev.put(Event.EVENT_ID, checkinData.eventId);
|
||||
cev.put(Event.EVENT_NAME, checkinData.eventName);
|
||||
cev.put(Event.EVENT_DATE_START, Long.parseLong(checkinData.eventStartDateStr));
|
||||
cev.put(Event.EVENT_DATE_END, Long.parseLong(checkinData.eventEndDateStr));
|
||||
cev.put(Event.EVENT_SERVER, checkinData.eventServerUrl);
|
||||
cev.put(Event.EVENT_IMAGE_URL, checkinData.eventFirstImageUrl);
|
||||
cev.put(Event.EVENT_LEADERBOARD_FK, lastLeaderboardId);
|
||||
|
||||
opList.add(ContentProviderOperation.newInsert(Event.CONTENT_URI)
|
||||
.withValues(cev).build());
|
||||
|
||||
ContentValues ccv = new ContentValues();
|
||||
|
||||
ccv.put(Competitor.COMPETITOR_COUNTRY_CODE,checkinData.competitorCountryCode);
|
||||
ccv.put(Competitor.COMPETITOR_DISPLAY_NAME,checkinData.competitorName);
|
||||
ccv.put(Competitor.COMPETITOR_ID, checkinData.competitorId);
|
||||
ccv.put(Competitor.COMPETITOR_NATIONALITY,checkinData.competitorNationality);
|
||||
ccv.put(Competitor.COMPETITOR_SAIL_ID, checkinData.competitorSailId);
|
||||
ccv.put(Competitor.COMPETITOR_LEADERBOARD_FK, lastLeaderboardId);
|
||||
|
||||
opList.add(ContentProviderOperation
|
||||
.newInsert(Competitor.CONTENT_URI).withValues(ccv).build());
|
||||
if (DatabaseHelper.getInstance().eventLeaderboardCompetitorCombnationAvailable(
|
||||
getActivity(), checkinData.eventId, checkinData.leaderboardName, checkinData.competitorId)) {
|
||||
|
||||
try {
|
||||
cr.applyBatch(AnalyticsContract.CONTENT_AUTHORITY, opList);
|
||||
DatabaseHelper.getInstance().storeCheckinRow(getActivity(), checkinData.getEvent(),
|
||||
checkinData.getCompetitor(), checkinData.getLeaderboard());
|
||||
adapter.notifyDataSetChanged();
|
||||
} catch (RemoteException e1) {
|
||||
ExLog.e(getActivity(), TAG, "Batch insert failed: " + e1.getMessage());
|
||||
displayDatabaseError();
|
||||
return;
|
||||
} catch (OperationApplicationException e1) {
|
||||
ExLog.e(getActivity(), TAG, "Batch insert failed: " + e1.getMessage());
|
||||
} catch (GeneralDatabaseHelperException e) {
|
||||
ExLog.e(getActivity(), TAG, "Batch insert failed: " + e.getMessage());
|
||||
displayDatabaseError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
ExLog.i(getActivity(), TAG,
|
||||
"Batch-insert of checkinData completed.");
|
||||
ExLog.i(getActivity(), TAG, "Batch-insert of checkinData completed.");
|
||||
}
|
||||
} else {
|
||||
ExLog.w(getActivity(), TAG,
|
||||
@@ -554,7 +463,6 @@ public class HomeFragment extends BaseFragment implements
|
||||
Date date = new Date();
|
||||
|
||||
StartActivity startActivity = (StartActivity)getActivity();
|
||||
|
||||
startActivity.showProgressDialog(R.string.please_wait, R.string.checking_in);
|
||||
|
||||
try {
|
||||
@@ -625,8 +533,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
* @param regattaName
|
||||
* @param eventName
|
||||
*/
|
||||
private void startRegatta(String leaderboardName, String eventId,
|
||||
String competitorId) {
|
||||
private void startRegatta(String leaderboardName, String eventId, String competitorId) {
|
||||
Intent intent = new Intent(getActivity(), RegattaActivity.class);
|
||||
intent.putExtra(getString(R.string.leaderboard_name), leaderboardName);
|
||||
intent.putExtra(getString(R.string.event_id), eventId);
|
||||
@@ -638,7 +545,8 @@ public class HomeFragment extends BaseFragment implements
|
||||
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
|
||||
switch (loaderId) {
|
||||
case REGATTA_LOADER:
|
||||
String[] projection = new String[] { "events.event_id",
|
||||
String[] projection = new String[] {
|
||||
"events.event_id",
|
||||
"events._id", "events.event_name", "events.event_server",
|
||||
"competitors.competitor_display_name",
|
||||
"competitors.competitor_id",
|
||||
@@ -678,25 +586,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private class CheckinData {
|
||||
// public String gcmId;
|
||||
public String leaderboardName;
|
||||
public String eventId;
|
||||
public String eventName;
|
||||
public String eventStartDateStr;
|
||||
public String eventEndDateStr;
|
||||
public String eventFirstImageUrl;
|
||||
public String eventServerUrl;
|
||||
public String checkinURL;
|
||||
public String competitorName;
|
||||
public String competitorId;
|
||||
public String competitorSailId;
|
||||
public String competitorNationality;
|
||||
public String competitorCountryCode;
|
||||
public String deviceUid;
|
||||
}
|
||||
|
||||
|
||||
private class ClickListener implements OnClickListener {
|
||||
|
||||
@Override
|
||||
@@ -757,6 +647,7 @@ public class HomeFragment extends BaseFragment implements
|
||||
public void onResponse(JSONObject response) {
|
||||
StartActivity startActivity = (StartActivity)getActivity();
|
||||
startActivity.dismissProgressDialog();
|
||||
|
||||
startRegatta(leaderboardName, eventId, competitorId);
|
||||
}
|
||||
}
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.LeaderboardWebViewActivity;
|
||||
|
||||
public class LeaderboardFragment extends BaseFragment {
|
||||
|
||||
private static final String TAG = LeaderboardFragment.class.getName();
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
View view = inflater.inflate(R.layout.fragment_leaderboard, container, false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
WebView webview = (WebView)getActivity().findViewById(R.id.web_view);
|
||||
|
||||
WebSettings webSettings = webview.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
|
||||
webview.setWebViewClient(new WebViewClient() {
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
String url = getLeaderboardURL();
|
||||
webview.loadUrl(url);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
LeaderboardWebViewActivity activity = (LeaderboardWebViewActivity)getActivity();
|
||||
activity.showErrorPopup(R.string.error, R.string.error_could_not_complete_operation_on_server_try_again);
|
||||
ExLog.e(getActivity(), TAG, "UnsupportedEncodingException when creating leaderboard-url: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getLeaderboardURL() throws UnsupportedEncodingException
|
||||
{
|
||||
LeaderboardWebViewActivity activity = (LeaderboardWebViewActivity)getActivity();
|
||||
String eventId = URLEncoder.encode(activity.eventId, "UTF-8");
|
||||
String leaderboardName = URLEncoder.encode(activity.leaderboardName, "UTF-8");
|
||||
String serverUrl = activity.serverUrl;
|
||||
|
||||
String formatString = "%s/gwt/Home.html#LeaderboardPlace:eventId=%s" +
|
||||
"&leaderboardName=%s&showRaceDetails=true&showSettings=true";
|
||||
return String.format(formatString, serverUrl, eventId, leaderboardName);
|
||||
}
|
||||
}
|
||||
+100
-25
@@ -1,6 +1,8 @@
|
||||
package com.sap.sailing.android.tracking.app.ui.fragments;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -24,7 +26,10 @@ import android.widget.RelativeLayout;
|
||||
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;
|
||||
|
||||
@@ -34,7 +39,11 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
private final int CAMERA_REQUEST_CODE = 3118;
|
||||
private final int SELECT_PHOTO_REQUEST_CODE = 1693;
|
||||
|
||||
private final int IMAGE_MAX_SIZE = 2000;
|
||||
|
||||
private final String CAMERA_TEMP_FILE = "cameraTempFile";
|
||||
|
||||
|
||||
private boolean showingThankYouNote;
|
||||
|
||||
private TimerRunnable timer;
|
||||
@@ -48,6 +57,9 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
Button startTrackingButton = (Button) view.findViewById(R.id.start_tracking);
|
||||
startTrackingButton.setOnClickListener(this);
|
||||
|
||||
Button showLeaderboardButton = (Button) view.findViewById(R.id.show_leaderboards_button);
|
||||
showLeaderboardButton.setOnClickListener(this);
|
||||
|
||||
Button changePhotoButton = (Button) view.findViewById(R.id.change_photo_button);
|
||||
changePhotoButton.setOnClickListener(this);
|
||||
@@ -63,7 +75,7 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
private void checkAndSwitchToThankYouScreenIfRegattaOver() {
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
long regattaEnd = regattaActivity.getEvent().endMillis;
|
||||
long regattaEnd = regattaActivity.event.endMillis;
|
||||
|
||||
if (System.currentTimeMillis() > regattaEnd) {
|
||||
switchToThankYouScreen();
|
||||
@@ -77,7 +89,7 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
TextView textView = (TextView)getActivity().findViewById(R.id.regatta_starts_in);
|
||||
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
long regattaStart = regattaActivity.getEvent().startMillis;
|
||||
long regattaStart = regattaActivity.event.startMillis;
|
||||
|
||||
LinearLayout threeBoxesLayout = (LinearLayout) getActivity()
|
||||
.findViewById(R.id.three_boxes_regatta_starts);
|
||||
@@ -94,6 +106,10 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isShowingBigCheckoutButton() {
|
||||
return showingThankYouNote;
|
||||
}
|
||||
|
||||
private void switchToThankYouScreen() {
|
||||
showingThankYouNote = true;
|
||||
|
||||
@@ -130,6 +146,9 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.show_leaderboards_button:
|
||||
startLeaderboardActivity();
|
||||
break;
|
||||
case R.id.start_tracking:
|
||||
if (showingThankYouNote) {
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
@@ -198,6 +217,8 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
|
||||
private void showTakePhotoActivity() {
|
||||
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
File photoFile = ((RegattaActivity)getActivity()).getImageFile(CAMERA_TEMP_FILE);
|
||||
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
|
||||
startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@@ -207,39 +228,99 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
RegattaActivity activity = (RegattaActivity) getActivity();
|
||||
|
||||
if (requestCode == CAMERA_REQUEST_CODE) {
|
||||
Bitmap photo = (Bitmap) data.getExtras().get("data");
|
||||
activity.updatePictureChosenByUser(photo);
|
||||
File photoFile = ((RegattaActivity)getActivity()).getImageFile(CAMERA_TEMP_FILE);
|
||||
Bitmap photo;
|
||||
try {
|
||||
photo = decodeUri(Uri.fromFile(photoFile));
|
||||
activity.updateLeaderboardPictureChosenByUser(photo);
|
||||
} catch (FileNotFoundException e) {
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
ExLog.i(getActivity(), TAG, "update photo, file not found: " + photoFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
ExLog.i(getActivity(), TAG, "update photo, io exception: " + e.getMessage());
|
||||
}
|
||||
} finally {
|
||||
((RegattaActivity)getActivity()).deleteFile(CAMERA_TEMP_FILE);
|
||||
}
|
||||
} else if (requestCode == SELECT_PHOTO_REQUEST_CODE) {
|
||||
Uri selectedImage = data.getData();
|
||||
InputStream imageStream;
|
||||
|
||||
try {
|
||||
imageStream = getActivity().getContentResolver()
|
||||
.openInputStream(selectedImage);
|
||||
Bitmap photo = BitmapFactory.decodeStream(imageStream);
|
||||
activity.updatePictureChosenByUser(photo);
|
||||
Bitmap photo = decodeUri(selectedImage);
|
||||
activity.updateLeaderboardPictureChosenByUser(photo);
|
||||
} catch (FileNotFoundException e) {
|
||||
ExLog.e(getActivity(), TAG,
|
||||
"File not found exception after picking image from gallery");
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
ExLog.i(getActivity(), TAG, "update photo, io exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode image with maximum size
|
||||
* @param uri
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private Bitmap decodeUri(Uri uri) throws IOException{
|
||||
Bitmap bitmap = null;
|
||||
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
|
||||
InputStream fis = getActivity().getContentResolver().openInputStream(uri);
|
||||
BitmapFactory.decodeStream(fis, null, options);
|
||||
fis.close();
|
||||
|
||||
int scale = 1;
|
||||
if (options.outHeight > IMAGE_MAX_SIZE || options.outWidth > IMAGE_MAX_SIZE) {
|
||||
scale = (int)Math.pow(2, (int) Math.ceil(Math.log(IMAGE_MAX_SIZE /
|
||||
(double) Math.max(options.outHeight, options.outWidth)) / Math.log(0.5)));
|
||||
}
|
||||
|
||||
BitmapFactory.Options options2 = new BitmapFactory.Options();
|
||||
options2.inSampleSize = scale;
|
||||
fis = getActivity().getContentResolver().openInputStream(uri);
|
||||
bitmap = BitmapFactory.decodeStream(fis, null, options2);
|
||||
fis.close();
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private void startLeaderboardActivity() {
|
||||
RegattaActivity activity = (RegattaActivity)getActivity();
|
||||
|
||||
Intent intent = new Intent(getActivity(), LeaderboardWebViewActivity.class);
|
||||
intent.putExtra(LeaderboardWebViewActivity.LEADERBOARD_EXTRA_SERVER_URL, activity.event.server);
|
||||
intent.putExtra(LeaderboardWebViewActivity.LEADERBOARD_EXTRA_EVENT_ID, activity.event.id);
|
||||
intent.putExtra(LeaderboardWebViewActivity.LEADERBOARD_EXTRA_LEADERBOARD_NAME, activity.leaderboard.name);
|
||||
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
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.getEvent().id);
|
||||
regattaActivity.event.id);
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
private void timerFired() {
|
||||
RegattaActivity regattaActivity = (RegattaActivity) getActivity();
|
||||
updateCountdownTimer(regattaActivity.getEvent().startMillis);
|
||||
updateCountdownTimer(regattaActivity.event.startMillis);
|
||||
}
|
||||
|
||||
private void updateCountdownTimer(long startTime) {
|
||||
@@ -258,19 +339,13 @@ public class RegattaFragment extends BaseFragment implements OnClickListener {
|
||||
}
|
||||
|
||||
private void setCountdownTime(int days, int hours, int minutes) {
|
||||
TextView daysTextView = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_days);
|
||||
TextView hoursTextView = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_hours);
|
||||
TextView minutesTextView = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_minutes);
|
||||
TextView daysTextView = (TextView) getActivity().findViewById(R.id.starts_in_days);
|
||||
TextView hoursTextView = (TextView) getActivity().findViewById(R.id.starts_in_hours);
|
||||
TextView minutesTextView = (TextView) getActivity().findViewById(R.id.starts_in_minutes);
|
||||
|
||||
TextView daysTextViewLabel = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_days_label);
|
||||
TextView hoursTextViewLabel = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_hours_label);
|
||||
TextView minutesTextViewLabel = (TextView) getActivity().findViewById(
|
||||
R.id.starts_in_minutes_label);
|
||||
TextView daysTextViewLabel = (TextView) getActivity().findViewById(R.id.starts_in_days_label);
|
||||
TextView hoursTextViewLabel = (TextView) getActivity().findViewById(R.id.starts_in_hours_label);
|
||||
TextView minutesTextViewLabel = (TextView) getActivity().findViewById(R.id.starts_in_minutes_label);
|
||||
|
||||
daysTextView.setText(String.format("%02d", days));
|
||||
hoursTextView.setText(String.format("%02d", hours));
|
||||
|
||||
+22
-25
@@ -11,22 +11,20 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sap.sailing.android.tracking.app.R;
|
||||
import com.sap.sailing.android.tracking.app.ui.activities.TrackingActivity;
|
||||
|
||||
public class SpeedFragment extends BaseFragment {
|
||||
|
||||
private String TAG = SpeedFragment.class.getName();
|
||||
private final String SIS_SPEED_TEXTIVEW = "SpeedFragmentSpeedTextView";
|
||||
//private String TAG = SpeedFragment.class.getName();
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_speed, container, false);
|
||||
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_speed, container, false);
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setSpeed(float speedInMetersPerSecond)
|
||||
{
|
||||
if (isAdded())
|
||||
{
|
||||
public void setSpeed(float speedInMetersPerSecond) {
|
||||
if (isAdded()) {
|
||||
float speedInKnots = speedInMetersPerSecond * 1.9438444924574f;
|
||||
|
||||
NumberFormat df = DecimalFormat.getInstance();
|
||||
@@ -34,30 +32,29 @@ public class SpeedFragment extends BaseFragment {
|
||||
df.setMaximumFractionDigits(2);
|
||||
df.setRoundingMode(RoundingMode.HALF_UP);
|
||||
String formattedSpeed = df.format(speedInKnots);
|
||||
|
||||
|
||||
TextView speedText = (TextView) getActivity().findViewById(R.id.speed_text_view);
|
||||
speedText.setText(formattedSpeed + "kn");
|
||||
TrackingActivity activity = (TrackingActivity) getActivity();
|
||||
|
||||
if (activity != null) {
|
||||
activity.lastSpeedIndicatorText = speedText.getText().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
TextView speedText = (TextView)getActivity().findViewById(R.id.speed_text_view);
|
||||
if (savedInstanceState != null)
|
||||
{
|
||||
speedText.setText(savedInstanceState.getString(SIS_SPEED_TEXTIVEW));
|
||||
}
|
||||
else
|
||||
{
|
||||
speedText.setText("--kn");
|
||||
|
||||
TextView speedText = (TextView) getActivity().findViewById(R.id.speed_text_view);
|
||||
|
||||
TrackingActivity activity = (TrackingActivity) getActivity();
|
||||
if (activity != null) {
|
||||
speedText.setText(activity.lastSpeedIndicatorText);
|
||||
} else {
|
||||
speedText.setText("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
TextView speedText = (TextView)getActivity().findViewById(R.id.speed_text_view);
|
||||
outState.putString(SIS_SPEED_TEXTIVEW, speedText.getText().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
-4
@@ -31,7 +31,6 @@ public class TrackingFragment extends BaseFragment {
|
||||
static final String SIS_GPS_ACCURACY = "instanceStateGpsAccuracy";
|
||||
static final String SIS_GPS_UNSENT_FIXES = "instanceStateGpsUnsentFixes";
|
||||
|
||||
|
||||
private AppPreferences prefs;
|
||||
private long lastGPSQualityUpdate;
|
||||
|
||||
@@ -247,11 +246,8 @@ public class TrackingFragment extends BaseFragment {
|
||||
{
|
||||
unsentGpsFixesTextView.setText(String.valueOf(count));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+110
-2
@@ -3,16 +3,20 @@ 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;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
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;
|
||||
@@ -195,18 +199,19 @@ public class DatabaseHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public EventInfo getEventInfo(Context context, String eventId) {
|
||||
public EventInfo getEventInfo(Context context, String eventId) {
|
||||
EventInfo event = new EventInfo();
|
||||
event.id = eventId;
|
||||
|
||||
Cursor cursor = context.getContentResolver().query(Event.CONTENT_URI,
|
||||
null, "event_id = \"" + eventId + "\"", null, null);
|
||||
null, "event_id = \"" + eventId + "\"", null, null);
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
event.name = cursor.getString(cursor.getColumnIndex(Event.EVENT_NAME));
|
||||
event.imageUrl = cursor.getString(cursor.getColumnIndex(Event.EVENT_IMAGE_URL));
|
||||
event.startMillis = cursor.getLong(cursor.getColumnIndex(Event.EVENT_DATE_START));
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -277,4 +282,107 @@ public class DatabaseHelper {
|
||||
ExLog.i(context, TAG, "Checkout, number of leaderbards deleted: " + d3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to check in to a race.
|
||||
*
|
||||
* @param context
|
||||
* @param event
|
||||
* @param competitor
|
||||
* @param leaderboard
|
||||
* @return success or failure
|
||||
* @throws GeneralDatabaseHelperException
|
||||
* @throws OperationApplicationException
|
||||
* @throws RemoteException
|
||||
*/
|
||||
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.
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
|
||||
ContentValues clv = new ContentValues();
|
||||
clv.put(Leaderboard.LEADERBOARD_NAME, leaderboard.name);
|
||||
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.
|
||||
|
||||
ArrayList<ContentProviderOperation> opList = new ArrayList<ContentProviderOperation>();
|
||||
|
||||
ContentValues cev = new ContentValues();
|
||||
cev.put(Event.EVENT_ID, event.id);
|
||||
cev.put(Event.EVENT_NAME, event.name);
|
||||
cev.put(Event.EVENT_DATE_START, event.startMillis);
|
||||
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);
|
||||
|
||||
opList.add(ContentProviderOperation.newInsert(Event.CONTENT_URI).withValues(cev).build());
|
||||
|
||||
ContentValues ccv = new ContentValues();
|
||||
|
||||
ccv.put(Competitor.COMPETITOR_COUNTRY_CODE, competitor.countryCode);
|
||||
ccv.put(Competitor.COMPETITOR_DISPLAY_NAME, competitor.name);
|
||||
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);
|
||||
|
||||
opList.add(ContentProviderOperation.newInsert(Competitor.CONTENT_URI).withValues(ccv).build());
|
||||
|
||||
try {
|
||||
cr.applyBatch(AnalyticsContract.CONTENT_AUTHORITY, opList);
|
||||
} catch (RemoteException e) {
|
||||
throw new GeneralDatabaseHelperException(e.getMessage());
|
||||
} catch (OperationApplicationException e) {
|
||||
throw new GeneralDatabaseHelperException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the combination of eventId, leaderboardName and
|
||||
* competitorId does not exist in the DB.
|
||||
*
|
||||
* @param eventId
|
||||
* @param leaderboardName
|
||||
* @param competitorId
|
||||
* @return
|
||||
*/
|
||||
public boolean eventLeaderboardCompetitorCombnationAvailable(Context context,
|
||||
String eventId, String leaderboardName, String competitorId) {
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
String sel = "leaderboards.leaderboard_name = \"" + leaderboardName
|
||||
+ "\" AND competitors.competitor_id = \"" + competitorId
|
||||
+ "\" AND events.event_id = \"" + eventId + "\"";
|
||||
|
||||
int count = cr.query(
|
||||
AnalyticsContract.EventLeaderboardCompetitorJoined.CONTENT_URI,
|
||||
null, sel, null, null).getCount();
|
||||
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
public class GeneralDatabaseHelperException extends Exception {
|
||||
private static final long serialVersionUID = 4333494334720305541L;
|
||||
|
||||
public GeneralDatabaseHelperException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+495
@@ -0,0 +1,495 @@
|
||||
package com.sap.sailing.android.tracking.app.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.media.ExifInterface;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Base64;
|
||||
|
||||
/**
|
||||
* Todo: Use this class?
|
||||
*
|
||||
*/
|
||||
public class ImageController {
|
||||
|
||||
public static String getRealPathFromURI(ContentResolver contentResolver,
|
||||
Uri contentUri) {
|
||||
String res = null;
|
||||
String[] proj = { MediaStore.Images.Media.DATA };
|
||||
Cursor cursor = contentResolver.query(contentUri, proj, null, null,
|
||||
null);
|
||||
if (cursor.moveToFirst()) {
|
||||
int column_index = cursor
|
||||
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||
res = cursor.getString(column_index);
|
||||
}
|
||||
cursor.close();
|
||||
return res;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public static Bitmap scaleCenterCrop(Bitmap source, int newWidth,
|
||||
int newHeight) {
|
||||
int sourceWidth = source.getWidth();
|
||||
int sourceHeight = source.getHeight();
|
||||
|
||||
// Compute the scaling factors to fit the new height and width,
|
||||
// respectively.
|
||||
// To cover the final image, the final scaling will be the bigger
|
||||
// of these two.
|
||||
float xScale = (float) newWidth / sourceWidth;
|
||||
float yScale = (float) newHeight / sourceHeight;
|
||||
float scale = Math.max(xScale, yScale);
|
||||
|
||||
// Now get the size of the source bitmap when scaled
|
||||
float scaledWidth = scale * sourceWidth;
|
||||
float scaledHeight = scale * sourceHeight;
|
||||
|
||||
// Let's find out the upper left coordinates if the scaled bitmap
|
||||
// should be centered in the new size give by the parameters
|
||||
float left = (newWidth - scaledWidth) / 2;
|
||||
float top = (newHeight - scaledHeight) / 2;
|
||||
|
||||
// The target rectangle for the new, scaled version of the source bitmap
|
||||
// will now
|
||||
// be
|
||||
RectF targetRect = new RectF(left, top, left + scaledWidth, top
|
||||
+ scaledHeight);
|
||||
|
||||
// Finally, we create a new bitmap of the specified size and draw our
|
||||
// new,
|
||||
// scaled bitmap onto it.
|
||||
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight,
|
||||
source.getConfig());
|
||||
Canvas canvas = new Canvas(dest);
|
||||
canvas.drawBitmap(source, null, targetRect, null);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
|
||||
Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight,
|
||||
Config.ARGB_8888);
|
||||
|
||||
float ratioX = newWidth / (float) bitmap.getWidth();
|
||||
float ratioY = newHeight / (float) bitmap.getHeight();
|
||||
float middleX = newWidth / 2.0f;
|
||||
float middleY = newHeight / 2.0f;
|
||||
|
||||
Matrix scaleMatrix = new Matrix();
|
||||
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
|
||||
|
||||
Canvas canvas = new Canvas(scaledBitmap);
|
||||
canvas.setMatrix(scaleMatrix);
|
||||
float left = middleX - (float) bitmap.getWidth() / 2;
|
||||
float top = middleY - (float) bitmap.getHeight() / 2;
|
||||
canvas.drawBitmap(bitmap, left, top,
|
||||
new Paint(Paint.FILTER_BITMAP_FLAG));
|
||||
return scaledBitmap;
|
||||
}
|
||||
|
||||
public static Bitmap scaleBitmapAspectRatio(Bitmap bitmap, int targetWidth,
|
||||
int targetHeight) {
|
||||
float ratioX = targetWidth / (float) bitmap.getWidth();
|
||||
float ratioY = targetHeight / (float) bitmap.getHeight();
|
||||
float aspectRatio = (float) bitmap.getWidth() / bitmap.getHeight();
|
||||
if (ratioX < ratioY) {
|
||||
aspectRatio = ratioX;
|
||||
} else {
|
||||
aspectRatio = ratioY;
|
||||
}
|
||||
int newWidth = Math.round(bitmap.getWidth() * aspectRatio);
|
||||
if (newWidth < 1) {
|
||||
newWidth = 1;
|
||||
}
|
||||
int newHeight = Math.round(bitmap.getHeight() * aspectRatio);
|
||||
if (newHeight < 1) {
|
||||
newHeight = 1;
|
||||
}
|
||||
return scaleBitmap(bitmap, newWidth, newHeight);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// http://stackoverflow.com/a/10028267
|
||||
public static Bitmap fastblur(Bitmap sentBitmap, int radius) {
|
||||
|
||||
// Stack Blur v1.0 from
|
||||
// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
|
||||
//
|
||||
// Java Author: Mario Klingemann <mario at quasimondo.com>
|
||||
// http://incubator.quasimondo.com
|
||||
// created Feburary 29, 2004
|
||||
// Android port : Yahel Bouaziz <yahel at kayenko.com>
|
||||
// http://www.kayenko.com
|
||||
// ported april 5th, 2012
|
||||
|
||||
// This is a compromise between Gaussian Blur and Box blur
|
||||
// It creates much better looking blurs than Box Blur, but is
|
||||
// 7x faster than my Gaussian Blur implementation.
|
||||
//
|
||||
// I called it Stack Blur because this describes best how this
|
||||
// filter works internally: it creates a kind of moving stack
|
||||
// of colors whilst scanning through the image. Thereby it
|
||||
// just has to add one new block of color to the right side
|
||||
// of the stack and remove the leftmost color. The remaining
|
||||
// colors on the topmost layer of the stack are either added on
|
||||
// or reduced by one, depending on if they are on the right or
|
||||
// on the left side of the stack.
|
||||
//
|
||||
// If you are using this algorithm in your code please add
|
||||
// the following line:
|
||||
//
|
||||
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
|
||||
|
||||
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
|
||||
|
||||
if (radius < 1) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
|
||||
int[] pix = new int[w * h];
|
||||
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
int wm = w - 1;
|
||||
int hm = h - 1;
|
||||
int wh = w * h;
|
||||
int div = radius + radius + 1;
|
||||
|
||||
int r[] = new int[wh];
|
||||
int g[] = new int[wh];
|
||||
int b[] = new int[wh];
|
||||
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
|
||||
int vmin[] = new int[Math.max(w, h)];
|
||||
|
||||
int divsum = (div + 1) >> 1;
|
||||
divsum *= divsum;
|
||||
int dv[] = new int[256 * divsum];
|
||||
for (i = 0; i < 256 * divsum; i++) {
|
||||
dv[i] = (i / divsum);
|
||||
}
|
||||
|
||||
yw = yi = 0;
|
||||
|
||||
int[][] stack = new int[div][3];
|
||||
int stackpointer;
|
||||
int stackstart;
|
||||
int[] sir;
|
||||
int rbs;
|
||||
int r1 = radius + 1;
|
||||
int routsum, goutsum, boutsum;
|
||||
int rinsum, ginsum, binsum;
|
||||
|
||||
for (y = 0; y < h; y++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
p = pix[yi + Math.min(wm, Math.max(i, 0))];
|
||||
sir = stack[i + radius];
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
rbs = r1 - Math.abs(i);
|
||||
rsum += sir[0] * rbs;
|
||||
gsum += sir[1] * rbs;
|
||||
bsum += sir[2] * rbs;
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
}
|
||||
stackpointer = radius;
|
||||
|
||||
for (x = 0; x < w; x++) {
|
||||
|
||||
r[yi] = dv[rsum];
|
||||
g[yi] = dv[gsum];
|
||||
b[yi] = dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (y == 0) {
|
||||
vmin[x] = Math.min(x + radius + 1, wm);
|
||||
}
|
||||
p = pix[yw + vmin[x]];
|
||||
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[(stackpointer) % div];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi++;
|
||||
}
|
||||
yw += w;
|
||||
}
|
||||
for (x = 0; x < w; x++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
yp = -radius * w;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
yi = Math.max(0, yp) + x;
|
||||
|
||||
sir = stack[i + radius];
|
||||
|
||||
sir[0] = r[yi];
|
||||
sir[1] = g[yi];
|
||||
sir[2] = b[yi];
|
||||
|
||||
rbs = r1 - Math.abs(i);
|
||||
|
||||
rsum += r[yi] * rbs;
|
||||
gsum += g[yi] * rbs;
|
||||
bsum += b[yi] * rbs;
|
||||
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
|
||||
if (i < hm) {
|
||||
yp += w;
|
||||
}
|
||||
}
|
||||
yi = x;
|
||||
stackpointer = radius;
|
||||
for (y = 0; y < h; y++) {
|
||||
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
|
||||
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
|
||||
| (dv[gsum] << 8) | dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (x == 0) {
|
||||
vmin[y] = Math.min(y + r1, hm) * w;
|
||||
}
|
||||
p = x + vmin[y];
|
||||
|
||||
sir[0] = r[p];
|
||||
sir[1] = g[p];
|
||||
sir[2] = b[p];
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[stackpointer];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi += w;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
return (bitmap);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
|
||||
public static int calculateInSampleSize(BitmapFactory.Options options,
|
||||
int reqWidth, int reqHeight) {
|
||||
// Raw height and width of image
|
||||
final int height = options.outHeight;
|
||||
final int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
|
||||
final int halfHeight = height / 2;
|
||||
final int halfWidth = width / 2;
|
||||
|
||||
// Calculate the largest inSampleSize value that is a power of 2 and
|
||||
// keeps both
|
||||
// height and width larger than the requested height and width.
|
||||
while ((halfHeight / inSampleSize) > reqHeight
|
||||
&& (halfWidth / inSampleSize) > reqWidth) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
return inSampleSize;
|
||||
}
|
||||
|
||||
public static Bitmap decodeSampledBitmapFromFile(
|
||||
ContentResolver contentResolver, Uri uri, String filename,
|
||||
int reqWidth, int reqHeight) {
|
||||
|
||||
// First decode with inJustDecodeBounds=true to check dimensions
|
||||
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
if (filename == null) {
|
||||
try {
|
||||
InputStream inputStream = contentResolver.openInputStream(uri);
|
||||
BitmapFactory.decodeStream(inputStream, null, options);
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
} else {
|
||||
BitmapFactory.decodeFile(filename, options);
|
||||
|
||||
}
|
||||
// Calculate inSampleSize
|
||||
options.inSampleSize = calculateInSampleSize(options, reqWidth,
|
||||
reqHeight);
|
||||
|
||||
// Decode bitmap with inSampleSize set
|
||||
options.inJustDecodeBounds = false;
|
||||
Bitmap bitmap = null;
|
||||
if (filename == null) {
|
||||
try {
|
||||
InputStream inputStream = contentResolver.openInputStream(uri);
|
||||
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
} else {
|
||||
bitmap = BitmapFactory.decodeFile(filename, options);
|
||||
}
|
||||
|
||||
// check orientation
|
||||
if (bitmap != null && filename != null) {
|
||||
try {
|
||||
ExifInterface exif = new ExifInterface(filename);
|
||||
int orientation = exif.getAttributeInt(
|
||||
ExifInterface.TAG_ORIENTATION, 1);
|
||||
int angle = 0;
|
||||
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
angle = -90;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
angle = -180;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||
angle = -270;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (angle != 0) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postRotate(90);
|
||||
Bitmap rotatedBitmap = Bitmap
|
||||
.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
|
||||
bitmap.getHeight(), matrix, true);
|
||||
bitmap.recycle();
|
||||
bitmap = rotatedBitmap;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// http://stackoverflow.com/a/8557147
|
||||
private final static String[] projection = new String[] {
|
||||
MediaStore.Images.ImageColumns._ID,
|
||||
MediaStore.Images.ImageColumns.DATA,
|
||||
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
||||
MediaStore.Images.ImageColumns.DATE_TAKEN,
|
||||
MediaStore.Images.ImageColumns.MIME_TYPE };
|
||||
|
||||
public static File latestImage(Context context) {
|
||||
final Cursor cursor = context.getContentResolver().query(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
|
||||
null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
|
||||
|
||||
// Put it in the image view
|
||||
if (cursor.moveToFirst()) {
|
||||
String imageLocation = cursor.getString(1);
|
||||
File imageFile = new File(imageLocation);
|
||||
return imageFile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
public static String encodeTobase64(Bitmap image) {
|
||||
Bitmap immagex = image;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
immagex.compress(Bitmap.CompressFormat.JPEG, 60, baos);
|
||||
byte[] b = baos.toByteArray();
|
||||
String imageEncoded = Base64.encodeToString(b, Base64.NO_WRAP);
|
||||
return "data:image/jpeg;base64," + imageEncoded;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.sap.sailing.android.tracking.app.valueobjects;
|
||||
|
||||
public class CheckinData {
|
||||
// public String gcmId;
|
||||
public String leaderboardName;
|
||||
public String eventId;
|
||||
public String eventName;
|
||||
public String eventStartDateStr;
|
||||
public String eventEndDateStr;
|
||||
public String eventFirstImageUrl;
|
||||
public String eventServerUrl;
|
||||
public String checkinURL;
|
||||
public String competitorName;
|
||||
public String competitorId;
|
||||
public String competitorSailId;
|
||||
public String competitorNationality;
|
||||
public String competitorCountryCode;
|
||||
public String deviceUid;
|
||||
|
||||
public EventInfo getEvent()
|
||||
{
|
||||
EventInfo event = new EventInfo();
|
||||
event.name = eventName;
|
||||
event.id = eventId;
|
||||
event.startMillis = Long.parseLong(eventStartDateStr);
|
||||
event.endMillis = Long.parseLong(eventEndDateStr);
|
||||
event.imageUrl = eventFirstImageUrl;
|
||||
event.server = eventServerUrl;
|
||||
return event;
|
||||
}
|
||||
|
||||
public LeaderboardInfo getLeaderboard()
|
||||
{
|
||||
LeaderboardInfo leaderboard = new LeaderboardInfo();
|
||||
leaderboard.name = leaderboardName;
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
public CompetitorInfo getCompetitor()
|
||||
{
|
||||
CompetitorInfo competitor = new CompetitorInfo();
|
||||
competitor.name = competitorName;
|
||||
competitor.id = competitorId;
|
||||
competitor.sailId = competitorSailId;
|
||||
competitor.nationality = competitorNationality;
|
||||
competitor.countryCode = competitorCountryCode;
|
||||
return competitor;
|
||||
}
|
||||
}
|
||||
+1
@@ -5,6 +5,7 @@ public class CompetitorInfo {
|
||||
public String id;
|
||||
public String name;
|
||||
public String countryCode;
|
||||
public String nationality;
|
||||
public String sailId;
|
||||
public int rowId;
|
||||
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ public class EventInfo {
|
||||
public long startMillis;
|
||||
public long endMillis;
|
||||
public int rowId;
|
||||
public String server;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -16,6 +17,6 @@ public class EventInfo {
|
||||
+ leaderboardName + ", eventImageUrl: " + imageUrl
|
||||
+ ", eventStartMillis: " + startMillis
|
||||
+ ", eventEndMillis: " + endMillis + ", eventRowId: "
|
||||
+ rowId;
|
||||
+ rowId + ", server: " + server;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user