fix #1025 exportdir failed to create document

fix #254 illegal filename characters
This commit is contained in:
Peter Storch
2021-11-25 20:55:46 +01:00
parent 2eab7425f2
commit bb7efaa87c
6 changed files with 41 additions and 15 deletions
@@ -29,6 +29,7 @@ import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TracksColumns;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
import de.dennisguse.opentracks.util.FileUtils;
/**
* A content provider that mimics the behavior of {@link androidx.core.content.FileProvider}, which shares virtual (non-existing) KML-files.
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
@@ -24,6 +25,7 @@ public class ExportService extends JobIntentService {
private static final String EXTRA_TRACK_ID = "extra_track_id";
private static final String EXTRA_TRACK_FILE_FORMAT = "extra_track_file_format";
private static final String EXTRA_DIRECTORY_URI = "extra_directory_uri";
private static final String TAG = ExportService.class.getSimpleName();
public static void enqueue(Context context, ExportServiceResultReceiver receiver, Track.Id trackId, TrackFileFormat trackFileFormat, Uri directoryUri) {
Intent intent = new Intent(context, JobService.class);
@@ -42,18 +44,23 @@ public class ExportService extends JobIntentService {
TrackFileFormat trackFileFormat = (TrackFileFormat) intent.getSerializableExtra(EXTRA_TRACK_FILE_FORMAT);
Uri directoryUri = intent.getParcelableExtra(EXTRA_DIRECTORY_URI);
// Prepare resultCode and bundle to send to the receiver.
Bundle bundle = new Bundle();
bundle.putParcelable(ExportServiceResultReceiver.RESULT_EXTRA_TRACK_ID, trackId);
// Build directory file.
DocumentFile directoryFile = DocumentFile.fromTreeUri(this, directoryUri);
if (directoryFile == null || !directoryFile.canWrite()) {
Log.e(TAG, "Can't write to directory: " + directoryFile);
resultReceiver.send(ExportServiceResultReceiver.RESULT_CODE_ERROR, bundle);
return;
}
// Export.
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
Track track = contentProviderUtils.getTrack(trackId);
boolean success = ExportUtils.exportTrack(this, trackFileFormat, directoryFile, track);
// Prepare resultCode and bundle to send to the receiver.
Bundle bundle = new Bundle();
bundle.putParcelable(ExportServiceResultReceiver.RESULT_EXTRA_TRACK_ID, trackId);
// Send result to the receiver.
int resultCode = success ? ExportServiceResultReceiver.RESULT_CODE_SUCCESS : ExportServiceResultReceiver.RESULT_CODE_ERROR;
resultReceiver.send(resultCode, bundle);
@@ -3,10 +3,12 @@ package de.dennisguse.opentracks.io.file.importer;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.documentfile.provider.DocumentFile;
@@ -24,7 +26,7 @@ public abstract class DirectoryChooserActivity extends AppCompatActivity {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
DocumentFile directoryUri = configureDirectoryChooserIntent(intent);
if (directoryUri == null) {
if (!isDirectoryValid(directoryUri)) {
startActivityForResult(intent, DIRECTORY_PICKER_REQUEST_CODE);
} else {
startActivity(createNextActivityIntent(directoryUri.getUri())); //TODO Refactor to DocumentFile
@@ -32,6 +34,10 @@ public abstract class DirectoryChooserActivity extends AppCompatActivity {
}
}
protected boolean isDirectoryValid(final DocumentFile directoryUri) {
return directoryUri != null && directoryUri.isDirectory() && directoryUri.canRead();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
@@ -83,6 +89,11 @@ public abstract class DirectoryChooserActivity extends AppCompatActivity {
return PreferencesUtils.getDefaultExportDirectoryUri(this);
}
@Override
protected boolean isDirectoryValid(final DocumentFile directoryUri) {
return super.isDirectoryValid(directoryUri) && directoryUri.canWrite();
}
@Override
protected Intent createNextActivityIntent(Uri directoryUri) {
Intent intent = IntentUtils.newIntent(this, ExportActivity.class);
@@ -102,7 +113,7 @@ public abstract class DirectoryChooserActivity extends AppCompatActivity {
Uri directoryUri = resultData.getData();
PreferencesUtils.setDefaultExportDirectoryUri(directoryUri);
IntentUtils.persistDirectoryAccessPermission(getApplicationContext(), directoryUri);
IntentUtils.persistDirectoryAccessPermission(getApplicationContext(), directoryUri, resultData.getFlags());
break;
case RESULT_CANCELED:
PreferencesUtils.setDefaultExportDirectoryUri(null);
@@ -114,12 +125,19 @@ public abstract class DirectoryChooserActivity extends AppCompatActivity {
finish();
}
@Override
protected boolean isDirectoryValid(final DocumentFile directoryUri) {
return super.isDirectoryValid(directoryUri) && directoryUri.canWrite();
}
@Override
protected DocumentFile configureDirectoryChooserIntent(Intent intent) {
super.configureDirectoryChooserIntent(intent);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
if (PreferencesUtils.isDefaultExportDirectoryUri(this)) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, PreferencesUtils.getDefaultExportDirectoryUri(this).getUri());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, PreferencesUtils.getDefaultExportDirectoryUri(this).getUri());
}
}
return null;
}
@@ -100,7 +100,7 @@ public class ExportUtils {
}
private static String getExportFileNameForTrack(Track track, String trackFileFormatExtension) {
return track.getUuid().toString().substring(0, 8) + "_" + track.getName() + "." + trackFileFormatExtension;
return track.getUuid().toString().substring(0, 8) + "_" + FileUtils.sanitizeFileName(track.getName()) + "." + trackFileFormatExtension;
}
private static Uri findFile(Context context, Uri directoryUri, String exportFileName) {
@@ -149,7 +149,6 @@ public class FileUtils {
*
* @param name name
*/
// TODO Check if this function is still needed.
public static String sanitizeFileName(String name) {
StringBuilder builder = new StringBuilder(name.length());
for (int i = 0; i < name.length(); i++) {
@@ -92,8 +92,9 @@ public class IntentUtils {
continue;
}
Pair<Uri, String> uriTrackFile = ShareContentProvider.createURI(trackId, track.getName(), PreferencesUtils.getExportTrackFileFormat());
Pair<Uri, String> uriSharePicture = ShareContentProvider.createURI(trackId, track.getName(), TrackFileFormat.SHARE_PICTURE_PNG);
String trackName = FileUtils.sanitizeFileName(track.getName());
Pair<Uri, String> uriTrackFile = ShareContentProvider.createURI(trackId, trackName, PreferencesUtils.getExportTrackFileFormat());
Pair<Uri, String> uriSharePicture = ShareContentProvider.createURI(trackId, trackName, TrackFileFormat.SHARE_PICTURE_PNG);
uris.addAll(Arrays.asList(uriSharePicture.first, uriTrackFile.first));
}
@@ -203,8 +204,8 @@ public class IntentUtils {
return new Pair<>(intent, photoUri);
}
public static void persistDirectoryAccessPermission(Context context, Uri directoryUri) {
int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
context.getContentResolver().takePersistableUriPermission(directoryUri, flags);
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);
}
}