From 619b82a23e3e2fdf6923f339be1a280af563ac1f Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Sun, 16 Jan 2022 16:25:52 +0100 Subject: [PATCH] Package structure: moved functionality from FileUtils to MarkerUtils. Part of #963. --- .../opentracks/content/data/TestDataUtil.java | 3 +- .../opentracks/data/ContentProviderUtils.java | 3 +- .../io/file/exporter/KMLTrackExporter.java | 4 +- .../io/file/exporter/KmzTrackExporter.java | 3 +- .../io/file/importer/TrackImporter.java | 3 +- .../ui/markers/MarkerEditActivity.java | 3 +- .../ui/markers/MarkerEditViewModel.java | 4 +- .../opentracks/ui/markers/MarkerUtils.java | 97 ++++++++++++++++++- .../dennisguse/opentracks/util/FileUtils.java | 79 +-------------- .../opentracks/util/IntentUtils.java | 30 ------ 10 files changed, 110 insertions(+), 119 deletions(-) diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java index 10b5dd6a0..38100f62d 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -20,6 +20,7 @@ import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; +import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.FileUtils; public class TestDataUtil { @@ -150,7 +151,7 @@ public class TestDataUtil { } public static Marker createMarkerWithPhoto(Context context, Track.Id trackId, TrackPoint trackPoint) throws IOException { - File dstFile = new File(FileUtils.getImageUrl(context, trackId)); + File dstFile = new File(MarkerUtils.getImageUrl(context, trackId)); dstFile.createNewFile(); Uri photoUri = FileUtils.getUriForFile(context, dstFile); String photoUrl = photoUri.toString(); diff --git a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java index ebb110c45..1f35ffac4 100644 --- a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java @@ -54,6 +54,7 @@ import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.stats.SensorStatistics; import de.dennisguse.opentracks.stats.TrackStatistics; +import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.FileUtils; /** @@ -477,7 +478,7 @@ public class ContentProviderUtils { private void deleteMarkerPhoto(Context context, Marker marker) { if (marker != null && marker.hasPhoto()) { Uri uri = marker.getPhotoURI(); - File file = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), uri); + File file = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), uri); if (file.exists()) { File parent = file.getParentFile(); file.delete(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java index e11b23065..639090e19 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java @@ -40,7 +40,7 @@ import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; -import de.dennisguse.opentracks.util.FileUtils; +import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.StringUtils; /** @@ -267,7 +267,7 @@ public class KMLTrackExporter implements TrackExporter { private void writeMarker(Marker marker, ZoneOffset zoneOffset) { if (printWriter != null) { - boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null; + boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoURI()) != null; if (marker.hasPhoto() && exportPhotos && existsPhoto) { float heading = getHeading(marker.getTrackId(), marker.getLocation()); writePhotoOverlay(marker, heading, zoneOffset); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java index 6d0790603..99c59f0e0 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KmzTrackExporter.java @@ -34,6 +34,7 @@ import java.util.zip.ZipOutputStream; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; +import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.FileUtils; /** @@ -101,7 +102,7 @@ public class KmzTrackExporter implements TrackExporter { Marker marker = contentProviderUtils.createMarker(cursor); if (marker.hasPhoto()) { Uri uriPhoto = marker.getPhotoURI(); - boolean existsPhoto = FileUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null; + boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null; if (existsPhoto) { addImage(context, zipOutputStream, uriPhoto, marker); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index 77ebf13eb..e4fde80a6 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -27,6 +27,7 @@ import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; +import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.TrackIconUtils; @@ -275,7 +276,7 @@ public class TrackImporter { */ private String getInternalPhotoUrl(@NonNull Track.Id trackId, @NonNull String externalPhotoUrl) { String importFileName = KmzTrackImporter.importNameForFilename(externalPhotoUrl); - File file = FileUtils.buildInternalPhotoFile(context, trackId, Uri.parse(importFileName)); + File file = MarkerUtils.buildInternalPhotoFile(context, trackId, Uri.parse(importFileName)); if (file != null) { Uri photoUri = FileUtils.getUriForFile(context, file); return "" + photoUri; 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 425b48e19..faa6d4f45 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java @@ -44,7 +44,6 @@ 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.util.IntentUtils; /** * An activity to add/edit a marker. @@ -225,7 +224,7 @@ public class MarkerEditActivity extends AbstractActivity { } private void createMarkerWithPicture() { - Pair intentAndPhotoUri = IntentUtils.createTakePictureIntent(this, getTrackId()); + Pair intentAndPhotoUri = MarkerUtils.createTakePictureIntent(this, getTrackId()); cameraPhotoUri = intentAndPhotoUri.second; takePictureFromCamera.launch(intentAndPhotoUri.first); } 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 f76a98a33..ee58ccfcb 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java @@ -84,7 +84,7 @@ public class MarkerEditViewModel extends AndroidViewModel { return; } - File photoFile = FileUtils.getPhotoFileIfExists(getApplication(), markerData.getValue().getTrackId(), photoUri); + File photoFile = MarkerUtils.getPhotoFileIfExists(getApplication(), markerData.getValue().getTrackId(), photoUri); if (photoFile != null) { FileUtils.deleteDirectoryRecurse(photoFile); } @@ -124,7 +124,7 @@ public class MarkerEditViewModel extends AndroidViewModel { try (ParcelFileDescriptor parcelFd = getApplication().getContentResolver().openFileDescriptor(srcUri, "r")) { FileDescriptor srcFd = parcelFd.getFileDescriptor(); - File dstFile = new File(FileUtils.getImageUrl(getApplication(), marker.getTrackId())); + File dstFile = new File(MarkerUtils.getImageUrl(getApplication(), marker.getTrackId())); FileUtils.copy(srcFd, dstFile); Uri photoUri = FileUtils.getUriForFile(getApplication(), dstFile); diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerUtils.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerUtils.java index 85c173852..2dde157b7 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerUtils.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerUtils.java @@ -1,16 +1,34 @@ package de.dennisguse.opentracks.ui.markers; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.provider.MediaStore; +import android.util.Log; +import android.util.Pair; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.core.content.ContextCompat; +import androidx.core.content.FileProvider; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.data.models.Track; +import de.dennisguse.opentracks.util.FileUtils; public class MarkerUtils { - public static final int ICON_ID = R.drawable.ic_marker_orange_pushpin_with_shadow; + private static final String TAG = FileUtils.class.getSimpleName(); + + static final int ICON_ID = R.drawable.ic_marker_orange_pushpin_with_shadow; + + private static final String JPEG_EXTENSION = "jpeg"; private MarkerUtils() { } @@ -18,4 +36,81 @@ public class MarkerUtils { public static Drawable getDefaultPhoto(@NonNull Context context) { return ContextCompat.getDrawable(context, ICON_ID); } + + /** + * Sends a take picture request to the camera app. + * The picture is then stored in the track's folder. + * + * @param context the context + * @param trackId the track id + */ + static Pair createTakePictureIntent(Context context, Track.Id trackId) { + File dir = FileUtils.getPhotoDir(context, trackId); + + String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); + File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); + + Uri photoUri = FileProvider.getUriForFile(context, FileUtils.FILEPROVIDER, file); + Log.d(TAG, "Taking photo to URI: " + photoUri); + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE) + .putExtra(MediaStore.EXTRA_OUTPUT, photoUri); + return new Pair<>(intent, photoUri); + } + + @VisibleForTesting(otherwise = 3) + public static String getImageUrl(Context context, Track.Id trackId) { + File dir = FileUtils.getPhotoDir(context, trackId); + + String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); + File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); + + return file.getAbsolutePath(); + } + + /** + * Checks that there is a file inside track photo directory whose name is the same that uri file. + * If there is a file inside photo directory whose name is the same that uri then returns File. Otherwise returns null. + * + * @param context the Context. + * @param trackId the id of the Track. + * @param uri the uri to check. + * @return File object or null. + */ + public static File getPhotoFileIfExists(Context context, Track.Id trackId, Uri uri) { + if (uri == null) { + Log.w(TAG, "URI object is null."); + return null; + } + + String filename = uri.getLastPathSegment(); + if (filename == null) { + Log.w(TAG, "External photo contains no filename."); + return null; + } + + File dir = FileUtils.getPhotoDir(context, trackId); + File file = new File(dir, filename); + if (!file.exists()) { + return null; + } + + return file; + } + + @Nullable + public static File buildInternalPhotoFile(Context context, Track.Id trackId, @NonNull Uri fileNameUri) { + if (fileNameUri == null) { + Log.w(TAG, "URI object is null."); + return null; + } + + String filename = fileNameUri.getLastPathSegment(); + if (filename == null) { + Log.w(TAG, "External photo contains no filename."); + return null; + } + + File dir = FileUtils.getPhotoDir(context, trackId); + return new File(dir, filename); + } } diff --git a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java index 79e518b27..edaab6a27 100644 --- a/src/main/java/de/dennisguse/opentracks/util/FileUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/FileUtils.java @@ -20,7 +20,6 @@ import android.net.Uri; import android.os.Environment; import android.util.Log; -import androidx.annotation.NonNull; import androidx.core.content.FileProvider; import androidx.documentfile.provider.DocumentFile; @@ -29,9 +28,7 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; -import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import de.dennisguse.opentracks.BuildConfig; import de.dennisguse.opentracks.data.models.Track; @@ -45,12 +42,7 @@ public class FileUtils { private static final String TAG = FileUtils.class.getSimpleName(); - /** - * Used to transfer picture from the camera. - */ - static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider"; - - private static final String JPEG_EXTENSION = "jpeg"; + public static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider"; /** * The maximum FAT32 path length. See the FAT32 spec at @@ -218,21 +210,6 @@ public class FileUtils { return name; } - /** - * Returns the image's absolute path from a track identified by trackId. - * - * @param context the context. - * @param trackId the track id. - */ - public static String getImageUrl(Context context, Track.Id trackId) { - File dir = FileUtils.getPhotoDir(context, trackId); - - String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); - File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); - - return file.getAbsolutePath(); - } - /** * Copy a File (src) to a File (dst). * @@ -259,60 +236,6 @@ public class FileUtils { return FileProvider.getUriForFile(context, FileUtils.FILEPROVIDER, file); } - /** - * Checks that there is a file inside track photo directory whose name is the same that uri file. - * If there is a file inside photo directory whose name is the same that uri then returns File. Otherwise returns null. - * - * @param context the Context. - * @param trackId the id of the Track. - * @param uri the uri to check. - * @return File object or null. - */ - public static File getPhotoFileIfExists(Context context, Track.Id trackId, Uri uri) { - if (uri == null) { - Log.w(TAG, "URI object is null."); - return null; - } - - String filename = uri.getLastPathSegment(); - if (filename == null) { - Log.w(TAG, "External photo contains no filename."); - return null; - } - - File dir = FileUtils.getPhotoDir(context, trackId); - File file = new File(dir, filename); - if (!file.exists()) { - return null; - } - - return file; - } - - /** - * Builds interval photo file object for fileNameUri Uri. - * - * @param context the Context. - * @param trackId the id of the Track. - * @param fileNameUri the file name uri. - * @return file object or null. - */ - public static File buildInternalPhotoFile(Context context, Track.Id trackId, @NonNull Uri fileNameUri) { - if (fileNameUri == null) { - Log.w(TAG, "URI object is null."); - return null; - } - - String filename = fileNameUri.getLastPathSegment(); - if (filename == null) { - Log.w(TAG, "External photo contains no filename."); - return null; - } - - File dir = FileUtils.getPhotoDir(context, trackId); - return new File(dir, filename); - } - /** * Delete the directory recursively. * diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java index d9c326e24..3d7947d26 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentUtils.java @@ -20,19 +20,10 @@ import android.content.Context; import android.content.Intent; import android.content.UriPermission; import android.net.Uri; -import android.provider.MediaStore; -import android.util.Log; -import android.util.Pair; -import androidx.core.content.FileProvider; import androidx.documentfile.provider.DocumentFile; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; - import de.dennisguse.opentracks.data.models.Marker; -import de.dennisguse.opentracks.data.models.Track; /** * Utilities for creating intents. @@ -83,27 +74,6 @@ public class IntentUtils { context.startActivity(Intent.createChooser(intent, null)); } - - /** - * Sends a take picture request to the camera app. - * The picture is then stored in the track's folder. - * - * @param context the context - * @param trackId the track id - */ - public static Pair createTakePictureIntent(Context context, Track.Id trackId) { - File dir = FileUtils.getPhotoDir(context, trackId); - - String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date()); - File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION)); - - Uri photoUri = FileProvider.getUriForFile(context, FileUtils.FILEPROVIDER, file); - Log.d(TAG, "Taking photo to URI: " + photoUri); - Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE) - .putExtra(MediaStore.EXTRA_OUTPUT, photoUri); - return new Pair<>(intent, photoUri); - } - public static void persistDirectoryAccessPermission(Context context, Uri directoryUri, int existingFlags) { int newFlags = existingFlags & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); context.getContentResolver().takePersistableUriPermission(directoryUri, newFlags);