Package structure: moved functionality from FileUtils to MarkerUtils.

Part of #963.
This commit is contained in:
Dennis Guse
2022-01-16 16:25:52 +01:00
parent d18c67a648
commit 619b82a23e
10 changed files with 110 additions and 119 deletions
@@ -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();
@@ -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();
@@ -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);
@@ -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);
}
@@ -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;
@@ -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<Intent, Uri> intentAndPhotoUri = IntentUtils.createTakePictureIntent(this, getTrackId());
Pair<Intent, Uri> intentAndPhotoUri = MarkerUtils.createTakePictureIntent(this, getTrackId());
cameraPhotoUri = intentAndPhotoUri.second;
takePictureFromCamera.launch(intentAndPhotoUri.first);
}
@@ -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);
@@ -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<Intent, Uri> 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);
}
}
@@ -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.
*
@@ -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<Intent, Uri> 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);