forked from upstream-mirrors/OpenTracks
Export: replaced async task with thread.
Almost identical to the import.
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package de.dennisguse.opentracks.fragments;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||
import de.dennisguse.opentracks.util.DialogUtils;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
public class ExportProgressDialogFragment extends DialogFragment {
|
||||
|
||||
private static final String EXTRA_DIRECTORY_URI_KEY = "directory_uri";
|
||||
private static final String EXTRA_TRACKFILEFORMAT_KEY = "trackfileformat";
|
||||
|
||||
private static final String TAG = ExportProgressDialogFragment.class.getSimpleName();
|
||||
|
||||
public static final String EXPORT_DIALOG_TAG = "import_dialog_tag";
|
||||
|
||||
private DismissCallback caller;
|
||||
|
||||
private ExportThread exportThread;
|
||||
|
||||
private String directoryDisplayName;
|
||||
|
||||
private int trackExportSuccessCount;
|
||||
private int trackCount;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*/
|
||||
public static void showDialog(FragmentManager fragmentManager, String trackFileFormat, Uri documentFileUri) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(EXTRA_DIRECTORY_URI_KEY, documentFileUri);
|
||||
bundle.putString(EXTRA_DIRECTORY_URI_KEY, trackFileFormat);
|
||||
|
||||
ExportProgressDialogFragment dialogFragment = new ExportProgressDialogFragment();
|
||||
dialogFragment.setArguments(bundle);
|
||||
dialogFragment.setRetainInstance(true);
|
||||
dialogFragment.show(fragmentManager, EXPORT_DIALOG_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// This fragment uses a background thread, so it should not be recreated during activity re-creation.
|
||||
setRetainInstance(true);
|
||||
|
||||
Uri directoryUri = getArguments().getParcelable(EXTRA_DIRECTORY_URI_KEY);
|
||||
TrackFileFormat trackFileFormat = TrackFileFormat.valueOf(getArguments().getString(EXTRA_TRACKFILEFORMAT_KEY));
|
||||
DocumentFile documentFile = DocumentFile.fromTreeUri(getContext(), directoryUri);
|
||||
|
||||
directoryDisplayName = FileUtils.getPath(documentFile);
|
||||
|
||||
exportThread = new ExportThread(trackFileFormat, documentFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
try {
|
||||
caller = (DismissCallback) context;
|
||||
} catch (ClassCastException e) {
|
||||
throw new ClassCastException(context + " must implement " + DismissCallback.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
ProgressDialog progressDialog = DialogUtils.createHorizontalProgressDialog(getContext(),
|
||||
R.string.export_progress_message,
|
||||
dialog -> {
|
||||
exportThread.interrupt();
|
||||
dialog.dismiss();
|
||||
caller.onExportCanceled(directoryDisplayName, trackExportSuccessCount, trackCount);
|
||||
}, directoryDisplayName);
|
||||
|
||||
progressDialog.setIndeterminate(false);
|
||||
progressDialog.setMax(trackCount);
|
||||
progressDialog.setProgress(Math.min(trackExportSuccessCount, trackCount));
|
||||
|
||||
return progressDialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
setProgress();
|
||||
if (!exportThread.isAlive()) {
|
||||
exportThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (!exportThread.isAlive()) {
|
||||
exportThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
caller = null;
|
||||
}
|
||||
|
||||
private void onProgress(int trackImportSuccessCount, int fileCount) {
|
||||
this.trackExportSuccessCount = trackImportSuccessCount;
|
||||
this.trackCount = fileCount;
|
||||
setProgress();
|
||||
}
|
||||
|
||||
private void setProgress() {
|
||||
ProgressDialog dialog = (ProgressDialog) getDialog();
|
||||
if (dialog != null) {
|
||||
dialog.setIndeterminate(false);
|
||||
dialog.setMax(trackCount);
|
||||
dialog.setProgress(Math.min(trackExportSuccessCount, trackCount));
|
||||
}
|
||||
}
|
||||
|
||||
private void onExportCompleted(int successCount, int fileCount) {
|
||||
if (caller != null && !isDetached()) {
|
||||
caller.onExportFinished(directoryDisplayName, successCount, fileCount);
|
||||
}
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
||||
private class ExportThread extends Thread {
|
||||
|
||||
private TrackFileFormat trackFileFormat;
|
||||
|
||||
private DocumentFile directory;
|
||||
|
||||
ExportThread(TrackFileFormat trackFileFormat, DocumentFile directory) {
|
||||
this.directory = directory;
|
||||
this.trackFileFormat = trackFileFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Context context = ExportProgressDialogFragment.this.getContext();
|
||||
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
|
||||
|
||||
try (Cursor cursor = contentProviderUtils.getTrackCursor(null, null, TracksColumns._ID)) {
|
||||
if (cursor == null) {
|
||||
onExportCompleted(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
trackCount = cursor.getCount();
|
||||
for (int i = 0; i < trackCount; i++) {
|
||||
onProgress(i, trackCount);
|
||||
if (Thread.interrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cursor.moveToPosition(i);
|
||||
Track track = contentProviderUtils.createTrack(cursor);
|
||||
if (track != null && exportTrack(context, track)) {
|
||||
trackExportSuccessCount++;
|
||||
}
|
||||
}
|
||||
|
||||
onExportCompleted(trackExportSuccessCount, trackCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean exportTrack(Context context, Track track) {
|
||||
TrackExporter trackExporter = trackFileFormat.newTrackExporter(context, new Track[]{track});
|
||||
|
||||
//TODO Move to helper function
|
||||
String fileName = track.getId() + "." + trackFileFormat.getExtension();
|
||||
|
||||
// Overwrite a file if it exists; DocumentFile.createFile() creates a new file appending a suffix if the displayname already exists.
|
||||
DocumentFile file = directory.findFile(fileName);
|
||||
if (file == null) {
|
||||
file = directory.createFile(trackFileFormat.getMimeType(), fileName);
|
||||
}
|
||||
|
||||
try (OutputStream outputStream = context.getContentResolver().openOutputStream(file.getUri())) {
|
||||
if (trackExporter.writeTrack(context, outputStream)) {
|
||||
return true;
|
||||
} else {
|
||||
if (!file.delete()) {
|
||||
Log.e(TAG, "Unable to delete file");
|
||||
}
|
||||
Log.e(TAG, "Unable to export track");
|
||||
return false;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(TAG, "Unable to open file " + file.getName(), e);
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Unable to close file output stream", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface DismissCallback {
|
||||
void onExportCanceled(String directoryDisplayName, int successCount, int fileCount);
|
||||
|
||||
void onExportFinished(String directoryDisplayName, int successCount, int fileCount);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user