TrackController is now ControllerFragment.

This commit is contained in:
Dennis Guse
2021-05-10 22:33:39 +02:00
parent af72960cf6
commit ed6daeb48b
16 changed files with 469 additions and 484 deletions
@@ -39,13 +39,13 @@ public class EspressoUITest {
public void record_pause_resume_stop() {
{
// TrackListActivity: start recording
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
trackControllerRecordButton.perform(click());
}
{
// TrackRecordingActivity
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop));
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
// wait; stay recording
trackControllerRecordButton.perform(waitFor(5000));
@@ -72,13 +72,13 @@ public class EspressoUITest {
public void record_move_through_tabs() {
{
// TrackListActivity: start recording
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
trackControllerRecordButton.perform(click());
}
{
// TrackRecordingActivity
ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout));
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop));
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
tabLayout.perform(selectTabAtIndex(1));
tabLayout.perform(waitFor(1000));
@@ -0,0 +1,299 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks;
import android.annotation.SuppressLint;
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import java.time.Duration;
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.StringUtils;
/**
* Track controller for record, pause, resume, and stop.
*
* @author Jimmy Shih
*/
//TODO Move buttons into separate components
public class ControllerFragment extends Fragment implements View.OnTouchListener {
private static final String TAG = ControllerFragment.class.getSimpleName();
@Deprecated
//TODO TrackRecordingService should provide LifeData for time (replace internal timer)
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
@Deprecated
private Handler handlerUpdateTotalTime;
private Runnable buttonDelay;
private int buttonDelayDuration;
private ControllerFragmentBinding viewBinding;
private TransitionDrawable transition;
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackRecordingService.RecordingStatus recordingStatus;
private Duration totalTime;
private final Runnable bindChangedCallback = new Runnable() {
@Override
public void run() {
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
if (service == null) {
Log.w(TAG, "could not get TrackRecordingService");
return;
}
service.getRecordingStatusObservable()
.observe(ControllerFragment.this, status -> onRecordingStatusChanged(status));
}
};
// A runnable to update the total time.
@Deprecated
private final Runnable updateTotalTimeRunnable = new Runnable() {
public void run() {
if (isResumed() && recordingStatus.isRecordingAndNotPaused()) {
updateTotalTime();
setTotalTime();
handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
}
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
buttonDelayDuration = getResources().getInteger(R.integer.buttonDelayMillis);
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
handlerUpdateTotalTime = new Handler();
recordingStatus = TrackRecordingService.STATUS_DEFAULT;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
viewBinding = ControllerFragmentBinding.inflate(inflater, container, false);
viewBinding.controllerRecord.setOnTouchListener(this);
viewBinding.controllerRecord.setOnClickListener((view) -> {
if (buttonDelay != null || recordingStatus.isRecordingAndNotPaused()) {
return;
}
getCallback().recordStart();
});
viewBinding.controllerStop.setOnTouchListener(this);
transition = (TransitionDrawable) viewBinding.controllerContainer.getBackground();
onRecordingStatusChanged(recordingStatus);
return viewBinding.getRoot();
}
@Override
public void onResume() {
super.onResume();
trackRecordingServiceConnection.startConnection(getContext());
}
@Override
public void onPause() {
super.onPause();
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
}
@Override
public void onStop() {
super.onStop();
trackRecordingServiceConnection.unbind(getContext());
}
@Override
public void onDestroyView() {
super.onDestroyView();
viewBinding = null;
transition = null;
}
@Override
public void onDestroy() {
super.onDestroy();
trackRecordingServiceConnection = null;
handlerUpdateTotalTime = null;
recordingStatus = null;
}
//TODO Move into a separate object
@SuppressLint("ClickableViewAccessibility") //We do accessibility manually.
@Override
public boolean onTouch(final View view, MotionEvent event) {
if (!isResumed()) {
Log.w(TAG, "The UI is already gone, no need to update anything; seen on Android 7.1.2");
return false;
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
return false;
}
if (buttonDelay != null && event.getAction() == MotionEvent.ACTION_UP) {
handlerUpdateTotalTime.removeCallbacks(buttonDelay);
buttonDelay = null;
view.setPressed(false);
transition.resetTransition();
showStatusSetDefaultText();
return false;
}
//Trigger button pressed animation
view.setPressed(true);
//To pause a recording
if (viewBinding.controllerRecord.equals(view)
&& event.getAction() == MotionEvent.ACTION_DOWN
&& recordingStatus.isRecordingAndNotPaused()) {
transition.startTransition(buttonDelayDuration);
ActivityUtils.vibrate(getContext(), 150);
viewBinding.controllerStatus.setText(R.string.hold_to_pause);
buttonDelay = () -> {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
view.performClick();
getCallback().recordPause();
transition.resetTransition();
ActivityUtils.vibrate(getContext(), 1000);
};
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
return true;
}
//To stop a recording
if (viewBinding.controllerStop.equals(view)
&& event.getAction() == MotionEvent.ACTION_DOWN
&& recordingStatus.isRecording()) {
transition.startTransition(buttonDelayDuration);
ActivityUtils.vibrate(getContext(), 150);
viewBinding.controllerStatus.setText(R.string.hold_to_stop);
buttonDelay = () -> {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
getCallback().recordStop();
ActivityUtils.vibrate(getContext(), 1000);
transition.resetTransition();
};
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
return true;
}
return false;
}
public void hide() {
viewBinding.controllerContainer.setVisibility(View.GONE);
}
public void show() {
viewBinding.controllerContainer.setVisibility(View.VISIBLE);
}
private void updateTotalTime() {
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
if (trackRecordingService != null) {
totalTime = trackRecordingService.getTotalTime();
}
}
private void setTotalTime() {
if (totalTime != null) {
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
}
}
private void showStatusSetDefaultText() {
viewBinding.controllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
}
private Callback getCallback() {
return (Callback) getActivity();
}
public interface Callback {
void recordStart();
void recordPause();
void recordStop();
}
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
recordingStatus = status;
if (!recordingStatus.isRecording()) {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
}
if (recordingStatus.isRecordingAndNotPaused()) {
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UI_UPDATE_INTERVAL.toMillis());
}
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
viewBinding.controllerRecord.setContentDescription(getContext().getString(recordingStatus.isRecordingAndNotPaused() ? R.string.image_pause : R.string.image_record));
viewBinding.controllerStop.setEnabled(recordingStatus.isRecording());
viewBinding.controllerStatus.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
if (recordingStatus.isRecording()) {
viewBinding.controllerStatus.setTextColor(getContext().getResources().getColor(recordingStatus.isPaused() ? android.R.color.white : R.color.recording_text));
showStatusSetDefaultText();
}
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
if (recordingStatus.isRecording()) {
updateTotalTime();
setTotalTime();
}
}
}
@@ -175,7 +175,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker);
searchMenuItem = menu.findItem(R.id.marker_list_search);
ActivityUtils.configureSearchWidget(this, searchMenuItem, null);
ActivityUtils.configureSearchWidget(this, searchMenuItem);
return super.onCreateOptionsMenu(menu);
}
@@ -1,260 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import java.time.Duration;
import de.dennisguse.opentracks.databinding.TrackControllerBinding;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.StringUtils;
/**
* Track controller for record, pause, resume, and stop.
*
* @author Jimmy Shih
*/
//TODO Subscribe to TrackRecordingService.recordingStatus
//TODO Could be a fragment
public class TrackController implements View.OnTouchListener {
private static final String TAG = TrackController.class.getSimpleName();
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
private final Activity activity;
private final TrackRecordingServiceConnection trackRecordingServiceConnection;
private final Handler handlerUpdateTotalTime = new Handler();
private final boolean alwaysShow;
private Runnable buttonDelay;
private final int buttonDelayDuration;
private final TrackControllerBinding viewBinding;
private final TransitionDrawable transition;
private TrackRecordingService.RecordingStatus recordingStatus;
private Duration totalTime;
private final Callback callback;
// A runnable to update the total time.
private final Runnable updateTotalTimeRunnable = new Runnable() {
public void run() {
if (isResumed() && recordingStatus.isRecordingAndNotPaused()) {
updateTotalTime();
setTotalTime();
handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
}
}
};
@SuppressLint("ClickableViewAccessibility")
TrackController(Activity activity, TrackControllerBinding viewBinding, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, Callback callback) {
this.activity = activity;
this.viewBinding = viewBinding;
this.trackRecordingServiceConnection = trackRecordingServiceConnection;
this.alwaysShow = alwaysShow;
this.callback = callback;
buttonDelayDuration = activity.getResources().getInteger(R.integer.buttonDelayMillis);
viewBinding.trackControllerRecord.setOnTouchListener(this);
viewBinding.trackControllerRecord.setOnClickListener((view) -> {
if (buttonDelay != null || recordingStatus.isRecordingAndNotPaused()) {
return;
}
callback.recordStart();
});
viewBinding.trackControllerStop.setOnTouchListener(this);
transition = (TransitionDrawable) viewBinding.trackControllerContainer.getBackground();
}
@SuppressLint("ClickableViewAccessibility") //We do accessibility manually.
@Override
public boolean onTouch(final View view, MotionEvent event) {
if (!isResumed()) {
Log.w(TAG, "The UI is already gone, no need to update anything; seen on Android 7.1.2");
return false;
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
return false;
}
if (buttonDelay != null && event.getAction() == MotionEvent.ACTION_UP) {
handlerUpdateTotalTime.removeCallbacks(buttonDelay);
buttonDelay = null;
view.setPressed(false);
transition.resetTransition();
showStatusSetDefaultText();
return false;
}
//Trigger button pressed animation
view.setPressed(true);
//To pause a recording
if (viewBinding.trackControllerRecord.equals(view)
&& event.getAction() == MotionEvent.ACTION_DOWN
&& recordingStatus.isRecordingAndNotPaused()) {
transition.startTransition(buttonDelayDuration);
ActivityUtils.vibrate(activity, 150);
viewBinding.trackControllerStatus.setText(R.string.hold_to_pause);
buttonDelay = () -> {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
view.performClick();
callback.recordPause();
transition.resetTransition();
ActivityUtils.vibrate(activity, 1000);
};
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
return true;
}
//To stop a recording
if (viewBinding.trackControllerStop.equals(view)
&& event.getAction() == MotionEvent.ACTION_DOWN
&& recordingStatus.isRecording()) {
transition.startTransition(buttonDelayDuration);
ActivityUtils.vibrate(activity, 150);
viewBinding.trackControllerStatus.setText(R.string.hold_to_stop);
buttonDelay = () -> {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
callback.recordStop();
ActivityUtils.vibrate(activity, 1000);
transition.resetTransition();
};
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
return true;
}
return false;
}
public void update(TrackRecordingService.RecordingStatus recordingStatus) {
if (!isResumed()) {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
return;
}
this.recordingStatus = recordingStatus;
boolean isRecording = recordingStatus.isRecording();
boolean isRecordingPaused = recordingStatus.isPaused();
boolean visible = alwaysShow || isRecording;
viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
if (!visible) {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
return;
}
if (isRecording && !isRecordingPaused) {
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UI_UPDATE_INTERVAL.toMillis());
}
viewBinding.trackControllerRecord.setImageResource(isRecording && !isRecordingPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isRecordingPaused ? R.string.image_pause : R.string.image_record));
viewBinding.trackControllerStop.setEnabled(isRecording);
viewBinding.trackControllerStatus.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
if (isRecording) {
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isRecordingPaused ? android.R.color.white : R.color.recording_text));
showStatusSetDefaultText();
}
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
if (recordingStatus.isRecording()) {
updateTotalTime();
setTotalTime();
}
}
void onResume(TrackRecordingService.RecordingStatus recordingStatus) {
this.recordingStatus = recordingStatus;
update(recordingStatus);
}
void onPause() {
recordingStatus = null;
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
}
public void hide() {
viewBinding.trackControllerContainer.setVisibility(View.GONE);
}
public void show() {
viewBinding.trackControllerContainer.setVisibility(View.VISIBLE);
}
private void updateTotalTime() {
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
if (trackRecordingService != null) {
totalTime = trackRecordingService.getTotalTime();
}
}
private void setTotalTime() {
if (totalTime != null) {
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
}
}
private void showStatusSetDefaultText() {
viewBinding.trackControllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
}
private boolean isResumed() {
return recordingStatus != null;
}
public interface Callback {
void recordStart();
void recordPause();
void recordStop();
}
}
@@ -71,14 +71,13 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
*
* @author Leif Hendrik Wilden
*/
public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackController.Callback {
public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, ControllerFragment.Callback {
private static final String TAG = TrackListActivity.class.getSimpleName();
// The following are set in onCreate
private SharedPreferences sharedPreferences;
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackController trackController;
private ResourceCursorAdapter resourceCursorAdapter;
private TrackListBinding viewBinding;
@@ -118,7 +117,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
runOnUiThread(() -> {
TrackListActivity.this.invalidateOptionsMenu();
loaderCallbacks.restart();
trackController.onResume(recordingStatus);
});
}
}
@@ -132,9 +130,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
private final Runnable bindChangedCallback = new Runnable() {
@Override
public void run() {
// After binding changes (e.g., becomes available), update the total time in trackController.
runOnUiThread(() -> trackController.update(recordingStatus));
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
if (service == null) {
Log.e(TAG, "service not available to start gps or a new recording");
@@ -170,14 +165,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
trackController = new TrackController(this, viewBinding.trackControllerContainer, trackRecordingServiceConnection, true, this);
// Show trackController when search dialog is dismissed
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
if (searchManager != null) {
searchManager.setOnDismissListener(() -> trackController.show());
}
viewBinding.trackList.setEmptyView(viewBinding.trackListEmptyView);
viewBinding.trackList.setOnItemClickListener((parent, view, position, trackId) -> {
@@ -250,14 +237,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
trackRecordingServiceConnection.startConnection(this);
}
@Override
protected void onPause() {
super.onPause();
// Update UI
trackController.onPause();
}
@Override
protected void onResume() {
super.onResume();
@@ -265,7 +244,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
// Update UI
this.invalidateOptionsMenu();
LoaderManager.getInstance(this).restartLoader(0, null, loaderCallbacks);
trackController.onResume(recordingStatus);
}
@Override
@@ -298,7 +276,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
getMenuInflater().inflate(R.menu.track_list, menu);
searchMenuItem = menu.findItem(R.id.track_list_search);
ActivityUtils.configureSearchWidget(this, searchMenuItem, trackController);
ActivityUtils.configureSearchWidget(this, searchMenuItem);
startGpsMenuItem = menu.findItem(R.id.track_list_start_gps);
return super.onCreateOptionsMenu(menu);
@@ -396,13 +374,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
loaderCallbacks.setSearch(searchQuery);
}
@Override
public boolean onSearchRequested() {
// Hide trackController when search dialog is shown
trackController.hide();
return super.onSearchRequested();
}
@Override
protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
return trackRecordingServiceConnection;
@@ -585,10 +556,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
updateGpsMenuItem(true, recordingStatus.isRecording());
}
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
recordingStatus = status;
trackController.update(recordingStatus);
}
}
@@ -43,7 +43,7 @@ import de.dennisguse.opentracks.util.TrackUtils;
*/
//NOTE: This activity does NOT react to preference changes of R.string.recording_track_id_key.
//This mode of communication should be removed anyhow.
public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, TrackController.Callback {
public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, ControllerFragment.Callback {
public static final String EXTRA_TRACK_ID = "track_id";
@@ -56,7 +56,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
private SharedPreferences sharedPreferences;
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackDataHub trackDataHub;
private TrackController trackController;
private TrackRecordingBinding viewBinding;
@@ -90,8 +89,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
// A recording track is on.
trackDataHub.loadTrack(trackId);
trackDataHub.setRecordingStatus(recordingStatus);
trackController.onResume(recordingStatus);
}
}
};
@@ -148,8 +145,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
if (savedInstanceState != null) {
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
}
trackController = new TrackController(this, viewBinding.trackControllerContainer, trackRecordingServiceConnection, false, this);
}
@Override
@@ -214,7 +209,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
//TODO Pass recordingStatus directly to them
trackDataHub.loadTrack(trackId);
trackDataHub.setRecordingStatus(recordingStatus);
trackController.onResume(recordingStatus);
}
/*
@@ -233,12 +227,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
outState.putParcelable(EXTRA_TRACK_ID, trackId);
}
@Override
protected void onPause() {
super.onPause();
trackController.onPause();
}
@Override
protected void onStop() {
super.onStop();
@@ -406,7 +394,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
recordingStatus = status;
trackController.update(recordingStatus);
trackDataHub.setRecordingStatus(recordingStatus);
setLockscreenPolicy();
@@ -23,7 +23,6 @@ import java.util.ArrayList;
import de.dennisguse.opentracks.ContextualActionModeCallback;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackController;
import static android.content.Context.VIBRATOR_SERVICE;
@@ -88,7 +87,7 @@ public class ActivityUtils {
});
}
public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) {
public static void configureSearchWidget(Activity activity, final MenuItem menuItem) {
final SearchView searchView = (SearchView) menuItem.getActionView();
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null) {
@@ -99,16 +98,6 @@ public class ActivityUtils {
}
searchView.setQueryRefinementEnabled(true);
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
// Hide and show trackController when searchable widget has focus/no focus
if (trackController != null) {
if (hasFocus) {
trackController.hide();
} else {
trackController.show();
}
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
@@ -136,8 +125,8 @@ public class ActivityUtils {
});
}
public static void vibrate(Activity activity, int milliseconds) {
final Vibrator vibrator = (Vibrator) activity.getSystemService(VIBRATOR_SERVICE);
public static void vibrate(Context context, int milliseconds) {
final Vibrator vibrator = (Vibrator) context.getSystemService(VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/controller_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/controller_background"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<ImageButton
android:id="@+id/controller_record"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_record"
android:src="@drawable/ic_button_record" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6">
<TextView
android:id="@+id/controller_total_time"
style="@style/TextSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/controller_status"
style="@style/TextMicro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/controller_total_time"
android:layout_centerHorizontal="true"
android:singleLine="true" />
</RelativeLayout>
<ImageButton
android:id="@+id/controller_stop"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_stop"
android:src="@drawable/button_stop" />
</LinearLayout>
@@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2013 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="@+id/track_controller_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/track_controller_background"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<ImageButton
android:id="@+id/track_controller_record"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_record"
android:src="@drawable/ic_button_record" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6">
<TextView
android:id="@+id/track_controller_total_time"
style="@style/TextSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/track_controller_status"
style="@style/TextMicro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/track_controller_total_time"
android:layout_centerHorizontal="true"
android:singleLine="true" />
</RelativeLayout>
<ImageButton
android:id="@+id/track_controller_stop"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_stop"
android:src="@drawable/button_stop" />
</LinearLayout>
</merge>
+5 -3
View File
@@ -27,9 +27,11 @@ limitations under the License.
android:baselineAligned="false"
android:orientation="horizontal">
<include
android:id="@+id/track_controller_container"
layout="@layout/track_controller" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/controller_fragment"
android:name="de.dennisguse.opentracks.ControllerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/track_list"
+5 -3
View File
@@ -11,9 +11,11 @@
android:layout_height="match_parent"
android:orientation="horizontal">
<include
android:id="@+id/track_controller_container"
layout="@layout/track_controller" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/controller_fragment"
android:name="de.dennisguse.opentracks.ControllerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2012 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/controller_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/controller_background"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<ImageButton
android:id="@+id/controller_record"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_record"
android:src="@drawable/ic_button_record" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="6">
<TextView
android:id="@+id/controller_total_time"
style="@style/TextSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:gravity="center"
android:textColor="@android:color/white"
tools:text="0:12:34" />
<TextView
android:id="@+id/controller_status"
style="@style/TextMicro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/controller_total_time"
android:layout_alignParentStart="true"
android:gravity="center"
android:singleLine="true"
tools:text="@string/generic_recording" />
</RelativeLayout>
<ImageButton
android:id="@+id/controller_stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_stop"
android:src="@drawable/button_stop" />
</LinearLayout>
-75
View File
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2012 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/track_controller_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/track_controller_background"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<ImageButton
android:id="@+id/track_controller_record"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_record"
android:src="@drawable/ic_button_record" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="6">
<TextView
android:id="@+id/track_controller_total_time"
style="@style/TextSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:gravity="center"
android:textColor="@android:color/white"
tools:text="0:12:34" />
<TextView
android:id="@+id/track_controller_status"
style="@style/TextMicro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/track_controller_total_time"
android:layout_alignParentStart="true"
android:gravity="center"
android:singleLine="true"
tools:text="@string/generic_recording" />
</RelativeLayout>
<ImageButton
android:id="@+id/track_controller_stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="10"
android:background="@android:color/transparent"
android:contentDescription="@string/image_stop"
android:src="@drawable/button_stop" />
</LinearLayout>
</merge>
+5 -3
View File
@@ -83,7 +83,9 @@ limitations under the License.
</LinearLayout>
</RelativeLayout>
<include
android:id="@+id/track_controller_container"
layout="@layout/track_controller" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/controller_fragment"
android:name="de.dennisguse.opentracks.ControllerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
+5 -3
View File
@@ -17,7 +17,9 @@
android:layout_height="0dp"
android:layout_weight="1" />
<include
android:id="@+id/track_controller_container"
layout="@layout/track_controller" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/controller_fragment"
android:name="de.dennisguse.opentracks.ControllerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>