Merge to head

This commit is contained in:
Rodrigo Damazio
2011-12-06 16:34:48 -02:00
parent bb3a14aac0
commit ebe8cbc798
94 changed files with 2793 additions and 1892 deletions
@@ -6,6 +6,7 @@ import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
@@ -67,7 +68,7 @@ public class AggregatedStatsActivity extends Activity implements
sv.setScrollBarStyle(ScrollView.SCROLLBARS_OUTSIDE_INSET);
SharedPreferences preferences = getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
metricUnits = preferences.getBoolean(getString(R.string.metric_units_key), true);
preferences.registerOnSharedPreferenceChangeListener(this);
@@ -23,7 +23,7 @@ import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
* This class encapsulates meta data about one series of values for a chart.
@@ -33,7 +33,7 @@ import java.text.DecimalFormat;
public class ChartValueSeries {
private final ExtremityMonitor monitor = new ExtremityMonitor();
private final DecimalFormat format;
private final NumberFormat format;
private final Path path = new Path();
private final Paint fillPaint;
private final Paint strokePaint;
@@ -132,7 +132,6 @@ public class ChartValueSeries {
* Constructs a new chart value series.
*
* @param context The context for the chart
* @param formatString The format of the decimal format for this series
* @param fillColor The paint for filling the chart
* @param strokeColor The paint for stroking the outside the chart, optional
* @param zoomSettings The settings related to zooming
@@ -140,9 +139,9 @@ public class ChartValueSeries {
*
* TODO: Get rid of Context and inject appropriate values instead.
*/
public ChartValueSeries(Context context, String formatString, int fillColor, int strokeColor,
ZoomSettings zoomSettings, int titleId) {
this.format = new DecimalFormat(formatString);
public ChartValueSeries(
Context context, int fillColor, int strokeColor, ZoomSettings zoomSettings, int titleId) {
this.format = NumberFormat.getIntegerInstance();
fillPaint = new Paint();
fillPaint.setStyle(Style.FILL);
fillPaint.setColor(context.getResources().getColor(fillColor));
@@ -251,9 +250,9 @@ public class ChartValueSeries {
}
/**
* @return The format for the decimal format for this series
* @return The number format for this series
*/
DecimalFormat getFormat() {
NumberFormat getFormat() {
return format;
}
@@ -38,7 +38,6 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Scroller;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
@@ -120,8 +119,13 @@ public class ChartView extends View {
private ChartValueSeries[] series;
private final ExtremityMonitor xMonitor = new ExtremityMonitor();
private static final NumberFormat X_FORMAT = new DecimalFormat("###,###");
private static final NumberFormat X_SHORT_FORMAT = new DecimalFormat("#.0");
private static final NumberFormat X_FORMAT = NumberFormat.getIntegerInstance();
private static final NumberFormat X_SHORT_FORMAT = NumberFormat.getNumberInstance();
static {
X_SHORT_FORMAT.setMaximumFractionDigits(1);
X_SHORT_FORMAT.setMinimumFractionDigits(1);
}
/*
* Paints etc. used when drawing the chart:
@@ -205,7 +209,6 @@ public class ChartView extends View {
// Create the value series.
series[ELEVATION_SERIES] =
new ChartValueSeries(context,
"###,###",
R.color.elevation_fill,
R.color.elevation_border,
new ZoomSettings(MAX_INTERVALS,
@@ -214,7 +217,6 @@ public class ChartView extends View {
series[SPEED_SERIES] =
new ChartValueSeries(context,
"###,###",
R.color.speed_fill,
R.color.speed_border,
new ZoomSettings(MAX_INTERVALS, 0, Integer.MIN_VALUE,
@@ -222,14 +224,12 @@ public class ChartView extends View {
R.string.stat_speed);
series[POWER_SERIES] =
new ChartValueSeries(context,
"###,###",
R.color.power_fill,
R.color.power_border,
new ZoomSettings(MAX_INTERVALS, 0, 1000, new int[] {5, 50, 100, 200}),
R.string.sensor_state_power);
series[CADENCE_SERIES] =
new ChartValueSeries(context,
"###,###",
R.color.cadence_fill,
R.color.cadence_border,
new ZoomSettings(MAX_INTERVALS, 0, Integer.MIN_VALUE,
@@ -237,7 +237,6 @@ public class ChartView extends View {
R.string.sensor_state_cadence);
series[HEART_RATE_SERIES] =
new ChartValueSeries(context,
"###,###",
R.color.heartrate_fill,
R.color.heartrate_border,
new ZoomSettings(MAX_INTERVALS, 0, Integer.MIN_VALUE,
@@ -19,7 +19,6 @@ package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -37,7 +36,7 @@ class CheckUnits {
public static void check(final Context context) {
final SharedPreferences checkUnitsSharedPreferences = context.getSharedPreferences(
CHECK_UNITS_PREFERENCE_FILE, Activity.MODE_PRIVATE);
CHECK_UNITS_PREFERENCE_FILE, Context.MODE_PRIVATE);
if (checkUnitsSharedPreferences.getBoolean(CHECK_UNITS_PREFERENCE_KEY, false)) {
return;
}
@@ -61,7 +60,7 @@ class CheckUnits {
public void onClick(DialogInterface dialog, int which) {
recordCheckPerformed(checkUnitsSharedPreferences);
SharedPreferences useMetricPreferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Activity.MODE_PRIVATE);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = useMetricPreferences.edit();
String key = context.getString(R.string.metric_units_key);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(
@@ -23,6 +23,7 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
@@ -60,9 +61,9 @@ public class DeleteAllTracks extends Handler {
dialogInterface.dismiss();
Log.w(Constants.TAG, "deleting all!");
MyTracksProviderUtils.Factory.get(context).deleteAllTracks();
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
Editor editor = prefs.edit();
// TODO: Go through data manager
editor.putLong(context.getString(R.string.selected_track_key), -1);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
@@ -27,6 +27,7 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
@@ -105,7 +106,8 @@ public class DeleteTrack extends Activity
// If the track we just deleted was selected, unselect it.
String selectedKey = getString(R.string.selected_track_key);
SharedPreferences preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences.getLong(selectedKey, -1) == deleteTrackId) {
Editor editor = preferences.edit().putLong(selectedKey, -1);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
@@ -1,107 +0,0 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.ResourceUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
/**
* This class handles display of EULAs ("End User License Agreements") to the
* user.
*/
class Eula {
private static final String PREFERENCE_EULA_ACCEPTED = "eula.accepted";
private static final String PREFERENCES_EULA = "eula";
private Eula() {}
/**
* Displays the EULA if necessary. This method should be called from the
* onCreate() method of your main Activity. If the user accepts, the EULA
* will never be displayed again. If the user refuses, the activity will
* finish (exit).
*
* @param activity The Activity to finish if the user rejects the EULA
*/
static void showEulaRequireAcceptance(final Activity activity) {
final SharedPreferences preferences =
activity.getSharedPreferences(PREFERENCES_EULA, Activity.MODE_PRIVATE);
if (preferences.getBoolean(PREFERENCE_EULA_ACCEPTED, false)) {
return;
}
final AlertDialog.Builder builder = initDialog(activity);
builder.setPositiveButton(R.string.eula_accept,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
accept(activity, preferences);
}
});
builder.setNegativeButton(R.string.eula_decline,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
refuse(activity);
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
refuse(activity);
}
});
builder.show();
}
/**
* Display the EULA to the user in an informational context. They won't be
* given the choice of accepting or declining the EULA -- we're simply
* displaying it for them to read.
*/
static void showEula(Context context) {
AlertDialog.Builder builder = initDialog(context);
builder.setPositiveButton(R.string.generic_ok, null);
builder.show();
}
private static AlertDialog.Builder initDialog(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
builder.setTitle(R.string.eula_title);
builder.setMessage(ResourceUtils.readFile(context, R.raw.eula));
return builder;
}
private static void accept(Activity activity, SharedPreferences preferences) {
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true));
Intent startIntent = new Intent(activity, WelcomeActivity.class);
activity.startActivityForResult(startIntent, Constants.WELCOME);
}
private static void refuse(Activity activity) {
activity.finish();
}
}
@@ -26,6 +26,7 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.Cursor;
@@ -87,6 +88,7 @@ public class ExportAllTracks {
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.track_list_export_all);
builder.setSingleChoiceItems(choices, 0, itemClick);
builder.setPositiveButton(R.string.generic_ok, positiveClick);
builder.setNegativeButton(R.string.generic_cancel, null);
@@ -113,8 +115,8 @@ public class ExportAllTracks {
* current track.
*/
private void aquireLocksAndExport() {
SharedPreferences prefs =
activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = activity.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
long recordingTrackId = -1;
if (prefs != null) {
recordingTrackId =
@@ -26,6 +26,7 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -95,7 +96,8 @@ public class ImportAllTracks {
* track. Acquire a wake lock if there is no current track.
*/
private void aquireLocksAndImport() {
SharedPreferences prefs = activity.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = activity.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
long recordingTrackId = -1;
if (prefs != null) {
recordingTrackId = prefs.getLong(activity.getString(R.string.recording_track_key), -1);
@@ -128,8 +130,10 @@ public class ImportAllTracks {
if (gpxFileCount == 0) {
builder.setMessage(activity.getString(R.string.import_no_file, gpxPath));
} else {
String totalFiles = activity.getResources().getQuantityString(
R.plurals.importGpxFiles, gpxFileCount, gpxFileCount);
builder.setMessage(
activity.getString(R.string.import_success, importSuccessCount, gpxFileCount, gpxPath));
activity.getString(R.string.import_success, importSuccessCount, totalFiles, gpxPath));
}
builder.setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
@Override
@@ -163,8 +163,8 @@ public class MapOverlay extends Overlay implements OnSharedPreferenceChangeListe
trackPathPainter = TrackPathPainterFactory.getTrackPathPainter(context);
context.getSharedPreferences(Constants.SETTINGS_NAME, 0)
.registerOnSharedPreferenceChangeListener(this);
context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
}
/**
@@ -28,13 +28,18 @@ import com.google.android.apps.mytracks.services.ServiceUtils;
import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection;
import com.google.android.apps.mytracks.services.tasks.StatusAnnouncerFactory;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.EulaUtil;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.apps.mytracks.util.UriUtils;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.TabActivity;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
@@ -61,6 +66,8 @@ import android.widget.Toast;
*/
@SuppressWarnings("deprecation")
public class MyTracks extends TabActivity implements OnTouchListener {
private static final int DIALOG_EULA_ID = 0;
private TrackDataHub dataHub;
/**
@@ -145,7 +152,7 @@ public class MyTracks extends TabActivity implements OnTouchListener {
tracker.dispatch();
providerUtils = MyTracksProviderUtils.Factory.get(this);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
dataHub = ((MyTracksApplication) getApplication()).getTrackDataHub();
menuManager = new MenuManager(this);
serviceConnection = new TrackRecordingServiceConnection(this, serviceBindCallback);
@@ -191,10 +198,11 @@ public class MyTracks extends TabActivity implements OnTouchListener {
tabHost.addView(layout);
layout.setOnTouchListener(this);
// This will show the eula until the user accepts or quits the app.
Eula.showEulaRequireAcceptance(this);
if (!EulaUtil.getEulaValue(this)) {
showDialog(DIALOG_EULA_ID);
}
}
@Override
protected void onStart() {
Log.d(TAG, "MyTracks.onStart");
@@ -255,6 +263,40 @@ public class MyTracks extends TabActivity implements OnTouchListener {
super.onDestroy();
}
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_EULA_ID:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.eula_title);
builder.setMessage(R.string.eula_message);
builder.setPositiveButton(R.string.eula_accept, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
EulaUtil.setEulaValue(MyTracks.this);
Intent startIntent = new Intent(MyTracks.this, WelcomeActivity.class);
startActivityForResult(startIntent, Constants.WELCOME);
}
});
builder.setNegativeButton(R.string.eula_decline, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setCancelable(true);
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
}
});
return builder.create();
default:
return null;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
@@ -419,7 +461,8 @@ public class MyTracks extends TabActivity implements OnTouchListener {
*/
void stopRecording() {
// Save the track id as the shared preference will overwrite the recording track id.
SharedPreferences sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
long currentTrackId = sharedPreferences.getLong(getString(R.string.recording_track_key), -1);
ITrackRecordingService trackRecordingService = serviceConnection.getServiceIfBound();
@@ -32,7 +32,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
@@ -44,8 +44,7 @@ import java.util.TimerTask;
*/
public class SensorStateActivity extends Activity {
private static final SimpleDateFormat TIMESTAMP_FORMAT =
new SimpleDateFormat("HH:mm:ss");
private static final DateFormat TIMESTAMP_FORMAT = DateFormat.getTimeInstance(DateFormat.SHORT);
private static final long REFRESH_PERIOD_MS = 250;
private final StatsUtilities utils;
@@ -31,6 +31,7 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
@@ -682,7 +683,9 @@ public class SettingsActivity extends PreferenceActivity {
metricspeed = newValue;
}
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
prefs.edit().putString(getString(id), metricspeed).commit();
Editor editor = prefs.edit();
editor.putString(getString(id), metricspeed);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
/**
@@ -28,6 +28,7 @@ import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
@@ -100,7 +101,7 @@ public class StatsActivity extends Activity implements TrackDataListener {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
utils = new StatsUtilities(this);
// The volume we want to control is the Text-To-Speech volume
@@ -24,7 +24,6 @@ import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
@@ -35,15 +34,20 @@ import java.text.NumberFormat;
public class StatsUtilities {
private final Activity activity;
private static final NumberFormat LAT_LONG_FORMAT =
new DecimalFormat("##,###.00000");
private static final NumberFormat ALTITUDE_FORMAT =
new DecimalFormat("###,###");
private static final NumberFormat SPEED_FORMAT =
new DecimalFormat("#,###,###.00");
private static final NumberFormat GRADE_FORMAT =
new DecimalFormat("##.0%");
private static final NumberFormat LAT_LONG_FORMAT = NumberFormat.getNumberInstance();
private static final NumberFormat ALTITUDE_FORMAT = NumberFormat.getIntegerInstance();
private static final NumberFormat SPEED_FORMAT = NumberFormat.getNumberInstance();
private static final NumberFormat GRADE_FORMAT = NumberFormat.getPercentInstance();
static {
LAT_LONG_FORMAT.setMaximumFractionDigits(5);
LAT_LONG_FORMAT.setMinimumFractionDigits(5);
SPEED_FORMAT.setMaximumFractionDigits(2);
SPEED_FORMAT.setMinimumFractionDigits(2);
GRADE_FORMAT.setMaximumFractionDigits(1);
GRADE_FORMAT.setMinimumFractionDigits(1);
}
/**
* True if distances should be displayed in metric units (from shared
* preferences).
@@ -28,6 +28,7 @@ import com.google.android.maps.mytracks.R;
import android.app.ListActivity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
@@ -235,7 +236,7 @@ public class TrackList extends ListActivity
listView = getListView();
listView.setOnCreateContextMenuListener(contextMenuListener);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
serviceConnection = new TrackRecordingServiceConnection(this, serviceBindingChanged);
View deleteAll = findViewById(R.id.tracklist_btn_delete_all);
@@ -23,6 +23,7 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
@@ -65,8 +66,8 @@ public class WaypointDetails extends Activity
setContentView(R.layout.mytracks_waypoint_details);
utils = new StatsUtilities(this);
SharedPreferences preferences =
getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
boolean useMetric =
preferences.getBoolean(getString(R.string.metric_units_key), true);
@@ -28,6 +28,7 @@ import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -151,8 +152,8 @@ public class WaypointsList extends ListActivity
insertStatisticsButton =
(Button) findViewById(R.id.waypointslist_btn_insert_statistics);
insertStatisticsButton.setOnClickListener(this);
SharedPreferences preferences =
getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
// TODO: Get rid of selected and recording track IDs
long selectedTrackId = -1;
@@ -20,13 +20,12 @@ import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebView;
import android.widget.TextView;
/**
@@ -36,52 +35,54 @@ import android.widget.TextView;
*/
public class WelcomeActivity extends Activity {
private static final int DIALOG_ABOUT_ID = 0;
private static final int DIALOG_EULA_ID = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.welcome);
WebView web = (WebView) findViewById(R.id.welcome_web);
web.loadUrl("file:///android_asset/welcome.html");
findViewById(R.id.welcome_ok).setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
finish();
}
});
findViewById(R.id.welcome_ok).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
finish();
}
});
findViewById(R.id.welcome_about).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
about();
showDialog(DIALOG_ABOUT_ID);
}
});
}
/**
* Shows the "about" dialog.
*
* TODO: Add a menu option for showing the same thing.
*/
public void about() {
LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.about, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(view);
builder.setPositiveButton(R.string.generic_ok, null);
builder.setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Eula.showEula(WelcomeActivity.this);
}
});
builder.setIcon(R.drawable.arrow_icon);
AlertDialog dialog = builder.create();
dialog.show();
((TextView) dialog.findViewById(R.id.about_version_register)).
setText(SystemUtils.getMyTracksVersion(this));
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
switch (id) {
case DIALOG_ABOUT_ID:
LayoutInflater layoutInflator = LayoutInflater.from(this);
View view = layoutInflator.inflate(R.layout.about, null);
TextView aboutVersionTextView = (TextView) view.findViewById(R.id.about_version);
aboutVersionTextView.setText(SystemUtils.getMyTracksVersion(this));
builder = new AlertDialog.Builder(this);
builder.setView(view);
builder.setPositiveButton(R.string.generic_ok, null);
builder.setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
showDialog(DIALOG_EULA_ID);
}
});
return builder.create();
case DIALOG_EULA_ID:
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.eula_title);
builder.setMessage(R.string.eula_message);
builder.setPositiveButton(R.string.generic_ok, null);
builder.setCancelable(true);
return builder.create();
default:
return null;
}
}
}
@@ -193,7 +193,7 @@ public class MyTracksProvider extends ContentProvider {
} else {
Context context = getContext();
SharedPreferences sharedPreferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
return sharedPreferences.getBoolean(context.getString(R.string.allow_access_key), false);
}
}
@@ -201,7 +201,8 @@ public class TrackDataHub {
* Builds a new {@link TrackDataHub} instance.
*/
public synchronized static TrackDataHub newInstance(Context context) {
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
MyTracksProviderUtils providerUtils = MyTracksProviderUtils.Factory.get(context);
return new TrackDataHub(context,
new TrackDataListeners(),
@@ -22,7 +22,6 @@ import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.io.docs.DocsHelper;
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
import com.google.android.apps.mytracks.io.gdata.GDataWrapper;
import com.google.android.apps.mytracks.io.sendtogoogle.SendType;
import com.google.android.common.gdata.AndroidXmlParserFactory;
import com.google.android.maps.mytracks.R;
import com.google.wireless.gdata.client.GDataClient;
@@ -32,6 +31,7 @@ import com.google.wireless.gdata.docs.SpreadsheetsClient;
import com.google.wireless.gdata.docs.XmlDocsGDataParserFactory;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
@@ -55,10 +55,7 @@ public class SendToDocs {
private final ProgressIndicator progressIndicator;
private final boolean metricUnits;
private boolean createdNewSpreadSheet = false;
private boolean success = true;
private String statusMessage = "";
private Runnable onCompletion = null;
@@ -70,7 +67,7 @@ public class SendToDocs {
this.progressIndicator = progressIndicator;
SharedPreferences preferences = activity.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
metricUnits =
preferences.getBoolean(activity.getString(R.string.metric_units_key),
@@ -92,12 +89,7 @@ public class SendToDocs {
}
private void doUpload(long trackId) {
// TODO
String errorFormat = activity.getString(R.string.send_google_error_service);
String serviceName = activity.getString(SendType.DOCS.getServiceName());
statusMessage = String.format(errorFormat, serviceName);
success = false;
try {
if (trackId == -1) {
Log.w(Constants.TAG, "Cannot get track id.");
@@ -117,13 +109,6 @@ public class SendToDocs {
Log.d(Constants.TAG, "SendToDocs: Uploading to spreadsheet");
success = uploadToDocs(track);
if (success) {
String successFormat = createdNewSpreadSheet
? activity.getString(R.string.send_google_success_new)
: activity.getString(R.string.send_google_success_existing);
String url = activity.getString(SendType.DOCS.getServiceUrl());
statusMessage = String.format(successFormat, serviceName, url);
}
Log.d(Constants.TAG, "SendToDocs: Done.");
} finally {
if (onCompletion != null) {
@@ -136,10 +121,6 @@ public class SendToDocs {
return success;
}
public String getStatusMessage() {
return statusMessage;
}
public void setOnCompletion(Runnable onCompletion) {
this.onCompletion = onCompletion;
}
@@ -222,7 +203,6 @@ public class SendToDocs {
return false;
}
progressIndicator.setProgressValue(80);
createdNewSpreadSheet = true;
if (spreadsheetId == null) {
progressIndicator.setProgressValue(85);
@@ -45,6 +45,7 @@ import com.google.api.client.http.InputStreamContent;
import com.google.api.client.util.Strings;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Location;
@@ -72,7 +73,7 @@ public class SendToFusionTables implements Runnable {
* Listener invoked when sending to fusion tables completes.
*/
public interface OnSendCompletedListener {
void onSendCompleted(String tableId, boolean success, String statusMessage);
void onSendCompleted(String tableId, boolean success);
}
/** The GData service id for Fusion Tables. */
@@ -169,9 +170,6 @@ public class SendToFusionTables implements Runnable {
}
private void doUpload() {
String errorFormat = context.getString(R.string.send_google_error_service);
String serviceName = context.getString(SendType.FUSION_TABLES.getServiceName());
String statusMessage = String.format(errorFormat, serviceName);
boolean success = true;
try {
progressIndicator.setProgressValue(PROGRESS_INITIALIZATION);
@@ -190,6 +188,7 @@ public class SendToFusionTables implements Runnable {
// Create a new table:
progressIndicator.setProgressValue(PROGRESS_FUSION_TABLE_CREATE);
String creatingFormat = context.getString(R.string.send_google_progress_creating);
String serviceName = context.getString(SendType.FUSION_TABLES.getServiceName());
progressIndicator.setProgressMessage(String.format(creatingFormat, serviceName));
if (!createNewTable(track) || !makeTableUnlisted()) {
return;
@@ -211,18 +210,14 @@ public class SendToFusionTables implements Runnable {
return;
}
String successFormat = context.getString(R.string.send_google_success_new);
String url = context.getString(SendType.FUSION_TABLES.getServiceUrl());
statusMessage = String.format(successFormat, serviceName, url);
Log.d(Constants.TAG, "SendToFusionTables: Done: " + success);
progressIndicator.setProgressValue(PROGRESS_COMPLETE);
} finally {
final boolean finalSuccess = success;
final String finalStatusMessage = statusMessage;
context.runOnUiThread(new Runnable() {
public void run() {
if (onCompletion != null) {
onCompletion.onSendCompleted(tableId, finalSuccess, finalStatusMessage);
onCompletion.onSendCompleted(tableId, finalSuccess);
}
}
});
@@ -303,7 +298,8 @@ public class SendToFusionTables implements Runnable {
}
private boolean uploadAllTrackPoints(final Track track, String originalDescription) {
SharedPreferences preferences = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
boolean metricUnits = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
@@ -32,6 +32,7 @@ import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Location;
@@ -76,7 +77,7 @@ public class SendToMyMaps implements Runnable {
private int totalSegmentsUploaded;
public interface OnSendCompletedListener {
void onSendCompleted(String mapId, boolean success, String statusMessage);
void onSendCompleted(String mapId, boolean success);
}
public SendToMyMaps(Activity context, String mapId, AuthManager auth,
@@ -99,9 +100,6 @@ public class SendToMyMaps implements Runnable {
}
private void doUpload() {
String errorFormat = context.getString(R.string.send_google_error_service);
String serviceName = context.getString(SendType.MYMAPS.getServiceName());
String statusMessage = String.format(errorFormat, serviceName);
boolean success = true;
try {
progressIndicator.setProgressMessage(
@@ -124,7 +122,7 @@ public class SendToMyMaps implements Runnable {
boolean isNewMap = mapId.equals(NEW_MAP_ID);
if (isNewMap) {
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
boolean mapPublic = true;
if (preferences != null) {
mapPublic = preferences.getBoolean(
@@ -132,6 +130,7 @@ public class SendToMyMaps implements Runnable {
}
String creatingFormat = context.getString(R.string.send_google_progress_creating);
String serviceName = context.getString(SendType.MYMAPS.getServiceName());
progressIndicator.setProgressMessage(String.format(creatingFormat, serviceName));
StringBuilder mapIdBuilder = new StringBuilder();
@@ -175,12 +174,6 @@ public class SendToMyMaps implements Runnable {
}
}
if (success) {
String successFormat = isNewMap ? context.getString(R.string.send_google_success_new)
: context.getString(R.string.send_google_success_existing);
String url = context.getString(SendType.MYMAPS.getServiceUrl());
statusMessage = String.format(successFormat, serviceName, url);
}
Log.d(TAG, "SendToMyMaps: Done: " + success);
progressIndicator.setProgressValue(100);
} finally {
@@ -189,11 +182,10 @@ public class SendToMyMaps implements Runnable {
}
final boolean finalSuccess = success;
final String finalStatusMessage = statusMessage;
context.runOnUiThread(new Runnable() {
public void run() {
if (onCompletion != null) {
onCompletion.onSendCompleted(mapId, finalSuccess, finalStatusMessage);
onCompletion.onSendCompleted(mapId, finalSuccess);
}
}
});
@@ -203,7 +195,7 @@ public class SendToMyMaps implements Runnable {
private boolean uploadAllTrackPoints(
final Track track, String originalDescription) {
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
boolean metricUnits = true;
if (preferences != null) {
metricUnits =
@@ -32,7 +32,7 @@ import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
@@ -47,8 +47,8 @@ import java.util.Date;
public class BackupActivityHelper {
// Since the user sees this format, we use the local timezone
private static final SimpleDateFormat DISPLAY_BACKUP_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final DateFormat DISPLAY_BACKUP_FORMAT = DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT);
private static final Comparator<Date> REVERSE_DATE_ORDER =
new Comparator<Date>() {
@@ -201,8 +201,8 @@ class ExternalFileBackup {
}
// Dump preferences
SharedPreferences preferences =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
preferencesHelper.exportPreferences(preferences, outWriter);
} catch (IOException e) {
// We tried to delete the partially created file, but do nothing
@@ -255,8 +255,8 @@ class ExternalFileBackup {
pointImporter.importAllRows(reader);
// Restore preferences
SharedPreferences preferences =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
preferencesHelper.importPreferences(reader, preferences);
} finally {
compressedStream.close();
@@ -20,6 +20,7 @@ import com.google.android.apps.mytracks.Constants;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -41,7 +42,7 @@ public class MyTracksBackupAgent extends BackupAgent {
ParcelFileDescriptor newState) throws IOException {
Log.i(Constants.TAG, "Performing backup");
SharedPreferences preferences = this.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
backupPreferences(data, preferences);
Log.i(Constants.TAG, "Backup complete");
@@ -91,7 +92,7 @@ public class MyTracksBackupAgent extends BackupAgent {
}
SharedPreferences preferences = this.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
PreferenceBackupHelper importer = createPreferenceBackupHelper();
importer.importPreferences(dataBuffer, preferences);
}
@@ -16,6 +16,7 @@
package com.google.android.apps.mytracks.io.backup;
import com.google.android.apps.mytracks.content.ContentTypeIds;
import com.google.android.apps.mytracks.util.ApiFeatures;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
@@ -77,15 +78,14 @@ class PreferenceBackupHelper {
*
* @param data the byte array to read preferences from
* @param preferences the shared preferences to edit
* @return whether the preference change was successful
* @throws IOException if there are any errors while reading
*/
public boolean importPreferences(byte[] data, SharedPreferences preferences)
public void importPreferences(byte[] data, SharedPreferences preferences)
throws IOException {
ByteArrayInputStream bufStream = new ByteArrayInputStream(data);
DataInputStream reader = new DataInputStream(bufStream);
return importPreferences(reader, preferences);
importPreferences(reader, preferences);
}
/**
@@ -93,10 +93,9 @@ class PreferenceBackupHelper {
*
* @param reader the stream to read from
* @param preferences the shared preferences to edit
* @return whether the preference change was successful
* @throws IOException if there are any errors while reading
*/
public boolean importPreferences(DataInputStream reader,
public void importPreferences(DataInputStream reader,
SharedPreferences preferences) throws IOException {
Editor editor = preferences.edit();
editor.clear();
@@ -107,8 +106,7 @@ class PreferenceBackupHelper {
byte typeId = reader.readByte();
readAndSetPreference(name, typeId, reader, editor);
}
return editor.commit();
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
/**
@@ -34,7 +34,6 @@ import com.google.wireless.gdata.parser.ParseException;
import com.google.wireless.gdata2.client.AuthenticationException;
import android.content.Context;
import android.text.format.DateFormat;
import android.util.Log;
import java.io.BufferedReader;
@@ -45,6 +44,7 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicReference;
@@ -290,7 +290,7 @@ public class DocsHelper {
DocsTagBuilder tagBuilder = new DocsTagBuilder(metricUnits)
.append("name", track.getName())
.append("description", track.getDescription())
.append("date", getDisplayDate(context, stats.getStartTime()))
.append("date", getDisplayDate(stats.getStartTime()))
.append("totaltime", StringUtils.formatTimeAlwaysShowingHours(
stats.getTotalTime()))
.append("movingtime", StringUtils.formatTimeAlwaysShowingHours(
@@ -331,17 +331,15 @@ public class DocsHelper {
}
/**
* Gets the display string for a time based on the phone's setting.
* Gets the display string for a time.
*
* @param context the context to obtain the phone's setting.
* @param time the time
* @return the display string of the time
*/
protected String getDisplayDate(Context context, long time) {
java.text.DateFormat dateFormat = DateFormat.getDateFormat(context);
java.text.DateFormat timeFormat = DateFormat.getTimeFormat(context);
private String getDisplayDate(long time) {
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
Date startTime = new Date(time);
String dateString = dateFormat.format(startTime) + " " + timeFormat.format(startTime);
String dateString = format.format(startTime);
return dateString;
}
@@ -15,12 +15,9 @@
*/
package com.google.android.apps.mytracks.io.docs;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.StringUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
@@ -47,12 +44,16 @@ import java.util.Locale;
*/
class DocsTagBuilder {
private static final DecimalFormatSymbols FORMAT_SYMBOLS =
ApiFeatures.getInstance().getApiAdapter().getDecimalFormatSymbols(Locale.ENGLISH);
private static final NumberFormat LARGE_UNIT_FORMAT =
new DecimalFormat("#,###,###.00", FORMAT_SYMBOLS);
private static final NumberFormat SMALL_UNIT_FORMAT =
new DecimalFormat("###,###", FORMAT_SYMBOLS);
// Google Docs can only parse numbers in the English locale.
private static final NumberFormat LARGE_UNIT_FORMAT = NumberFormat.getNumberInstance(
Locale.ENGLISH);
private static final NumberFormat SMALL_UNIT_FORMAT = NumberFormat.getIntegerInstance(
Locale.ENGLISH);
static {
LARGE_UNIT_FORMAT.setMaximumFractionDigits(2);
LARGE_UNIT_FORMAT.setMinimumFractionDigits(2);
}
protected final boolean metricUnits;
protected final StringBuilder stringBuilder;
@@ -18,15 +18,14 @@ package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import android.location.Location;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Exports a track as a CSV file, according to RFC 4180.
@@ -46,13 +45,10 @@ import java.util.TimeZone;
*/
public class CsvTrackWriter implements TrackFormatWriter {
static final NumberFormat SHORT_FORMAT = NumberFormat.getInstance();
static final SimpleDateFormat TIMESTAMP_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
private static final NumberFormat SHORT_FORMAT = NumberFormat.getInstance();
static {
SHORT_FORMAT.setMaximumFractionDigits(4);
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private int segmentIdx = 0;
@@ -93,7 +89,7 @@ public class CsvTrackWriter implements TrackFormatWriter {
@Override
public void writeLocation(Location location) {
String timeStr = TIMESTAMP_FORMAT.format(new Date(location.getTime()));
String timeStr = FileUtils.FILE_TIMESTAMP_FORMAT.format(new Date(location.getTime()));
writeCommaSeparatedLine("P",
timeStr,
Double.toString(location.getLatitude()),
@@ -109,7 +105,7 @@ public class CsvTrackWriter implements TrackFormatWriter {
@Override
public void writeWaypoint(Waypoint waypoint) {
Location location = waypoint.getLocation();
String timeStr = TIMESTAMP_FORMAT.format(new Date(location.getTime()));
String timeStr = FileUtils.FILE_TIMESTAMP_FORMAT.format(new Date(location.getTime()));
writeCommaSeparatedLine("WAYPOINT",
timeStr,
Double.toString(location.getLatitude()),
@@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.io.file;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.StringUtils;
import android.location.Location;
@@ -27,10 +28,8 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* Log of one track.
@@ -38,11 +37,8 @@ import java.util.TimeZone;
* @author Sandor Dornbush
*/
public class GpxTrackWriter implements TrackFormatWriter {
private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private final NumberFormat elevationFormatter;
private final NumberFormat coordinateFormatter;
private final SimpleDateFormat timestampFormatter;
private PrintWriter pw = null;
private Track track;
@@ -57,9 +53,6 @@ public class GpxTrackWriter implements TrackFormatWriter {
coordinateFormatter.setMaximumFractionDigits(5);
coordinateFormatter.setMaximumIntegerDigits(3);
coordinateFormatter.setGroupingUsed(false);
timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT);
timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private String formatLocation(Location l) {
@@ -144,7 +137,7 @@ public class GpxTrackWriter implements TrackFormatWriter {
pw.println("<trkpt " + formatLocation(l) + ">");
Date d = new Date(l.getTime());
pw.println("<ele>" + elevationFormatter.format(l.getAltitude()) + "</ele>");
pw.println("<time>" + timestampFormatter.format(d) + "</time>");
pw.println("<time>" + FileUtils.FILE_TIMESTAMP_FORMAT.format(d) + "</time>");
pw.println("</trkpt>");
}
}
@@ -164,7 +157,7 @@ public class GpxTrackWriter implements TrackFormatWriter {
if (l != null) {
pw.println("<wpt " + formatLocation(l) + ">");
pw.println("<ele>" + elevationFormatter.format(l.getAltitude()) + "</ele>");
pw.println("<time>" + timestampFormatter.format(l.getTime()) + "</time>");
pw.println("<time>" + FileUtils.FILE_TIMESTAMP_FORMAT.format(l.getTime()) + "</time>");
pw.println("<name>" + StringUtils.stringAsCData(waypoint.getName())
+ "</name>");
pw.println("<desc>"
@@ -21,6 +21,7 @@ import com.google.android.apps.mytracks.content.Sensor.SensorDataSet;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.Waypoint;
import com.google.android.apps.mytracks.io.file.TrackWriterFactory.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import android.content.Context;
@@ -30,10 +31,8 @@ import android.os.Build;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* Write out a a track in the Garmin training center database, tcx format.
@@ -44,10 +43,9 @@ import java.util.TimeZone;
* Garmin Training Center 3.5.3.
*
* @author Sandor Dornbush
* @author Dominik Ršttsches
* @author Dominik Ršttsches
*/
public class TcxTrackWriter implements TrackFormatWriter {
protected static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
// These are the only sports allowed by the TCX v2 specification for fields
// of type Sport_t.
@@ -59,7 +57,6 @@ public class TcxTrackWriter implements TrackFormatWriter {
private static final String TCX_TYPE_RELEASE = "Release";
private static final String TCX_TYPE_INTERNAL = "Internal";
private final SimpleDateFormat timestampFormatter;
private final Context context;
private PrintWriter pw = null;
@@ -70,9 +67,6 @@ public class TcxTrackWriter implements TrackFormatWriter {
public TcxTrackWriter(Context context) {
this.context = context;
timestampFormatter = new SimpleDateFormat(TIMESTAMP_FORMAT);
timestampFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@SuppressWarnings("hiding")
@@ -117,7 +111,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
return;
}
String startTime = timestampFormatter.format(track.getStatistics().getStartTime());
String startTime = FileUtils.FILE_TIMESTAMP_FORMAT.format(track.getStatistics().getStartTime());
pw.println(" <Activities>");
pw.format(" <Activity Sport=\"%s\">\n", categoryToTcxSport(track.getCategory()));
@@ -150,7 +144,7 @@ public class TcxTrackWriter implements TrackFormatWriter {
}
pw.println(" <Trackpoint>");
Date d = new Date(location.getTime());
pw.println(" <Time>" + timestampFormatter.format(d) + "</Time>");
pw.println(" <Time>" + FileUtils.FILE_TIMESTAMP_FORMAT.format(d) + "</Time>");
pw.println(" <Position>");
pw.print(" <LatitudeDegrees>");
@@ -114,7 +114,7 @@ class TrackWriterImpl implements TrackWriter {
private void doWriteTrack() {
// Open the input and output
success = false;
errorMessage = R.string.export_error;
errorMessage = R.string.sd_card_error_write_file;
if (track != null) {
if (openFile()) {
try {
@@ -127,7 +127,7 @@ class TrackWriterImpl implements TrackWriter {
}
}
success = false;
errorMessage = R.string.export_canceled;
errorMessage = R.string.sd_card_canceled;
}
}
}
@@ -81,7 +81,7 @@ class WriteProgressController {
dialog.setIcon(android.R.drawable.ic_dialog_info);
dialog.setTitle(activity.getString(R.string.generic_progress_title));
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage(activity.getString(R.string.export_progress_message));
dialog.setMessage(activity.getString(R.string.sd_card_progress_write_file));
dialog.setIndeterminate(true);
dialog.setOnCancelListener(dialogCancelListener);
return dialog;
@@ -67,9 +67,6 @@ public class SendActivity extends Activity implements ProgressIndicator {
private static final String STATE_SEND_TO_MAPS = "mapsSend";
private static final String STATE_SEND_TO_FUSION_TABLES = "fusionSend";
private static final String STATE_SEND_TO_DOCS = "docsSend";
private static final String STATE_DOCS_MESSAGE = "docsMsg";
private static final String STATE_FUSION_TABLES_MESSAGE = "fusionMsg";
private static final String STATE_MAPS_MESSAGE = "mapsMsg";
private static final String STATE_DOCS_SUCCESS = "docsSuccess";
private static final String STATE_FUSION_SUCCESS = "fusionSuccess";
private static final String STATE_MAPS_SUCCESS = "mapsSuccess";
@@ -134,10 +131,6 @@ public class SendActivity extends Activity implements ProgressIndicator {
private boolean sendToMyMapsSuccess = false;
private boolean sendToFusionTablesSuccess = false;
private boolean sendToDocsSuccess = false;
// TODO: Make these be used for showing results
private String sendToMyMapsMessage;
private String sendToFusionTablesMessage;
private String sendToDocsMessage;
// Send result information, used to share a link.
private String sendToMyMapsMapId;
@@ -159,7 +152,7 @@ public class SendActivity extends Activity implements ProgressIndicator {
super.onCreate(savedInstanceState);
providerUtils = MyTracksProviderUtils.Factory.get(this);
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
tracker = GoogleAnalyticsTracker.getInstance();
// Start the tracker in manual dispatch mode...
@@ -259,10 +252,6 @@ public class SendActivity extends Activity implements ProgressIndicator {
sendToFusionTablesSuccess = savedInstanceState.getBoolean(STATE_FUSION_SUCCESS);
sendToDocsSuccess = savedInstanceState.getBoolean(STATE_DOCS_SUCCESS);
sendToMyMapsMessage = savedInstanceState.getString(STATE_MAPS_MESSAGE);
sendToFusionTablesMessage = savedInstanceState.getString(STATE_FUSION_TABLES_MESSAGE);
sendToDocsMessage = savedInstanceState.getString(STATE_DOCS_MESSAGE);
sendToMyMapsMapId = savedInstanceState.getString(STATE_MAP_ID);
sendToFusionTablesTableId = savedInstanceState.getString(STATE_TABLE_ID);
@@ -280,10 +269,6 @@ public class SendActivity extends Activity implements ProgressIndicator {
outState.putBoolean(STATE_FUSION_SUCCESS, sendToFusionTablesSuccess);
outState.putBoolean(STATE_DOCS_SUCCESS, sendToDocsSuccess);
outState.putString(STATE_MAPS_MESSAGE, sendToMyMapsMessage);
outState.putString(STATE_FUSION_TABLES_MESSAGE, sendToFusionTablesMessage);
outState.putString(STATE_DOCS_MESSAGE, sendToDocsMessage);
outState.putString(STATE_MAP_ID, sendToMyMapsMapId);
outState.putString(STATE_TABLE_ID, sendToFusionTablesTableId);
@@ -428,9 +413,7 @@ public class SendActivity extends Activity implements ProgressIndicator {
SendToMyMaps.OnSendCompletedListener onCompletion = new SendToMyMaps.OnSendCompletedListener() {
@Override
public void onSendCompleted(String mapId, boolean success, String statusMessage) {
// TODO: Use this message
sendToMyMapsMessage = statusMessage;
public void onSendCompleted(String mapId, boolean success) {
sendToMyMapsSuccess = success;
if (sendToMyMapsSuccess) {
sendToMyMapsMapId = mapId;
@@ -489,9 +472,7 @@ public class SendActivity extends Activity implements ProgressIndicator {
OnSendCompletedListener onCompletion = new OnSendCompletedListener() {
@Override
public void onSendCompleted(String tableId, boolean success, String statusMessage) {
// TODO: Use this message
sendToFusionTablesMessage = statusMessage;
public void onSendCompleted(String tableId, boolean success) {
sendToFusionTablesSuccess = success;
if (sendToFusionTablesSuccess) {
sendToFusionTablesTableId = tableId;
@@ -562,11 +543,7 @@ public class SendActivity extends Activity implements ProgressIndicator {
Runnable onCompletion = new Runnable() {
public void run() {
setProgressValue(100);
// TODO: Use this message
sendToDocsMessage = sender.getStatusMessage();
sendToDocsSuccess = sender.wasSuccess();
executeStateMachine(SendState.SEND_TO_DOCS_DONE);
}
};
@@ -871,11 +848,8 @@ public class SendActivity extends Activity implements ProgressIndicator {
private void resetState() {
currentState = SendState.SEND_OPTIONS;
sendToMyMapsMapId = null;
sendToMyMapsMessage = "";
sendToMyMapsSuccess = true;
sendToFusionTablesMessage = "";
sendToFusionTablesSuccess = true;
sendToDocsMessage = "";
sendToDocsSuccess = true;
sendToFusionTablesTableId = null;
}
@@ -44,7 +44,8 @@ public class DynamicSpeedTrackPathDescriptor
public DynamicSpeedTrackPathDescriptor(Context context){
this.context = context;
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
speedMargin = 25;
@@ -83,7 +84,8 @@ public class DynamicSpeedTrackPathDescriptor
|| !key.equals(context.getString(R.string.track_color_mode_dynamic_speed_variation_key))) {
return;
}
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
speedMargin = 25;
@@ -98,7 +100,8 @@ public class DynamicSpeedTrackPathDescriptor
@Override
public boolean needsRedraw() {
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
long currentTrackId = prefs.getLong(context.getString(R.string.selected_track_key), -1);
if(currentTrackId == -1) {
// Could not find track.
@@ -39,15 +39,15 @@ public class FixedSpeedTrackPathDescriptor implements TrackPathDescriptor, OnSha
public FixedSpeedTrackPathDescriptor(Context context) {
this.context = context;
context.getSharedPreferences(Constants.SETTINGS_NAME, 0)
.registerOnSharedPreferenceChangeListener(this);
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
slowSpeed = 9;
normalSpeed = 17;
return;
}
prefs.registerOnSharedPreferenceChangeListener(this);
try {
slowSpeed = Integer.parseInt(prefs.getString(context.getString(
R.string.track_color_mode_fixed_speed_slow_key), "9"));
@@ -87,7 +87,8 @@ public class FixedSpeedTrackPathDescriptor implements TrackPathDescriptor, OnSha
&& !key.equals(context.getString(R.string.track_color_mode_fixed_speed_medium_key)))) {
return;
}
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
slowSpeed = 9;
normalSpeed = 17;
@@ -40,8 +40,8 @@ public class TrackPathPainterFactory {
* @return The TrackPathPainter that corresponds to the track color mode setting.
*/
public static TrackPathPainter getTrackPathPainter(Context context) {
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
return new SingleColorTrackPathPainter(context);
}
@@ -21,7 +21,7 @@ import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Date;
/**
@@ -30,8 +30,6 @@ import java.util.Date;
* @author Matthew Simmons
*/
class DefaultTrackNameFactory {
private static final String TIMESTAMP_DATE_FORMAT = "yyyy-MM-dd HH:mm";
private final Context context;
DefaultTrackNameFactory(Context context) {
@@ -48,7 +46,7 @@ class DefaultTrackNameFactory {
*/
String newTrackName(long trackId, long startTime) {
if (useTimestampTrackName()) {
SimpleDateFormat formatter = new SimpleDateFormat(TIMESTAMP_DATE_FORMAT);
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
return formatter.format(new Date(startTime));
} else {
return String.format(context.getString(R.string.track_name_format), trackId);
@@ -57,8 +55,8 @@ class DefaultTrackNameFactory {
/** Determines whether the preferences allow a timestamp-based track name */
protected boolean useTimestampTrackName() {
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
return prefs.getBoolean(
context.getString(R.string.timestamp_track_name_key), true);
}
@@ -16,9 +16,12 @@
package com.google.android.apps.mytracks.services;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.util.Log;
@@ -45,7 +48,7 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
public PreferenceManager(TrackRecordingService service) {
this.service = service;
this.sharedPreferences = service.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (sharedPreferences == null) {
Log.w(Constants.TAG,
"TrackRecordingService: Couldn't get shared preferences.");
@@ -169,24 +172,21 @@ public class PreferenceManager implements OnSharedPreferenceChangeListener {
}
public void setAutoResumeTrackCurrentRetry(int retryAttempts) {
sharedPreferences
.edit()
.putInt(autoResumeTrackCurrentRetryKey, retryAttempts)
.commit();
Editor editor = sharedPreferences.edit();
editor.putInt(autoResumeTrackCurrentRetryKey, retryAttempts);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
public void setRecordingTrack(long id) {
sharedPreferences
.edit()
.putLong(recordingTrackKey, id)
.commit();
Editor editor = sharedPreferences.edit();
editor.putLong(recordingTrackKey, id);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
public void setSelectedTrack(long id) {
sharedPreferences
.edit()
.putLong(selectedTrackKey, id)
.commit();
Editor editor = sharedPreferences.edit();
editor.putLong(selectedTrackKey, id);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
public void shutdown() {
@@ -59,7 +59,7 @@ public class ServiceUtils {
}
if (preferences == null) {
preferences = ctx.getSharedPreferences(Constants.SETTINGS_NAME, 0);
preferences = ctx.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
}
return preferences.getLong(ctx.getString(R.string.recording_track_key), -1) > 0;
}
@@ -392,8 +392,8 @@ public class TrackRecordingService extends Service {
+ autoResumeTrackTimeout);
// Check if we haven't exceeded the maximum number of retry attempts.
SharedPreferences sharedPreferences =
getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
int retries = sharedPreferences.getInt(
getString(R.string.auto_resume_track_current_retry_key), 0);
Log.d(TAG,
@@ -561,7 +561,8 @@ public class TrackRecordingService extends Service {
}
private String getDefaultActivityType(Context context) {
SharedPreferences prefs = context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
return prefs.getString(context.getString(R.string.default_activity_key), "");
}
@@ -1056,7 +1057,8 @@ public class TrackRecordingService extends Service {
.putExtra(getString(R.string.track_id_broadcast_extra), trackId);
sendBroadcast(broadcastIntent, getString(R.string.permission_notification_value));
SharedPreferences sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (sharedPreferences.getBoolean(getString(R.string.allow_access_key), false)) {
sendBroadcast(broadcastIntent, getString(R.string.broadcast_notifications_permission));
}
@@ -1215,7 +1217,7 @@ public class TrackRecordingService extends Service {
return true;
} else {
SharedPreferences sharedPreferences = service.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
return sharedPreferences.getBoolean(service.getString(R.string.allow_access_key), false);
}
}
@@ -127,8 +127,8 @@ public class BluetoothSensorManager extends SensorManager {
Log.w(Constants.TAG, "Disabled manager onStartTrack");
return;
}
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
String address =
prefs.getString(context.getString(R.string.bluetooth_sensor_key), null);
if (address == null) {
@@ -40,8 +40,8 @@ public class SensorManagerFactory {
* @return The sensor manager that corresponds to the sensor type setting.
*/
public static SensorManager getSensorManager(Context context) {
SharedPreferences prefs =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) {
return null;
}
@@ -17,13 +17,13 @@ package com.google.android.apps.mytracks.services.sensors.ant;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.maps.mytracks.R;
import com.dsi.ant.AntDefine;
import com.dsi.ant.AntMesg;
import com.dsi.ant.exception.AntInterfaceException;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
@@ -57,7 +57,7 @@ public class AntDirectSensorManager extends AntSensorManager {
// First read the the device id that we will be pairing with.
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs != null) {
deviceNumberHRM =
(short) prefs.getInt(context.getString(R.string.ant_heart_rate_sensor_id_key), 0);
@@ -135,7 +135,7 @@ public class AntDirectSensorManager extends AntSensorManager {
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(context.getString(R.string.ant_heart_rate_sensor_id_key), deviceNumberHRM);
editor.commit();
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
private void handleMessageResponse(byte[] rawMessage) {
@@ -1,227 +0,0 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.services.sensors.ant;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.dsi.ant.AntDefine;
import com.dsi.ant.AntMesg;
import com.dsi.ant.exception.AntInterfaceException;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.services.sensors.SensorUtils;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
/**
* A sensor manager that can connect to an SRM Power Control 7 head unit.
*
* @author Sandor Dornbush
*/
public class AntSRMSensorManager extends AntSensorManager {
/*
* These constants are defined by the SRM Headunit spec.
*/
public static final byte NETWORK_NUMBER = (byte) 0;
public static final byte DEVICE_TYPE = (byte) 12;
public static final byte MANUFACTURER_ID = (byte) 1;
public static final short CHANNEL_PERIOD = (short) 8192;
public static final byte RF_FREQUENCY = (byte) 50;
public static final int MESSAGE_TYPE_INDEX = 3;
public static final int INITIALS_MESSAGE_TYPE = 5;
public static final int SENSOR_DATA_MESSAGE_TYPE = 6;
public static final int MESSAGE_ID_INDEX = 4;
/**
* This can be any value between 0..8
*/
private byte channel = (byte) 5;
/**
* This is the id of this device.
* The head unit must be programmed to expect this number.
*/
private byte deviceId;
/**
* The id of the last message received from the SRM head unit.
*/
private int lastMessageId;
public AntSRMSensorManager(Context context) {
super(context);
// First read the the device id that we will be announcing.
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
if (prefs != null) {
deviceId = (byte) prefs.getInt(
context.getString(R.string.ant_srm_bridge_sensor_id_key),
WILDCARD);
}
}
@Override
public void handleMessage(byte[] antMessage) {
// Parse channel number
byte recievedChannel = (byte) (antMessage[AntMesg.MESG_DATA_OFFSET]
& AntDefine.CHANNEL_NUMBER_MASK);
if (recievedChannel != channel) {
Log.d(TAG, "Unexpected channel: " + recievedChannel);
return;
}
switch (antMessage[AntMesg.MESG_ID_OFFSET]) {
case AntMesg.MESG_BROADCAST_DATA_ID:
handleBroadcastData(antMessage);
break;
case AntMesg.MESG_RESPONSE_EVENT_ID:
handleMessageResponse(antMessage);
break;
case AntMesg.MESG_CHANNEL_ID_ID:
handleChannelId(antMessage);
break;
default:
Log.e(TAG, "Unexpected message id: " + antMessage[3]);
}
}
private void handleBroadcastData(byte[] antMessage) {
if (deviceId == WILDCARD) {
try {
Log.d(TAG, "Requesting channel id id.");
getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID);
} catch (AntInterfaceException e) {
Log.e(TAG, "Failed to request channel id id", e);
}
}
setSensorState(Sensor.SensorState.CONNECTED);
switch(antMessage[MESSAGE_TYPE_INDEX]) {
case INITIALS_MESSAGE_TYPE:
// TODO handle initials message.
break;
case SENSOR_DATA_MESSAGE_TYPE:
parseSensorData(antMessage);
break;
default:
Log.e(TAG, "Unexpected message type: " + antMessage[MESSAGE_TYPE_INDEX]);
}
}
private void handleChannelId(byte[] antMessage) {
// Store the device id.
deviceId = antMessage[3];
Log.i(TAG, "Found device id: " + deviceId);
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(context.getString(R.string.ant_srm_bridge_sensor_id_key), deviceId);
editor.commit();
}
private void handleMessageResponse(byte[] antMessage) {
if (antMessage[3] == AntMesg.MESG_EVENT_ID
&& antMessage[4] == AntDefine.EVENT_RX_SEARCH_TIMEOUT) {
// Search timeout
Log.w(TAG, "Search timed out. Unassigning channel.");
try {
getAntReceiver().ANTUnassignChannel(channel);
} catch (AntInterfaceException e) {
Log.e(TAG, "Failed to unassign ANT channel", e);
}
setSensorState(Sensor.SensorState.DISCONNECTED);
} else if (antMessage[3] == AntMesg.MESG_UNASSIGN_CHANNEL_ID) {
setSensorState(Sensor.SensorState.DISCONNECTED);
Log.i(TAG, "Disconnected from the sensor: " + getSensorState());
}
}
private void parseSensorData(byte[] antMessage) {
if (antMessage.length != 11) {
Log.e(TAG, "Unexpected ant message length: " + antMessage.length);
return;
}
int newMessageId = antMessage[MESSAGE_ID_INDEX] & 0xFF;
if (lastMessageId == newMessageId) {
// Repeated message.
Log.i(TAG, String.format("SRM ignoring repeat: 0x%X", newMessageId));
return;
}
if (newMessageId < lastMessageId) {
if (!(newMessageId < 20 && lastMessageId > 200)) {
Log.i(TAG, String.format("SRM ignoring repeat: 0x%X", newMessageId));
return;
} // else assume the byte overflowed to 0.
}
lastMessageId = newMessageId;
Sensor.SensorDataSet.Builder builder = Sensor.SensorDataSet.newBuilder()
.setCreationTime(System.currentTimeMillis());
int power = SensorUtils.unsignedShortToInt(antMessage, 5);
if (power >= 0) {
Sensor.SensorData.Builder b = Sensor.SensorData.newBuilder()
.setValue(power)
.setState(Sensor.SensorState.SENDING);
builder.setPower(b);
}
int speed = SensorUtils.unsignedShortToInt(antMessage, 7);
if (speed >= 0) {
// The speed from srm is in 1/10 km/hr.
// Sensor data expects the speed as m/s.
// TODO finish this.
//sensorData.setWheelSpeed(UnitConversions.TENTH_KMH_TO_MPS * speed);
}
int cadence = antMessage[9] & 0xFF;
if (cadence >= 0) {
Sensor.SensorData.Builder b = Sensor.SensorData.newBuilder()
.setValue(cadence)
.setState(Sensor.SensorState.SENDING);
builder.setCadence(b);
}
int bpm = antMessage[10] & 0xFF;
if (bpm > 0) {
Sensor.SensorData.Builder b = Sensor.SensorData.newBuilder()
.setValue(bpm)
.setState(Sensor.SensorState.SENDING);
builder.setHeartRate(b);
}
sensorData = builder.build();
}
@Override
protected void setupAntSensorChannels() {
lastMessageId = 0;
setupAntSensorChannel(NETWORK_NUMBER,
channel,
deviceId,
DEVICE_TYPE,
MANUFACTURER_ID,
CHANNEL_PERIOD,
RF_FREQUENCY,
(byte) 0);
}
}
@@ -22,6 +22,7 @@ import com.dsi.ant.AntMesg;
import com.dsi.ant.exception.AntInterfaceException;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.Sensor;
import com.google.android.apps.mytracks.util.ApiFeatures;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.maps.mytracks.R;
@@ -68,7 +69,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
// First read the the device id that we will be pairing with.
SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, 0);
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs != null) {
deviceNumber =
(short) prefs.getInt(context.getString(
@@ -151,6 +152,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
int powerVal = (((msg[INDEX_MESSAGE_POWER] & 0xFF) << 8) |
(msg[INDEX_MESSAGE_POWER+1] & 0xFF));
@SuppressWarnings("unused")
int speedVal = (((msg[INDEX_MESSAGE_SPEED] & 0xFF) << 8) |
(msg[INDEX_MESSAGE_SPEED+1] & 0xFF));
int cadenceVal = (msg[INDEX_MESSAGE_CADENCE] & 0xFF);
@@ -162,12 +164,12 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
.setValue(powerVal)
.setState(Sensor.SensorState.SENDING);
// Although speed is available from the SRM Bridge, MyTracks doesn't
// use the value, and computes speed from the GPS location data.
// Sensor.SensorData.Builder speed =
// Sensor.SensorData.newBuilder()
// .setValue(speedVal)
// .setState(Sensor.SensorState.SENDING);
/*
* Although speed is available from the SRM Bridge, MyTracks doesn't use the value, and
* computes speed from the GPS location data.
*/
// Sensor.SensorData.Builder speed = Sensor.SensorData.newBuilder().setValue(speedVal).setState(
// Sensor.SensorState.SENDING);
Sensor.SensorData.Builder cadence =
Sensor.SensorData.newBuilder()
@@ -197,7 +199,7 @@ public class AntSrmBridgeSensorManager extends AntSensorManager {
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt(context.getString(R.string.ant_srm_bridge_sensor_id_key), deviceNumber);
editor.commit();
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
private void handleMessageResponse(byte[] rawMessage) {
@@ -150,66 +150,81 @@ public class StatusAnnouncerTask implements PeriodicTask {
*/
// @VisibleForTesting
protected String getAnnouncement(TripStatistics stats) {
SharedPreferences preferences =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
boolean metricUnits = true;
boolean reportSpeed = true;
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
metricUnits =
preferences.getBoolean(context.getString(R.string.metric_units_key),
true);
reportSpeed =
preferences.getBoolean(context.getString(R.string.report_speed_key),
true);
metricUnits = preferences.getBoolean(context.getString(R.string.metric_units_key), true);
reportSpeed = preferences.getBoolean(context.getString(R.string.report_speed_key), true);
}
double d = stats.getTotalDistance() / 1000;
double s = stats.getAverageMovingSpeed() * 3.6;
double d = stats.getTotalDistance() / 1000; // d is in kilometers
double s = stats.getAverageMovingSpeed() * 3.6; // s is in kilometers per hour
if (d == 0) {
return context.getString(R.string.voice_no_distance);
return context.getString(R.string.voice_total_distance_zero);
}
int speedLabel;
if (metricUnits) {
if (reportSpeed) {
speedLabel = R.string.voice_kilometer_per_hour;
} else {
speedLabel = R.string.voice_per_kilometer;
}
} else {
s *= UnitConversions.KMH_TO_MPH;
if (!metricUnits) {
d *= UnitConversions.KM_TO_MI;
if (reportSpeed) {
speedLabel = R.string.voice_mile_per_hour;
} else {
speedLabel = R.string.voice_per_mile;
}
s *= UnitConversions.KMH_TO_MPH;
}
String speed = null;
if ((s == 0) || Double.isNaN(s)) {
speed = context.getString(R.string.value_unknown);
if (!reportSpeed) {
s = 3600000.0 / s; // converts from speed to pace
}
// Makes sure s is not NaN.
if (Double.isNaN(s)) {
s = 0;
}
String speed;
if (reportSpeed) {
int speedId = metricUnits ? R.plurals.voiceSpeedKilometersPerHour
: R.plurals.voiceSpeedMilesPerHour;
speed = context.getResources().getQuantityString(speedId, getQuantityCount(s), s);
} else {
if (reportSpeed) {
speed = String.format("%.1f", s);
} else {
double pace = 3600000.0 / s;
Log.w(Constants.TAG,
"Converted speed: " + s + " to pace: " + pace);
speed = getAnnounceTime((long) pace);
}
int paceId = metricUnits ? R.string.voice_pace_per_kilometer : R.string.voice_pace_per_mile;
speed = String.format(context.getString(paceId), getAnnounceTime((long) s));
}
return context.getString(R.string.voice_template,
d,
context.getString(metricUnits
? R.string.voice_kilometers
: R.string.voice_miles),
getAnnounceTime(stats.getMovingTime()),
speed,
context.getString(speedLabel));
}
int totalDistanceId = metricUnits ? R.plurals.voiceTotalDistanceKilometers
: R.plurals.voiceTotalDistanceMiles;
String totalDistance = context.getResources().getQuantityString(
totalDistanceId, getQuantityCount(d), d);
return context.getString(
R.string.voice_template, totalDistance, getAnnounceTime(stats.getMovingTime()), speed);
}
/**
* Gets the plural count to be used by getQuantityString. getQuantityString
* only supports integer quantities, not a double quantity like "2.2".
* <p>
* As a temporary workaround, we convert a double quantity to an integer
* quantity. If the double quantity is exactly 0, 1, or 2, then we can return
* these integer quantities. Otherwise, we cast the double quantity to an
* integer quantity. However, we need to make sure that if the casted value is
* 0, 1, or 2, we don't return those, instead, return the next biggest integer
* 3.
*
* @param d the double value
*/
private int getQuantityCount(double d) {
if (d == 0) {
return 0;
} else if (d == 1) {
return 1;
} else if (d == 2) {
return 2;
} else {
int count = (int) d;
return count < 3 ? 3 : count;
}
}
@Override
public void start() {
Log.i(Constants.TAG, "Starting TTS");
@@ -331,30 +346,22 @@ public class StatusAnnouncerTask implements PeriodicTask {
@VisibleForTesting
String getAnnounceTime(long time) {
int[] parts = StringUtils.getTimeParts(time);
String secLabel =
context.getString(parts[0] == 1 ? R.string.voice_second : R.string.voice_seconds);
String minLabel =
context.getString(parts[1] == 1 ? R.string.voice_minute : R.string.voice_minutes);
String hourLabel =
context.getString(parts[2] == 1 ? R.string.voice_hour : R.string.voice_hours);
String seconds = context.getResources().getQuantityString(
R.plurals.voiceSeconds, parts[0], parts[0]);
String minutes = context.getResources().getQuantityString(
R.plurals.voiceMinutes, parts[1], parts[1]);
String hours = context.getResources().getQuantityString(
R.plurals.voiceHours, parts[2], parts[2]);
StringBuilder sb = new StringBuilder();
if (parts[2] != 0) {
sb.append(parts[2]);
sb.append(hours);
sb.append(" ");
sb.append(hourLabel);
sb.append(" ");
sb.append(parts[1]);
sb.append(" ");
sb.append(minLabel);
sb.append(minutes);
} else {
sb.append(parts[1]);
sb.append(minutes);
sb.append(" ");
sb.append(minLabel);
sb.append(" ");
sb.append(parts[0]);
sb.append(" ");
sb.append(secLabel);
sb.append(seconds);
}
return sb.toString();
}
@@ -33,8 +33,6 @@ import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* API level 3 specific implementation of the {@link ApiLevelAdapter}.
@@ -112,11 +110,6 @@ public class ApiLevel3Adapter implements ApiLevelAdapter {
return output;
}
@Override
public DecimalFormatSymbols getDecimalFormatSymbols(Locale locale) {
return new DecimalFormatSymbols(locale);
}
@Override
public HttpTransport getHttpTransport() {
return new ApacheHttpTransport();
@@ -8,9 +8,7 @@ import android.content.SharedPreferences.Editor;
import android.os.StrictMode;
import android.util.Log;
import java.text.DecimalFormatSymbols;
import java.util.Arrays;
import java.util.Locale;
/**
* API level 9 specific implementation of the {@link ApiLevelAdapter}.
@@ -43,12 +41,7 @@ public class ApiLevel9Adapter extends ApiLevel8Adapter {
public byte[] copyByteArray(byte[] input, int start, int end) {
return Arrays.copyOfRange(input, start, end);
}
@Override
public DecimalFormatSymbols getDecimalFormatSymbols(Locale locale) {
return DecimalFormatSymbols.getInstance(locale);
}
@Override
public HttpTransport getHttpTransport() {
return new NetHttpTransport();
@@ -25,9 +25,6 @@ import android.app.Service;
import android.content.Context;
import android.content.SharedPreferences;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* A set of methods that may be implemented differently depending on the Android API level.
*
@@ -107,16 +104,6 @@ public interface ApiLevelAdapter {
byte[] copyByteArray(byte[] input, int start, int end);
/**
* Gets an instance of {@link DecimalFormatSymbols} for a locale.
*
* Due to changes in API level 9.
*
* @param locale the locale
* @return a new instance of {@link DecimalFormatSymbols}
*/
DecimalFormatSymbols getDecimalFormatSymbols(Locale locale);
/**
* Gets a {@link HttpTransport}.
*
@@ -49,8 +49,8 @@ public class ChartURLGenerator {
*/
public static String getChartUrl(Vector<Double> distances,
Vector<Double> elevations, Track track, Context context) {
SharedPreferences preferences =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
boolean metricUnits = true;
if (preferences != null) {
metricUnits = preferences.getBoolean(
@@ -0,0 +1,44 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
/**
* Utilities for the EULA preference value.
*/
public class EulaUtil {
private static final String EULA_PREFERENCE_FILE = "eula";
private static final String EULA_PREFERENCE_KEY = "eula.accepted";
private EulaUtil() {}
public static boolean getEulaValue(Context context) {
SharedPreferences preferences = context.getSharedPreferences(
EULA_PREFERENCE_FILE, Context.MODE_PRIVATE);
return preferences.getBoolean(EULA_PREFERENCE_KEY, false);
}
public static void setEulaValue(Context context) {
SharedPreferences preferences = context.getSharedPreferences(
EULA_PREFERENCE_FILE, Context.MODE_PRIVATE);
Editor editor = preferences.edit();
editor.putBoolean(EULA_PREFERENCE_KEY, true);
ApiFeatures.getInstance().getApiAdapter().applyPreferenceChanges(editor);
}
}
@@ -20,6 +20,8 @@ import com.google.android.apps.mytracks.Constants;
import android.os.Environment;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.regex.Pattern;
/**
@@ -39,6 +41,16 @@ public class FileUtils {
private static final Pattern PROHIBITED_CHAR_PATTERN =
Pattern.compile("[^ A-Za-z0-9_.()-]+");
/**
* Timestamp format in UTC time zone.
*/
public static final SimpleDateFormat FILE_TIMESTAMP_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static {
FILE_TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
/**
* Builds a path inside the My Tracks directory in the SD card.
*
@@ -25,7 +25,7 @@ import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.content.SharedPreferences;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -66,7 +66,12 @@ public class StringUtils implements DescriptionGenerator {
return formatTimeInternal(time, true);
}
private static final DecimalFormat SINGLE_DECIMAL_PLACE_FORMAT = new DecimalFormat("#.#");
private static final NumberFormat SINGLE_DECIMAL_PLACE_FORMAT = NumberFormat.getNumberInstance();
static {
SINGLE_DECIMAL_PLACE_FORMAT.setMaximumFractionDigits(1);
SINGLE_DECIMAL_PLACE_FORMAT.setMinimumFractionDigits(1);
}
/**
* Formats a double precision number as decimal number with a single decimal
@@ -231,8 +236,8 @@ public class StringUtils implements DescriptionGenerator {
public String generateTrackDescription(Track track, Vector<Double> distances,
Vector<Double> elevations) {
boolean displaySpeed = true;
SharedPreferences preferences =
context.getSharedPreferences(Constants.SETTINGS_NAME, 0);
SharedPreferences preferences = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (preferences != null) {
displaySpeed =
preferences.getBoolean(context.getString(R.string.report_speed_key), true);
@@ -94,7 +94,7 @@ public class TrackWidgetProvider
providerUtils = MyTracksProviderUtils.Factory.get(context);
unknown = context.getString(R.string.value_unknown);
sharedPreferences = context.getSharedPreferences(SETTINGS_NAME, 0);
sharedPreferences = context.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(sharedPreferences, null);