Improve import/export
This commit is contained in:
Román Martínez
2020-04-23 08:21:55 +02:00
committed by GitHub
9 changed files with 276 additions and 61 deletions
@@ -88,6 +88,40 @@ public class DescriptionGeneratorTest {
Assert.assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true)); Assert.assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
} }
@Test
public void testGenerateTrackDescriptionWithoutMaxMinElevation() {
Track track = new Track();
TrackStatistics stats = new TrackStatistics();
stats.setTotalDistance(20000);
stats.setTotalTime(600000);
stats.setMovingTime(300000);
stats.setMaxSpeed(100);
stats.setMaxElevation(Double.POSITIVE_INFINITY);
stats.setMinElevation(Double.NEGATIVE_INFINITY);
stats.setTotalElevationGain(6000);
stats.setStartTime_ms(START_TIME);
track.setTrackStatistics(stats);
track.setCategory("hiking");
String expected = //"Created by"
"<a href='https://github.com/OpenTracksApp/OpenTracks'>OpenTracks</a><p>"
+ "Name: -<br>"
+ "Activity type: hiking<br>"
+ "Description: -<br>"
+ "Total distance: 20.00 km (12.4 mi)<br>"
+ "Total time: 10:00<br>"
+ "Moving time: 05:00<br>"
+ "Average speed: 120.00 km/h (74.6 mi/h)<br>"
+ "Average moving speed: 240.00 km/h (149.1 mi/h)<br>"
+ "Max speed: 360.00 km/h (223.7 mi/h)<br>"
+ "Average pace: 0:30 min/km (0:48 min/mi)<br>"
+ "Average moving pace: 0:15 min/km (0:24 min/mi)<br>"
+ "Fastest pace: 0:10 min/km (0:16 min/mi)<br>"
+ "Elevation gain: 6000 m (19685 ft)<br>"
+ "Recorded: " + StringUtils.formatDateTime(context, START_TIME) + "<br>";
Assert.assertEquals(expected, descriptionGenerator.generateTrackDescription(track, true));
}
/** /**
* Tests {@link DescriptionGenerator#writeDistance(double, StringBuilder, int, String)}. * Tests {@link DescriptionGenerator#writeDistance(double, StringBuilder, int, String)}.
@@ -126,10 +126,14 @@ public class DescriptionGenerator {
writePace(stats.getMaxSpeed(), builder, R.string.description_fastest_pace_in_minute, lineBreak); writePace(stats.getMaxSpeed(), builder, R.string.description_fastest_pace_in_minute, lineBreak);
// Max elevation // Max elevation
writeElevation(stats.getMaxElevation(), builder, R.string.description_max_elevation, lineBreak); if (stats.hasElevationMax()) {
writeElevation(stats.getMaxElevation(), builder, R.string.description_max_elevation, lineBreak);
}
// Min elevation // Min elevation
writeElevation(stats.getMinElevation(), builder, R.string.description_min_elevation, lineBreak); if (stats.hasElevationMin()) {
writeElevation(stats.getMinElevation(), builder, R.string.description_min_elevation, lineBreak);
}
// Elevation gain // Elevation gain
writeElevation(stats.getTotalElevationGain(), builder, R.string.description_elevation_gain, lineBreak); writeElevation(stats.getTotalElevationGain(), builder, R.string.description_elevation_gain, lineBreak);
@@ -32,6 +32,7 @@ import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.data.Waypoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.content.sensor.SensorDataSet;
import de.dennisguse.opentracks.util.FileUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
/** /**
@@ -162,9 +163,10 @@ public class KmlTrackWriter implements TrackWriter {
@Override @Override
public void writeWaypoint(Waypoint waypoint) { public void writeWaypoint(Waypoint waypoint) {
if (printWriter != null && exportTrackDetail) { if (printWriter != null && exportTrackDetail) {
if (waypoint.hasPhoto() && exportPhotos) { boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, waypoint.getTrackId(), waypoint.getPhotoURI()) != null;
if (waypoint.hasPhoto() && exportPhotos && existsPhoto) {
float heading = getHeading(waypoint.getTrackId(), waypoint.getLocation()); float heading = getHeading(waypoint.getTrackId(), waypoint.getLocation());
writePhotoOverlay(waypoint.getName(), waypoint.getCategory(), waypoint.getDescription(), waypoint.getLocation(), waypoint.getPhotoUrl(), heading); writePhotoOverlay(waypoint, heading);
} else { } else {
writePlacemark(waypoint.getName(), waypoint.getCategory(), waypoint.getDescription(), WAYPOINT_STYLE, waypoint.getLocation()); writePlacemark(waypoint.getName(), waypoint.getCategory(), waypoint.getDescription(), WAYPOINT_STYLE, waypoint.getLocation());
} }
@@ -322,32 +324,29 @@ public class KmlTrackWriter implements TrackWriter {
} }
/** /**
* Writes a photo overlay. * Writes a photo overlay from waypoint.
* @param name the name *
* @param category the category * @param waypoint Waypoint object.
* @param description the description * @param heading the heading.
* @param location the location
* @param photoUrl the photo url
* @param heading the heading
*/ */
private void writePhotoOverlay(String name, String category, String description, Location location, String photoUrl, float heading) { private void writePhotoOverlay(Waypoint waypoint, float heading) {
if (location != null && exportTrackDetail) { if (exportTrackDetail) {
printWriter.println("<PhotoOverlay>"); printWriter.println("<PhotoOverlay>");
printWriter.println("<name>" + StringUtils.formatCData(name) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(waypoint.getName()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(description) + "</description>"); printWriter.println("<description>" + StringUtils.formatCData(waypoint.getDescription()) + "</description>");
printWriter.print("<Camera>"); printWriter.print("<Camera>");
printWriter.print("<longitude>" + location.getLongitude() + "</longitude>"); printWriter.print("<longitude>" + waypoint.getLocation().getLongitude() + "</longitude>");
printWriter.print("<latitude>" + location.getLatitude() + "</latitude>"); printWriter.print("<latitude>" + waypoint.getLocation().getLatitude() + "</latitude>");
printWriter.print("<altitude>20</altitude>"); printWriter.print("<altitude>20</altitude>");
printWriter.print("<heading>" + heading + "</heading>"); printWriter.print("<heading>" + heading + "</heading>");
printWriter.print("<tilt>90</tilt>"); printWriter.print("<tilt>90</tilt>");
printWriter.println("</Camera>"); printWriter.println("</Camera>");
printWriter.println("<TimeStamp><when>" + getTime(location) + "</when></TimeStamp>"); printWriter.println("<TimeStamp><when>" + getTime(waypoint.getLocation()) + "</when></TimeStamp>");
printWriter.println("<styleUrl>#" + KmlTrackWriter.WAYPOINT_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + KmlTrackWriter.WAYPOINT_STYLE + "</styleUrl>");
writeCategory(category); writeCategory(waypoint.getCategory());
if (exportPhotos) { if (exportPhotos) {
printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(Uri.parse(photoUrl)) + "</href></Icon>"); printWriter.println("<Icon><href>" + KmzTrackExporter.buildKmzImageFilePath(waypoint) + "</href></Icon>");
} }
printWriter.print("<ViewVolume>"); printWriter.print("<ViewVolume>");
@@ -358,7 +357,7 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.print("<topFov>45</topFov>"); printWriter.print("<topFov>45</topFov>");
printWriter.println("</ViewVolume>"); printWriter.println("</ViewVolume>");
printWriter.println("<Point>"); printWriter.println("<Point>");
printWriter.println("<coordinates>" + getCoordinates(location, ",") + "</coordinates>"); printWriter.println("<coordinates>" + getCoordinates(waypoint.getLocation(), ",") + "</coordinates>");
printWriter.println("</Point>"); printWriter.println("</Point>");
printWriter.println("</PhotoOverlay>"); printWriter.println("</PhotoOverlay>");
} }
@@ -112,7 +112,11 @@ public class KmzTrackExporter implements TrackExporter {
} }
Waypoint waypoint = contentProviderUtils.createWaypoint(cursor); Waypoint waypoint = contentProviderUtils.createWaypoint(cursor);
if (waypoint.hasPhoto()) { if (waypoint.hasPhoto()) {
addImage(context, zipOutputStream, waypoint.getPhotoUrl()); Uri uriPhoto = waypoint.getPhotoURI();
boolean existsPhoto = FileUtils.getPhotoFileIfExists(context, track.getId(), uriPhoto) != null;
if (existsPhoto) {
addImage(context, zipOutputStream, uriPhoto, waypoint);
}
} }
cursor.moveToNext(); cursor.moveToNext();
@@ -122,11 +126,9 @@ public class KmzTrackExporter implements TrackExporter {
} }
} }
private void addImage(Context context, ZipOutputStream zipOutputStream, String photoUrl) throws IOException { private void addImage(Context context, ZipOutputStream zipOutputStream, Uri uri, Waypoint waypoint) throws IOException {
Uri uri = Uri.parse(photoUrl);
try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
ZipEntry zipEntry = new ZipEntry(buildKmzImageFilePath(uri)); ZipEntry zipEntry = new ZipEntry(buildKmzImageFilePath(waypoint));
zipOutputStream.putNextEntry(zipEntry); zipOutputStream.putNextEntry(zipEntry);
if (inputStream == null) throw new FileNotFoundException(); if (inputStream == null) throw new FileNotFoundException();
@@ -149,11 +151,13 @@ public class KmzTrackExporter implements TrackExporter {
} }
/** /**
* Builds and returns the path for the file that will be saved inside KMZ_IMAGES_DIR. * Builds and returns the path for the image that will be saved inside KMZ_IMAGES_DIR for the waypoint.
* *
* @param uri URI object. * @param waypoint Waypoint object.
*/ */
public static String buildKmzImageFilePath(Uri uri) { public static String buildKmzImageFilePath(Waypoint waypoint) {
return KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(uri.getLastPathSegment()); String ext = FileUtils.getExtension(waypoint.getPhotoUrl());
ext = ext == null ? "" : "." + ext;
return KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(waypoint.getId() + ext);
} }
} }
@@ -313,6 +313,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
*/ */
protected TrackPoint getTrackPoint() throws SAXException { protected TrackPoint getTrackPoint() throws SAXException {
TrackPoint trackPoint = createTrackPoint(); TrackPoint trackPoint = createTrackPoint();
if (trackPoint == null) {
throw new SAXException(createErrorMessage("Invalid location detected: " + trackPoint));
}
// Calculate derived attributes from the previous point // Calculate derived attributes from the previous point
if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) { if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) {
@@ -380,23 +383,15 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
return null; return null;
} }
Uri externalPhotoUri = Uri.parse(externalPhotoUrl); String importFileName = KmzTrackImporter.importNameForFilename(externalPhotoUrl);
if (externalPhotoUri == null) { File file = FileUtils.getPhotoFileIfExists(context, importTrackId, Uri.parse(importFileName));
Log.w(TAG, "Could not parse external photo url."); if (file != null) {
Uri photoUri = FileUtils.getUriForFile(context, file);
return "" + photoUri;
}
else {
return null; return null;
} }
String filename = externalPhotoUri.getLastPathSegment();
if (filename == null) {
Log.w(TAG, "External photo contains no filename.");
return null;
}
File dir = FileUtils.getPhotoDir(context, importTrackId);
File file = new File(dir, filename);
Uri photoUri = FileUtils.getUriForFile(context, file);
return "" + photoUri;
} }
/** /**
@@ -99,7 +99,7 @@ class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
for (DocumentFile candidate : file.listFiles()) { for (DocumentFile candidate : file.listFiles()) {
if (!candidate.isDirectory()) { if (!candidate.isDirectory()) {
String extension = FileUtils.getExtension(candidate.getName()); String extension = FileUtils.getExtension(candidate.getName());
if (trackFileFormat.getExtension().equals(extension)) { if (extension != null && trackFileFormat.getExtension().equals(extension)) {
files.add(candidate); files.add(candidate);
} }
} else { } else {
@@ -186,7 +186,7 @@ class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
Uri uri = contentProviderUtils.insertTrack(new Track()); Uri uri = contentProviderUtils.insertTrack(new Track());
long newId = Long.parseLong(uri.getLastPathSegment()); long newId = Long.parseLong(uri.getLastPathSegment());
trackImporter = new KmzTrackImporter(importActivity, newId); trackImporter = new KmzTrackImporter(importActivity, newId, file.getUri());
} }
} }
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.io.file.importer; package de.dennisguse.opentracks.io.file.importer;
import android.content.Context; import android.content.Context;
import android.net.Uri;
import android.util.Log; import android.util.Log;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@@ -25,9 +26,13 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import de.dennisguse.opentracks.content.data.Waypoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter; import de.dennisguse.opentracks.io.file.exporter.KmzTrackExporter;
import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.FileUtils;
@@ -42,58 +47,190 @@ public class KmzTrackImporter implements TrackImporter {
private static final String TAG = KmzTrackImporter.class.getSimpleName(); private static final String TAG = KmzTrackImporter.class.getSimpleName();
public static final List<String> KMZ_IMAGES_EXT = Arrays.asList("jpeg", "jpg", "png");
private static final int BUFFER_SIZE = 4096; private static final int BUFFER_SIZE = 4096;
private final Context context; private final Context context;
private final long importTrackId; private final long importTrackId;
private Uri uriKmzFile;
/** /**
* Constructor. * Constructor.
* *
* @param context the context * @param context the context
* @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported. * @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported.
* @param uriFile URI of the kmz file.
*/ */
KmzTrackImporter(Context context, long importTrackId) { KmzTrackImporter(Context context, long importTrackId, Uri uriFile) {
this.context = context; this.context = context;
this.importTrackId = importTrackId; this.importTrackId = importTrackId;
this.uriKmzFile = uriFile;
} }
@Override @Override
public long importFile(InputStream inputStream) { public long importFile(InputStream inputStream) {
long trackId = importTrackId; long trackId;
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
if (!copyKmzImages()) {
cleanImport(context, importTrackId);
return -1L;
}
trackId = findAndParseKmlFile(inputStream);
if (trackId == -1L) {
cleanImport(context, importTrackId);
return -1L;
}
deleteOrphanImages(context, trackId);
return trackId;
}
/**
* Copies all images that are inside KMZ to OpenTracks external storage.
*
* @return false if there are errors or true otherwise.
*/
private boolean copyKmzImages() {
try (InputStream inputStream = context.getContentResolver().openInputStream(uriKmzFile);
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
ZipEntry zipEntry; ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) { while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (Thread.interrupted()) { if (Thread.interrupted()) {
Log.d(TAG, "Thread interrupted"); Log.d(TAG, "Thread interrupted");
cleanImport(context, trackId); return false;
}
String fileName = zipEntry.getName();
if (hasImageExtension(fileName)) {
readAndSaveImageFile(zipInputStream, importNameForFilename(fileName));
}
zipInputStream.closeEntry();
}
return true;
} catch (IOException e) {
Log.e(TAG, "Unable to import file", e);
return false;
}
}
/**
* From path fileName generates an import unique name and returns it.
* The name generator is simple: change the path fileName with '-' instead of File.separatorChar.
*
* @param fileName the file name.
*/
public static String importNameForFilename(String fileName) {
// TODO this tricky code for maintain backward compatibility must be deleted some day.
/*
* In versions before v3.5.0 photo URL in KML files were wrong.
* For compatibility reasons it checks if fileName begins with "content://" or "file://".
* All fileName begins with "content:/" or "file://" are cooked.
* We cannot guess what's the folder name where images are so we use "images" that was the folder name expected in versions before v3.5.0.
*/
if (fileName.startsWith("content://") || fileName.startsWith("file://")) {
fileName = "images/" + fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
}
return fileName.replace(File.separatorChar, '-');
}
/**
* Returns true if fileName ends with some of the KMZ_IMAGES_EXT suffixes.
* Otherwise returns false.
*/
private boolean hasImageExtension(String fileName) {
if (fileName == null) {
return false;
}
String fileExt = FileUtils.getExtension(fileName.toLowerCase());
if (fileExt == null) {
return false;
}
if (KMZ_IMAGES_EXT.contains(fileExt)) {
return true;
}
return false;
}
/**
* Finds KmzTrackExporter.KMZ_KML_FILE file inside kmz file (inputStream) and it parses it.
*
* @param inputStream kmz input stream.
* @return -1 if error or the id of the track otherwise.
*/
private long findAndParseKmlFile(InputStream inputStream) {
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
ZipEntry zipEntry;
long trackId = -1L;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (Thread.interrupted()) {
Log.d(TAG, "Thread interrupted");
return -1L; return -1L;
} }
String fileName = zipEntry.getName(); String fileName = zipEntry.getName();
if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) { if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) {
trackId = parseKml(zipInputStream); trackId = parseKml(zipInputStream);
if (trackId == -1L) { if (trackId == -1L) {
Log.d(TAG, "Unable to parse kml in kmz"); Log.d(TAG, "Unable to parse kml in kmz");
cleanImport(context, trackId);
return -1L; return -1L;
} }
} else {
String prefix = KmzTrackExporter.KMZ_IMAGES_DIR + File.separatorChar;
if (fileName.startsWith(prefix)) {
readImageFile(zipInputStream, fileName.substring(prefix.length()));
}
} }
zipInputStream.closeEntry(); zipInputStream.closeEntry();
} }
return trackId; return trackId;
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Unable to import file", e); Log.e(TAG, "Unable to import file", e);
cleanImport(context, trackId);
return -1L; return -1L;
} }
} }
/**
* Deletes all images that remained in external storage that doesn't have waypoint (marker) associated.
*
* @param context the Context object.
* @param trackId the id of the Track.
*/
private void deleteOrphanImages(Context context, long trackId) {
if (trackId != 1L) {
// 1.- Gets all photo names in the waypoints of the track identified by id.
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
List<Waypoint> waypoints = contentProviderUtils.getWaypoints(trackId);
List<String> photosName = new ArrayList<>();
for (Waypoint w : waypoints) {
if (w.hasPhoto()) {
String photoUrl = Uri.decode(w.getPhotoUrl());
photosName.add(photoUrl.substring(photoUrl.lastIndexOf(File.separatorChar) + 1));
}
}
// 2.- Deletes all orphan photos from external storage.
File dir = FileUtils.getPhotoDir(context, trackId);
if (dir.exists() && dir.isDirectory()) {
for (File file : dir.listFiles()) {
if (!photosName.contains(file.getName())) {
file.delete();
}
}
if (dir.listFiles().length == 0) {
dir.delete();
}
}
}
}
/** /**
* Cleans up import. * Cleans up import.
* *
@@ -147,12 +284,12 @@ public class KmzTrackImporter implements TrackImporter {
} }
/** /**
* Reads an image file. * Reads an image file (zipInputStream) and save it in a file called fileName inside photo folder.
* *
* @param zipInputStream the zip input stream * @param zipInputStream the zip input stream
* @param fileName the file name * @param fileName the file name
*/ */
private void readImageFile(ZipInputStream zipInputStream, String fileName) throws IOException { private void readAndSaveImageFile(ZipInputStream zipInputStream, String fileName) throws IOException {
if (importTrackId == -1L || fileName.equals("")) { if (importTrackId == -1L || fileName.equals("")) {
return; return;
} }
@@ -176,6 +176,10 @@ public class TrackStatistics {
this.maxSpeed_mps = maxSpeed; this.maxSpeed_mps = maxSpeed;
} }
public boolean hasElevationMin() {
return !Double.isInfinite(getMinElevation());
}
/** /**
* Gets the minimum elevation. * Gets the minimum elevation.
* This is calculated from the smoothed elevation, so this can actually be more than the current elevation. * This is calculated from the smoothed elevation, so this can actually be more than the current elevation.
@@ -193,6 +197,10 @@ public class TrackStatistics {
elevationExtremities.setMin(elevation); elevationExtremities.setMin(elevation);
} }
public boolean hasElevationMax() {
return !Double.isInfinite(getMaxElevation());
}
/** /**
* Gets the maximum elevation. * Gets the maximum elevation.
* This is calculated from the smoothed elevation, so this can actually be less than the current elevation. * This is calculated from the smoothed elevation, so this can actually be less than the current elevation.
@@ -95,11 +95,15 @@ public class FileUtils {
/** /**
* Gets the extension from a file name. * Gets the extension from a file name.
* Returns null if there is no extension.
* *
* @param fileName the file name * @param fileName the file name
* @return null if there is no extension or fileName is null.
*/ */
public static String getExtension(String fileName) { public static String getExtension(String fileName) {
if (fileName == null) {
return null;
}
int index = fileName.lastIndexOf('.'); int index = fileName.lastIndexOf('.');
if (index == -1) { if (index == -1) {
return null; return null;
@@ -250,4 +254,34 @@ public class FileUtils {
public static Uri getUriForFile(Context context, File file) { public static Uri getUriForFile(Context context, File file) {
return FileProvider.getUriForFile(context, FileUtils.FILEPROVIDER, file); 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, long 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;
}
} }