diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java index 97c3bc725..9ea5ffa1c 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceConnection.java @@ -111,6 +111,13 @@ public class TrackRecordingServiceConnection { stopService(context); } + /** + * WARNING: Do not keep a reference to this returned value. + */ + public TrackRecordingService getTrackRecordingService() { + return trackRecordingService; + } + private void setTrackRecordingService(TrackRecordingService value) { trackRecordingService = value; if (value != null) { @@ -128,16 +135,16 @@ public class TrackRecordingServiceConnection { try { Marker.Id marker = trackRecordingService.insertMarker(name, category, description, photoUrl); - if (marker != null) { - Toast.makeText(context, R.string.marker_add_success, Toast.LENGTH_SHORT).show(); - return marker; + if (marker == null) { + Toast.makeText(context, R.string.marker_add_error, Toast.LENGTH_LONG).show(); + return null; } + + return marker; } catch (IllegalStateException e) { Log.e(TAG, "Unable to add marker.", e); + return null; } - - Toast.makeText(context, R.string.marker_add_error, Toast.LENGTH_LONG).show(); - return null; } public void stopRecording(@NonNull Context context) { diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java index 97d597ebe..c0c3805cb 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java @@ -36,6 +36,7 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.PickVisualMediaRequest; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.ViewModelProvider; import java.io.FileDescriptor; @@ -46,6 +47,7 @@ import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.databinding.MarkerEditBinding; +import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; /** * An activity to add/edit a marker. @@ -59,6 +61,8 @@ public class MarkerEditActivity extends AbstractActivity { private static final String CAMERA_PHOTO_URI_KEY = "camera_photo_uri_key"; + private static final String NEW_MARKER_ID = "new_marker_id"; + private static final String TAG = MarkerEditActivity.class.getSimpleName(); private Track.Id trackId; private Marker marker; @@ -88,10 +92,15 @@ public class MarkerEditActivity extends AbstractActivity { super.onCreate(savedInstanceState); trackId = getIntent().getParcelableExtra(EXTRA_TRACK_ID); - Marker.Id markerId = getIntent().getParcelableExtra(EXTRA_MARKER_ID); + @Nullable Marker.Id markerId = getIntent().getParcelableExtra(EXTRA_MARKER_ID); + final boolean isNewMarker = markerId == null; if (savedInstanceState != null) { cameraPhotoUri = Uri.parse(savedInstanceState.getString(CAMERA_PHOTO_URI_KEY, "")); + Marker.Id newMarkerId = savedInstanceState.getParcelable(NEW_MARKER_ID); + if (newMarkerId != null) { + markerId = newMarkerId; + } } hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY); @@ -104,11 +113,10 @@ public class MarkerEditActivity extends AbstractActivity { viewBinding.markerEditDescription.getText().toString())); viewBinding.markerEditCancel.setOnClickListener(v -> { - viewModel.onCancel(); + viewModel.onCancel(isNewMarker); finish(); }); - boolean isNewMarker = markerId == null; if (!isNewMarker) { viewBinding.markerEditToolbar.setTitle(R.string.menu_edit); } @@ -121,19 +129,6 @@ public class MarkerEditActivity extends AbstractActivity { }); viewModel = new ViewModelProvider(this).get(MarkerEditViewModel.class); - viewModel.getMarkerData(trackId, markerId).observe(this, data -> { - marker = data; - viewBinding.markerEditName.setText(marker.getName()); - viewBinding.markerEditMarkerType.setText(marker.getCategory()); - viewBinding.markerEditDescription.setText(marker.getDescription()); - if (marker.hasPhoto()) { - setMarkerImageView(marker.getPhotoURI()); - } else { - viewBinding.markerEditPhoto.setImageDrawable(null); - } - - hideAndShowOptions(); - }); takePictureFromCamera = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), @@ -161,9 +156,40 @@ public class MarkerEditActivity extends AbstractActivity { } }); + + if (markerId == null) { + new TrackRecordingServiceConnection((service, self) -> { + Marker.Id newMarkerId = self.addMarker(MarkerEditActivity.this, "", "", "", null); + if (newMarkerId == null) { + finish(); + } else { + loadMarkerData(newMarkerId); + } + self.unbind(this); + }).bind(this); + } else { + loadMarkerData(markerId); + } + setSupportActionBar(viewBinding.bottomAppBarLayout.bottomAppBar); } + private void loadMarkerData(Marker.Id markerId) { + viewModel.getMarkerData(markerId).observe(this, data -> { + marker = data; + viewBinding.markerEditName.setText(marker.getName()); + viewBinding.markerEditMarkerType.setText(marker.getCategory()); + viewBinding.markerEditDescription.setText(marker.getDescription()); + if (marker.hasPhoto()) { + setMarkerImageView(marker.getPhotoURI()); + } else { + viewBinding.markerEditPhoto.setImageDrawable(null); + } + + hideAndShowOptions(); + }); + } + @Override protected void onDestroy() { super.onDestroy(); @@ -181,6 +207,8 @@ public class MarkerEditActivity extends AbstractActivity { if (cameraPhotoUri != null) { outState.putString(CAMERA_PHOTO_URI_KEY, cameraPhotoUri.toString()); } + + outState.putParcelable(NEW_MARKER_ID, marker.getId()); } @Override @@ -238,7 +266,7 @@ public class MarkerEditActivity extends AbstractActivity { viewBinding.markerEditPhoto.setImageBitmap(bitmap); hideAndShowOptions(); } catch (IOException e) { - Log.e(TAG, "" + e); + Log.e(TAG, e.getMessage()); Toast.makeText(this, R.string.marker_add_photo_canceled, Toast.LENGTH_LONG).show(); } } diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java index 40f83c784..832d9baee 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java @@ -15,14 +15,11 @@ import androidx.lifecycle.MutableLiveData; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; -import java.time.Instant; import java.util.NoSuchElementException; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Marker; -import de.dennisguse.opentracks.data.models.Track; -import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.util.FileUtils; public class MarkerEditViewModel extends AndroidViewModel { @@ -30,49 +27,29 @@ public class MarkerEditViewModel extends AndroidViewModel { private static final String TAG = MarkerEditViewModel.class.getSimpleName(); private MutableLiveData markerData; - private boolean isNewMarker; private Uri photoOriginalUri; - private final TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection((service, connection) -> {}); public MarkerEditViewModel(@NonNull Application application) { super(application); } - public LiveData getMarkerData(@NonNull Track.Id trackId, @Nullable Marker.Id markerId) { + public LiveData getMarkerData(@NonNull Marker.Id markerId) { if (markerData == null) { markerData = new MutableLiveData<>(); - trackRecordingServiceConnection.bind(getApplication()); - loadData(trackId, markerId); - } - return markerData; - } - @Override - protected void onCleared() { - super.onCleared(); - trackRecordingServiceConnection.unbind(getApplication()); - } - - private void loadData(Track.Id trackId, Marker.Id markerId) { - Marker marker; - isNewMarker = markerId == null; - if (isNewMarker) { - int nextMarkerNumber = trackId == null ? 0 : new ContentProviderUtils(getApplication()).getNextMarkerNumber(trackId); - marker = new Marker(trackId, (Instant) null); - marker.setName(getApplication().getString(R.string.marker_name_format, nextMarkerNumber)); - } else { - marker = new ContentProviderUtils(getApplication()).getMarker(markerId); + Marker marker = new ContentProviderUtils(getApplication()).getMarker(markerId); if (marker.hasPhoto()) { photoOriginalUri = marker.getPhotoURI(); } + + markerData.postValue(marker); } - markerData.postValue(marker); + return markerData; } private @NonNull Marker getMarker() throws NoSuchElementException { Marker marker = markerData != null ? markerData.getValue() : null; if (marker == null) { - Log.d(TAG, "Marker data shouldn't be null. Call getMarkerData before."); throw new NoSuchElementException("Marker data shouldn't be null. Call getMarkerData before."); } @@ -97,7 +74,7 @@ public class MarkerEditViewModel extends AndroidViewModel { } public void onPhotoDelete(String name, String category, String description) { - Marker marker = getMarker(); + Marker marker = getMarker(); if (marker.hasPhoto()) { if (!marker.getPhotoURI().equals(photoOriginalUri)) { deletePhoto(marker.getPhotoURI()); @@ -111,7 +88,7 @@ public class MarkerEditViewModel extends AndroidViewModel { } public void onNewCameraPhoto(@NonNull Uri photoUri, String name, String category, String description) { - Marker marker = getMarker(); + Marker marker = getMarker(); marker.setPhotoUrl(photoUri.toString()); marker.setName(name); marker.setCategory(category); @@ -120,7 +97,7 @@ public class MarkerEditViewModel extends AndroidViewModel { } public void onNewGalleryPhoto(@NonNull Uri srcUri, String name, String category, String description) { - Marker marker = getMarker(); + Marker marker = getMarker(); try (ParcelFileDescriptor parcelFd = getApplication().getContentResolver().openFileDescriptor(srcUri, "r")) { FileDescriptor srcFd = parcelFd.getFileDescriptor(); @@ -139,11 +116,9 @@ public class MarkerEditViewModel extends AndroidViewModel { } } - private void onAddDone(@NonNull Marker marker, String name, String category, String description) { - trackRecordingServiceConnection.addMarker(getApplication(), name, category, description, marker.hasPhoto() ? marker.getPhotoURI().toString() : null); - } + public void onDone(String name, String category, String description) { + Marker marker = getMarker(); - private void onSaveDone(@NonNull Marker marker, String name, String category, String description) { marker.setName(name); marker.setCategory(category); marker.setDescription(description); @@ -154,21 +129,15 @@ public class MarkerEditViewModel extends AndroidViewModel { } } - public void onDone(String name, String category, String description) { - Marker marker = getMarker(); - if (isNewMarker) { - onAddDone(marker, name, category, description); - } else { - onSaveDone(marker, name, category, description); - } - } - - public void onCancel() { + public void onCancel(boolean isNewMarker) { Marker marker = getMarker(); if (isNewMarker) { // it's new marker -> clean all photos. deletePhoto(marker); deletePhoto(photoOriginalUri); + + new ContentProviderUtils(getApplication()).deleteMarker(getApplication(), marker.getId()); + } else if (photoOriginalUri == null || (marker.hasPhoto() && !marker.getPhotoURI().equals(photoOriginalUri))) { // it's an edit marker -> delete photo if it was empty or it was changed (leaving the original in that case). deletePhoto(marker);