Merge heads

This commit is contained in:
youtaol
2012-08-31 09:57:35 +08:00
30 changed files with 430 additions and 313 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ limitations under the License.
<uses-sdk <uses-sdk
android:minSdkVersion="7" android:minSdkVersion="7"
android:targetSdkVersion="15" /> android:targetSdkVersion="16" />
<!-- Required features --> <!-- Required features -->
<uses-feature <uses-feature
android:name="android.hardware.location" android:name="android.hardware.location"
+1 -1
View File
@@ -11,5 +11,5 @@
split.density=false split.density=false
proguard.config=proguard.cfg proguard.config=proguard.cfg
# Project target. # Project target.
target=Google Inc.:Google APIs:15 target=Google Inc.:Google APIs:16
android.library.reference.1=../MyTracksLib android.library.reference.1=../MyTracksLib
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

+51 -23
View File
@@ -14,34 +14,62 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<merge xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_width="fill_parent" > android:layout_width="fill_parent"
android:orientation="vertical" >
<ListView <ListView
android:id="@+id/track_list" android:id="@+id/track_list"
android:layout_height="fill_parent" android:layout_height="0dp"
android:layout_weight="1.0"
android:layout_width="fill_parent" /> android:layout_width="fill_parent" />
<LinearLayout <TextView
android:gravity="center" android:id="@+id/track_list_empty_view"
android:id="@+id/track_list_empty" android:layout_height="0dp"
android:layout_height="fill_parent" android:layout_weight="1.0"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:orientation="vertical" > android:text="@string/track_list_empty_message"
<TextView android:visibility="gone"
android:id="@+id/track_list_empty_message" style="@style/ListEmptyTextView" >
android:text="@string/track_list_empty_message" </TextView>
android:visibility="gone" <LinearLayout
style="@style/ListEmptyTextView" > android:layout_gravity="center"
</TextView> android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="horizontal" >
<ImageButton <ImageButton
android:background="@color/transparent" android:background="@android:color/transparent"
android:contentDescription="@string/menu_record_track" android:id="@+id/track_list_record_track_button"
android:id="@+id/track_list_record_button" android:layout_height="100dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:padding="16dp" android:scaleType="centerInside" />
android:src="@drawable/menu_record_track" <RelativeLayout
android:visibility="gone" android:layout_height="100dp"
style="@android:style/Widget.DeviceDefault.ImageButton" /> android:layout_marginLeft="-32dp"
android:layout_width="wrap_content" >
<TextView
android:id="@+id/track_list_record_time"
android:layout_centerInParent="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingLeft="24dp"
android:paddingRight="8dp"
android:textColor="@android:color/white"
style="@style/TextSmall" />
<TextView
android:id="@+id/track_list_record_state"
android:layout_above="@id/track_list_record_time"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingBottom="12dp"
style="@style/TextSmall" />
</RelativeLayout>
<ImageButton
android:background="@android:color/transparent"
android:contentDescription="@string/menu_stop_recording"
android:id="@+id/track_list_stop_recording_button"
android:layout_height="100dp"
android:layout_width="wrap_content"
android:scaleType="centerInside" />
</LinearLayout> </LinearLayout>
</merge> </LinearLayout>
-15
View File
@@ -15,21 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:icon="@drawable/menu_record_track"
android:id="@+id/track_list_record_track"
android:showAsAction="ifRoom"
android:title="@string/menu_record_track"/>
<item
android:icon="@drawable/menu_pause_track"
android:id="@+id/track_list_pause_track"
android:showAsAction="ifRoom"
android:title="@string/menu_pause_track"/>
<item
android:icon="@drawable/menu_stop_recording"
android:id="@+id/track_list_stop_recording"
android:showAsAction="ifRoom"
android:title="@string/menu_stop_recording"/>
<item <item
android:actionViewClass="android.widget.SearchView" android:actionViewClass="android.widget.SearchView"
android:icon="@drawable/menu_search" android:icon="@drawable/menu_search"
-1
View File
@@ -19,7 +19,6 @@ limitations under the License.
<color name="blue">#FF0000FF</color> <color name="blue">#FF0000FF</color>
<color name="gray">#FFAAAAAA</color> <color name="gray">#FFAAAAAA</color>
<color name="red">#FFFF0000</color> <color name="red">#FFFF0000</color>
<color name="transparent">#00000000</color>
<!-- holo_orange_dark --> <!-- holo_orange_dark -->
<color name="warning_background">#FFFF8800</color> <color name="warning_background">#FFFF8800</color>
+8 -12
View File
@@ -648,10 +648,18 @@ limitations under the License.
translation_description="The text on a button to say ok."> translation_description="The text on a button to say ok.">
OK OK
</string> </string>
<string name="generic_paused"
translation_description="Text indicating a track is paused.">
Paused
</string>
<string name="generic_progress_title" <string name="generic_progress_title"
translation_description="The title on a progress dialog asking the user to wait."> translation_description="The title on a progress dialog asking the user to wait.">
Please wait... Please wait...
</string> </string>
<string name="generic_recording"
translation_description="Text indicating a track is recording.">
Recording...
</string>
<string name="generic_save" <string name="generic_save"
translation_description="The text on a button to say save."> translation_description="The text on a button to say save.">
Save Save
@@ -882,10 +890,6 @@ limitations under the License.
translation_description="The accessibility description for the 'My Location' icon."> translation_description="The accessibility description for the 'My Location' icon.">
My Location My Location
</string> </string>
<string name="icon_recording"
translation_description="The accessibility description for the 'Recording' icon.">
Recording
</string>
<string name="icon_track" <string name="icon_track"
translation_description="The accessibility description for the 'Track' icon."> translation_description="The accessibility description for the 'Track' icon.">
Track Track
@@ -2231,14 +2235,6 @@ limitations under the License.
translation_description="In the track detail page, the title of the tab showing the stats."> translation_description="In the track detail page, the title of the tab showing the stats.">
Stats Stats
</string> </string>
<string name="track_detail_title_paused"
translation_description="In the track detail page, the title when paused.">
Paused
</string>
<string name="track_detail_title_recording"
translation_description="In the track detail page, the title when recording.">
Recording...
</string>
<string name="track_edit_activity_type" <string name="track_edit_activity_type"
translation_description="In the page to edit a track, the label for the text field to edit the translation_description="In the page to edit a track, the label for the text field to edit the
activity type, including an example."> activity type, including an example.">
@@ -84,9 +84,10 @@ public class MarkerListActivity extends AbstractMyTracksActivity {
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
// Note that key can be null // Note that the key can be null
if (PreferencesUtils.getKey(MarkerListActivity.this, R.string.recording_track_id_key) if (PreferencesUtils.getKey(MarkerListActivity.this, R.string.recording_track_id_key)
.equals(key)) { .equals(key) || PreferencesUtils.getKey(
MarkerListActivity.this, R.string.recording_track_paused_key).equals(key)) {
updateMenu(); updateMenu();
} }
} }
@@ -187,8 +188,11 @@ public class MarkerListActivity extends AbstractMyTracksActivity {
private void updateMenu() { private void updateMenu() {
if (insertMarkerMenuItem != null) { if (insertMarkerMenuItem != null) {
insertMarkerMenuItem.setVisible( boolean isRecording = trackId
trackId == PreferencesUtils.getLong(this, R.string.recording_track_id_key)); == PreferencesUtils.getLong(this, R.string.recording_track_id_key);
boolean isPaused = PreferencesUtils.getBoolean(this, R.string.recording_track_paused_key,
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
insertMarkerMenuItem.setVisible(isRecording && !isPaused);
} }
} }
@@ -91,10 +91,18 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_id_key) if (key == null || key.equals(
.equals(key)) { PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_id_key))) {
recordingTrackId = PreferencesUtils.getLong( recordingTrackId = PreferencesUtils.getLong(
SearchListActivity.this, R.string.recording_track_id_key); SearchListActivity.this, R.string.recording_track_id_key);
}
if (key == null || key.equals(PreferencesUtils.getKey(
SearchListActivity.this, R.string.recording_track_paused_key))) {
recordingTrackPaused = PreferencesUtils.getBoolean(SearchListActivity.this,
R.string.recording_track_paused_key,
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
}
if (key != null) {
arrayAdapter.notifyDataSetChanged(); arrayAdapter.notifyDataSetChanged();
} }
} }
@@ -115,6 +123,7 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
private SearchRecentSuggestions searchRecentSuggestions; private SearchRecentSuggestions searchRecentSuggestions;
private MyTracksLocationManager myTracksLocationManager; private MyTracksLocationManager myTracksLocationManager;
private long recordingTrackId; private long recordingTrackId;
private boolean recordingTrackPaused;
private boolean metricUnits; private boolean metricUnits;
private ArrayAdapter<Map<String, Object>> arrayAdapter; private ArrayAdapter<Map<String, Object>> arrayAdapter;
@@ -133,9 +142,10 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
searchEngine = new SearchEngine(myTracksProviderUtils); searchEngine = new SearchEngine(myTracksProviderUtils);
searchRecentSuggestions = SearchEngineProvider.newHelper(this); searchRecentSuggestions = SearchEngineProvider.newHelper(this);
myTracksLocationManager = new MyTracksLocationManager(this); myTracksLocationManager = new MyTracksLocationManager(this);
getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE) SharedPreferences sharedPreferences = getSharedPreferences(
.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
recordingTrackId = PreferencesUtils.getLong(this, R.string.recording_track_id_key); sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
listView = (ListView) findViewById(R.id.search_list); listView = (ListView) findViewById(R.id.search_list);
listView.setEmptyView(findViewById(R.id.search_list_empty)); listView.setEmptyView(findViewById(R.id.search_list_empty));
@@ -425,10 +435,18 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
boolean isRecording = track.getId() == recordingTrackId; boolean isRecording = track.getId() == recordingTrackId;
TripStatistics tripStatitics = track.getTripStatistics(); TripStatistics tripStatitics = track.getTripStatistics();
resultMap.put(NAME_FIELD, track.getName()); resultMap.put(NAME_FIELD, track.getName());
resultMap.put(ICON_FIELD, isRecording int iconId;
? R.drawable.menu_record_track : TrackIconUtils.getIconDrawable(track.getIcon())); int iconContentDescriptionId;
resultMap.put(ICON_CONTENT_DESCRIPTION_FIELD, getString(isRecording ? R.string.icon_recording if (isRecording) {
: R.string.icon_track)); iconId = recordingTrackPaused ? R.drawable.menu_pause_track : R.drawable.menu_record_track;
iconContentDescriptionId = recordingTrackPaused ? R.string.menu_pause_track
: R.drawable.menu_record_track;
} else {
iconId = TrackIconUtils.getIconDrawable(track.getIcon());
iconContentDescriptionId = R.string.icon_track;
}
resultMap.put(ICON_FIELD, iconId);
resultMap.put(ICON_CONTENT_DESCRIPTION_FIELD, getString(iconContentDescriptionId));
resultMap.put(CATEGORY_FIELD, track.getCategory()); resultMap.put(CATEGORY_FIELD, track.getCategory());
resultMap.put(TOTAL_TIME_FIELD, isRecording ? null : StringUtils.formatElapsedTime( resultMap.put(TOTAL_TIME_FIELD, isRecording ? null : StringUtils.formatElapsedTime(
tripStatitics.getTotalTime())); tripStatitics.getTotalTime()));
@@ -89,8 +89,6 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
private MenuItem insertMarkerMenuItem; private MenuItem insertMarkerMenuItem;
private MenuItem playMenuItem; private MenuItem playMenuItem;
private MenuItem shareMenuItem; private MenuItem shareMenuItem;
private MenuItem voiceFrequencyMenuItem;
private MenuItem splitFrequencyMenuItem;
private MenuItem sendGoogleMenuItem; private MenuItem sendGoogleMenuItem;
private MenuItem saveMenuItem; private MenuItem saveMenuItem;
@@ -110,7 +108,8 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
recordingTrackId = PreferencesUtils.getLong( recordingTrackId = PreferencesUtils.getLong(
TrackDetailActivity.this, R.string.recording_track_id_key); TrackDetailActivity.this, R.string.recording_track_id_key);
if (key != null) { if (key != null) {
updateMenuItems(trackId == recordingTrackId); updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
return;
} }
} }
if (key == null || key.equals(PreferencesUtils.getKey( if (key == null || key.equals(PreferencesUtils.getKey(
@@ -197,7 +196,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
super.onResume(); super.onResume();
trackDataHub.loadTrack(trackId); trackDataHub.loadTrack(trackId);
TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection); TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection);
updateMenuItems(trackId == recordingTrackId); updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
} }
@Override @Override
@@ -237,12 +236,10 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker); insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
playMenuItem = menu.findItem(R.id.track_detail_play); playMenuItem = menu.findItem(R.id.track_detail_play);
shareMenuItem = menu.findItem(R.id.track_detail_share); shareMenuItem = menu.findItem(R.id.track_detail_share);
voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency);
splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency);
sendGoogleMenuItem = menu.findItem(R.id.track_detail_send_google); sendGoogleMenuItem = menu.findItem(R.id.track_detail_send_google);
saveMenuItem = menu.findItem(R.id.track_detail_save); saveMenuItem = menu.findItem(R.id.track_detail_save);
updateMenuItems(trackId == recordingTrackId); updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
return true; return true;
} }
@@ -267,18 +264,15 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
Intent intent; Intent intent;
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.track_detail_record_track: case R.id.track_detail_record_track:
recordingTrackPaused = false; updateMenuItems(true, false);
updateMenuItems(true);
TrackRecordingServiceConnectionUtils.resumeTrack(trackRecordingServiceConnection); TrackRecordingServiceConnectionUtils.resumeTrack(trackRecordingServiceConnection);
return true; return true;
case R.id.track_detail_pause_track: case R.id.track_detail_pause_track:
recordingTrackPaused = true; updateMenuItems(true, true);
updateMenuItems(true);
TrackRecordingServiceConnectionUtils.pauseTrack(trackRecordingServiceConnection); TrackRecordingServiceConnectionUtils.pauseTrack(trackRecordingServiceConnection);
return true; return true;
case R.id.track_detail_stop_recording: case R.id.track_detail_stop_recording:
recordingTrackPaused = true; updateMenuItems(false, true);
updateMenuItems(false);
TrackRecordingServiceConnectionUtils.stopRecording( TrackRecordingServiceConnectionUtils.stopRecording(
this, trackRecordingServiceConnection, true); this, trackRecordingServiceConnection, true);
return true; return true;
@@ -369,7 +363,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
@Override @Override
public boolean onTrackballEvent(MotionEvent event) { public boolean onTrackballEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (trackId == recordingTrackId) { if (trackId == recordingTrackId && !recordingTrackPaused) {
TrackRecordingServiceConnectionUtils.addMarker( TrackRecordingServiceConnectionUtils.addMarker(
this, trackRecordingServiceConnection, WaypointCreationRequest.DEFAULT_WAYPOINT); this, trackRecordingServiceConnection, WaypointCreationRequest.DEFAULT_WAYPOINT);
return true; return true;
@@ -442,18 +436,18 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
* *
* @param isRecording true if recording * @param isRecording true if recording
*/ */
private void updateMenuItems(boolean isRecording) { private void updateMenuItems(boolean isRecording, boolean isPaused) {
if (recordTrackMenuItem != null) { if (recordTrackMenuItem != null) {
recordTrackMenuItem.setVisible(isRecording && recordingTrackPaused); recordTrackMenuItem.setVisible(isRecording && isPaused);
} }
if (pauseTrackMenuItem != null) { if (pauseTrackMenuItem != null) {
pauseTrackMenuItem.setVisible(isRecording && !recordingTrackPaused); pauseTrackMenuItem.setVisible(isRecording && !isPaused);
} }
if (stopRecordingMenuItem != null) { if (stopRecordingMenuItem != null) {
stopRecordingMenuItem.setVisible(isRecording); stopRecordingMenuItem.setVisible(isRecording);
} }
if (insertMarkerMenuItem != null) { if (insertMarkerMenuItem != null) {
insertMarkerMenuItem.setVisible(isRecording); insertMarkerMenuItem.setVisible(isRecording && !isPaused);
} }
if (playMenuItem != null) { if (playMenuItem != null) {
playMenuItem.setVisible(!isRecording); playMenuItem.setVisible(!isRecording);
@@ -461,12 +455,6 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
if (shareMenuItem != null) { if (shareMenuItem != null) {
shareMenuItem.setVisible(!isRecording); shareMenuItem.setVisible(!isRecording);
} }
if (voiceFrequencyMenuItem != null) {
voiceFrequencyMenuItem.setVisible(isRecording);
}
if (splitFrequencyMenuItem != null) {
splitFrequencyMenuItem.setVisible(isRecording);
}
if (sendGoogleMenuItem != null) { if (sendGoogleMenuItem != null) {
sendGoogleMenuItem.setVisible(!isRecording); sendGoogleMenuItem.setVisible(!isRecording);
} }
@@ -475,8 +463,8 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
} }
String title; String title;
if (isRecording) { if (isRecording) {
title = getString(recordingTrackPaused ? R.string.track_detail_title_paused title = getString(
: R.string.track_detail_title_recording); isPaused ? R.string.generic_paused : R.string.generic_recording);
} else { } else {
Track track = MyTracksProviderUtils.Factory.get(this).getTrack(trackId); Track track = MyTracksProviderUtils.Factory.get(this).getTrack(trackId);
title = track != null ? track.getName() : getString(R.string.my_tracks_app_name); title = track != null ? track.getName() : getString(R.string.my_tracks_app_name);
@@ -16,6 +16,8 @@
package com.google.android.apps.mytracks; package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.Track;
import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.apps.mytracks.fragments.CheckUnitsDialogFragment; import com.google.android.apps.mytracks.fragments.CheckUnitsDialogFragment;
import com.google.android.apps.mytracks.fragments.DeleteAllTrackDialogFragment; import com.google.android.apps.mytracks.fragments.DeleteAllTrackDialogFragment;
@@ -45,6 +47,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor; import android.database.Cursor;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable; import android.os.Parcelable;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
@@ -65,30 +68,28 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
/** /**
* An activity displaying a list of tracks. * An activity displaying a list of tracks.
* *
* @author Leif Hendrik Wilden * @author Leif Hendrik Wilden
*/ */
public class TrackListActivity extends FragmentActivity implements DeleteOneTrackCaller { public class TrackListActivity extends FragmentActivity implements DeleteOneTrackCaller {
private static final String TAG = TrackListActivity.class.getSimpleName(); private static final String TAG = TrackListActivity.class.getSimpleName();
private static final String[] PROJECTION = new String[] { // One second in milliseconds
TracksColumns._ID, private static final int ONE_SECOND = 1000;
TracksColumns.NAME,
TracksColumns.DESCRIPTION, private static final String[] PROJECTION = new String[] { TracksColumns._ID, TracksColumns.NAME,
TracksColumns.CATEGORY, TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
TracksColumns.STARTTIME, TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON };
TracksColumns.TOTALDISTANCE,
TracksColumns.TOTALTIME,
TracksColumns.ICON};
// Callback when the trackRecordingServiceConnection binding changes. // Callback when the trackRecordingServiceConnection binding changes.
private final Runnable bindChangedCallback = new Runnable() { private final Runnable bindChangedCallback = new Runnable() {
@Override @Override
public void run() { public void run() {
if (!startNewRecording) { if (!startNewRecording) {
return; return;
@@ -123,12 +124,14 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
boolean updateList = false;
if (key == null || key.equals( if (key == null || key.equals(
PreferencesUtils.getKey(TrackListActivity.this, R.string.metric_units_key))) { PreferencesUtils.getKey(TrackListActivity.this, R.string.metric_units_key))) {
metricUnits = PreferencesUtils.getBoolean(TrackListActivity.this, metricUnits = PreferencesUtils.getBoolean(TrackListActivity.this,
R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT); R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
updateList = key != null; if (key != null) {
resourceCursorAdapter.notifyDataSetChanged();
return;
}
} }
if (key == null || key.equals( if (key == null || key.equals(
PreferencesUtils.getKey(TrackListActivity.this, R.string.recording_track_id_key))) { PreferencesUtils.getKey(TrackListActivity.this, R.string.recording_track_id_key))) {
@@ -140,7 +143,9 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
trackRecordingServiceConnection.startAndBind(); trackRecordingServiceConnection.startAndBind();
} }
updateMenuItems(isRecording); updateMenuItems(isRecording);
updateList = true; resourceCursorAdapter.notifyDataSetChanged();
startUpdateRecordTime(isRecording);
return;
} }
} }
if (key == null || key.equals(PreferencesUtils.getKey( if (key == null || key.equals(PreferencesUtils.getKey(
@@ -148,40 +153,63 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
recordingTrackPaused = PreferencesUtils.getBoolean(TrackListActivity.this, recordingTrackPaused = PreferencesUtils.getBoolean(TrackListActivity.this,
R.string.recording_track_paused_key, R.string.recording_track_paused_key,
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT); PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
updateList = updateList || key != null; if (key != null) {
} updateButtons(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
if (updateList) { recordingTrackPaused);
resourceCursorAdapter.notifyDataSetChanged(); resourceCursorAdapter.notifyDataSetChanged();
return;
}
} }
} }
}; };
// Callback when an item is selected in the contextual action mode // Callback when an item is selected in the contextual action mode
private ContextualActionModeCallback contextualActionModeCallback = private ContextualActionModeCallback
new ContextualActionModeCallback() { contextualActionModeCallback = new ContextualActionModeCallback() {
@Override @Override
public boolean onClick(int itemId, int position, long id) { public boolean onClick(int itemId, int position, long id) {
return handleContextItem(itemId, id); return handleContextItem(itemId, id);
}
};
// A runnable to update the record time.
private final Runnable updateRecordTimeRunnable = new Runnable() {
public void run() {
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT
&& !recordingTrackPaused) {
recordTimeTextView.setText(StringUtils.formatElapsedTimeWithHour(
System.currentTimeMillis() - lastResumeTime + recordTime));
handler.postDelayed(this, ONE_SECOND);
}
} }
}; };
// The following are set in the constructor
private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackRecordingServiceConnection trackRecordingServiceConnection;
private boolean metricUnits; private Handler handler;
private long recordingTrackId; private TextView recordStateTextView;
private boolean recordingTrackPaused; private TextView recordTimeTextView;
private ImageButton recordTrackImageButton;
private ImageButton stopRecordingImageButton;
private ListView listView; private ListView listView;
private ResourceCursorAdapter resourceCursorAdapter; private ResourceCursorAdapter resourceCursorAdapter;
// True to start a new recording. // Preferences
private boolean startNewRecording = false; private boolean metricUnits;
private long recordingTrackId;
private boolean recordingTrackPaused;
private MenuItem recordTrackMenuItem; // Menu items
private MenuItem pauseTrackMenuItem;
private MenuItem stopRecordingMenuItem;
private MenuItem searchMenuItem; private MenuItem searchMenuItem;
private MenuItem importMenuItem; private MenuItem importMenuItem;
private MenuItem saveAllMenuItem; private MenuItem saveAllMenuItem;
private MenuItem deleteAllMenuItem; private MenuItem deleteAllMenuItem;
private boolean startNewRecording = false; // true to start a new recording
// For recordTimeTextView
private long recordTime = 0;
private long lastResumeTime = 0;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -197,19 +225,58 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
Constants.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null); sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
ImageButton recordImageButton = (ImageButton) findViewById(R.id.track_list_record_button);
recordImageButton.setOnClickListener(new View.OnClickListener() { handler = new Handler();
@Override recordStateTextView = (TextView) findViewById(R.id.track_list_record_state);
recordTimeTextView = (TextView) findViewById(R.id.track_list_record_time);
recordTrackImageButton = (ImageButton) findViewById(R.id.track_list_record_track_button);
recordTrackImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { public void onClick(View v) {
updateMenuItems(true); if (!(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT)) {
startRecording(); // Not recording -> Recording
AnalyticsUtils.sendPageViews(TrackListActivity.this, "/action/record_track");
updateMenuItems(true);
updateButtons(true, false);
startRecording();
} else {
if (recordingTrackPaused) {
// Paused -> Resume
AnalyticsUtils.sendPageViews(TrackListActivity.this, "/action/resume_track");
updateMenuItems(true);
updateButtons(true, false);
TrackRecordingServiceConnectionUtils.resumeTrack(trackRecordingServiceConnection);
startUpdateRecordTime(true);
} else {
// Recording -> Paused
AnalyticsUtils.sendPageViews(TrackListActivity.this, "/action/pause_track");
updateMenuItems(true);
updateButtons(true, true);
TrackRecordingServiceConnectionUtils.pauseTrack(trackRecordingServiceConnection);
stopUpdateRecordTime(true);
}
}
} }
}); });
stopRecordingImageButton = (ImageButton) findViewById(R.id.track_list_stop_recording_button);
stopRecordingImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AnalyticsUtils.sendPageViews(TrackListActivity.this, "/action/stop_recording");
updateMenuItems(false);
updateButtons(false, true);
TrackRecordingServiceConnectionUtils.stopRecording(
TrackListActivity.this, trackRecordingServiceConnection, true);
stopUpdateRecordTime(false);
}
});
updateButtons(
recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, recordingTrackPaused);
listView = (ListView) findViewById(R.id.track_list); listView = (ListView) findViewById(R.id.track_list);
listView.setEmptyView(findViewById(R.id.track_list_empty)); listView.setEmptyView(findViewById(R.id.track_list_empty_view));
listView.setOnItemClickListener(new OnItemClickListener() { listView.setOnItemClickListener(new OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class) Intent intent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class)
.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, id); .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, id);
@@ -227,58 +294,50 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE); int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME); int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON); int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
boolean isRecording = cursor.getLong(idIndex) == recordingTrackId; boolean isRecording = cursor.getLong(idIndex) == recordingTrackId;
String name = cursor.getString(nameIndex); String name = cursor.getString(nameIndex);
int iconId; int iconId;
int iconContentDescriptionId;
if (isRecording) { if (isRecording) {
iconId = recordingTrackPaused ? R.drawable.menu_pause_track iconId = recordingTrackPaused ? R.drawable.menu_pause_track
: R.drawable.menu_record_track; : R.drawable.menu_record_track;
iconContentDescriptionId = recordingTrackPaused ? R.string.menu_pause_track
: R.string.menu_record_track;
} else { } else {
iconId = TrackIconUtils.getIconDrawable(cursor.getString(iconIndex)); iconId = TrackIconUtils.getIconDrawable(cursor.getString(iconIndex));
iconContentDescriptionId = R.string.icon_track;
} }
String iconContentDescription = getString(isRecording ? R.string.icon_recording String iconContentDescription = getString(iconContentDescriptionId);
: R.string.icon_track);
String category = cursor.getString(categoryIndex); String category = cursor.getString(categoryIndex);
String totalTime = isRecording String totalTime = isRecording ? null
? null : StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex)); : StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
String totalDistance = isRecording ? null : StringUtils.formatDistance( String totalDistance = isRecording ? null
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits); : StringUtils.formatDistance(
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
long startTime = cursor.getLong(startTimeIndex); long startTime = cursor.getLong(startTimeIndex);
String description = cursor.getString(descriptionIndex); String description = cursor.getString(descriptionIndex);
ListItemUtils.setListItem(TrackListActivity.this, ListItemUtils.setListItem(TrackListActivity.this, view, name, iconId,
view, iconContentDescription, category, totalTime, totalDistance, startTime, description);
name,
iconId,
iconContentDescription,
category,
totalTime,
totalDistance,
startTime,
description);
} }
}; };
listView.setAdapter(resourceCursorAdapter); listView.setAdapter(resourceCursorAdapter);
ApiAdapterFactory.getApiAdapter() ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback); .configureListViewContextualMenu(this, listView, contextualActionModeCallback);
getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() { getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() {
@Override @Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new CursorLoader(TrackListActivity.this, return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null,
TracksColumns.CONTENT_URI, null, TracksColumns._ID + " DESC");
PROJECTION,
null,
null,
TracksColumns._ID + " DESC");
} }
@Override @Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
resourceCursorAdapter.swapCursor(cursor); resourceCursorAdapter.swapCursor(cursor);
} }
@Override @Override
public void onLoaderReset(Loader<Cursor> loader) { public void onLoaderReset(Loader<Cursor> loader) {
resourceCursorAdapter.swapCursor(null); resourceCursorAdapter.swapCursor(null);
} }
@@ -287,50 +346,17 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
showStartupDialogs(); showStartupDialogs();
} }
/** @Override
* Shows start up dialogs. protected void onPause() {
*/ super.onPause();
public void showStartupDialogs() { stopUpdateRecordTime(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
if (!EulaUtils.getAcceptEula(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(EulaDialogFragment.EULA_DIALOG_TAG);
if (fragment == null) {
EulaDialogFragment.newInstance(false)
.show(getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG);
}
} else if (EulaUtils.getShowWelcome(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(WelcomeDialogFragment.WELCOME_DIALOG_TAG);
if (fragment == null) {
new WelcomeDialogFragment().show(
getSupportFragmentManager(), WelcomeDialogFragment.WELCOME_DIALOG_TAG);
}
} else if (EulaUtils.getShowCheckUnits(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG);
if (fragment == null) {
new CheckUnitsDialogFragment().show(
getSupportFragmentManager(), CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG);
}
} else {
enableEmptyView();
}
}
/**
* Enables the content of the empty view.
*/
private void enableEmptyView() {
View emptyMessage = findViewById(R.id.track_list_empty_message);
emptyMessage.setVisibility(View.VISIBLE);
View recordButton = findViewById(R.id.track_list_record_button);
recordButton.setVisibility(View.VISIBLE);
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection); TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection);
startUpdateRecordTime(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
} }
@Override @Override
@@ -351,10 +377,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
.setTitle(getString(R.string.menu_save_format, fileTypes[2])); .setTitle(getString(R.string.menu_save_format, fileTypes[2]));
menu.findItem(R.id.track_list_save_all_tcx) menu.findItem(R.id.track_list_save_all_tcx)
.setTitle(getString(R.string.menu_save_format, fileTypes[3])); .setTitle(getString(R.string.menu_save_format, fileTypes[3]));
recordTrackMenuItem = menu.findItem(R.id.track_list_record_track);
pauseTrackMenuItem = menu.findItem(R.id.track_list_pause_track);
stopRecordingMenuItem = menu.findItem(R.id.track_list_stop_recording);
searchMenuItem = menu.findItem(R.id.track_list_search); searchMenuItem = menu.findItem(R.id.track_list_search);
importMenuItem = menu.findItem(R.id.track_list_import); importMenuItem = menu.findItem(R.id.track_list_import);
saveAllMenuItem = menu.findItem(R.id.track_list_save_all); saveAllMenuItem = menu.findItem(R.id.track_list_save_all);
@@ -365,62 +388,10 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
return true; return true;
} }
/**
* Updates the menu items.
*
* @param isRecording true if recording
*
*/
private void updateMenuItems(boolean isRecording) {
boolean showPause = isRecording && !recordingTrackPaused;
if (recordTrackMenuItem != null) {
recordTrackMenuItem.setVisible(!showPause);
}
if (pauseTrackMenuItem != null) {
pauseTrackMenuItem.setVisible(showPause);
}
if (stopRecordingMenuItem != null) {
stopRecordingMenuItem.setVisible(isRecording);
}
if (importMenuItem != null) {
importMenuItem.setVisible(!isRecording);
}
if (saveAllMenuItem != null) {
saveAllMenuItem.setVisible(!isRecording);
}
if (deleteAllMenuItem != null) {
deleteAllMenuItem.setVisible(!isRecording);
}
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
Intent intent; Intent intent;
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.track_list_record_track:
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
AnalyticsUtils.sendPageViews(
this, isRecording ? "/action/resume_track" : "/action/record_track");
recordingTrackPaused = false;
updateMenuItems(true);
if (isRecording) {
TrackRecordingServiceConnectionUtils.resumeTrack(trackRecordingServiceConnection);
} else {
startRecording();
}
return true;
case R.id.track_list_pause_track:
AnalyticsUtils.sendPageViews(this, "/action/pause_track");
recordingTrackPaused = true;
updateMenuItems(true);
TrackRecordingServiceConnectionUtils.pauseTrack(trackRecordingServiceConnection);
return true;
case R.id.track_list_stop_recording:
AnalyticsUtils.sendPageViews(this, "/action/stop_recording");
recordingTrackPaused = false;
updateMenuItems(false);
TrackRecordingServiceConnectionUtils.stopRecording(this, trackRecordingServiceConnection, true);
return true;
case R.id.track_list_search: case R.id.track_list_search:
return ApiAdapterFactory.getApiAdapter().handleSearchMenuSelection(this); return ApiAdapterFactory.getApiAdapter().handleSearchMenuSelection(this);
case R.id.track_list_import: case R.id.track_list_import:
@@ -462,9 +433,156 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
} }
} }
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (handleContextItem(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).id)) {
return true;
}
return super.onContextItemSelected(item);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
if (ApiAdapterFactory.getApiAdapter().handleSearchKey(searchMenuItem)) {
return true;
}
}
return super.onKeyUp(keyCode, event);
}
@Override
public TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
return trackRecordingServiceConnection;
}
/**
* Shows start up dialogs.
*/
public void showStartupDialogs() {
if (!EulaUtils.getAcceptEula(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(EulaDialogFragment.EULA_DIALOG_TAG);
if (fragment == null) {
EulaDialogFragment.newInstance(false)
.show(getSupportFragmentManager(), EulaDialogFragment.EULA_DIALOG_TAG);
}
} else if (EulaUtils.getShowWelcome(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(WelcomeDialogFragment.WELCOME_DIALOG_TAG);
if (fragment == null) {
new WelcomeDialogFragment().show(
getSupportFragmentManager(), WelcomeDialogFragment.WELCOME_DIALOG_TAG);
}
} else if (EulaUtils.getShowCheckUnits(this)) {
Fragment fragment = getSupportFragmentManager()
.findFragmentByTag(CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG);
if (fragment == null) {
new CheckUnitsDialogFragment().show(
getSupportFragmentManager(), CheckUnitsDialogFragment.CHECK_UNITS_DIALOG_TAG);
}
} else {
/*
* Before the welcome sequence, the empty view is not visible so that it
* doesn't show through.
*/
findViewById(R.id.track_list_empty_view).setVisibility(View.VISIBLE);
}
}
/**
* Updates the menu items.
*
* @param isRecording true if recording
*/
private void updateMenuItems(boolean isRecording) {
if (importMenuItem != null) {
importMenuItem.setVisible(!isRecording);
}
if (saveAllMenuItem != null) {
saveAllMenuItem.setVisible(!isRecording);
}
if (deleteAllMenuItem != null) {
deleteAllMenuItem.setVisible(!isRecording);
}
}
private void updateButtons(boolean isRecording, boolean isPaused) {
recordTrackImageButton.setImageResource(
isRecording && !isPaused ? R.drawable.btn_pause : R.drawable.btn_record);
recordTrackImageButton.setContentDescription(getString(
isRecording && !isPaused ? R.string.menu_pause_track : R.string.menu_record_track));
stopRecordingImageButton.setImageResource(
isRecording ? R.drawable.btn_stop_1 : R.drawable.btn_stop_0);
stopRecordingImageButton.setEnabled(isRecording);
if (isRecording) {
recordStateTextView.setTextColor(
getResources().getColor(isPaused ? android.R.color.white : R.color.red));
recordStateTextView.setText(isPaused ? R.string.generic_paused : R.string.generic_recording);
recordStateTextView.setVisibility(View.VISIBLE);
} else {
recordStateTextView.setVisibility(View.INVISIBLE);
}
}
private void startUpdateRecordTime(boolean isRecording) {
stopUpdateRecordTime(false);
if (isRecording) {
recordTime = getRecordTime();
lastResumeTime = System.currentTimeMillis();
recordTimeTextView.setEnabled(true);
recordTimeTextView.setText(StringUtils.formatElapsedTimeWithHour(recordTime));
handler.postDelayed(updateRecordTimeRunnable, ONE_SECOND);
}
}
private void stopUpdateRecordTime(boolean isRecording) {
handler.removeCallbacks(updateRecordTimeRunnable);
if (isRecording) {
recordTime = getRecordTime();
recordTimeTextView.setEnabled(true);
recordTimeTextView.setText(StringUtils.formatElapsedTimeWithHour(recordTime));
} else {
recordTimeTextView.setEnabled(false);
recordTimeTextView.setText(StringUtils.formatElapsedTimeWithHour(0L));
}
}
/**
* Gets the current record time.
*/
private long getRecordTime() {
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this);
Track track = myTracksProviderUtils.getTrack(recordingTrackId);
return track.getTripStatistics().getTotalTime();
}
/**
* Starts a new recording.
*/
private void startRecording() {
startNewRecording = true;
trackRecordingServiceConnection.startAndBind();
/*
* If the binding has happened, then invoke the callback to start a new
* recording. If the binding hasn't happened, then invoking the callback
* will have no effect. But when the binding occurs, the callback will get
* invoked.
*/
bindChangedCallback.run();
}
/** /**
* Starts the {@link SaveActivity} to save all tracks. * Starts the {@link SaveActivity} to save all tracks.
* *
* @param trackFileFormat the track file format * @param trackFileFormat the track file format
*/ */
private void startSaveActivity(TrackFileFormat trackFileFormat) { private void startSaveActivity(TrackFileFormat trackFileFormat) {
@@ -473,20 +591,6 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat); .putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
startActivity(intent); startActivity(intent);
} }
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (handleContextItem(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).id)) {
return true;
}
return super.onContextItemSelected(item);
}
/** /**
* Handles a context item selection. * Handles a context item selection.
@@ -516,35 +620,4 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
return false; return false;
} }
} }
/**
* Starts a new recording.
*/
private void startRecording() {
startNewRecording = true;
trackRecordingServiceConnection.startAndBind();
/*
* If the binding has happened, then invoke the callback to start a new
* recording. If the binding hasn't happened, then invoking the callback
* will have no effect. But when the binding occurs, the callback will get
* invoked.
*/
bindChangedCallback.run();
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
if (ApiAdapterFactory.getApiAdapter().handleSearchKey(searchMenuItem)) {
return true;
}
}
return super.onKeyUp(keyCode, event);
}
@Override
public TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
return trackRecordingServiceConnection;
}
} }
@@ -72,6 +72,6 @@ public class CheckUnitsDialogFragment extends DialogFragment {
private void onDone() { private void onDone() {
EulaUtils.setShowCheckUnits(getActivity()); EulaUtils.setShowCheckUnits(getActivity());
TrackListActivity trackListActivity = (TrackListActivity) getActivity(); TrackListActivity trackListActivity = (TrackListActivity) getActivity();
trackListActivity.showStartupDialogs(); trackListActivity.showStartupDialogs();
} }
} }
@@ -317,22 +317,16 @@ class TrackWriterImpl implements TrackWriter {
LocationIterator it = providerUtils.getTrackPointLocationIterator(track.getId(), 0, false, LocationIterator it = providerUtils.getTrackPointLocationIterator(track.getId(), 0, false,
locationFactory); locationFactory);
try { try {
if (!it.hasNext()) {
// Writes an empty track
writer.writeBeginTrack(null);
writer.writeEndTrack(null);
return;
}
int pointNumber = 0; int pointNumber = 0;
while (it.hasNext()) { while (it.hasNext()) {
Location loc = it.next(); Location location = it.next();
if (Thread.interrupted()) { if (Thread.interrupted()) {
throw new InterruptedException(); throw new InterruptedException();
} }
pointNumber++; pointNumber++;
boolean isValid = LocationUtils.isValidLocation(loc); boolean isValid = LocationUtils.isValidLocation(location);
boolean validSegment = isValid && isLastValid; boolean validSegment = isValid && isLastValid;
if (!wroteFirst && validSegment) { if (!wroteFirst && validSegment) {
// Found the first two consecutive points which are valid // Found the first two consecutive points which are valid
@@ -351,7 +345,7 @@ class TrackWriterImpl implements TrackWriter {
} }
// Write the current point // Write the current point
writer.writeLocation(loc); writer.writeLocation(location);
if (onWriteListener != null) { if (onWriteListener != null) {
onWriteListener.onWrite(pointNumber, track.getNumberOfPoints()); onWriteListener.onWrite(pointNumber, track.getNumberOfPoints());
} }
@@ -371,6 +365,10 @@ class TrackWriterImpl implements TrackWriter {
} }
if (wroteFirst) { if (wroteFirst) {
writer.writeEndTrack(locationFactory.lastLocation); writer.writeEndTrack(locationFactory.lastLocation);
} else {
// Writes an empty track
writer.writeBeginTrack(null);
writer.writeEndTrack(null);
} }
} finally { } finally {
it.close(); it.close();
+1 -1
View File
@@ -26,7 +26,7 @@ limitations under the License.
--> -->
<uses-sdk <uses-sdk
android:minSdkVersion="7" android:minSdkVersion="7"
android:targetSdkVersion="15" /> android:targetSdkVersion="16" />
<application <application
android:icon="@drawable/my_tracks_icon" android:icon="@drawable/my_tracks_icon"
+1 -1
View File
@@ -9,4 +9,4 @@
android.library=true android.library=true
# Project target. # Project target.
target=android-15 target=Google Inc.:Google APIs:16
+1 -1
View File
@@ -29,7 +29,7 @@ limitations under the License.
<uses-sdk <uses-sdk
android:minSdkVersion="7" android:minSdkVersion="7"
android:targetSdkVersion="15" /> android:targetSdkVersion="16" />
<application <application
android:label="My Tracks Tests" > android:label="My Tracks Tests" >
+1 -1
View File
@@ -10,4 +10,4 @@
# Indicates whether an apk should be generated for each density. # Indicates whether an apk should be generated for each density.
split.density=false split.density=false
# Project target. # Project target.
target=Google Inc.:Google APIs:15 target=Google Inc.:Google APIs:16
@@ -161,7 +161,7 @@ public class CreateAndSendTrackTest extends ActivityInstrumentationTestCase2<Tra
if (EndToEndTestUtils.hasActionBar) { if (EndToEndTestUtils.hasActionBar) {
// Check the title is Recording. // Check the title is Recording.
assertTrue(EndToEndTestUtils.SOLO.searchText(activityMyTracks assertTrue(EndToEndTestUtils.SOLO.searchText(activityMyTracks
.getString(R.string.icon_recording))); .getString(R.string.generic_recording)));
} }
createWaypoint(); createWaypoint();
@@ -237,6 +237,34 @@ public class TrackWriterTest extends AndroidTestCase {
mocksControl.verify(); mocksControl.verify();
} }
/**
* Tests when a track only contains invalid locations. Make sure an empty
* track is written.
*/
public void testWriteDocument_oneInvalidLocation() throws Exception {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);
Location[] locs = { new Location("fake0") };
fillLocations(locs);
// Make location invalid
locs[0].setLatitude(100);
assertEquals(locs.length, providerUtils.bulkInsertTrackPoint(locs, locs.length, TRACK_ID));
formatWriter.writeHeader();
formatWriter.writeBeginTrack(null);
formatWriter.writeEndTrack(null);
formatWriter.writeFooter();
formatWriter.close();
mocksControl.replay();
writer.writeDocument();
assertTrue(writer.wasSuccess());
mocksControl.verify();
}
public void testWriteDocument() throws Exception { public void testWriteDocument() throws Exception {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter); writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);