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
android:minSdkVersion="7"
android:targetSdkVersion="15" />
android:targetSdkVersion="16" />
<!-- Required features -->
<uses-feature
android:name="android.hardware.location"
+1 -1
View File
@@ -11,5 +11,5 @@
split.density=false
proguard.config=proguard.cfg
# Project target.
target=Google Inc.:Google APIs:15
target=Google Inc.:Google APIs:16
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
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_width="fill_parent" >
android:layout_width="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/track_list"
android:layout_height="fill_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:layout_width="fill_parent" />
<LinearLayout
android:gravity="center"
android:id="@+id/track_list_empty"
android:layout_height="fill_parent"
<TextView
android:id="@+id/track_list_empty_view"
android:layout_height="0dp"
android:layout_weight="1.0"
android:layout_width="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/track_list_empty_message"
android:text="@string/track_list_empty_message"
android:visibility="gone"
style="@style/ListEmptyTextView" >
</TextView>
android:text="@string/track_list_empty_message"
android:visibility="gone"
style="@style/ListEmptyTextView" >
</TextView>
<LinearLayout
android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="horizontal" >
<ImageButton
android:background="@color/transparent"
android:contentDescription="@string/menu_record_track"
android:id="@+id/track_list_record_button"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:id="@+id/track_list_record_track_button"
android:layout_height="100dp"
android:layout_width="wrap_content"
android:padding="16dp"
android:src="@drawable/menu_record_track"
android:visibility="gone"
style="@android:style/Widget.DeviceDefault.ImageButton" />
android:scaleType="centerInside" />
<RelativeLayout
android:layout_height="100dp"
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>
</merge>
</LinearLayout>
-15
View File
@@ -15,21 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<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
android:actionViewClass="android.widget.SearchView"
android:icon="@drawable/menu_search"
-1
View File
@@ -19,7 +19,6 @@ limitations under the License.
<color name="blue">#FF0000FF</color>
<color name="gray">#FFAAAAAA</color>
<color name="red">#FFFF0000</color>
<color name="transparent">#00000000</color>
<!-- holo_orange_dark -->
<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.">
OK
</string>
<string name="generic_paused"
translation_description="Text indicating a track is paused.">
Paused
</string>
<string name="generic_progress_title"
translation_description="The title on a progress dialog asking the user to wait.">
Please wait...
</string>
<string name="generic_recording"
translation_description="Text indicating a track is recording.">
Recording...
</string>
<string name="generic_save"
translation_description="The text on a button to say save.">
Save
@@ -882,10 +890,6 @@ limitations under the License.
translation_description="The accessibility description for the 'My Location' icon.">
My Location
</string>
<string name="icon_recording"
translation_description="The accessibility description for the 'Recording' icon.">
Recording
</string>
<string name="icon_track"
translation_description="The accessibility description for the 'Track' icon.">
Track
@@ -2231,14 +2235,6 @@ limitations under the License.
translation_description="In the track detail page, the title of the tab showing the stats.">
Stats
</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"
translation_description="In the page to edit a track, the label for the text field to edit the
activity type, including an example.">
@@ -84,9 +84,10 @@ public class MarkerListActivity extends AbstractMyTracksActivity {
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override
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)
.equals(key)) {
.equals(key) || PreferencesUtils.getKey(
MarkerListActivity.this, R.string.recording_track_paused_key).equals(key)) {
updateMenu();
}
}
@@ -187,8 +188,11 @@ public class MarkerListActivity extends AbstractMyTracksActivity {
private void updateMenu() {
if (insertMarkerMenuItem != null) {
insertMarkerMenuItem.setVisible(
trackId == PreferencesUtils.getLong(this, R.string.recording_track_id_key));
boolean isRecording = trackId
== 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() {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_id_key)
.equals(key)) {
if (key == null || key.equals(
PreferencesUtils.getKey(SearchListActivity.this, R.string.recording_track_id_key))) {
recordingTrackId = PreferencesUtils.getLong(
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();
}
}
@@ -115,6 +123,7 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
private SearchRecentSuggestions searchRecentSuggestions;
private MyTracksLocationManager myTracksLocationManager;
private long recordingTrackId;
private boolean recordingTrackPaused;
private boolean metricUnits;
private ArrayAdapter<Map<String, Object>> arrayAdapter;
@@ -133,9 +142,10 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
searchEngine = new SearchEngine(myTracksProviderUtils);
searchRecentSuggestions = SearchEngineProvider.newHelper(this);
myTracksLocationManager = new MyTracksLocationManager(this);
getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
recordingTrackId = PreferencesUtils.getLong(this, R.string.recording_track_id_key);
SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
listView = (ListView) findViewById(R.id.search_list);
listView.setEmptyView(findViewById(R.id.search_list_empty));
@@ -425,10 +435,18 @@ public class SearchListActivity extends AbstractMyTracksActivity implements Dele
boolean isRecording = track.getId() == recordingTrackId;
TripStatistics tripStatitics = track.getTripStatistics();
resultMap.put(NAME_FIELD, track.getName());
resultMap.put(ICON_FIELD, isRecording
? R.drawable.menu_record_track : TrackIconUtils.getIconDrawable(track.getIcon()));
resultMap.put(ICON_CONTENT_DESCRIPTION_FIELD, getString(isRecording ? R.string.icon_recording
: R.string.icon_track));
int iconId;
int iconContentDescriptionId;
if (isRecording) {
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(TOTAL_TIME_FIELD, isRecording ? null : StringUtils.formatElapsedTime(
tripStatitics.getTotalTime()));
@@ -89,8 +89,6 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
private MenuItem insertMarkerMenuItem;
private MenuItem playMenuItem;
private MenuItem shareMenuItem;
private MenuItem voiceFrequencyMenuItem;
private MenuItem splitFrequencyMenuItem;
private MenuItem sendGoogleMenuItem;
private MenuItem saveMenuItem;
@@ -110,7 +108,8 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
recordingTrackId = PreferencesUtils.getLong(
TrackDetailActivity.this, R.string.recording_track_id_key);
if (key != null) {
updateMenuItems(trackId == recordingTrackId);
updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
return;
}
}
if (key == null || key.equals(PreferencesUtils.getKey(
@@ -197,7 +196,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
super.onResume();
trackDataHub.loadTrack(trackId);
TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection);
updateMenuItems(trackId == recordingTrackId);
updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
}
@Override
@@ -237,12 +236,10 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker);
playMenuItem = menu.findItem(R.id.track_detail_play);
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);
saveMenuItem = menu.findItem(R.id.track_detail_save);
updateMenuItems(trackId == recordingTrackId);
updateMenuItems(trackId == recordingTrackId, recordingTrackPaused);
return true;
}
@@ -267,18 +264,15 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
Intent intent;
switch (item.getItemId()) {
case R.id.track_detail_record_track:
recordingTrackPaused = false;
updateMenuItems(true);
updateMenuItems(true, false);
TrackRecordingServiceConnectionUtils.resumeTrack(trackRecordingServiceConnection);
return true;
case R.id.track_detail_pause_track:
recordingTrackPaused = true;
updateMenuItems(true);
updateMenuItems(true, true);
TrackRecordingServiceConnectionUtils.pauseTrack(trackRecordingServiceConnection);
return true;
case R.id.track_detail_stop_recording:
recordingTrackPaused = true;
updateMenuItems(false);
updateMenuItems(false, true);
TrackRecordingServiceConnectionUtils.stopRecording(
this, trackRecordingServiceConnection, true);
return true;
@@ -369,7 +363,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
@Override
public boolean onTrackballEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (trackId == recordingTrackId) {
if (trackId == recordingTrackId && !recordingTrackPaused) {
TrackRecordingServiceConnectionUtils.addMarker(
this, trackRecordingServiceConnection, WaypointCreationRequest.DEFAULT_WAYPOINT);
return true;
@@ -442,18 +436,18 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
*
* @param isRecording true if recording
*/
private void updateMenuItems(boolean isRecording) {
private void updateMenuItems(boolean isRecording, boolean isPaused) {
if (recordTrackMenuItem != null) {
recordTrackMenuItem.setVisible(isRecording && recordingTrackPaused);
recordTrackMenuItem.setVisible(isRecording && isPaused);
}
if (pauseTrackMenuItem != null) {
pauseTrackMenuItem.setVisible(isRecording && !recordingTrackPaused);
pauseTrackMenuItem.setVisible(isRecording && !isPaused);
}
if (stopRecordingMenuItem != null) {
stopRecordingMenuItem.setVisible(isRecording);
}
if (insertMarkerMenuItem != null) {
insertMarkerMenuItem.setVisible(isRecording);
insertMarkerMenuItem.setVisible(isRecording && !isPaused);
}
if (playMenuItem != null) {
playMenuItem.setVisible(!isRecording);
@@ -461,12 +455,6 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
if (shareMenuItem != null) {
shareMenuItem.setVisible(!isRecording);
}
if (voiceFrequencyMenuItem != null) {
voiceFrequencyMenuItem.setVisible(isRecording);
}
if (splitFrequencyMenuItem != null) {
splitFrequencyMenuItem.setVisible(isRecording);
}
if (sendGoogleMenuItem != null) {
sendGoogleMenuItem.setVisible(!isRecording);
}
@@ -475,8 +463,8 @@ public class TrackDetailActivity extends AbstractMyTracksActivity implements Del
}
String title;
if (isRecording) {
title = getString(recordingTrackPaused ? R.string.track_detail_title_paused
: R.string.track_detail_title_recording);
title = getString(
isPaused ? R.string.generic_paused : R.string.generic_recording);
} else {
Track track = MyTracksProviderUtils.Factory.get(this).getTrack(trackId);
title = track != null ? track.getName() : getString(R.string.my_tracks_app_name);
@@ -16,6 +16,8 @@
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.fragments.CheckUnitsDialogFragment;
import com.google.android.apps.mytracks.fragments.DeleteAllTrackDialogFragment;
@@ -45,6 +47,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.speech.tts.TextToSpeech;
import android.support.v4.app.Fragment;
@@ -65,30 +68,28 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
/**
* An activity displaying a list of tracks.
*
*
* @author Leif Hendrik Wilden
*/
public class TrackListActivity extends FragmentActivity implements DeleteOneTrackCaller {
private static final String TAG = TrackListActivity.class.getSimpleName();
private static final String[] PROJECTION = new String[] {
TracksColumns._ID,
TracksColumns.NAME,
TracksColumns.DESCRIPTION,
TracksColumns.CATEGORY,
TracksColumns.STARTTIME,
TracksColumns.TOTALDISTANCE,
TracksColumns.TOTALTIME,
TracksColumns.ICON};
// One second in milliseconds
private static final int ONE_SECOND = 1000;
private static final String[] PROJECTION = new String[] { TracksColumns._ID, TracksColumns.NAME,
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON };
// Callback when the trackRecordingServiceConnection binding changes.
private final Runnable bindChangedCallback = new Runnable() {
@Override
@Override
public void run() {
if (!startNewRecording) {
return;
@@ -123,12 +124,14 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
boolean updateList = false;
if (key == null || key.equals(
PreferencesUtils.getKey(TrackListActivity.this, R.string.metric_units_key))) {
metricUnits = PreferencesUtils.getBoolean(TrackListActivity.this,
R.string.metric_units_key, PreferencesUtils.METRIC_UNITS_DEFAULT);
updateList = key != null;
if (key != null) {
resourceCursorAdapter.notifyDataSetChanged();
return;
}
}
if (key == null || key.equals(
PreferencesUtils.getKey(TrackListActivity.this, R.string.recording_track_id_key))) {
@@ -140,7 +143,9 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
trackRecordingServiceConnection.startAndBind();
}
updateMenuItems(isRecording);
updateList = true;
resourceCursorAdapter.notifyDataSetChanged();
startUpdateRecordTime(isRecording);
return;
}
}
if (key == null || key.equals(PreferencesUtils.getKey(
@@ -148,40 +153,63 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
recordingTrackPaused = PreferencesUtils.getBoolean(TrackListActivity.this,
R.string.recording_track_paused_key,
PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
updateList = updateList || key != null;
}
if (updateList) {
resourceCursorAdapter.notifyDataSetChanged();
if (key != null) {
updateButtons(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT,
recordingTrackPaused);
resourceCursorAdapter.notifyDataSetChanged();
return;
}
}
}
};
// Callback when an item is selected in the contextual action mode
private ContextualActionModeCallback contextualActionModeCallback =
new ContextualActionModeCallback() {
@Override
public boolean onClick(int itemId, int position, long id) {
return handleContextItem(itemId, id);
private ContextualActionModeCallback
contextualActionModeCallback = new ContextualActionModeCallback() {
@Override
public boolean onClick(int itemId, int position, long 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 boolean metricUnits;
private long recordingTrackId;
private boolean recordingTrackPaused;
private Handler handler;
private TextView recordStateTextView;
private TextView recordTimeTextView;
private ImageButton recordTrackImageButton;
private ImageButton stopRecordingImageButton;
private ListView listView;
private ResourceCursorAdapter resourceCursorAdapter;
// True to start a new recording.
private boolean startNewRecording = false;
// Preferences
private boolean metricUnits;
private long recordingTrackId;
private boolean recordingTrackPaused;
private MenuItem recordTrackMenuItem;
private MenuItem pauseTrackMenuItem;
private MenuItem stopRecordingMenuItem;
// Menu items
private MenuItem searchMenuItem;
private MenuItem importMenuItem;
private MenuItem saveAllMenuItem;
private MenuItem deleteAllMenuItem;
private boolean startNewRecording = false; // true to start a new recording
// For recordTimeTextView
private long recordTime = 0;
private long lastResumeTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -197,19 +225,58 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
ImageButton recordImageButton = (ImageButton) findViewById(R.id.track_list_record_button);
recordImageButton.setOnClickListener(new View.OnClickListener() {
@Override
handler = new Handler();
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) {
updateMenuItems(true);
startRecording();
if (!(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT)) {
// 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.setEmptyView(findViewById(R.id.track_list_empty));
listView.setEmptyView(findViewById(R.id.track_list_empty_view));
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class)
.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, id);
@@ -227,58 +294,50 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
boolean isRecording = cursor.getLong(idIndex) == recordingTrackId;
String name = cursor.getString(nameIndex);
int iconId;
int iconContentDescriptionId;
if (isRecording) {
iconId = recordingTrackPaused ? R.drawable.menu_pause_track
: R.drawable.menu_record_track;
iconContentDescriptionId = recordingTrackPaused ? R.string.menu_pause_track
: R.string.menu_record_track;
} else {
iconId = TrackIconUtils.getIconDrawable(cursor.getString(iconIndex));
iconContentDescriptionId = R.string.icon_track;
}
String iconContentDescription = getString(isRecording ? R.string.icon_recording
: R.string.icon_track);
String iconContentDescription = getString(iconContentDescriptionId);
String category = cursor.getString(categoryIndex);
String totalTime = isRecording
? null : StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
String totalDistance = isRecording ? null : StringUtils.formatDistance(
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
String totalTime = isRecording ? null
: StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
String totalDistance = isRecording ? null
: StringUtils.formatDistance(
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
long startTime = cursor.getLong(startTimeIndex);
String description = cursor.getString(descriptionIndex);
ListItemUtils.setListItem(TrackListActivity.this,
view,
name,
iconId,
iconContentDescription,
category,
totalTime,
totalDistance,
startTime,
description);
ListItemUtils.setListItem(TrackListActivity.this, view, name, iconId,
iconContentDescription, category, totalTime, totalDistance, startTime, description);
}
};
listView.setAdapter(resourceCursorAdapter);
ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback);
getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() {
@Override
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new CursorLoader(TrackListActivity.this,
TracksColumns.CONTENT_URI,
PROJECTION,
null,
null,
TracksColumns._ID + " DESC");
return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null,
null, TracksColumns._ID + " DESC");
}
@Override
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
resourceCursorAdapter.swapCursor(cursor);
}
@Override
@Override
public void onLoaderReset(Loader<Cursor> loader) {
resourceCursorAdapter.swapCursor(null);
}
@@ -287,50 +346,17 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
showStartupDialogs();
}
/**
* 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 {
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
protected void onPause() {
super.onPause();
stopUpdateRecordTime(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
}
@Override
protected void onResume() {
super.onResume();
TrackRecordingServiceConnectionUtils.resumeConnection(this, trackRecordingServiceConnection);
startUpdateRecordTime(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
}
@Override
@@ -351,10 +377,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
.setTitle(getString(R.string.menu_save_format, fileTypes[2]));
menu.findItem(R.id.track_list_save_all_tcx)
.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);
importMenuItem = menu.findItem(R.id.track_list_import);
saveAllMenuItem = menu.findItem(R.id.track_list_save_all);
@@ -365,62 +388,10 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
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
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
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:
return ApiAdapterFactory.getApiAdapter().handleSearchMenuSelection(this);
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.
*
*
* @param trackFileFormat the track file format
*/
private void startSaveActivity(TrackFileFormat trackFileFormat) {
@@ -473,20 +591,6 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
.putExtra(SaveActivity.EXTRA_TRACK_FILE_FORMAT, (Parcelable) trackFileFormat);
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.
@@ -516,35 +620,4 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
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() {
EulaUtils.setShowCheckUnits(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,
locationFactory);
try {
if (!it.hasNext()) {
// Writes an empty track
writer.writeBeginTrack(null);
writer.writeEndTrack(null);
return;
}
int pointNumber = 0;
while (it.hasNext()) {
Location loc = it.next();
Location location = it.next();
if (Thread.interrupted()) {
throw new InterruptedException();
}
pointNumber++;
boolean isValid = LocationUtils.isValidLocation(loc);
boolean isValid = LocationUtils.isValidLocation(location);
boolean validSegment = isValid && isLastValid;
if (!wroteFirst && validSegment) {
// Found the first two consecutive points which are valid
@@ -351,7 +345,7 @@ class TrackWriterImpl implements TrackWriter {
}
// Write the current point
writer.writeLocation(loc);
writer.writeLocation(location);
if (onWriteListener != null) {
onWriteListener.onWrite(pointNumber, track.getNumberOfPoints());
}
@@ -371,6 +365,10 @@ class TrackWriterImpl implements TrackWriter {
}
if (wroteFirst) {
writer.writeEndTrack(locationFactory.lastLocation);
} else {
// Writes an empty track
writer.writeBeginTrack(null);
writer.writeEndTrack(null);
}
} finally {
it.close();
+1 -1
View File
@@ -26,7 +26,7 @@ limitations under the License.
-->
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
android:targetSdkVersion="16" />
<application
android:icon="@drawable/my_tracks_icon"
+1 -1
View File
@@ -9,4 +9,4 @@
android.library=true
# 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
android:minSdkVersion="7"
android:targetSdkVersion="15" />
android:targetSdkVersion="16" />
<application
android:label="My Tracks Tests" >
+1 -1
View File
@@ -10,4 +10,4 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# 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) {
// Check the title is Recording.
assertTrue(EndToEndTestUtils.SOLO.searchText(activityMyTracks
.getString(R.string.icon_recording)));
.getString(R.string.generic_recording)));
}
createWaypoint();
@@ -237,6 +237,34 @@ public class TrackWriterTest extends AndroidTestCase {
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 {
writer = new TrackWriterImpl(getContext(), providerUtils, track, formatWriter);