/*------------------------------------------------------------------------------ ** Ident: Innovation en Inspiration > Google Android ** Author: rene ** Copyright: (c) Jan 22, 2009 Sogeti Nederland B.V. All Rights Reserved. **------------------------------------------------------------------------------ ** Sogeti Nederland B.V. | No part of this file may be reproduced ** Distributed Software Engineering | or transmitted in any form or by any ** Lange Dreef 17 | means, electronic or mechanical, for the ** 4131 NJ Vianen | purpose, without the express written ** The Netherlands | permission of the copyright holder. *------------------------------------------------------------------------------ * * This file is part of OpenGPSTracker. * * OpenGPSTracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGPSTracker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGPSTracker. If not, see <http://www.gnu.org/licenses/>. * */ package edu.stanford.cs.sujogger.viewer; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.app.AlertDialog.Builder; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.ContentObserver; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.RemoteException; import android.os.PowerManager.WakeLock; import android.preference.PreferenceManager; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.catchnotes.integration.IntentIntegrator; import com.facebook.android.AsyncFacebookRunner; import com.facebook.android.Facebook; import com.facebook.android.FacebookError; import com.facebook.android.AsyncFacebookRunner.RequestListener; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.MyLocationOverlay; import com.google.android.maps.Overlay; import edu.stanford.cs.gaming.sdk.model.AppResponse; import edu.stanford.cs.gaming.sdk.model.ScoreBoard; import edu.stanford.cs.gaming.sdk.model.User; import edu.stanford.cs.gaming.sdk.service.GamingServiceConnection; import edu.stanford.cs.sujogger.R; import edu.stanford.cs.sujogger.actions.Statistics; import edu.stanford.cs.sujogger.db.DatabaseHelper; import edu.stanford.cs.sujogger.db.GPStracking.Media; import edu.stanford.cs.sujogger.db.GPStracking.Segments; import edu.stanford.cs.sujogger.db.GPStracking.Stats; import edu.stanford.cs.sujogger.db.GPStracking.Tracks; import edu.stanford.cs.sujogger.db.GPStracking.Waypoints; import edu.stanford.cs.sujogger.logger.GPSLoggerServiceManager; import edu.stanford.cs.sujogger.util.Common; import edu.stanford.cs.sujogger.util.Constants; import edu.stanford.cs.sujogger.util.Track; import edu.stanford.cs.sujogger.util.UnitsI18n; /** * Main activity showing a track and allowing logging control * * @version $Id: LoggerMap.java 479 2010-04-18 13:18:18Z rcgroot $ * @author rene (c) Jan 18, 2009, Sogeti B.V. */ public class LoggerMap extends MapActivity { private static final int ZOOM_LEVEL = 19; // Menus //private static final int MENU_SETTINGS = 1; private static final int MENU_TRACKLIST = 3; private static final int MENU_STATS = 4; private static final int MENU_ABOUT = 5; private static final int MENU_LAYERS = 6; private static final int MENU_CLEARTRACK = 7; //private static final int MENU_NOTE = 7; private static final int MENU_NAME = 8; private static final int MENU_PICTURE = 9; private static final int MENU_TEXT = 10; private static final int MENU_VOICE = 11; private static final int MENU_VIDEO = 12; private static final int MENU_SHARE = 13; private static final int MENU_CURRENT_LOCATION = 14; // Dialogs private static final int DIALOG_TRACKNAME = 23; //private static final int DIALOG_LAYERS = 31; private static final int DIALOG_TEXT = 32; private static final int DIALOG_NAME = 33; // Views private MapView mMapView = null; private MyLocationOverlay mMylocation; //private CheckBox mSatellite; //private CheckBox mTraffic; //private CheckBox mSpeed; //private CheckBox mCompass; //private CheckBox mLocation; private EditText mTrackNameView; private TextView[] mSpeedtexts = null; private TextView mLastGPSSpeedView = null; private EditText mNoteNameView; private EditText mNoteTextView; private Button mStartButton; private Button mResumeButton; private static final String TAG = "OGT.LoggerMap"; public static final String PARTNER_RUN_KEY = "partner_run"; //private double mAverageSpeed = 4.4704; //in m/s private double mAverageSpeed = 2.2352; //in m/s //ASLAI private ArrayList<Track> mTrackIds = new ArrayList<Track>(); private ArrayList<Track> mTrackIdsForDialog; // private long mTrackId = -1; private boolean statisticsPresent = false; private long mLastSegment = -1; private long mLastWaypoint = -1; private UnitsI18n mUnits; private WakeLock mWakeLock = null; private MapController mMapController = null; private SharedPreferences mSharedPreferences; // private GPSLoggerServiceManager GPSLoggerServiceManager; private DatabaseHelper mDbHelper; private boolean mIsPartnerRun; private boolean mTrackNameDialogShowing; private boolean mStatsUpdating; private double mCalculatedDistance; private long mCalculatedDuration; private Facebook mFacebook; private AsyncFacebookRunner mAsyncRunner; public static final int UPDATE_SBS_RID = 1; public static final int GET_SBS_RID = 2; private GamingServiceConnection mGameCon; private ScoreboardUpdateReceiver mReceiver; private ProgressDialog mDialogUpdate; //ASLAI: created new function to do animateTo private void animateTo() { int state = GPSLoggerServiceManager.getLoggingState(); if (mTrackIds.size() > 0 && Track.visibleExists(mTrackIds)) { if (state == Constants.LOGGING || state == Constants.PAUSED) { Common.log(TAG, "ASLAI: GOING TO LAST TRACK POINT"); mMapView.getController().animateTo(getLastTrackPoint()); } else { Common.log(TAG, "ASLAI: GOING TO FIRST TRACK POINT"); mMapView.getController().animateTo(getFirstTrackPoint()); } } } private ArrayList<Long> toTrackIdsLongArray(long[] longArray) { if (longArray == null || longArray.length <=0) { return new ArrayList<Long>(); } ArrayList<Long> arrayList = new ArrayList<Long>(); for (int i=0; i < longArray.length; i++) { arrayList.add(longArray[i]); } return arrayList; } private long[] getTrackIdsLongArray() { int arraySize = mTrackIds.size(); if (arraySize <= 0) { return new long[0]; } long[] longArray = new long[arraySize]; for (int i = 0; i < arraySize; i++) { longArray[i] = mTrackIds.get(i).id; } return longArray; } private void addTrackIds(long val, boolean startLogging) { for (int i=0; i < mTrackIds.size(); i++) { if (mTrackIds.get(i).id == val) { mTrackIds.remove(i); } } int state = GPSLoggerServiceManager.getLoggingState(); Common.log(TAG, "ADDTRACKIDS STATE IS " + state); long loggingTrackId = GPSLoggerServiceManager.isLogging(); if (loggingTrackId != -1 && val != loggingTrackId) mTrackIds.add(mTrackIds.size()-1, new Track(val)); else mTrackIds.add(mTrackIds.size(), new Track(val)); /* if ((state == Constants.LOGGING || state == Constants.PAUSED) && !startLogging && mTrackIds.size() > 0) { Common.log(TAG, "ASLAI: Adding track while logging"); mTrackIds.add(mTrackIds.size()-1, new Track(val)); } else { Common.log(TAG, "ASLAI: Adding track while not logging"); mTrackIds.add(new Track(val)); } */ Common.log(TAG, "ASLAI1: " + getTrackIdsString()); } private String getTrackIdsString() { String str = "Track ids are: "; for (Track track : mTrackIds) { str += "" + track.id + ", "; } return str; } private long getLastTrackId() { long trackId = -1; if ((trackId = GPSLoggerServiceManager.isLogging()) != -1) { Common.log(TAG, "LastTrackId: " + trackId); return trackId; } if (mTrackIds.size() == 0) { return trackId; } int i = 1; while (mTrackIds.size() - i >=0 && !mTrackIds.get(mTrackIds.size()-i).visible) i++; if (mTrackIds.size() -i >=0) trackId = mTrackIds.get(mTrackIds.size()-i).id; else trackId = -1; Common.log(TAG, "LastTrackId: " + trackId); return trackId; } private String trackIdsToPreference() { if (mTrackIds == null || mTrackIds.size() == 0) return ""; int size = mTrackIds.size(); String str = "" + mTrackIds.get(0).id + "qwertyuioplkjh" + mTrackIds.get(0).visible; for (int i = 1; i < size; i++) { str += "zxcvbnmlkjh"+ mTrackIds.get(i).id+ "qwertyuioplkjh" + mTrackIds.get(i).visible; } return str; } private ArrayList<Track> preferenceToTrackIds(SharedPreferences sharedPreferences) { // return new ArrayList<Long>(); try { String value = sharedPreferences.getString("mTrackIds", ""); Common.log(TAG, "VALUE IS: " + value); if ("".equals(value)) { return new ArrayList<Track>(); } ArrayList<Track> arrList = new ArrayList<Track>(); String[] strArray = value.split("zxcvbnmlkjh"); for (int i=0; i < strArray.length; i++) { String[] trackArray = strArray[i].split("qwertyuioplkjh"); Common.log(TAG, "TRACKARRAY[0]: " + trackArray[0] + " TRACKARRAY[1]: " + trackArray[1]); arrList.add(new Track(new Long(trackArray[0]), new Boolean(trackArray[1]))); } return arrList; } catch (Exception e) { e.printStackTrace(); Common.log(TAG, "ASLAI: EXCEPTION CONVERTING TO TRACKS"); return new ArrayList<Track>(); } } private final ContentObserver mTrackSegmentsObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfUpdate) { if (!selfUpdate) { Common.log(TAG, "mTrackSegmentsObserver " + getTrackIdsString()); LoggerMap.this.updateDataOverlays(); } else { Common.log(TAG, "mTrackSegmentsObserver skipping change on " + mLastSegment); } } }; private final ContentObserver mSegmentWaypointsObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfUpdate) { if (!selfUpdate) { Common.log(TAG, "mSegmentWaypointsObserver " + mLastSegment); LoggerMap.this.createSpeedDisplayNumbers(); if (mLastSegmentOverlay != null) { moveActiveViewWindow(); mLastSegmentOverlay.calculateTrack(); mMapView.postInvalidate(); } } else { Common.log(TAG, "mSegmentWaypointsObserver skipping change on " + mLastSegment); } } }; private final ContentObserver mTrackMediasObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfUpdate) { if (!selfUpdate) { Common.log(TAG, "mTrackMediasObserver " + getTrackIdsString()); if (mLastSegmentOverlay != null) { mLastSegmentOverlay.calculateMedia(); mMapView.postInvalidate(); } } else { Common.log(TAG, "mTrackMediasObserver skipping change on " + mLastSegment); } } }; private final View.OnClickListener mTrackNameDialogListener = new View.OnClickListener() { public void onClick(View view) { String trackName = mTrackNameView.getText().toString(); Common.log(TAG, "mTrackNameDialogListener: " + trackName); if (trackName == null || trackName.trim().equals("")) { Toast toast = Toast.makeText(LoggerMap.this.getApplicationContext(), "Track name cannot be empty", Toast.LENGTH_SHORT); toast.show(); return; } ContentValues values = new ContentValues(); values.put(Tracks.NAME, trackName); values.put(Tracks.USER_ID, Common.getRegisteredUser(LoggerMap.this).id); Uri uri = ContentUris.withAppendedId(Tracks.CONTENT_URI, LoggerMap.this.getLastTrackId()); getContentResolver().update(uri, values, null, null); getContentResolver().notifyChange(uri, null); updateTitleBar(); mTrackNameDialogShowing = false; if (mStatsUpdating) mDialogUpdate = ProgressDialog.show(LoggerMap.this, "", getString(R.string.dialog_updating_stats), true); else updateAchievements(); /* // Create a sample location Location location = new Location(LocationManager.NETWORK_PROVIDER); location.setLatitude(30.267153); location.setLongitude(-97.743061); // Create the note IntentIntegrator notesIntent = new IntentIntegrator(context); notesIntent.createNote("#sample", location); */ LoggerMap.this.dismissDialog(DIALOG_TRACKNAME); } }; // private final OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() { // public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // int which = buttonView.getId(); // switch (which) { // case R.id.layer_satellite: // setSatelliteOverlay(isChecked); // break; // case R.id.layer_traffic: // setTrafficOverlay(isChecked); // break; // case R.id.layer_speed: // setSpeedOverlay(isChecked); // break; // // TODO: remove unnecessary preferences // // //case R.id.layer_compass: setCompassOverlay( isChecked ); break; // //case R.id.layer_location: setLocationOverlay( isChecked ); break; // // default: // break; // } // } // }; private final OnSharedPreferenceChangeListener mSharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // TODO: Clear removed preferences /* * if( key.equals( Constants.TRACKCOLORING ) ) { int * trackColoringMethod = new Integer( sharedPreferences.getString( * Constants.TRACKCOLORING, "3" ) ).intValue(); * updateSpeedbarVisibility(); List<Overlay> overlays = * LoggerMap.this.mMapView.getOverlays(); for (Overlay overlay : * overlays) { if( overlay instanceof SegmentOverlay ) { ( * (SegmentOverlay) overlay ).setTrackColoringMethod( * trackColoringMethod, mAverageSpeed ); } } } */ // else if( key.equals( Constants.DISABLEBLANKING ) ) // { // updateBlankingBehavior(); // } if (key.equals(Constants.SPEED)) { updateSpeedDisplayVisibility(); } // else if( key.equals( Constants.COMPASS ) ) // { // updateCompassDisplayVisibility(); // } else if (key.equals(Constants.TRAFFIC)) { LoggerMap.this.mMapView.setTraffic(sharedPreferences.getBoolean(key, false)); } else if (key.equals(Constants.SATELLITE)) { LoggerMap.this.mMapView.setSatellite(sharedPreferences.getBoolean(key, false)); } // else if( key.equals( Constants.LOCATION ) ) // { // updateLocationDisplayVisibility(); // } } }; private final UnitsI18n.UnitsChangeListener mUnitsChangeListener = new UnitsI18n.UnitsChangeListener() { public void onUnitsChange() { createSpeedDisplayNumbers(); updateSpeedbarVisibility(); } }; private final OnClickListener mNoteTextDialogListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String noteText = mNoteTextView.getText().toString(); Calendar c = Calendar.getInstance(); String newName = String.format("Textnote_%tY-%tm-%td_%tH%tM%tS.txt", c, c, c, c, c, c); String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath(); File file = new File(sdcard + Constants.EXTERNAL_DIR + newName); FileWriter filewriter = null; try { file.getParentFile().mkdirs(); file.createNewFile(); filewriter = new FileWriter(file); filewriter.append(noteText); filewriter.flush(); } catch (IOException e) { Log.e(TAG, "Note storing failed", e); CharSequence text = e.getLocalizedMessage(); Toast toast = Toast.makeText(LoggerMap.this.getApplicationContext(), text, Toast.LENGTH_LONG); toast.show(); } finally { if (filewriter != null) { try { filewriter.close(); } catch (IOException e) { /* */ } } } GPSLoggerServiceManager.storeMediaUri(Uri.fromFile(file)); } }; private final OnClickListener mNoteNameDialogListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String name = mNoteNameView.getText().toString(); Uri media = Uri.withAppendedPath(Constants.NAME_URI, Uri.encode(name)); GPSLoggerServiceManager.storeMediaUri(media); } }; private SegmentOverlay mLastSegmentOverlay; /** * Called when the activity is first created. */ @Override protected void onCreate(Bundle load) { Common.log(TAG, "onCreate()"); super.onCreate(load); this.startService(new Intent(Constants.SERVICENAME)); /* if (load != null) { Common.log(TAG, "BUNDLE IS NOT NULL"); mTrackIds = toTrackIdsLongArray(load.getLongArray("trackIds")); } else { Common.log(TAG, "BUNDLE IS NULL"); mTrackIds = new ArrayList<Long>(); } */ mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); mTrackIds = preferenceToTrackIds(mSharedPreferences); Common.log(TAG, "ASLAI: GETTRACKIDSSTRING" + getTrackIdsString()); /* Object previousInstanceData = getLastNonConfigurationInstance(); if (previousInstanceData != null && previousInstanceData instanceof GPSLoggerServiceManager) { GPSLoggerServiceManager = (GPSLoggerServiceManager) previousInstanceData; Common.log(TAG, "getting previous GPSLoggerServiceManager"); } else { GPSLoggerServiceManager = new GPSLoggerServiceManager((Context) this); Common.log(TAG, "creating new GPSLoggerServiceManager"); } */ GPSLoggerServiceManager.setContext(this); GPSLoggerServiceManager.startup(); mDbHelper = new DatabaseHelper(this); mReceiver = new ScoreboardUpdateReceiver(); mGameCon = new GamingServiceConnection(this, mReceiver, Constants.APP_ID, Constants.APP_API_KEY, LoggerMap.class.toString()); mGameCon.bind(); User user = Common.getRegisteredUser(this); mGameCon.setUserId(user.id, user.fb_id, user.fb_token); mFacebook = new Facebook(Constants.FB_APP_ID); mAsyncRunner = new AsyncFacebookRunner(mFacebook); mFacebook.setAccessToken(mSharedPreferences.getString(Constants.USERREG_TOKEN_KEY, null)); mUnits = new UnitsI18n(this, mUnitsChangeListener); mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); mSharedPreferences .registerOnSharedPreferenceChangeListener(mSharedPreferenceChangeListener); setContentView(R.layout.map); mMapView = (MapView) findViewById(R.id.myMapView); mMylocation = new FixedMyLocationOverlay(this, mMapView); mMapController = this.mMapView.getController(); //ASLAI: Added mMylocation.enableMyLocation(); mMylocation.enableCompass(); mMapView.setBuiltInZoomControls(true); mMapView.displayZoomControls(true); mMapView.setClickable(true); mMapView.setStreetView(false); mMapView.setSatellite(mSharedPreferences.getBoolean(Constants.SATELLITE, false)); mMapView.setTraffic(mSharedPreferences.getBoolean(Constants.TRAFFIC, false)); //ASLAI: Added mMapController.setZoom(ZOOM_LEVEL); mStartButton = (Button)findViewById(R.id.startbutton); mStartButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { int state = GPSLoggerServiceManager.getLoggingState(); switch (state) { case Constants.STOPPED: Common.log(TAG, "mLoggingControlListener: start GPS logging..."); long loggerTrackId = GPSLoggerServiceManager.startGPSLogging(null); moveToTrack(loggerTrackId, true, true); //showDialog(DIALOG_TRACKNAME); break; case Constants.LOGGING: case Constants.PAUSED: GPSLoggerServiceManager.stopGPSLogging(); Common.log(TAG, "stopped GPS logging!!!!!!!!!!!!!!!!!!!!"); if (calculateTrackStatistics()) { mTrackNameDialogShowing = true; showDialog(DIALOG_TRACKNAME); syncGroupStats(); } else { Toast toast = Toast.makeText(LoggerMap.this.getApplicationContext(), "Discarding track of zero length", Toast.LENGTH_SHORT); toast.show(); } break; default: break; } updateTrackingButtons(); } }); mResumeButton = (Button)findViewById(R.id.resumebutton); mResumeButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { int state = GPSLoggerServiceManager.getLoggingState(); switch (state) { case Constants.LOGGING: GPSLoggerServiceManager.pauseGPSLogging(); break; case Constants.PAUSED: GPSLoggerServiceManager.resumeGPSLogging(); break; default: break; } updateTrackingButtons(); } }); TextView[] speeds = { (TextView) findViewById(R.id.speedview02), (TextView) findViewById(R.id.speedview01), (TextView) findViewById(R.id.speedview00) }; mSpeedtexts = speeds; mLastGPSSpeedView = (TextView) findViewById(R.id.currentSpeed); Bundle extras = getIntent().getExtras(); mIsPartnerRun = extras != null ? extras.getBoolean(PARTNER_RUN_KEY) : false; onRestoreInstanceState(load); //ASLAI: Added Common.log(TAG, "ASLAI: Enabling my location"); List<Overlay> overlays = this.mMapView.getOverlays(); overlays.clear(); updateTitleBar(); updateDataOverlays(); updateSpeedbarVisibility(); mMylocation.enableMyLocation(); mMylocation.enableCompass(); overlays.add(mMylocation); mMapView.invalidate(); Common.log(TAG, "ASLAI: Enabled my location"); } protected void onPause() { super.onPause(); Common.log(TAG, "onPause()"); mDbHelper.close(); if (this.mWakeLock != null && this.mWakeLock.isHeld()) { this.mWakeLock.release(); Log.w(TAG, "onPause(): Released lock to keep screen on!"); } if (mTrackIds.size() > 0) { ContentResolver resolver = this.getApplicationContext().getContentResolver(); resolver.unregisterContentObserver(this.mTrackSegmentsObserver); resolver.unregisterContentObserver(this.mSegmentWaypointsObserver); resolver.unregisterContentObserver(this.mTrackMediasObserver); } // mMylocation.disableMyLocation(); // mMylocation.disableCompass(); } protected void onResume() { super.onResume(); Common.log(TAG, "onResume"); mDbHelper.openAndGetDb(); updateTitleBar(); updateSpeedbarVisibility(); updateSpeedDisplayVisibility(); mMylocation.enableCompass(); mMylocation.enableMyLocation(); updateTrackingButtons(); if (mTrackIds.size() >= 0) { ContentResolver resolver = this.getApplicationContext().getContentResolver(); Uri trackUri = Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/segments"); Uri lastSegmentUri = Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/segments/" + mLastSegment + "/waypoints"); Uri mediaUri = ContentUris.withAppendedId(Media.CONTENT_URI, getLastTrackId()); resolver.unregisterContentObserver(this.mTrackSegmentsObserver); resolver.unregisterContentObserver(this.mSegmentWaypointsObserver); resolver.unregisterContentObserver(this.mTrackMediasObserver); resolver.registerContentObserver(trackUri, false, this.mTrackSegmentsObserver); resolver.registerContentObserver(lastSegmentUri, true, this.mSegmentWaypointsObserver); resolver.registerContentObserver(mediaUri, true, this.mTrackMediasObserver); } updateDataOverlays(); } /* * (non-Javadoc) * * @see com.google.android.maps.MapActivity#onPause() */ @Override protected void onDestroy() { Common.log(TAG, "onDestroy"); if (mMylocation != null) mMylocation.disableMyLocation(); Editor editor = mSharedPreferences.edit(); editor.putString("mTrackIds", trackIdsToPreference()); editor.commit(); GPSLoggerServiceManager.shutdown(); if (mWakeLock != null && mWakeLock.isHeld()) { mWakeLock.release(); Log.w(TAG, "onDestroy(): Released lock to keep screen on!"); } mSharedPreferences .unregisterOnSharedPreferenceChangeListener(this.mSharedPreferenceChangeListener); if (GPSLoggerServiceManager.getLoggingState() == Constants.STOPPED) { stopService(new Intent(Constants.SERVICENAME)); } mGameCon.unbind(); super.onDestroy(); } /** * @param newIntent * an Intent containing the track to move the map to * @see com.google.android.maps.MapActivity#onNewIntent(android.content.Intent) */ @Override public void onNewIntent(Intent newIntent) { Common.log(TAG, "ASLAI: ONNEWINTENT"); Uri data = newIntent.getData(); if (data != null) { moveToTrack(Long.parseLong(data.getLastPathSegment()), true, false); } } @Override protected void onRestoreInstanceState(Bundle load) { if (load != null) { Common.log(TAG, "Restoring the previous map "); super.onRestoreInstanceState(load); } //ASLAI TODO Uri data = this.getIntent().getData(); if (load != null && load.containsKey("track")) // 1st track from a // previous instance of // this activity { Common.log(TAG, "FIRST TRACK RESTORE"); long loadTrackId = load.getLong("track"); Common.log(TAG, "Moving to restored track " + loadTrackId); moveToTrack(loadTrackId, false, false); } else if (data != null) // 2nd track ordered to make { Common.log(TAG, "SECOND TRACK RESTORE"); long loadTrackId = Long.parseLong(data.getLastPathSegment()); Common.log(TAG, "Moving to intented track " + loadTrackId); moveToTrack(loadTrackId, true, false); setIntent(new Intent()); } else { Common.log(TAG, "Moving to last track "); // moveToLastTrack(); // 3rd just try the last track } if (load != null && load.containsKey(PARTNER_RUN_KEY)) mIsPartnerRun = load.getBoolean(PARTNER_RUN_KEY); if (load != null && load.containsKey("zoom")) { this.mMapController.setZoom(load.getInt("zoom")); } else { this.mMapController.setZoom(ZOOM_LEVEL); } if (load != null && load.containsKey("e6lat") && load.containsKey("e6long")) { GeoPoint storedPoint = new GeoPoint(load.getInt("e6lat"), load.getInt("e6long")); Common.log(TAG, "ASLAI: ANIMATING TO STORED POINT"); this.mMapView.getController().animateTo(storedPoint); } else { GeoPoint lastPoint = getLastTrackPoint(); animateTo(); // this.mMapView.getController().animateTo(lastPoint); } redrawOverlays(); Common.log(TAG, "onRestoreInstanceState(): mIsPartnerRun = " + mIsPartnerRun); } @Override protected void onSaveInstanceState(Bundle save) { super.onSaveInstanceState(save); Common.log(TAG, "ONSAVEINSTANCESTATE: " + getTrackIdsString()); save.putLongArray("trackIds", this.getTrackIdsLongArray()); // save.putLong("track", this.mTrackId); save.putInt("zoom", this.mMapView.getZoomLevel()); GeoPoint point = this.mMapView.getMapCenter(); save.putInt("e6lat", point.getLatitudeE6()); save.putInt("e6long", point.getLongitudeE6()); save.putBoolean(PARTNER_RUN_KEY, mIsPartnerRun); } /* * (non-Javadoc) * * @see android.app.Activity#onRetainNonConfigurationInstance() */ /* @Override public Object onRetainNonConfigurationInstance() { Object nonConfigurationInstance = GPSLoggerServiceManager; return nonConfigurationInstance; } */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean propagate = true; switch (keyCode) { case KeyEvent.KEYCODE_T: propagate = this.mMapView.getController().zoomIn(); break; case KeyEvent.KEYCODE_G: propagate = this.mMapView.getController().zoomOut(); break; case KeyEvent.KEYCODE_S: setSatelliteOverlay(!this.mMapView.isSatellite()); propagate = false; break; case KeyEvent.KEYCODE_A: setTrafficOverlay(!this.mMapView.isTraffic()); propagate = false; break; /* case KeyEvent.KEYCODE_F: moveToTrack(this.mTrackId - 1, true); propagate = false; break; case KeyEvent.KEYCODE_H: moveToTrack(this.mTrackId + 1, true); propagate = false; break; */ default: propagate = super.onKeyDown(keyCode, event); break; } return propagate; } private void setTrafficOverlay(boolean b) { Editor editor = mSharedPreferences.edit(); editor.putBoolean(Constants.TRAFFIC, b); editor.commit(); } private void setSatelliteOverlay(boolean b) { Editor editor = mSharedPreferences.edit(); editor.putBoolean(Constants.SATELLITE, b); editor.commit(); } private void setSpeedOverlay(boolean b) { Editor editor = mSharedPreferences.edit(); editor.putBoolean(Constants.SPEED, b); editor.commit(); } // TODO: remove unnecessary preferences /* * private void setCompassOverlay( boolean b ) { Editor editor = * mSharedPreferences.edit(); editor.putBoolean( Constants.COMPASS, b ); * editor.commit(); } * * private void setLocationOverlay( boolean b ) { Editor editor = * mSharedPreferences.edit(); editor.putBoolean( Constants.LOCATION, b ); * editor.commit(); } */ /** * Adds items into the main menu (map screen) */ @Override public boolean onCreateOptionsMenu(Menu menu) { boolean result = super.onCreateOptionsMenu(menu); Common.log(TAG, "onCreateOptionsMenu()"); //menu.add(ContextMenu.NONE, MENU_TRACKING, ContextMenu.NONE, R.string.menu_tracking) // .setIcon(R.drawable.ic_menu_movie).setAlphabeticShortcut('T'); menu.add(ContextMenu.NONE, MENU_LAYERS, ContextMenu.NONE, R.string.menu_showLayers) .setIcon(R.drawable.ic_menu_mapmode).setAlphabeticShortcut('L'); // SubMenu notemenu = menu.addSubMenu( ContextMenu.NONE, MENU_NOTE, // ContextMenu.NONE, R.string.menu_insertnote ).setIcon( // R.drawable.ic_menu_myplaces ); // menu.add(ContextMenu.NONE, MENU_CLEARTRACK, ContextMenu.NONE, R.string.menu_clear_track) // .setIcon(R.drawable.ic_menu_close_clear_cancel).setAlphabeticShortcut('C'); menu.add(ContextMenu.NONE, MENU_STATS, ContextMenu.NONE, R.string.menu_statistics).setIcon( R.drawable.ic_menu_picture).setAlphabeticShortcut('S'); menu.add(ContextMenu.NONE, MENU_SHARE, ContextMenu.NONE, R.string.menu_shareTrack).setIcon( R.drawable.ic_menu_share).setAlphabeticShortcut('I'); menu.add(ContextMenu.NONE, MENU_CURRENT_LOCATION, ContextMenu.NONE, R.string.menu_current_location).setIcon( R.drawable.ic_menu_myplaces).setAlphabeticShortcut('C'); // More // menu.add( ContextMenu.NONE, MENU_TRACKLIST, ContextMenu.NONE, // R.string.menu_tracklist ).setIcon( R.drawable.ic_menu_show_list // ).setAlphabeticShortcut( 'P' ); //menu.add(ContextMenu.NONE, MENU_SETTINGS, ContextMenu.NONE, R.string.menu_settings) // .setIcon(R.drawable.ic_menu_preferences).setAlphabeticShortcut('C'); // menu.add( ContextMenu.NONE, MENU_ABOUT, ContextMenu.NONE, // R.string.menu_about ).setIcon( R.drawable.ic_menu_info_details // ).setAlphabeticShortcut( 'A' ); /* * notemenu.add( ContextMenu.NONE, MENU_NAME, ContextMenu.NONE, * R.string.menu_notename ); notemenu.add( ContextMenu.NONE, MENU_TEXT, * ContextMenu.NONE, R.string.menu_notetext ); notemenu.add( * ContextMenu.NONE, MENU_VOICE, ContextMenu.NONE, * R.string.menu_notespeech ); notemenu.add( ContextMenu.NONE, * MENU_PICTURE, ContextMenu.NONE, R.string.menu_notepicture ); * notemenu.add( ContextMenu.NONE, MENU_VIDEO, ContextMenu.NONE, * R.string.menu_notevideo ); */ return result; } /** * Enables or disables the "Make note" and "Share track" items when * appropriate * * @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu) */ @Override public boolean onPrepareOptionsMenu(Menu menu) { // MenuItem notemenu = menu.findItem( MENU_NOTE ); // notemenu.setEnabled( GPSLoggerServiceManager.isMediaPrepared() ); long loggingTrackId = GPSLoggerServiceManager.isLogging(); long remoteTrackId = 0; Intent actionIntent = null; ContentResolver resolver = this.getApplicationContext().getContentResolver(); Uri trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, this.getLastTrackId()); Cursor trackCursor = null; try { trackCursor = resolver.query(trackUri, new String[] { Tracks.NAME, Tracks.TRACK_ID }, null, null, null); if (trackCursor != null && trackCursor.moveToLast()) { remoteTrackId = trackCursor.getLong(1); } } finally { if (trackCursor != null) { trackCursor.close(); } } MenuItem sharemenu = menu.findItem(MENU_SHARE); sharemenu.setEnabled(mTrackIds.size() > 0 && loggingTrackId == -1 && remoteTrackId == 0); MenuItem layermenu = menu.findItem(MENU_LAYERS); layermenu.setEnabled(mTrackIds.size() > 1 || (mTrackIds.size() == 1 && loggingTrackId == -1)); MenuItem statsmenu = menu.findItem(MENU_STATS); statsmenu.setEnabled(mTrackIds.size() > 0); return super.onPrepareOptionsMenu(menu); } /** * Big switch statement for handling menu selection */ @Override public boolean onOptionsItemSelected(MenuItem item) { boolean handled = false; Uri trackUri; switch (item.getItemId()) { case MENU_LAYERS: // showDialog(DIALOG_LAYERS); Dialog dialog = null; LayoutInflater factory = null; View view = null; Builder builder = null; builder = new AlertDialog.Builder(this); factory = LayoutInflater.from(this); view = factory.inflate(R.layout.layerdialog, null); builder.setTitle(R.string.dialog_layer_title).setIcon(android.R.drawable.ic_dialog_map) .setPositiveButton(R.string.btn_okay, null).setView(view); Common.log(TAG, "" + Track.tracksToCharSequence(mTrackIds, this) + "===" + Track.tracksToVisibleBoolArray(mTrackIds)); int state = GPSLoggerServiceManager.getLoggingState(); if (state == Constants.LOGGING || state == Constants.PAUSED) { Common.log(TAG, "ASLAI: COPYING WHEN WE ARE TRACKING"); mTrackIdsForDialog = Track.shadowCopy(mTrackIds, true); } else { Common.log(TAG, "ASLAI: COPYING WHEN WE ARE NOT TRACKING"); mTrackIdsForDialog = Track.shadowCopy(mTrackIds, false); } if (mTrackIdsForDialog.size() > 0) { builder.setMultiChoiceItems(Track.tracksToCharSequence(mTrackIdsForDialog, this), Track.tracksToVisibleBoolArray(mTrackIdsForDialog), new OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) { Track track = mTrackIdsForDialog.get(whichButton); if (isChecked) { Common.log(TAG, "SETTING TRACK VISIBLE FOR POSITION: " + whichButton); track.visible = true; LoggerMap.this.moveToTrack(track.id, true, false); } else { Common.log(TAG, "SETTING TRACK INVISIBLE FOR POSITION: " + whichButton); LoggerMap.this.setTrackInvisible(Track.findTrackPosById(mTrackIds, track.id)); } } }).setNegativeButton(R.string.btn_remove_all, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { LoggerMap.this.clearOverlays(); dialog.cancel(); } }).setNeutralButton(R.string.btn_clear_all, new OnClickListener() { public void onClick(DialogInterface dialog, int which) { LoggerMap.this.setAllTracksInvisible(mTrackIdsForDialog); } }); } dialog = builder.create(); dialog.show(); handled = true; break; //case MENU_SETTINGS: // Intent i = new Intent(this, SettingsDialog.class); // startActivity(i); // handled = true; // break; case MENU_CLEARTRACK: clearOverlays(); handled = true; break; case MENU_TRACKLIST: Intent tracklistIntent = new Intent(this, TrackList.class); tracklistIntent.putExtra(Tracks._ID, this.getLastTrackId()); startActivityForResult(tracklistIntent, MENU_TRACKLIST); break; case MENU_STATS: if (this.mTrackIds.size() > 0) { Intent actionIntent = new Intent(this, Statistics.class); trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, this.getLastTrackId()); actionIntent.setData(trackUri); startActivity(actionIntent); handled = true; break; } handled = true; break; case MENU_SHARE: // Don't really need to check whether the remoteTrackId exists, // as we now checking it in onCreateMenu long remoteTrackId = 0; Intent actionIntent = null; ContentResolver resolver = this.getApplicationContext().getContentResolver(); trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, this.getLastTrackId()); Cursor trackCursor = null; String trackName = this.getTitle().toString(); try { trackCursor = resolver.query(trackUri, new String[] { Tracks.NAME, Tracks.TRACK_ID }, null, null, null); if (trackCursor != null && trackCursor.moveToLast()) { trackName = trackCursor.getString(0); remoteTrackId = trackCursor.getLong(1); this.setTitle(trackName); } } finally { if (trackCursor != null) { trackCursor.close(); } } if (remoteTrackId == 0) actionIntent = new Intent("android.intent.action.PUBLISH"); else actionIntent = new Intent(Intent.ACTION_RUN); // Intent actionIntent = new Intent(Intent.ACTION_RUN); actionIntent.setDataAndType(trackUri, Tracks.CONTENT_ITEM_TYPE); actionIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); actionIntent.putExtra("name", trackName); Common.log(TAG, "MENU_TRACKLIST " + this.getTitle()); startActivity(Intent.createChooser(actionIntent, getString(R.string.chooser_title))); handled = true; break; case MENU_CURRENT_LOCATION: if (mMylocation != null && mMylocation.getMyLocation() != null) mMapView.getController().animateTo(mMylocation.getMyLocation()); else Toast.makeText(this, R.string.msg_my_location_not_available, Toast.LENGTH_SHORT).show(); handled = true; break; case MENU_PICTURE: addPicture(); handled = true; break; case MENU_VIDEO: addVideo(); handled = true; break; case MENU_VOICE: addVoice(); handled = true; break; case MENU_TEXT: showDialog(DIALOG_TEXT); handled = true; break; case MENU_NAME: showDialog(DIALOG_NAME); handled = true; break; default: handled = super.onOptionsItemSelected(item); break; } return handled; } /* * (non-Javadoc) * * @see android.app.Activity#onCreateDialog(int) */ @Override protected Dialog onCreateDialog(int id) { Dialog dialog = null; LayoutInflater factory = null; View view = null; Builder builder = null; switch (id) { case DIALOG_TRACKNAME: dialog = new Dialog(this); dialog.setContentView(R.layout.namedialog); dialog.setTitle(R.string.dialog_routename_title); dialog.setCancelable(false); mTrackNameView = (EditText)dialog.findViewById(R.id.nameField); Button okButton = (Button)dialog.findViewById(R.id.ok_button); okButton.setVisibility(View.VISIBLE); okButton.setOnClickListener(mTrackNameDialogListener); return dialog; /* case DIALOG_LAYERS: builder = new AlertDialog.Builder(this); factory = LayoutInflater.from(this); view = factory.inflate(R.layout.layerdialog, null); mSatellite = (CheckBox) view.findViewById(R.id.layer_satellite); mSatellite.setOnCheckedChangeListener(mCheckedChangeListener); mTraffic = (CheckBox) view.findViewById(R.id.layer_traffic); mTraffic.setOnCheckedChangeListener(mCheckedChangeListener); mSpeed = (CheckBox) view.findViewById(R.id.layer_speed); mSpeed.setOnCheckedChangeListener(mCheckedChangeListener); // TODO: remove unnecessary preferences // mCompass = (CheckBox) view.findViewById( R.id.layer_compass ); // mCompass.setOnCheckedChangeListener( mCheckedChangeListener ); // mLocation = (CheckBox) view.findViewById( R.id.layer_location ); // mLocation.setOnCheckedChangeListener( mCheckedChangeListener ); builder.setTitle(R.string.dialog_layer_title).setIcon(android.R.drawable.ic_dialog_map) .setPositiveButton(R.string.btn_okay, null).setView(view); Common.log(TAG, "" + Track.tracksToCharSequence(mTrackIds, this) + "===" + Track.tracksToVisibleBoolArray(mTrackIds)); if (mTrackIds.size() > 0) { builder.setMultiChoiceItems(Track.tracksToCharSequence(mTrackIds, this), Track.tracksToVisibleBoolArray(mTrackIds), new OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) { Track track = mTrackIds.get(whichButton); if (isChecked) { Common.log(TAG, "SETTING TRACK VISIBLE FOR POSITION: " + whichButton); track.visible = true; LoggerMap.this.moveToTrack(track.id, true, false); } else { Common.log(TAG, "SETTING TRACK INVISIBLE FOR POSITION: " + whichButton); LoggerMap.this.setTrackInvisible(whichButton); } } }); } dialog = builder.create(); */ /* LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.layer); View checkboxView = factory.inflate(R.layout.checkbox_item, null); linearLayout.addView(checkboxView); checkboxView = factory.inflate(R.layout.checkbox_item, null); linearLayout.addView(checkboxView); */ /* // CheckBox checkBox = (CheckBox) findViewById(R.layout.checkbox_item); // dialog.addContentView(checkboxView, mSatellite.getLayoutParams()); // dialog.addContentView(checkBox, checkBox.getLayoutParams()); return dialog; */ case DIALOG_TEXT: builder = new AlertDialog.Builder(this); factory = LayoutInflater.from(this); view = factory.inflate(R.layout.notetextdialog, null); mNoteTextView = (EditText) view.findViewById(R.id.notetext); builder.setTitle(R.string.dialog_notetexttitle).setMessage( R.string.dialog_notetext_message).setIcon(android.R.drawable.ic_dialog_map) .setPositiveButton(R.string.btn_okay, mNoteTextDialogListener) .setNegativeButton(R.string.btn_cancel, null).setView(view); dialog = builder.create(); return dialog; case DIALOG_NAME: builder = new AlertDialog.Builder(this); factory = LayoutInflater.from(this); view = factory.inflate(R.layout.notenamedialog, null); mNoteNameView = (EditText) view.findViewById(R.id.notename); builder.setTitle(R.string.dialog_notenametitle).setMessage( R.string.dialog_notename_message).setIcon(android.R.drawable.ic_dialog_map) .setPositiveButton(R.string.btn_okay, mNoteNameDialogListener) .setNegativeButton(R.string.btn_cancel, null).setView(view); dialog = builder.create(); return dialog; default: return super.onCreateDialog(id); } } /* * (non-Javadoc) * * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog) */ @Override protected void onPrepareDialog(int id, Dialog dialog) { /* switch (id) { case DIALOG_LAYERS: mSatellite.setChecked(mSharedPreferences.getBoolean(Constants.SATELLITE, false)); mTraffic.setChecked(mSharedPreferences.getBoolean(Constants.TRAFFIC, false)); mSpeed.setChecked(mSharedPreferences.getBoolean(Constants.SPEED, false)); break; default: break; } */ super.onPrepareDialog(id, dialog); } /* * (non-Javadoc) * * @see android.app.Activity#onActivityResult(int, int, * android.content.Intent) */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (resultCode != RESULT_CANCELED) { String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath(); File file; Uri uri; File newFile; String newName; Uri fileUri; android.net.Uri.Builder builder; switch (requestCode) { case MENU_TRACKLIST: Uri trackUri = intent.getData(); long trackId = Long.parseLong(trackUri.getLastPathSegment()); moveToTrack(trackId, true, false); break; case MENU_ABOUT: break; case MENU_PICTURE: file = new File(sdcard + Constants.TMPICTUREFILE_PATH); Calendar c = Calendar.getInstance(); newName = String.format("Picture_%tY-%tm-%td_%tH%tM%tS.jpg", c, c, c, c, c, c); newFile = new File(sdcard + Constants.EXTERNAL_DIR + newName); file.getParentFile().mkdirs(); file.renameTo(newFile); Bitmap bm = BitmapFactory.decodeFile(newFile.getAbsolutePath()); String height = Integer.toString(bm.getHeight()); String width = Integer.toString(bm.getWidth()); bm.recycle(); bm = null; builder = new Uri.Builder(); fileUri = builder.scheme("file").appendEncodedPath("/").appendEncodedPath( newFile.getAbsolutePath()).appendQueryParameter("width", width) .appendQueryParameter("height", height).build(); GPSLoggerServiceManager.storeMediaUri(fileUri); mLastSegmentOverlay.calculateMedia(); mMapView.postInvalidate(); break; case MENU_VIDEO: file = new File(sdcard + Constants.TMPICTUREFILE_PATH); c = Calendar.getInstance(); newName = String.format("Video_%tY%tm%td_%tH%tM%tS.3gp", c, c, c, c, c, c); newFile = new File(sdcard + Constants.EXTERNAL_DIR + newName); file.getParentFile().mkdirs(); file.renameTo(newFile); builder = new Uri.Builder(); fileUri = builder.scheme("file").appendPath(newFile.getAbsolutePath()).build(); GPSLoggerServiceManager.storeMediaUri(fileUri); mLastSegmentOverlay.calculateMedia(); mMapView.postInvalidate(); break; case MENU_VOICE: uri = Uri.parse(intent.getDataString()); GPSLoggerServiceManager.storeMediaUri(uri); mLastSegmentOverlay.calculateMedia(); mMapView.postInvalidate(); break; default: Log.e(TAG, "Returned form unknow activity: " + requestCode); break; } } } /** * (non-Javadoc) * * @see com.google.android.maps.MapActivity#isRouteDisplayed() */ @Override protected boolean isRouteDisplayed() { return true; } // OnDoubleTapListener methods public boolean onDoubleTap(MotionEvent e) { Common.log(TAG, "onDoubleTap()"); return true; } public boolean onDoubleTapEvent(MotionEvent e) { return true; } public boolean onSingleTapConfirmed (MotionEvent e) { return true; } private void updateTrackingButtons() { int state = GPSLoggerServiceManager.getLoggingState(); switch (state) { case Constants.STOPPED: mStartButton.setText(R.string.map_start); mStartButton.setBackgroundResource(R.drawable.custom_btn_green); mResumeButton.setVisibility(View.GONE); break; case Constants.LOGGING: mStartButton.setText(R.string.map_stop); mStartButton.setBackgroundResource(R.drawable.custom_btn_red); mResumeButton.setVisibility(View.VISIBLE); mResumeButton.setText(R.string.map_pause); break; case Constants.PAUSED: mStartButton.setText(R.string.map_stop); mStartButton.setBackgroundResource(R.drawable.custom_btn_red); mResumeButton.setVisibility(View.VISIBLE); mResumeButton.setText(R.string.map_resume); break; default: break; } } private void updateTitleBar() { if (mTrackIds.size() == 0 || !Track.visibleExists(mTrackIds)) { this.setTitle(R.string.map_title); return; } ContentResolver resolver = this.getApplicationContext().getContentResolver(); Cursor trackCursor = null; try { trackCursor = resolver.query(ContentUris.withAppendedId(Tracks.CONTENT_URI, this.getLastTrackId()), new String[] { Tracks.NAME }, null, null, null); if (trackCursor != null && trackCursor.moveToLast()) { String trackName = trackCursor.getString(0); this.setTitle(trackName); } } finally { if (trackCursor != null) { trackCursor.close(); } } } private void updateSpeedbarVisibility() { View speedbar = findViewById(R.id.speedbar); drawSpeedTexts(mAverageSpeed); speedbar.setVisibility(View.VISIBLE); for (int i = 0; i < mSpeedtexts.length; i++) mSpeedtexts[i].setVisibility(View.VISIBLE); } private void updateSpeedDisplayVisibility() { boolean showspeed = mSharedPreferences.getBoolean(Constants.SPEED, false); if (showspeed) { mLastGPSSpeedView.setVisibility(View.VISIBLE); mLastGPSSpeedView.setText(""); } else { mLastGPSSpeedView.setVisibility(View.INVISIBLE); } } /* * private void updateCompassDisplayVisibility() { boolean compass = * mSharedPreferences.getBoolean( Constants.COMPASS, false ); if( compass ) * { mMylocation.enableCompass(); } else { mMylocation.disableCompass(); } } * * private void updateLocationDisplayVisibility() { boolean location = * mSharedPreferences.getBoolean( Constants.LOCATION, false ); if( location * ) { mMylocation.enableMyLocation(); } else { * mMylocation.disableMyLocation(); } } */ protected void createSpeedDisplayNumbers() { ContentResolver resolver = this.getApplicationContext().getContentResolver(); Cursor waypointsCursor = null; try { Uri lastSegmentUri = Uri.withAppendedPath(Tracks.CONTENT_URI, this.getTaskId() + "/segments/" + mLastSegment + "/waypoints"); waypointsCursor = resolver.query(lastSegmentUri, new String[] { Waypoints.SPEED }, null, null, null); if (waypointsCursor != null && waypointsCursor.moveToLast()) { double speed = waypointsCursor.getDouble(0); speed = mUnits.conversionFromMetersPerSecond(speed); String speedText = String.format("%.0f %s", speed, mUnits.getSpeedUnit()); mLastGPSSpeedView.setText(speedText); } } finally { if (waypointsCursor != null) { waypointsCursor.close(); } } } /** * For the current track identifier the route of that track is drawn by * adding a OverLay for each segments in the track * * @param trackId * @see SegmentOverlay */ private void createDataOverlays() { Common.log(TAG, "CREATEDATAOVERLAYS"); mLastSegmentOverlay = null; List<Overlay> overlays = this.mMapView.getOverlays(); //ASLAI HERE Long lastTrackId = getLastTrackId(); overlays.clear(); overlays.add(mMylocation); ContentResolver resolver = this.getApplicationContext().getContentResolver(); Cursor segments = null; int trackColoringMethod = SegmentOverlay.DRAW_MEASURED;// new Integer( // mSharedPreferences.getString( // Constants.TRACKCOLORING, // "2" ) // ).intValue(); for (Track track: mTrackIds) { if (track.visible) { long trackId = track.id; Common.log(TAG, "CREATEDATAOVERLAYS FOR TRACK ID: " + trackId); try { Uri segmentsUri = Uri.withAppendedPath(Tracks.CONTENT_URI, trackId + "/segments"); segments = resolver.query(segmentsUri, new String[] { Segments._ID }, null, null, null); if (segments != null && segments.moveToFirst()) { do { long segmentsId = segments.getLong(0); Uri segmentUri = ContentUris.withAppendedId(segmentsUri, segmentsId); SegmentOverlay segmentOverlay = new SegmentOverlay((Context) this, segmentUri, trackColoringMethod, mAverageSpeed, this.mMapView); overlays.add(segmentOverlay); mLastSegmentOverlay = segmentOverlay; if (segments.isFirst()) { segmentOverlay.addPlacement(SegmentOverlay.FIRST_SEGMENT); } if (segments.isLast()) { segmentOverlay.addPlacement(SegmentOverlay.LAST_SEGMENT); getLastTrackPoint(); } if (trackId == lastTrackId) mLastSegment = segmentsId; } while (segments.moveToNext()); } } finally { if (segments != null) { segments.close(); } } moveActiveViewWindow(); } } Uri lastSegmentUri = Uri.withAppendedPath(Tracks.CONTENT_URI, lastTrackId + "/segments/" + mLastSegment + "/waypoints"); resolver.unregisterContentObserver(this.mSegmentWaypointsObserver); resolver.registerContentObserver(lastSegmentUri, false, this.mSegmentWaypointsObserver); Common.log(TAG, "LAST SEGMENT URI IS " + lastSegmentUri); } /* private void createDataOverlays(long trackId) { Common.log(TAG, "CREATEDATAOVERLAYS"); mLastSegmentOverlay = null; List<Overlay> overlays = this.mMapView.getOverlays(); //ASLAI HERE Long lastTrackId = getLastTrackId(); overlays.clear(); overlays.add(mMylocation); ContentResolver resolver = this.getApplicationContext().getContentResolver(); Cursor segments = null; int trackColoringMethod = SegmentOverlay.DRAW_MEASURED;// new Integer( // mSharedPreferences.getString( // Constants.TRACKCOLORING, // "2" ) // ).intValue(); Common.log(TAG, "CREATEDATAOVERLAYS FOR TRACK ID: " + trackId); try { Uri segmentsUri = Uri.withAppendedPath(Tracks.CONTENT_URI, trackId + "/segments"); segments = resolver.query(segmentsUri, new String[] { Segments._ID }, null, null, null); if (segments != null && segments.moveToFirst()) { do { long segmentsId = segments.getLong(0); Uri segmentUri = ContentUris.withAppendedId(segmentsUri, segmentsId); SegmentOverlay segmentOverlay = new SegmentOverlay((Context) this, segmentUri, trackColoringMethod, mAverageSpeed, this.mMapView); overlays.add(segmentOverlay); mLastSegmentOverlay = segmentOverlay; if (segments.isFirst()) { segmentOverlay.addPlacement(SegmentOverlay.FIRST_SEGMENT); } if (segments.isLast()) { segmentOverlay.addPlacement(SegmentOverlay.LAST_SEGMENT); getLastTrackPoint(); } if (trackId == lastTrackId) mLastSegment = segmentsId; } while (segments.moveToNext()); } } finally { if (segments != null) { segments.close(); } } moveActiveViewWindow(); Uri lastSegmentUri = Uri.withAppendedPath(Tracks.CONTENT_URI, lastTrackId + "/segments/" + mLastSegment + "/waypoints"); resolver.unregisterContentObserver(this.mSegmentWaypointsObserver); resolver.registerContentObserver(lastSegmentUri, false, this.mSegmentWaypointsObserver); Common.log(TAG, "LAST SEGMENT URI IS " + lastSegmentUri); } */ private void updateDataOverlays() { boolean createOverlayExecuted = false; ContentResolver resolver = this.getApplicationContext().getContentResolver(); for (Track track: mTrackIds) { if (track.visible) { long trackId = track.id; Common.log(TAG, "UPDATEDATAOVERLAYS FOR TRACK ID: " + trackId); Uri segmentsUri = Uri.withAppendedPath(Tracks.CONTENT_URI, trackId + "/segments"); Cursor segmentsCursor = null; List<Overlay> overlays = this.mMapView.getOverlays(); int segmentOverlaysCount = 0; for (Overlay overlay : overlays) { if (overlay instanceof SegmentOverlay) { segmentOverlaysCount++; } } try { segmentsCursor = resolver.query(segmentsUri, new String[] { Segments._ID }, null, null, null); if (segmentsCursor != null && segmentsCursor.getCount() == segmentOverlaysCount) { Common.log(TAG, "UPDATEDATAOVERLAYS SAME SEGMENT COUNT"); // Common.log( TAG, "Alignment of segments" ); } else { Common.log(TAG, "CREATEDATAOVERLAYS FROM UPDATEOVERLAYS"); createDataOverlays(); break; } } finally { if (segmentsCursor != null) { segmentsCursor.close(); } } moveActiveViewWindow(); } } } private void moveActiveViewWindow() { GeoPoint lastPoint = getLastTrackPoint(); if (lastPoint != null && GPSLoggerServiceManager.getLoggingState() == Constants.LOGGING) { Point out = new Point(); this.mMapView.getProjection().toPixels(lastPoint, out); int height = this.mMapView.getHeight(); int width = this.mMapView.getWidth(); if (out.x < 0 || out.y < 0 || out.y > height || out.x > width) { this.mMapView.clearAnimation(); this.mMapView.getController().setCenter(lastPoint); // Common.log( TAG, "mMapView.setCenter()" ); } else if (out.x < width / 4 || out.y < height / 4 || out.x > (width / 4) * 3 || out.y > (height / 4) * 3) { this.mMapView.clearAnimation(); animateTo(); // this.mMapView.getController().animateTo(lastPoint); // Common.log( TAG, "mMapView.animateTo()" ); } } } /** * @param avgSpeed * avgSpeed in m/s */ private void drawSpeedTexts(double avgSpeed) { avgSpeed = mUnits.conversionFromMetersPerSecond(avgSpeed); Common.log(TAG, "drawSpeedTexts(): avgSpeed = " + avgSpeed); mSpeedtexts[0].setVisibility(View.VISIBLE); mSpeedtexts[0].setText(String.format("%.0f %s", 0d, mUnits.getSpeedUnit())); mSpeedtexts[1].setVisibility(View.VISIBLE); mSpeedtexts[1].setText(String.format("%.0f %s", avgSpeed, mUnits.getSpeedUnit())); mSpeedtexts[2].setVisibility(View.VISIBLE); mSpeedtexts[2].setText(String.format("%.0f %s", avgSpeed*2, mUnits.getSpeedUnit())); /* for (int i = 0; i < mSpeedtexts.length; i++) { mSpeedtexts[i].setVisibility(View.VISIBLE); double speed = ((avgSpeed * 2d) / 5d) * i; String speedText = String.format("%.0f %s", speed, mUnits.getSpeedUnit()); mSpeedtexts[i].setText(speedText); }*/ } private void redrawOverlays() { //ASLAI DIAGNOSTICS TILL HERE Common.log(TAG, "ASLAI: REDRAW OVERLAYS"); mMapView.getOverlays().clear(); List<Overlay> overlays = this.mMapView.getOverlays(); overlays.add(mMylocation); //ASLAI REMOVED HERE //ASLAI DIAGNOSTIC PROBLEM SHOULD BE HERE // GeoPoint lastPoint = getLastTrackPoint(); // mMapView.getController().animateTo(lastPoint); if (mTrackIds.size() > 0) { //ASLAI DIAGNOSTICS CHANGED HERE, There's still another place doing animate ArrayList<Track> tracksTmp = Track.shadowCopy(mTrackIds, false); for (Track track: tracksTmp) { // if (mTrackIds.get(mTrackIds.size() -1).visible) if (track.visible) moveToTrack(getLastTrackId(), false, false); // moveToTrack(getLastTrackId(), true, true); } } } // ASLAI private void clearOverlays() { int state = GPSLoggerServiceManager.getLoggingState(); Common.log("TAG", "ASLAI STATE IS: " + state); ArrayList<Track> tmpTrackIds = new ArrayList<Track>(); if (state == Constants.LOGGING || state == Constants.PAUSED) { tmpTrackIds.add(mTrackIds.get(mTrackIds.size()-1)); } mTrackIds = tmpTrackIds; Common.log(TAG, "ASLAI: TRACKIDSTOPREFERENCE IS: " + trackIdsToPreference()); Editor editor = mSharedPreferences.edit(); editor.putString("mTrackIds", trackIdsToPreference()); editor.commit(); List<Overlay> overlays = this.mMapView.getOverlays(); overlays.clear(); redrawOverlays(); overlays.add(mMylocation); updateTitleBar(); mMapView.invalidate(); // createDataOverlays(); // updateDataOverlays(); // moveActiveViewWindow(); } private void setTrackInvisible(int trackPosition) { int state = GPSLoggerServiceManager.getLoggingState(); Common.log("TAG", "ASLAI STATE IS: " + state); if (trackPosition == mTrackIds.size()-1 && (state == Constants.LOGGING || state == Constants.PAUSED)) { return; } mTrackIds.get(trackPosition).visible = false; Common.log(TAG, "ASLAI: TRACKIDSTOPREFERENCE IS: " + trackIdsToPreference()); Editor editor = mSharedPreferences.edit(); editor.putString("mTrackIds", trackIdsToPreference()); editor.commit(); List<Overlay> overlays = this.mMapView.getOverlays(); overlays.clear(); redrawOverlays(); overlays.add(mMylocation); updateTitleBar(); mMapView.invalidate(); // createDataOverlays(); // updateDataOverlays(); // moveActiveViewWindow(); } private void setAllTracksInvisible(ArrayList<Track> tracks) { Track.setAllInvisible(tracks); Common.log(TAG, "ASLAI: TRACKIDSTOPREFERENCE IS: " + trackIdsToPreference()); Editor editor = mSharedPreferences.edit(); editor.putString("mTrackIds", trackIdsToPreference()); editor.commit(); List<Overlay> overlays = this.mMapView.getOverlays(); overlays.clear(); redrawOverlays(); overlays.add(mMylocation); updateTitleBar(); mMapView.invalidate(); } /** * Alter this to set a new track as current. * * @param trackId * @param center * center on the end of the track */ private void moveToTrack(long trackId, boolean center, boolean startLogging) { Common.log(TAG, "ASLAI: MOVE TO TRACK: " + trackId); Cursor track = null; try { ContentResolver resolver = this.getApplicationContext().getContentResolver(); Uri trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, trackId); Uri mediaUri = ContentUris.withAppendedId(Media.CONTENT_URI, this.getLastTrackId()); track = resolver.query(trackUri, new String[] { Tracks.NAME, Tracks.DURATION, Tracks.DISTANCE }, null, null, null); addTrackIds(trackId, startLogging); if (track != null && track.moveToFirst()) { // this.mTrackId = trackId; mLastSegment = -1; mLastWaypoint = -1; // ASLAI PROBLEM HERE if (trackId == this.getLastTrackId() && track.getInt(1) != 0 && track.getDouble(2) != 0) statisticsPresent = true; else statisticsPresent = false; resolver.unregisterContentObserver(this.mTrackSegmentsObserver); resolver.unregisterContentObserver(this.mTrackMediasObserver); Uri tracksegmentsUri = Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/segments"); resolver.registerContentObserver(tracksegmentsUri, false, this.mTrackSegmentsObserver); resolver.registerContentObserver(mediaUri, false, this.mTrackMediasObserver); //ASLAI CHANGED this.mMapView.getOverlays().clear(); } } finally { if (track != null) { track.close(); } } /* if (center) { GeoPoint lastPoint = getLastTrackPoint(trackId); //ASLAI CHANGED GeoPoint lastPoint = getLastTrackPoint(); this.mMapView.getController().animateTo(lastPoint); } */ updateTitleBar(); updateDataOverlays(); updateSpeedbarVisibility(); if (center) { Common.log(TAG, "ASLAI: Animating to track: " + trackId); GeoPoint lastPoint = getLastTrackPoint(trackId); //ASLAI CHANGED GeoPoint lastPoint = getLastTrackPoint(); animateTo(); // this.mMapView.getController().animateTo(lastPoint); Common.log(TAG, "ASLAI: Animating to :" + lastPoint.getLatitudeE6() + " " + lastPoint.getLongitudeE6()); //ASLAI ADDED BELOW this.mMapView.invalidate(); } } /* //ASLAI private void moveToLoggingTrack(long trackId) { Cursor track = null; try { ContentResolver resolver = this.getApplicationContext().getContentResolver(); Uri trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, trackId); Uri mediaUri = ContentUris.withAppendedId(Media.CONTENT_URI, trackId); track = resolver.query(trackUri, new String[] { Tracks.NAME, Tracks.DURATION, Tracks.DISTANCE }, null, null, null); if (track != null && track.moveToFirst()) { addTrackIds(trackId, true); // this.mTrackId = trackId; mLastSegment = -1; mLastWaypoint = -1; if (track.getInt(1) != 0 && track.getDouble(2) != 0) statisticsPresent = true; else statisticsPresent = false; resolver.unregisterContentObserver(this.mTrackSegmentsObserver); resolver.unregisterContentObserver(this.mTrackMediasObserver); Uri tracksegmentsUri = Uri.withAppendedPath(Tracks.CONTENT_URI, trackId + "/segments"); resolver.registerContentObserver(tracksegmentsUri, false, this.mTrackSegmentsObserver); resolver.registerContentObserver(mediaUri, false, this.mTrackMediasObserver); //ASLAI CHANGED // this.mMapView.getOverlays().clear(); updateTitleBar(); updateDataOverlays(); updateSpeedbarVisibility(); if (true) { GeoPoint lastPoint = getLastTrackPoint(); this.mMapView.getController().animateTo(lastPoint); } } } finally { if (track != null) { track.close(); } } } */ /** * Get the last know position from the GPS provider and return that * information wrapped in a GeoPoint to which the Map can navigate. * * @see GeoPoint * @return */ private GeoPoint getLastKnowGeopointLocation() { int microLatitude = 0; int microLongitude = 0; LocationManager locationManager = (LocationManager) this.getApplication().getSystemService( Context.LOCATION_SERVICE); Location locationFine = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (locationFine != null) { microLatitude = (int) (locationFine.getLatitude() * 1E6d); microLongitude = (int) (locationFine.getLongitude() * 1E6d); } if (locationFine == null || microLatitude == 0 || microLongitude == 0) { Location locationCoarse = locationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (locationCoarse != null) { microLatitude = (int) (locationCoarse.getLatitude() * 1E6d); microLongitude = (int) (locationCoarse.getLongitude() * 1E6d); } if (locationCoarse == null || microLatitude == 0 || microLongitude == 0) { //default location to Stanford, CA, USA microLatitude = 37424166; microLongitude = -122165000; } } GeoPoint geoPoint = new GeoPoint(microLatitude, microLongitude); return geoPoint; } /** * Retrieve the last point of the current track * * @param context */ private GeoPoint getLastTrackPoint() { Cursor waypoint = null; GeoPoint lastPoint = null; try { ContentResolver resolver = this.getContentResolver(); waypoint = resolver.query(Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/waypoints"), new String[] { Waypoints.LATITUDE, Waypoints.LONGITUDE, "max(" + Waypoints.TABLE + "." + Waypoints._ID + ")" }, null, null, null); if (waypoint != null && waypoint.moveToLast()) { int microLatitude = (int) (waypoint.getDouble(0) * 1E6d); int microLongitude = (int) (waypoint.getDouble(1) * 1E6d); lastPoint = new GeoPoint(microLatitude, microLongitude); } if (lastPoint == null || lastPoint.getLatitudeE6() == 0 || lastPoint.getLongitudeE6() == 0) { lastPoint = getLastKnowGeopointLocation(); } else { mLastWaypoint = waypoint.getLong(2); } } finally { if (waypoint != null) { waypoint.close(); } } return lastPoint; } //ASLAI Added private GeoPoint getFirstTrackPoint() { long waypointId = 0; Cursor minwaypoint = null; Cursor waypoint = null; GeoPoint lastPoint = null; ContentResolver resolver = this.getContentResolver(); try { waypoint = resolver.query(Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/waypoints"), new String[] { "max(" + Waypoints.TABLE + "." + Waypoints._ID + ")" }, null, null, null); if (waypoint != null && waypoint.moveToLast()) { mLastWaypoint = waypoint.getLong(0); } } finally { if (waypoint != null) { waypoint.close(); } } try { minwaypoint = resolver.query(Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/waypoints"), new String[] { "min(" + Waypoints.TABLE + "." + Waypoints._ID + ")" }, null, null, null); if (minwaypoint != null && minwaypoint.moveToLast()) { waypointId = minwaypoint.getLong(0); waypoint = resolver.query(Uri.withAppendedPath(Tracks.CONTENT_URI, getLastTrackId() + "/waypoints"), new String[] { Waypoints.LATITUDE, Waypoints.LONGITUDE }, Waypoints.TABLE + "." + Waypoints._ID + " = " + waypointId, null, null); if (waypoint != null && waypoint.moveToLast()) { int microLatitude = (int) (waypoint.getDouble(0) * 1E6d); int microLongitude = (int) (waypoint.getDouble(1) * 1E6d); Common.log(TAG, "FIRST TRACK POINT IS : " + waypoint.getDouble(0) + ", " + waypoint.getDouble(1)); lastPoint = new GeoPoint(microLatitude, microLongitude); } if (lastPoint == null || lastPoint.getLatitudeE6() == 0 || lastPoint.getLongitudeE6() == 0) { lastPoint = getLastKnowGeopointLocation(); } /* else { mLastWaypoint = waypoint.getLong(2); } */ } } finally { if (minwaypoint != null) { minwaypoint.close(); } if (waypoint != null) { waypoint.close(); } } /* if (waypoint != null) { waypoint.moveToFirst(); Common.log(TAG, "WAYPOINTS ARE: \n"); while (!waypoint.isAfterLast()) { Common.log(TAG, waypoint.getDouble(0) + ", " + waypoint.getDouble(1) + "\n"); waypoint.moveToNext(); } } */ return lastPoint; } //ASLAI Added private GeoPoint getLastTrackPoint(long trackId) { Cursor waypoint = null; GeoPoint lastPoint = null; try { ContentResolver resolver = this.getContentResolver(); waypoint = resolver.query(Uri.withAppendedPath(Tracks.CONTENT_URI, trackId + "/waypoints"), new String[] { Waypoints.LATITUDE, Waypoints.LONGITUDE, "max(" + Waypoints.TABLE + "." + Waypoints._ID + ")" }, null, null, null); if (waypoint != null && waypoint.moveToLast()) { Common.log(TAG, "ASLAI HERE1"); int microLatitude = (int) (waypoint.getDouble(0) * 1E6d); int microLongitude = (int) (waypoint.getDouble(1) * 1E6d); lastPoint = new GeoPoint(microLatitude, microLongitude); } if (lastPoint == null || lastPoint.getLatitudeE6() == 0 || lastPoint.getLongitudeE6() == 0) { Common.log(TAG, "ASLAI HERE2"); lastPoint = getLastKnowGeopointLocation(); } else { Common.log(TAG, "ASLAI HERE3"); //ASLAI PROBLEM HERE mLastWaypoint = waypoint.getLong(2); } } finally { if (waypoint != null) { waypoint.close(); } } return lastPoint; } private void moveToLastTrack() { Common.log(TAG, "ASLAI: MOVETOLASTTRACK"); int trackId = -1; Cursor track = null; try { ContentResolver resolver = this.getApplicationContext().getContentResolver(); track = resolver.query(Tracks.CONTENT_URI, new String[] { "max(" + Tracks._ID + ")", Tracks.NAME, }, null, null, null); if (track != null && track.moveToLast()) { trackId = track.getInt(0); moveToTrack(trackId, true, false); } } finally { if (track != null) { track.close(); } } } private void syncGroupStats() { mStatsUpdating = true; if (!mTrackNameDialogShowing) mDialogUpdate = ProgressDialog.show(this, "", getString(R.string.dialog_updating_stats), true); int[] groupStatIds = mDbHelper.getGroupStatisticIds(); if (groupStatIds == null || groupStatIds.length == 0) { updateUserStats(); } else { try { mGameCon.getScoreBoards(GET_SBS_RID, mDbHelper.getGroupStatisticIds()); } catch (RemoteException e) {} } } /** * Calculates track duration, distance, etc. right after we stop tracking */ private boolean calculateTrackStatistics() { if (statisticsPresent) return false; Common.log(TAG, "calculateTrackStatistics()"); long starttime = 0; double distanceTraveled = 0f; long duration = 0; Uri trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, this.getLastTrackId()); Common.log(TAG, "trackUri = " + trackUri); ContentResolver resolver = this.getApplicationContext().getContentResolver(); Cursor segments = null; Location lastLocation = null; Location currentLocation = null; try { Uri segmentsUri = Uri.withAppendedPath(trackUri, "segments"); segments = resolver.query(segmentsUri, new String[] { Segments._ID }, null, null, null); if (segments.moveToFirst()) { do { long segmentsId = segments.getLong(0); Cursor waypoints = null; try { Uri waypointsUri = Uri.withAppendedPath(segmentsUri, segmentsId + "/waypoints"); waypoints = resolver.query(waypointsUri, new String[] { Waypoints._ID, Waypoints.TIME, Waypoints.LONGITUDE, Waypoints.LATITUDE }, null, null, null); if (waypoints.moveToFirst()) { do { if (starttime == 0) { starttime = waypoints.getLong(1); } currentLocation = new Location(this.getClass().getName()); currentLocation.setTime(waypoints.getLong(1)); currentLocation.setLongitude(waypoints.getDouble(2)); currentLocation.setLatitude(waypoints.getDouble(3)); if (lastLocation != null) { distanceTraveled += lastLocation.distanceTo(currentLocation); duration += currentLocation.getTime() - lastLocation.getTime(); } lastLocation = currentLocation; } while (waypoints.moveToNext()); } } finally { if (waypoints != null) { waypoints.close(); } } lastLocation = null; } while (segments.moveToNext()); } } finally { if (segments != null) { segments.close(); } } ContentValues values = new ContentValues(); values.put(Tracks.DURATION, new Long(duration)); mCalculatedDuration = duration; values.put(Tracks.DISTANCE, new Double(distanceTraveled)); mCalculatedDistance = distanceTraveled; if (mIsPartnerRun) values.put(Tracks.IS_PARTNER, 1); Common.log(TAG, "calculateTrackStatistics(): duration = " + duration + "; distanceTraveled = " + distanceTraveled); resolver.update(trackUri, values, null, null); // resolver.notifyChange(trackUri, null); if (distanceTraveled > 0) { return true; } else { resolver.delete(trackUri, null, null); return false; } } private void updateUserStats() { double dist = mCalculatedDistance; long duration = mCalculatedDuration; Common.log(TAG, "updateUserStats(): dist = " + dist + "; duration = " + duration); int selfId = Common.getRegisteredUser(this).id; Editor editor = mSharedPreferences.edit(); // Mark statistics as dirty editor.putBoolean(Constants.STATS_DIRTY_KEY, true); if (dist > 0 && duration > 0) { mDbHelper.increaseStatistic(Stats.DISTANCE_RAN_ID, -1, dist); mDbHelper.increaseStatistic(Stats.RUNNING_TIME_ID, -1, (double) duration); mDbHelper.updateDistanceRan(selfId); mDbHelper.updateRunningTime(selfId); float diffDistanceRan = mSharedPreferences.getFloat(Constants.DIFF_DISTANCE_RAN_KEY, 0f); float diffRunningTime = mSharedPreferences.getFloat(Constants.DIFF_RUNNING_TIME_KEY, 0f); editor.putFloat(Constants.DIFF_DISTANCE_RAN_KEY, diffDistanceRan + (float)dist); editor.putFloat(Constants.DIFF_DISTANCE_RAN_KEY, diffRunningTime + (float)duration); } if (mIsPartnerRun) { mDbHelper.increaseStatisticByOne(Stats.NUM_PARTNER_RUNS_ID, -1); mDbHelper.updateNumPartnerRuns(selfId); int diffPartnerRuns = mSharedPreferences.getInt(Constants.DIFF_NUM_PARTNER_RUNS_KEY, 0); editor.putInt(Constants.DIFF_NUM_PARTNER_RUNS_KEY, diffPartnerRuns + 1); } mDbHelper.increaseStatisticByOne(Stats.NUM_RUNS_ID, -1); mDbHelper.updateNumRuns(selfId); mDbHelper.updateAvgSpeed(); //mDbHelper.updateMedDuration(); //mDbHelper.updateMedDistance(); int diffRuns = mSharedPreferences.getInt(Constants.DIFF_NUM_RUNS_KEY, 0); editor.putInt(Constants.DIFF_NUM_RUNS_KEY, diffRuns + 1); editor.commit(); ScoreBoard[] scores = mDbHelper.getAllStatistics(); try { mGameCon.updateScoreBoards(UPDATE_SBS_RID, scores); } catch (RemoteException e) {} } private void updateAchievements() { Cursor newAchCursor = mDbHelper.updateAchievements(); if (newAchCursor.getCount() > 0) { // Display a toast notification of the first achievement newAchCursor.moveToNext(); View toastLayout = getLayoutInflater().inflate(R.layout.ach_toast, (ViewGroup) findViewById(R.id.toast_layout_root)); String title = newAchCursor.getString(8); Common.displayAchievementToast(title, newAchCursor.getInt(7), newAchCursor.getInt(4) == 0, getApplicationContext(), toastLayout); if (mSharedPreferences.getBoolean(Constants.POST_FB_KEY, false)) { Bundle params = new Bundle(); params.putString("message", "I just ran " + Common.distanceString(this, mCalculatedDistance) + ". Got the \"" + title + "\" badge!"); params.putString("link", Constants.SITE_URL); params.putString("name", Constants.SITE_TITLE); params.putString("caption", Constants.SITE_SLOGAN); params.putString("picture", Constants.SITE_LOGO); params.putString("privacy", "{\"value\": \"ALL_FRIENDS\"}"); mAsyncRunner.request("me/feed", params, "POST", new WallPostListener()); } //TODO:Snaptic integration if (mSharedPreferences.getBoolean(Constants.POST_CATCH_KEY, false)) { IntentIntegrator notesIntent = new IntentIntegrator(LoggerMap.this); notesIntent.createNote("I just ran " + Common.distanceString(this, mCalculatedDistance) + ". Got the \"" + title + "\" badge!\n\n#Moovy", true); } } else { if (mSharedPreferences.getBoolean(Constants.POST_FB_KEY, false)) { Bundle params = new Bundle(); params.putString("message", "Just ran " + Common.distanceString(this, mCalculatedDistance) + "!"); params.putString("link", Constants.SITE_URL); params.putString("name", Constants.SITE_TITLE); params.putString("caption", Constants.SITE_SLOGAN); params.putString("picture", Constants.SITE_LOGO); params.putString("privacy", "{\"value\": \"ALL_FRIENDS\"}"); mAsyncRunner.request("me/feed", params, "POST", new WallPostListener()); } if (mSharedPreferences.getBoolean(Constants.POST_CATCH_KEY, false)) { IntentIntegrator notesIntent = new IntentIntegrator(LoggerMap.this); notesIntent.createNote("Just ran " + Common.distanceString(this, mCalculatedDistance) + "!\n\n#Moovy", true); } } newAchCursor.close(); } /*** * Collecting additional data */ private void addPicture() { Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + Constants.TMPICTUREFILE_PATH); // Common.log( TAG, "Picture requested at: " + file ); i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); i.putExtra(android.provider.MediaStore.EXTRA_VIDEO_QUALITY, 1); startActivityForResult(i, MENU_PICTURE); } /*** * Collecting additional data */ private void addVideo() { Intent i = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE); File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + Constants.TMPICTUREFILE_PATH); // Common.log( TAG, "Video requested at: " + file ); i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); i.putExtra(android.provider.MediaStore.EXTRA_VIDEO_QUALITY, 1); startActivityForResult(i, MENU_VIDEO); } private void addVoice() { Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION); startActivityForResult(intent, MENU_VOICE); } private class ScoreboardUpdateReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Common.log(TAG, "onReceive()"); try { AppResponse appResponse = null; while ((appResponse = mGameCon.getNextPendingNotification()) != null) { Common.log(TAG, appResponse.toString()); if (appResponse.result_code.equals(GamingServiceConnection.RESULT_CODE_ERROR)) { final int requestId = appResponse.request_id; LoggerMap.this.runOnUiThread(new Runnable() { public void run() { if (mDialogUpdate != null) mDialogUpdate.dismiss(); Toast toast = Toast.makeText(LoggerMap.this, R.string.connection_error_toast, Toast.LENGTH_SHORT); toast.show(); if (requestId == GET_SBS_RID) //Continue calculating track stats even if we can't // sync group stats from server updateUserStats(); else if (requestId == UPDATE_SBS_RID) { //Update achievements with local solo stats even if can't // do so for group stats mStatsUpdating = false; if (!mTrackNameDialogShowing) updateAchievements(); } } }); continue; } else if (appResponse.result_code.equals(GamingServiceConnection.RESULT_CODE_VERSION_ERROR)) { LoggerMap.this.runOnUiThread(new Runnable() { public void run() { if (mDialogUpdate != null) mDialogUpdate.dismiss(); Common.displayUpgradeDialog(LoggerMap.this); } }); continue; } switch(appResponse.request_id) { case GET_SBS_RID: final ScoreBoard[] scores = (ScoreBoard[])(appResponse.object); LoggerMap.this.runOnUiThread(new Runnable() { public void run() { if (scores != null) { mDbHelper.updateScoreboards(scores); if (mSharedPreferences.getBoolean(Constants.STATS_DIRTY_KEY, false)) mDbHelper.applyStatDiffs(); } updateUserStats(); } }); break; case UPDATE_SBS_RID: LoggerMap.this.runOnUiThread(new Runnable() { public void run() { if (mDialogUpdate != null) mDialogUpdate.dismiss(); //Reset dirty bit and all diffs Editor editor = mSharedPreferences.edit(); editor.putBoolean(Constants.STATS_DIRTY_KEY, false); editor.putFloat(Constants.DIFF_DISTANCE_RAN_KEY, 0f); editor.putFloat(Constants.DIFF_DISTANCE_RAN_KEY, 0f); editor.putInt(Constants.DIFF_NUM_RUNS_KEY, 0); editor.putInt(Constants.DIFF_NUM_PARTNER_RUNS_KEY, 0); editor.commit(); mStatsUpdating = false; if (!mTrackNameDialogShowing) updateAchievements(); } }); break; default: break; } } } catch (Exception e) { e.printStackTrace(); } } } private class WallPostListener implements RequestListener { public void onComplete(final String response) { // process the response here: executed in background thread Common.log(TAG, "Wall Post Response: " + response.toString()); } public void onFacebookError(FacebookError e) {} public void onFileNotFoundException(FileNotFoundException e) {} public void onIOException(IOException e) {} public void onMalformedURLException(MalformedURLException e) {} } }