forked from upstream-mirrors/OpenTracks
BREAKING CHANGE: pictures are now stored in getExternalFilesDir(); no migration takes place!
This commit is contained in:
@@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package de.dennisguse.opentracks.util;
|
package de.dennisguse.opentracks.util;
|
||||||
|
|
||||||
import android.os.Environment;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -32,16 +30,6 @@ import java.io.File;
|
|||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class FileUtilsTest {
|
public class FileUtilsTest {
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests {@link FileUtils#getPath(String...)}.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testBuildExternalDirectoryPath() {
|
|
||||||
String expectedName = Environment.getExternalStorageDirectory() + File.separator + FileUtils.SDCARD_TOP_DIR + File.separator + "a" + File.separator + "b" + File.separator + "c";
|
|
||||||
String dirName = FileUtils.getPath("a", "b", "c");
|
|
||||||
Assert.assertEquals(expectedName, dirName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the file is new.
|
* Tests {@link FileUtils#buildUniqueFileName(File, String, String)} when the file is new.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -383,10 +383,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_insert_photo:
|
case R.id.track_detail_insert_photo:
|
||||||
if (!FileUtils.isExternalStorageWriteable() || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
|
|
||||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
createWaypointWithPicture();
|
createWaypointWithPicture();
|
||||||
return true;
|
return true;
|
||||||
case R.id.track_detail_menu_show_on_map:
|
case R.id.track_detail_menu_show_on_map:
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public class ContentProviderUtils {
|
|||||||
// Delete tracks last since it triggers a database vaccum call
|
// Delete tracks last since it triggers a database vaccum call
|
||||||
contentResolver.delete(TracksColumns.CONTENT_URI, null, null);
|
contentResolver.delete(TracksColumns.CONTENT_URI, null, null);
|
||||||
|
|
||||||
File dir = FileUtils.getPhotoDir();
|
File dir = FileUtils.getPhotoDir(context);
|
||||||
deleteDirectoryRecurse(context, dir);
|
deleteDirectoryRecurse(context, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ public class ContentProviderUtils {
|
|||||||
|
|
||||||
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?",
|
contentResolver.delete(WaypointsColumns.CONTENT_URI, WaypointsColumns.TRACKID + "=?",
|
||||||
new String[]{Long.toString(trackId)});
|
new String[]{Long.toString(trackId)});
|
||||||
deleteDirectoryRecurse(context, FileUtils.getPhotoDir(trackId));
|
deleteDirectoryRecurse(context, FileUtils.getPhotoDir(context, trackId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,12 +229,10 @@ public class ContentProviderUtils {
|
|||||||
*/
|
*/
|
||||||
private void deleteDirectoryRecurse(Context context, File dir) {
|
private void deleteDirectoryRecurse(Context context, File dir) {
|
||||||
// TODO Does not work with
|
// TODO Does not work with
|
||||||
if (FileUtils.isDirectory(dir)) {
|
if (dir.exists() && dir.isDirectory()) {
|
||||||
for (File child : dir.listFiles()) {
|
for (File child : dir.listFiles()) {
|
||||||
deleteDirectoryRecurse(context, child);
|
deleteDirectoryRecurse(context, child);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (dir.exists()) {
|
|
||||||
dir.delete();
|
dir.delete();
|
||||||
FileUtils.updateMediaScanner(context, Uri.fromFile(dir));
|
FileUtils.updateMediaScanner(context, Uri.fromFile(dir));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,11 +72,6 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr
|
|||||||
super.onActivityResult(requestCode, resultCode, resultData);
|
super.onActivityResult(requestCode, resultCode, resultData);
|
||||||
if (requestCode == EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
|
if (requestCode == EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
// final int takeFlags = resultData.getFlags()
|
|
||||||
// & (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
// | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
//// Check for the freshest data.
|
|
||||||
// getContentResolver().takePersistableUriPermission(uri, takeFlags);
|
|
||||||
directoryUri = resultData.getData();
|
directoryUri = resultData.getData();
|
||||||
fileTypeDialogStart();
|
fileTypeDialogStart();
|
||||||
} else {
|
} else {
|
||||||
@@ -93,9 +88,9 @@ public class ExportActivity extends FragmentActivity implements FileTypeDialogFr
|
|||||||
@Override
|
@Override
|
||||||
public void onFileTypeDone(TrackFileFormat trackFileFormat) {
|
public void onFileTypeDone(TrackFileFormat trackFileFormat) {
|
||||||
DocumentFile pickedDirectory = DocumentFile.fromTreeUri(this, directoryUri);
|
DocumentFile pickedDirectory = DocumentFile.fromTreeUri(this, directoryUri);
|
||||||
DocumentFile exportDirectory = pickedDirectory.findFile(FileUtils.SDCARD_TOP_DIR);
|
DocumentFile exportDirectory = pickedDirectory.findFile(FileUtils.EXPORT_DIR);
|
||||||
if (exportDirectory == null) {
|
if (exportDirectory == null) {
|
||||||
exportDirectory = pickedDirectory.createDirectory(FileUtils.SDCARD_TOP_DIR);
|
exportDirectory = pickedDirectory.createDirectory(FileUtils.EXPORT_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
directoryDisplayName = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
|
directoryDisplayName = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
|
||||||
|
|||||||
+1
-1
@@ -377,7 +377,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
if (importTrackId == -1L) {
|
if (importTrackId == -1L) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
File dir = FileUtils.getPhotoDir(importTrackId);
|
File dir = FileUtils.getPhotoDir(context, importTrackId);
|
||||||
File file = new File(dir, fileName);
|
File file = new File(dir, fileName);
|
||||||
return Uri.fromFile(file).toString();
|
return Uri.fromFile(file).toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,11 +73,6 @@ public class ImportActivity extends FragmentActivity implements FileTypeDialogFr
|
|||||||
super.onActivityResult(requestCode, resultCode, resultData);
|
super.onActivityResult(requestCode, resultCode, resultData);
|
||||||
if (requestCode == EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
|
if (requestCode == EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
// final int takeFlags = resultData.getFlags()
|
|
||||||
// & (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
// | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
//// Check for the freshest data.
|
|
||||||
// getContentResolver().takePersistableUriPermission(uri, takeFlags);
|
|
||||||
directoryUri = resultData.getData();
|
directoryUri = resultData.getData();
|
||||||
fileTypeDialogStart();
|
fileTypeDialogStart();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
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(trackId);
|
cleanImport(context, trackId);
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
String fileName = zipEntry.getName();
|
String fileName = zipEntry.getName();
|
||||||
@@ -76,7 +76,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
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(trackId);
|
cleanImport(context, trackId);
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -90,7 +90,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
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(trackId);
|
cleanImport(context, trackId);
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,15 +100,15 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
*
|
*
|
||||||
* @param trackId the trackId
|
* @param trackId the trackId
|
||||||
*/
|
*/
|
||||||
private void cleanImport(long trackId) {
|
private void cleanImport(Context context, long trackId) {
|
||||||
if (PreferencesUtils.isRecording(trackId)) {
|
if (PreferencesUtils.isRecording(trackId)) {
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
||||||
contentProviderUtils.deleteTrack(context, trackId);
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importTrackId != -1L) {
|
if (importTrackId != -1L) {
|
||||||
File dir = FileUtils.getPhotoDir(importTrackId);
|
File dir = FileUtils.getPhotoDir(context, importTrackId);
|
||||||
if (FileUtils.isDirectory(dir)) {
|
if (dir.exists() && dir.isDirectory()) {
|
||||||
for (File file : dir.listFiles()) {
|
for (File file : dir.listFiles()) {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
@@ -159,8 +159,7 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File dir = FileUtils.getPhotoDir(importTrackId);
|
File dir = FileUtils.getPhotoDir(context, importTrackId);
|
||||||
FileUtils.ensureDirectoryExists(dir);
|
|
||||||
File file = new File(dir, fileName);
|
File file = new File(dir, fileName);
|
||||||
|
|
||||||
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
|
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
|
||||||
|
|||||||
@@ -36,64 +36,25 @@ public class FileUtils {
|
|||||||
*/
|
*/
|
||||||
static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider";
|
static final String FILEPROVIDER = BuildConfig.APPLICATION_ID + ".fileprovider";
|
||||||
|
|
||||||
/**
|
public static final String EXPORT_DIR = "OpenTracks";
|
||||||
* Our external storage directory.
|
|
||||||
*/
|
|
||||||
public static final String SDCARD_TOP_DIR = "OpenTracks"; // TODO RENAME
|
|
||||||
private static final String TRACK_PREFIX = "OpenTracks";
|
|
||||||
/**
|
/**
|
||||||
* The maximum FAT32 path length. See the FAT32 spec at
|
* The maximum FAT32 path length. See the FAT32 spec at
|
||||||
* http://msdn.microsoft.com/en-us/windows/hardware/gg463080
|
* http://msdn.microsoft.com/en-us/windows/hardware/gg463080
|
||||||
*/
|
*/
|
||||||
static final int MAX_FAT32_PATH_LENGTH = 260;
|
static final int MAX_FAT32_PATH_LENGTH = 260;
|
||||||
/**
|
|
||||||
* The pictures directory under the app's external storage directory.
|
|
||||||
*/
|
|
||||||
private static final String PICTURES_DIR = "pictures";
|
|
||||||
|
|
||||||
private FileUtils() {
|
private FileUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static File getPhotoDir(Context context) {
|
||||||
* Returns true if the external storage is writable.
|
return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||||
*/
|
|
||||||
public static boolean isExternalStorageWriteable() {
|
|
||||||
String state = Environment.getExternalStorageState();
|
|
||||||
return Environment.MEDIA_MOUNTED.equals(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static File getPhotoDir(Context context, long trackId) {
|
||||||
* Returns true if the directory exists.
|
File photoDirectory = new File(getPhotoDir(context), "" + trackId);
|
||||||
*
|
photoDirectory.mkdirs();
|
||||||
* @param dir the directory
|
return photoDirectory;
|
||||||
*/
|
|
||||||
@Deprecated // TODO REMOVE" rewrite all locations this was used.
|
|
||||||
public static boolean isDirectory(File dir) {
|
|
||||||
return dir.exists() && dir.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the directory exists by creating it and its parents if necessary.
|
|
||||||
*
|
|
||||||
* @return whether the directory exists (either already existed or was
|
|
||||||
* successfully created)
|
|
||||||
*/
|
|
||||||
@Deprecated // TODO REMOVE" rewrite all locations this was used.
|
|
||||||
public static boolean ensureDirectoryExists(File dir) {
|
|
||||||
if (isDirectory(dir)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return dir.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated // TODO REMOVE" rewrite all locations this was used.
|
|
||||||
public static File getPhotoDir() {
|
|
||||||
return new File(getPath(PICTURES_DIR));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated // TODO REMOVE" rewrite all locations this was used.
|
|
||||||
public static File getPhotoDir(long trackId) {
|
|
||||||
return new File(getPath(PICTURES_DIR, TRACK_PREFIX + trackId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +65,7 @@ public class FileUtils {
|
|||||||
public static String getPathDisplayName(String... components) {
|
public static String getPathDisplayName(String... components) {
|
||||||
StringBuilder dirNameBuilder = new StringBuilder();
|
StringBuilder dirNameBuilder = new StringBuilder();
|
||||||
dirNameBuilder.append(File.separatorChar);
|
dirNameBuilder.append(File.separatorChar);
|
||||||
dirNameBuilder.append(SDCARD_TOP_DIR);
|
dirNameBuilder.append(EXPORT_DIR);
|
||||||
for (String component : components) {
|
for (String component : components) {
|
||||||
dirNameBuilder.append(File.separatorChar);
|
dirNameBuilder.append(File.separatorChar);
|
||||||
dirNameBuilder.append(component);
|
dirNameBuilder.append(component);
|
||||||
@@ -112,16 +73,6 @@ public class FileUtils {
|
|||||||
return dirNameBuilder.toString();
|
return dirNameBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a path on the external storage.
|
|
||||||
*
|
|
||||||
* @param components the components
|
|
||||||
*/
|
|
||||||
@Deprecated // TODO REMOVE" rewrite all locations this was used.
|
|
||||||
public static String getPath(String... components) {
|
|
||||||
return Environment.getExternalStorageDirectory() + getPathDisplayName(components);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a filename with the given base name (prefix) and the given extension, possibly adding a suffix to ensure the file doesn't exist.
|
* Builds a filename with the given base name (prefix) and the given extension, possibly adding a suffix to ensure the file doesn't exist.
|
||||||
*
|
*
|
||||||
@@ -161,6 +112,7 @@ public class FileUtils {
|
|||||||
return fileName.substring(index + 1);
|
return fileName.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Make user configurable!
|
||||||
public static void updateMediaScanner(Context context, Uri uri) {
|
public static void updateMediaScanner(Context context, Uri uri) {
|
||||||
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||||
mediaScanIntent.setData(uri);
|
mediaScanIntent.setData(uri);
|
||||||
|
|||||||
@@ -157,8 +157,7 @@ public class IntentUtils {
|
|||||||
* @param trackId the track id
|
* @param trackId the track id
|
||||||
*/
|
*/
|
||||||
public static Pair<Intent, Uri> createTakePictureIntent(Context context, long trackId) {
|
public static Pair<Intent, Uri> createTakePictureIntent(Context context, long trackId) {
|
||||||
File dir = FileUtils.getPhotoDir(trackId);
|
File dir = FileUtils.getPhotoDir(context, trackId);
|
||||||
FileUtils.ensureDirectoryExists(dir);
|
|
||||||
|
|
||||||
String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date());
|
String fileName = SimpleDateFormat.getDateTimeInstance().format(new Date());
|
||||||
File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION));
|
File file = new File(dir, FileUtils.buildUniqueFileName(dir, fileName, JPEG_EXTENSION));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<paths>
|
<paths>
|
||||||
<external-path
|
<files-path
|
||||||
name="mytracks_pictures"
|
name="pictures"
|
||||||
path="/" />
|
path="/" />
|
||||||
</paths>
|
</paths>
|
||||||
|
|||||||
Reference in New Issue
Block a user