Activity with progress and summary for import all option. Fixes #471.

ErrorListDialog shared by ExportActivity and ImportActivity.
This commit is contained in:
Román Martínez
2020-10-23 18:57:37 +02:00
parent 48c3695b5d
commit acc2627bde
19 changed files with 701 additions and 445 deletions
@@ -1,111 +0,0 @@
/*
* 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.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import de.dennisguse.opentracks.R;
public class ImportFinishedDialogFragment extends DialogFragment {
private static final String TAG = ImportFinishedDialogFragment.class.getSimpleName();
private static final String EXTRA_DIRECTORY_NAME_KEY = "directory_name";
private static final String EXTRA_IMPORTED_TRACK_COUNT = "imported_track_count";
private static final String EXTRA_FILE_COUNT = "file_count";
private static final String FINISHED_DIALOG_TAG = "finished_dialog_tag";
private DismissCallback caller;
public static void showDialog(FragmentManager fragmentManager, String directoryDisplayName, int successCount, int fileCount) {
Bundle bundle = new Bundle();
bundle.putString(EXTRA_DIRECTORY_NAME_KEY, directoryDisplayName);
bundle.putInt(EXTRA_IMPORTED_TRACK_COUNT, successCount);
bundle.putInt(EXTRA_FILE_COUNT, fileCount);
ImportFinishedDialogFragment dialogFragment = new ImportFinishedDialogFragment();
dialogFragment.setArguments(bundle);
dialogFragment.show(fragmentManager, FINISHED_DIALOG_TAG);
}
@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) {
String directoryDisplayName = getArguments().getString(EXTRA_DIRECTORY_NAME_KEY);
int importedTrackCount = getArguments().getInt(EXTRA_IMPORTED_TRACK_COUNT);
int totalTrackCount = getArguments().getInt(EXTRA_FILE_COUNT);
int iconId;
int titleId;
String message;
String totalFiles = getResources().getQuantityString(R.plurals.files, totalTrackCount, totalTrackCount);
if (importedTrackCount == totalTrackCount) {
if (totalTrackCount == 0) {
iconId = R.drawable.ic_dialog_info_24dp;
titleId = R.string.import_no_file_title;
message = getString(R.string.import_no_file, directoryDisplayName);
} else {
iconId = R.drawable.ic_dialog_success_24dp;
titleId = R.string.generic_success_title;
message = getString(R.string.import_success, totalFiles, directoryDisplayName);
}
} else {
iconId = R.drawable.ic_dialog_error_24dp;
titleId = R.string.generic_error_title;
message = getString(R.string.import_error, importedTrackCount, totalFiles, directoryDisplayName);
}
Dialog dialog = new AlertDialog.Builder(getContext())
.setCancelable(true).setIcon(iconId)
.setMessage(message)
.setPositiveButton(R.string.generic_ok, (dialogInterface, which) -> {
dialogInterface.dismiss();
caller.onDismissed();
})
.setTitle(titleId)
.create();
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
@Override
public void onDetach() {
super.onDetach();
caller = null;
}
public interface DismissCallback {
void onDismissed();
}
}
@@ -1,230 +0,0 @@
/*
* 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.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.IOException;
import java.io.InputStream;
import java.util.List;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.importer.GpxFileTrackImporter;
import de.dennisguse.opentracks.io.file.importer.KmlFileTrackImporter;
import de.dennisguse.opentracks.io.file.importer.KmzTrackImporter;
import de.dennisguse.opentracks.io.file.importer.TrackImporter;
import de.dennisguse.opentracks.util.DialogUtils;
import de.dennisguse.opentracks.util.FileUtils;
public class ImportProgressDialogFragment extends DialogFragment {
private static final String EXTRA_IS_TREE_KEY = "tree_uri";
private static final String EXTRA_DATA_URI_KEY = "data_uri";
private static final String TAG = ImportProgressDialogFragment.class.getSimpleName();
public static final String IMPORT_DIALOG_TAG = "import_dialog_tag";
private DismissCallback caller;
private ImportThread importThread;
private String directoryDisplayName;
private int trackImportSuccessCount;
private int fileCount;
public static void showDialog(FragmentManager fragmentManager, Uri documentFileUri, boolean isDirectory) {
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_DATA_URI_KEY, documentFileUri);
bundle.putBoolean(EXTRA_IS_TREE_KEY, isDirectory);
ImportProgressDialogFragment dialogFragment = new ImportProgressDialogFragment();
dialogFragment.setArguments(bundle);
dialogFragment.setRetainInstance(true);
dialogFragment.show(fragmentManager, IMPORT_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_DATA_URI_KEY);
DocumentFile documentFile;
if (getArguments().getBoolean(EXTRA_IS_TREE_KEY)) {
documentFile = DocumentFile.fromTreeUri(getContext(), directoryUri);
} else {
documentFile = DocumentFile.fromSingleUri(getContext(), directoryUri);
}
directoryDisplayName = FileUtils.getPath(documentFile);
importThread = new ImportThread(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.import_progress_message,
dialogInterface -> {
importThread.interrupt();
dialogInterface.dismiss();
caller.onImportCanceled(directoryDisplayName, trackImportSuccessCount, fileCount);
}, directoryDisplayName);
progressDialog.setIndeterminate(false);
progressDialog.setMax(fileCount);
progressDialog.setProgress(Math.min(trackImportSuccessCount, fileCount));
return progressDialog;
}
@Override
public void onStart() {
super.onStart();
setProgress();
if (!importThread.isAlive()) {
importThread.start();
}
}
@Override
public void onPause() {
super.onPause();
if (!importThread.isAlive()) {
importThread.interrupt();
}
}
@Override
public void onDetach() {
super.onDetach();
caller = null;
}
private void onProgress(int trackImportSuccessCount, int fileCount) {
this.trackImportSuccessCount = trackImportSuccessCount;
this.fileCount = fileCount;
setProgress();
}
private void setProgress() {
ProgressDialog dialog = (ProgressDialog) getDialog();
if (dialog != null) {
dialog.setIndeterminate(false);
dialog.setMax(fileCount);
dialog.setProgress(Math.min(trackImportSuccessCount, fileCount));
}
}
private void onImportCompleted(int successCount, int fileCount) {
if (caller != null && !isDetached()) {
caller.onImportFinished(directoryDisplayName, successCount, fileCount);
}
dismissAllowingStateLoss();
}
private class ImportThread extends Thread {
private final DocumentFile file;
ImportThread(DocumentFile file) {
this.file = file;
}
@Override
public void run() {
Context context = ImportProgressDialogFragment.this.getContext();
List<DocumentFile> files = FileUtils.getFiles(file);
int importedTrackCount = 0;
for (int i = 0; i < files.size(); i++) {
onProgress(i, files.size());
if (Thread.interrupted()) {
return;
}
if (importFile(context, files.get(i))) {
importedTrackCount++;
}
}
onImportCompleted(importedTrackCount, files.size());
}
/**
* Imports a file.
*
* @param file the file
*/
private boolean importFile(final Context context, final DocumentFile file) {
TrackImporter trackImporter;
String fileExtension = FileUtils.getExtension(file);
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
trackImporter = new GpxFileTrackImporter(context);
} else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
trackImporter = new KmlFileTrackImporter(ImportProgressDialogFragment.this.getContext());
} else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
trackImporter = new KmzTrackImporter(context, file.getUri());
} else {
Log.i(TAG, "Unsupported file format.");
return false;
}
try (InputStream inputStream = context.getContentResolver().openInputStream(file.getUri())) {
return trackImporter.importFile(inputStream) != null;
} catch (IOException e) {
Log.e(TAG, "Unable to import file", e);
return false;
}
}
}
public interface DismissCallback {
void onImportCanceled(String directoryDisplayName, int successCount, int fileCount);
void onImportFinished(String directoryDisplayName, int successCount, int fileCount);
}
}