diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index 7e03389db..8caa7a529 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -2123,6 +2123,10 @@ limitations under the License. translation_description="In the track detail page, the title of the tab showing the stats."> Stats + + Recording... + Track diff --git a/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java b/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java index fc79e07d5..78b0e697a 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/SensorStateActivity.java @@ -13,9 +13,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.android.apps.mytracks; -import static com.google.android.apps.mytracks.Constants.TAG; +package com.google.android.apps.mytracks; import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.services.ITrackRecordingService; @@ -24,6 +23,7 @@ import com.google.android.apps.mytracks.services.sensors.SensorManager; import com.google.android.apps.mytracks.services.sensors.SensorManagerFactory; import com.google.android.apps.mytracks.services.sensors.SensorUtils; import com.google.android.apps.mytracks.util.StringUtils; +import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils; import com.google.android.maps.mytracks.R; import com.google.protobuf.InvalidProtocolBufferException; @@ -37,182 +37,92 @@ import java.util.TimerTask; /** * An activity that displays information about sensors. - * + * * @author Sandor Dornbush */ public class SensorStateActivity extends AbstractMyTracksActivity { + private static final String TAG = SensorStateActivity.class.getName(); private static final long REFRESH_PERIOD_MS = 250; /** - * This timer periodically invokes the refresh timer task. + * A Runnable to update the UI. */ - private Timer timer; - - private final Runnable stateUpdater = new Runnable() { + private final Runnable updateRunnable = new Runnable() { public void run() { - if (isVisible) // only update when UI is visible - updateState(); + ITrackRecordingService trackRecordingService = trackRecordingServiceConnection + .getServiceIfBound(); + + // Check if service is available and recording + boolean isRecording = false; + if (trackRecordingService != null) { + try { + isRecording = trackRecordingService.isRecording(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to determine if the track recording service is recording.", e); + } + } + + if (!isRecording) { + updateFromTempSensorManager(); + } else { + stopTempSensorManager(); + updateFromSystemSensorManager(); + } } }; /** - * Connection to the recording service. + * A TimeTask to update the UI. */ - private TrackRecordingServiceConnection serviceConnection; - - /** - * A task which will update the U/I. - */ - private class RefreshTask extends TimerTask { + private class UpdateTimerTask extends TimerTask { @Override public void run() { - runOnUiThread(stateUpdater); + if (isVisible) { + runOnUiThread(updateRunnable); + } } }; - - /** - * A temporary sensor manager, when none is available. - */ - private SensorManager tempSensorManager = null; - - /** - * A state flag set to true when the activity is active/visible, - * i.e. after resume, and before pause - * - * Used to avoid updating after the pause event, because sometimes an update - * event occurs even after the timer is cancelled. In this case, - * it could cause the {@link #tempSensorManager} to be recreated, after it - * is destroyed at the pause event. - */ + private TrackRecordingServiceConnection trackRecordingServiceConnection; private boolean isVisible = false; + private Timer timer = null; + private SensorManager tempSensorManager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Log.w(TAG, "SensorStateActivity.onCreate"); - setContentView(R.layout.sensor_state); - - serviceConnection = new TrackRecordingServiceConnection(this, stateUpdater); - serviceConnection.bindIfRunning(); - updateState(); + trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null); } @Override protected void onResume() { super.onResume(); - + TrackRecordingServiceConnectionUtils.resume(this, trackRecordingServiceConnection); isVisible = true; - - serviceConnection.bindIfRunning(); - timer = new Timer(); - timer.schedule(new RefreshTask(), REFRESH_PERIOD_MS, REFRESH_PERIOD_MS); + timer.schedule(new UpdateTimerTask(), 0, REFRESH_PERIOD_MS); } @Override protected void onPause() { + super.onPause(); isVisible = false; - timer.cancel(); timer.purge(); timer = null; stopTempSensorManager(); - super.onPause(); } @Override protected void onDestroy() { - serviceConnection.unbind(); super.onDestroy(); - } - - private void updateState() { - Log.d(TAG, "Updating SensorStateActivity"); - - ITrackRecordingService service = serviceConnection.getServiceIfBound(); - - // Check if service is available, and recording. - boolean isRecording = false; - if (service != null) { - try { - isRecording = service.isRecording(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to determine if service is recording.", e); - } - } - - // If either service isn't available, or not recording. - if (!isRecording) { - updateFromTempSensorManager(); - } else { - updateFromSysSensorManager(); - } - } - - private void updateFromTempSensorManager() { - // Use variables to hold the sensor state and data set. - Sensor.SensorState currentState = null; - Sensor.SensorDataSet currentDataSet = null; - - // If no temp sensor manager is present, create one, and start it. - if (tempSensorManager == null) { - tempSensorManager = SensorManagerFactory.getInstance().getSensorManager(this); - } - - // If a temp sensor manager is available, use states from temp sensor - // manager. - if (tempSensorManager != null) { - currentState = tempSensorManager.getSensorState(); - currentDataSet = tempSensorManager.getSensorDataSet(); - } - - // Update the sensor state, and sensor data, using the variables. - updateSensorStateAndData(currentState, currentDataSet); - } - - private void updateFromSysSensorManager() { - // Use variables to hold the sensor state and data set. - Sensor.SensorState currentState = null; - Sensor.SensorDataSet currentDataSet = null; - - ITrackRecordingService service = serviceConnection.getServiceIfBound(); - - // If a temp sensor manager is present, shut it down, - // probably recording just started. - stopTempSensorManager(); - - // Get sensor details from the service. - if (service == null) { - Log.d(TAG, "Could not get track recording service."); - } else { - try { - byte[] buff = service.getSensorData(); - if (buff != null) { - currentDataSet = Sensor.SensorDataSet.parseFrom(buff); - } - } catch (RemoteException e) { - Log.e(TAG, "Could not read sensor data.", e); - } catch (InvalidProtocolBufferException e) { - Log.e(TAG, "Could not read sensor data.", e); - } - - try { - currentState = Sensor.SensorState.valueOf(service.getSensorState()); - } catch (RemoteException e) { - Log.e(TAG, "Could not read sensor state.", e); - currentState = Sensor.SensorState.NONE; - } - } - - // Update the sensor state, and sensor data, using the variables. - updateSensorStateAndData(currentState, currentDataSet); + trackRecordingServiceConnection.unbind(); } /** - * Stops the temporary sensor manager, if one exists. + * Stops the temp sensor manager. */ private void stopTempSensorManager() { if (tempSensorManager != null) { @@ -221,23 +131,83 @@ public class SensorStateActivity extends AbstractMyTracksActivity { } } - private void updateSensorStateAndData(Sensor.SensorState state, Sensor.SensorDataSet dataSet) { - updateSensorState(state == null ? Sensor.SensorState.NONE : state); - updateSensorData(dataSet); + /** + * Updates from a temp sensor manager. + */ + private void updateFromTempSensorManager() { + Sensor.SensorState sensorState = Sensor.SensorState.NONE; + Sensor.SensorDataSet sensorDataSet = null; + + if (tempSensorManager == null) { + tempSensorManager = SensorManagerFactory.getInstance().getSensorManager(this); + } + + if (tempSensorManager != null) { + sensorState = tempSensorManager.getSensorState(); + sensorDataSet = tempSensorManager.getSensorDataSet(); + } + + updateSensorStateAndDataSet(sensorState, sensorDataSet); } - private void updateSensorState(Sensor.SensorState state) { - ((TextView) findViewById(R.id.sensor_state)).setText(SensorUtils.getStateAsString(state, this)); + /** + * Updates from the system sensor manager. + */ + private void updateFromSystemSensorManager() { + Sensor.SensorState sensorState = Sensor.SensorState.NONE; + Sensor.SensorDataSet sensorDataSet = null; + + ITrackRecordingService trackRecordingService = trackRecordingServiceConnection + .getServiceIfBound(); + + // Get sensor details from the service. + if (trackRecordingService == null) { + Log.d(TAG, "Cannot get teh track recording service."); + } else { + try { + sensorState = Sensor.SensorState.valueOf(trackRecordingService.getSensorState()); + } catch (RemoteException e) { + Log.e(TAG, "Cannote read sensor state.", e); + sensorState = Sensor.SensorState.NONE; + } + + try { + byte[] buff = trackRecordingService.getSensorData(); + if (buff != null) { + sensorDataSet = Sensor.SensorDataSet.parseFrom(buff); + } + } catch (RemoteException e) { + Log.e(TAG, "Cannot read sensor data set.", e); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Cannot read sensor data set.", e); + } + } + + updateSensorStateAndDataSet(sensorState, sensorDataSet); } - private void updateSensorData(Sensor.SensorDataSet sds) { - String lastSensorTime = sds == null ? getString(R.string.value_unknown) - : getLastSensorTime(sds); - String power = sds == null ? getString(R.string.value_unknown) : getPower(sds); - String cadence = sds == null ? getString(R.string.value_unknown) : getCadence(sds); - String heartRate = sds == null ? getString(R.string.value_unknown) : getHeartRate(sds); - String battery = sds == null ? getString(R.string.value_unknown) : getBattery(sds); - + /** + * Updates the sensor state and data set. + * + * @param sensorState sensor state + * @param sensorDataSet sensor data set + */ + private void updateSensorStateAndDataSet( + Sensor.SensorState sensorState, Sensor.SensorDataSet sensorDataSet) { + ((TextView) findViewById(R.id.sensor_state)).setText( + SensorUtils.getStateAsString(sensorState, this)); + + String lastSensorTime = sensorDataSet == null ? getString(R.string.value_unknown) + : getLastSensorTime(sensorDataSet); + String power = sensorDataSet == null ? getString(R.string.value_unknown) + : getPower(sensorDataSet); + String cadence = sensorDataSet == null ? getString(R.string.value_unknown) + : getCadence(sensorDataSet); + String heartRate = sensorDataSet == null ? getString(R.string.value_unknown) + : getHeartRate(sensorDataSet); + String battery = sensorDataSet == null ? getString(R.string.value_unknown) + : getBattery(sensorDataSet); + ((TextView) findViewById(R.id.sensor_state_last_sensor_time)).setText(lastSensorTime); ((TextView) findViewById(R.id.sensor_state_power)).setText(power); ((TextView) findViewById(R.id.sensor_state_cadence)).setText(cadence); @@ -247,80 +217,84 @@ public class SensorStateActivity extends AbstractMyTracksActivity { /** * Gets the last sensor time. - * - * @param sds sensor data set + * + * @param sensorDataSet sensor data set */ - private String getLastSensorTime(Sensor.SensorDataSet sds) { - return StringUtils.formatTime(this, sds.getCreationTime()); + private String getLastSensorTime(Sensor.SensorDataSet sensorDataSet) { + return StringUtils.formatTime(this, sensorDataSet.getCreationTime()); } /** * Gets the power. - * - * @param sds sensor data set + * + * @param sensorDataSet sensor data set */ - private String getPower(Sensor.SensorDataSet sds) { + private String getPower(Sensor.SensorDataSet sensorDataSet) { String value; - if (sds.hasPower() && sds.getPower().hasValue() - && sds.getPower().getState() == Sensor.SensorState.SENDING) { + if (sensorDataSet.hasPower() && sensorDataSet.getPower().hasValue() + && sensorDataSet.getPower().getState() == Sensor.SensorState.SENDING) { String format = getString(R.string.sensor_state_power_value); - value = String.format(format, sds.getPower().getValue()); + value = String.format(format, sensorDataSet.getPower().getValue()); } else { value = SensorUtils.getStateAsString( - sds.hasPower() ? sds.getPower().getState() : Sensor.SensorState.NONE, this); + sensorDataSet.hasPower() ? sensorDataSet.getPower().getState() : Sensor.SensorState.NONE, + this); } return value; } /** * Gets the cadence. - * - * @param sds sensor data set + * + * @param sensorDataSet sensor data set */ - private String getCadence(Sensor.SensorDataSet sds) { + private String getCadence(Sensor.SensorDataSet sensorDataSet) { String value; - if (sds.hasCadence() && sds.getCadence().hasValue() - && sds.getCadence().getState() == Sensor.SensorState.SENDING) { + if (sensorDataSet.hasCadence() && sensorDataSet.getCadence().hasValue() + && sensorDataSet.getCadence().getState() == Sensor.SensorState.SENDING) { String format = getString(R.string.sensor_state_cadence_value); - value = String.format(format, sds.getCadence().getValue()); + value = String.format(format, sensorDataSet.getCadence().getValue()); } else { value = SensorUtils.getStateAsString( - sds.hasCadence() ? sds.getCadence().getState() : Sensor.SensorState.NONE, this); + sensorDataSet.hasCadence() ? sensorDataSet.getCadence().getState() + : Sensor.SensorState.NONE, this); } return value; } /** * Gets the heart rate. - * - * @param sds sensor data set + * + * @param sensorDataSet sensor data set */ - private String getHeartRate(Sensor.SensorDataSet sds) { + private String getHeartRate(Sensor.SensorDataSet sensorDataSet) { String value; - if (sds.hasHeartRate() && sds.getHeartRate().hasValue() - && sds.getHeartRate().getState() == Sensor.SensorState.SENDING) { + if (sensorDataSet.hasHeartRate() && sensorDataSet.getHeartRate().hasValue() + && sensorDataSet.getHeartRate().getState() == Sensor.SensorState.SENDING) { String format = getString(R.string.sensor_state_heart_rate_value); - value = String.format(format, sds.getHeartRate().getValue()); + value = String.format(format, sensorDataSet.getHeartRate().getValue()); } else { value = SensorUtils.getStateAsString( - sds.hasHeartRate() ? sds.getHeartRate().getState() : Sensor.SensorState.NONE, this); + sensorDataSet.hasHeartRate() ? sensorDataSet.getHeartRate().getState() + : Sensor.SensorState.NONE, this); } return value; } /** * Gets the battery. - * - * @param sds sensor data set + * + * @param sensorDataSet sensor data set */ - private String getBattery(Sensor.SensorDataSet sds) { + private String getBattery(Sensor.SensorDataSet sensorDataSet) { String value; - if (sds.hasBatteryLevel() && sds.getBatteryLevel().hasValue() - && sds.getBatteryLevel().getState() == Sensor.SensorState.SENDING) { - value = getString(R.string.value_integer_percent, sds.getBatteryLevel().getValue()); + if (sensorDataSet.hasBatteryLevel() && sensorDataSet.getBatteryLevel().hasValue() + && sensorDataSet.getBatteryLevel().getState() == Sensor.SensorState.SENDING) { + value = getString(R.string.value_integer_percent, sensorDataSet.getBatteryLevel().getValue()); } else { value = SensorUtils.getStateAsString( - sds.hasBatteryLevel() ? sds.getBatteryLevel().getState() : Sensor.SensorState.NONE, this); + sensorDataSet.hasBatteryLevel() ? sensorDataSet.getBatteryLevel().getState() + : Sensor.SensorState.NONE, this); } return value; } diff --git a/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java b/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java index f1f56de4e..ca14bf755 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/TrackDetailActivity.java @@ -17,6 +17,7 @@ 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.TrackDataHub; import com.google.android.apps.mytracks.content.Waypoint; import com.google.android.apps.mytracks.content.WaypointCreationRequest; @@ -76,6 +77,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { private TabHost tabHost; private TabManager tabManager; private long trackId; + private long markerId; private MenuItem stopRecordingMenuItem; private MenuItem insertMarkerMenuItem; @@ -126,14 +128,16 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + handleIntent(getIntent()); ApiAdapterFactory.getApiAdapter().hideTitle(this); setContentView(R.layout.track_detail); getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE) .registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); - trackDataHub = ((MyTracksApplication) getApplication()).getTrackDataHub(); trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, null); - + trackDataHub = ((MyTracksApplication) getApplication()).getTrackDataHub(); + trackDataHub.loadTrack(trackId); + mapViewContainer = getLayoutInflater().inflate(R.layout.map, null); tabHost = (TabHost) findViewById(android.R.id.tabhost); tabHost.setup(); @@ -152,14 +156,15 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { if (savedInstanceState != null) { tabHost.setCurrentTabByTag(savedInstanceState.getString(CURRENT_TAG_KEY)); } - - handleIntent(getIntent()); + showMarker(); } @Override public void onNewIntent(Intent intent) { setIntent(intent); handleIntent(intent); + trackDataHub.loadTrack(trackId); + showMarker(); } @Override @@ -172,6 +177,7 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { protected void onResume() { super.onResume(); TrackRecordingServiceConnectionUtils.resume(this, trackRecordingServiceConnection); + setTitle(trackId == PreferencesUtils.getLong(this, R.string.recording_track_id_key)); } @Override @@ -232,13 +238,23 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { Intent intent = IntentUtils.newIntent(this, TrackListActivity.class); startActivity(intent); } - + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + String sensorTypeValueNone = getString(R.string.sensor_type_value_none); + boolean showSensorState = !sensorTypeValueNone.equals( + PreferencesUtils.getString(this, R.string.sensor_type_key, sensorTypeValueNone)); + menu.findItem(R.id.track_detail_sensor_state).setVisible(showSensorState); + return super.onPrepareOptionsMenu(menu); + } + @Override public boolean onOptionsItemSelected(MenuItem item) { Intent intent; switch (item.getItemId()) { case R.id.track_detail_stop_recording: updateMenuItems(false); + setTitle(false); TrackRecordingServiceConnectionUtils.stop(this, trackRecordingServiceConnection); return true; case R.id.track_detail_insert_marker: @@ -351,26 +367,35 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { * Handles the data in the intent. */ private void handleIntent(Intent intent) { - trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); - long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); + trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); + markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); if (markerId != -1L) { Waypoint waypoint = MyTracksProviderUtils.Factory.get(this).getWaypoint(markerId); if (waypoint == null) { - Intent newIntent = IntentUtils.newIntent(this, TrackListActivity.class); - startActivity(newIntent); - finish(); + exit(); return; } trackId = waypoint.getTrackId(); } if (trackId == -1L) { - Intent newIntent = IntentUtils.newIntent(this, TrackListActivity.class); - startActivity(newIntent); - finish(); + exit(); return; } - trackDataHub.loadTrack(trackId); + } + /** + * Exists and returns to {@link TrackListActivity}. + */ + private void exit() { + Intent newIntent = IntentUtils.newIntent(this, TrackListActivity.class); + startActivity(newIntent); + finish(); + } + + /** + * Shows marker. + */ + private void showMarker() { if (markerId != -1L) { MapFragment mapFragmet = (MapFragment) getSupportFragmentManager() .findFragmentByTag(MapFragment.MAP_FRAGMENT_TAG); @@ -383,6 +408,22 @@ public class TrackDetailActivity extends AbstractMyTracksActivity { } } + /** + * Sets the title. + * + * @param isRecording true if recording + */ + private void setTitle(boolean isRecording) { + String title; + if (isRecording) { + title = getString(R.string.track_detail_title_recording); + } else { + Track track = MyTracksProviderUtils.Factory.get(this).getTrack(trackId); + title = track != null ? track.getName() : getString(R.string.my_tracks_app_name); + } + setTitle(title); + } + /** * Updates the menu. */