diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 10b7451b4..6c8d740ff 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -395,11 +395,6 @@ limitations under the License.
android:icon="@drawable/ic_logo_color_24dp"
android:label="@string/recording_service" />
-
-
documentUris = new ArrayList<>();
private boolean isDirectory;
- private ImportViewModel viewModel;
- private ImportViewModel.Summary summary;
+ private Importer importer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- viewBinding = ImportActivityBinding.inflate(getLayoutInflater());
- setContentView(viewBinding.getRoot());
final Intent intent = getIntent();
final ClipData intentClipData = intent.getClipData();
@@ -99,16 +95,36 @@ public class ImportActivity extends FragmentActivity {
documentFiles = documentUris.stream().map(it -> DocumentFile.fromSingleUri(this, it)).collect(Collectors.toList());
}
- viewModel = new ViewModelProvider(this).get(ImportViewModel.class);
- viewModel.getImportData(documentFiles).observe(this, data -> {
- summary = data;
- setProgress();
- });
+ importer = new Importer(this, documentFiles);
+ importer.getLiveData()
+ .observe(this, summary -> {
+ setProgress(summary);
+ });
+ importer.startImport();
//Works for a directory, but we might have received multiple files via SEND_MULTIPLE.
viewBinding.importActivityToolbar.setTitle(getString(R.string.import_progress_message, documentFiles.get(0).getName()));
}
+ @NonNull
+ @Override
+ protected View createRootView() {
+ viewBinding = ImportActivityBinding.inflate(getLayoutInflater());
+ return viewBinding.getRoot();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ viewBinding = null;
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ importer.cancel();
+ return super.onSupportNavigateUp();
+ }
+
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
@@ -116,7 +132,7 @@ public class ImportActivity extends FragmentActivity {
outState.putBoolean(BUNDLE_IS_DIRECTORY, isDirectory);
}
- private void setProgress() {
+ private void setProgress(Importer.Summary summary) {
int done = summary.getCount();
viewBinding.importProgressDone.setText("" + done);
viewBinding.importProgressTotal.setText("" + summary.getTotalCount());
@@ -130,11 +146,11 @@ public class ImportActivity extends FragmentActivity {
viewBinding.importProgressSummaryErrorsGroup.setVisibility(summary.getErrorCount() > 0 ? View.VISIBLE : View.GONE);
if (summary.isDone()) {
- onImportEnded();
+ onImportEnded(summary);
}
}
- private void onImportEnded() {
+ private void onImportEnded(Importer.Summary summary) {
viewBinding.importProgressAlertMsg.setVisibility(View.VISIBLE);
viewBinding.importProgressAlertIcon.setVisibility(View.VISIBLE);
@@ -146,13 +162,13 @@ public class ImportActivity extends FragmentActivity {
});
if (summary.getErrorCount() > 0) {
- toggleUIEndWithErrors();
+ toggleUIEndWithErrors(summary);
} else {
- toggleUIEndOk();
+ toggleUIEndOk(summary);
}
}
- private void toggleUIEndWithErrors() {
+ private void toggleUIEndWithErrors(Importer.Summary summary) {
viewBinding.importProgressLeftButton.setVisibility(View.VISIBLE);
viewBinding.importProgressLeftButton.setText(getString(R.string.generic_show_errors));
viewBinding.importProgressLeftButton.setOnClickListener((view) -> ErrorListDialog.showDialog(getSupportFragmentManager(), getString(R.string.import_error_list_dialog_title), summary.getFileErrors()));
@@ -160,7 +176,7 @@ public class ImportActivity extends FragmentActivity {
viewBinding.importProgressAlertMsg.setText(getResources().getQuantityString(R.plurals.generic_completed_with_errors, summary.getErrorCount(), summary.getErrorCount()));
}
- private void toggleUIEndOk() {
+ private void toggleUIEndOk(Importer.Summary summary) {
viewBinding.importProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_dialog_success_24dp));
viewBinding.importProgressAlertMsg.setText(getString(R.string.generic_completed));
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportService.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportService.java
deleted file mode 100644
index 5c9dab50c..000000000
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportService.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package de.dennisguse.opentracks.io.file.importer;
-
-import android.app.job.JobService;
-import android.content.Context;
-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;
-import androidx.documentfile.provider.DocumentFile;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import de.dennisguse.opentracks.R;
-import de.dennisguse.opentracks.data.ContentProviderUtils;
-import de.dennisguse.opentracks.data.models.Distance;
-import de.dennisguse.opentracks.data.models.Track;
-import de.dennisguse.opentracks.io.file.TrackFileFormat;
-import de.dennisguse.opentracks.settings.PreferencesUtils;
-import de.dennisguse.opentracks.util.FileUtils;
-
-public class ImportService extends JobIntentService {
-
- private static final String TAG = ImportService.class.getSimpleName();
-
- private static final int JOB_ID = 2;
-
- private static final String EXTRA_RECEIVER = "extra_receiver";
- private static final String EXTRA_URI = "extra_uri";
-
- private ResultReceiver resultReceiver;
-
- public static void enqueue(Context context, ImportServiceResultReceiver receiver, Uri uri) {
- Intent intent = new Intent(context, JobService.class);
- intent.putExtra(EXTRA_RECEIVER, receiver);
- intent.putExtra(EXTRA_URI, uri);
- enqueueWork(context, ImportService.class, JOB_ID, intent);
- }
-
- @Override
- protected void onHandleWork(@NonNull Intent intent) {
- resultReceiver = intent.getParcelableExtra(EXTRA_RECEIVER);
- Uri uri = intent.getParcelableExtra(EXTRA_URI);
- importFile(DocumentFile.fromSingleUri(this, uri));
- }
-
- private void importFile(DocumentFile file) {
- ArrayList trackIds = new ArrayList<>();
-
- String fileExtension = FileUtils.getExtension(file);
- try {
- Distance maxRecordingDistance = PreferencesUtils.getMaxRecordingDistance();
- boolean preventReimport = PreferencesUtils.getPreventReimportTracks();
-
- TrackImporter trackImporter = new TrackImporter(this, new ContentProviderUtils(this), maxRecordingDistance, preventReimport);
-
- if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
- trackIds.addAll(new XMLImporter(new GPXTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
- } else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
- trackIds.addAll(new XMLImporter(new KMLTrackImporter(this, trackImporter)).importFile(this, file.getUri()));
- } else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
- trackIds.addAll(new KMZTrackImporter(this, trackImporter).importFile(file.getUri()));
- } else {
- Log.d(TAG, "Unsupported file format.");
- sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, null, file, getString(R.string.import_unsupported_format));
- return;
- }
-
- if (!trackIds.isEmpty()) {
- sendResult(ImportServiceResultReceiver.RESULT_CODE_IMPORTED, trackIds, file, getString(R.string.import_file_imported, file.getName()));
- } else {
- sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, trackIds, file, getString(R.string.import_unable_to_import_file, file.getName()));
- }
- } catch (IOException e) {
- Log.d(TAG, "Unable to import file", e);
- sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, null, file, getString(R.string.import_unable_to_import_file, e.getMessage()));
- } catch (ImportParserException e) {
- Log.d(TAG, "Parser error: " + e.getMessage(), e);
- sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, null, file, getString(R.string.import_parser_error, e.getMessage()));
- } catch (ImportAlreadyExistsException e) {
- Log.d(TAG, "Track already exists: " + e.getMessage(), e);
- sendResult(ImportServiceResultReceiver.RESULT_CODE_ALREADY_EXISTS, null, file, e.getMessage());
- }
- }
-
- private void sendResult(int resultCode, ArrayList trackId, DocumentFile file, String message) {
- Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(ImportServiceResultReceiver.RESULT_EXTRA_LIST_TRACK_ID, trackId);
- bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_FILENAME, file.getName());
- bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_MESSAGE, message);
- resultReceiver.send(resultCode, bundle);
- }
-}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportServiceResultReceiver.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportServiceResultReceiver.java
deleted file mode 100644
index e31631417..000000000
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportServiceResultReceiver.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package de.dennisguse.opentracks.io.file.importer;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-
-import androidx.annotation.NonNull;
-
-/**
- * Create a new ResultReceive to receive results.
- * Your {@link #onReceiveResult} method will be called from the thread running handler if given, or from an arbitrary thread if null.
- */
-public class ImportServiceResultReceiver extends ResultReceiver {
-
- public static final int RESULT_CODE_ERROR = 0;
- public static final int RESULT_CODE_IMPORTED = 1;
- public static final int RESULT_CODE_ALREADY_EXISTS = 2;
-
- public static final String RESULT_EXTRA_LIST_TRACK_ID = "result_track_id";
- public static final String RESULT_EXTRA_FILENAME = "result_extra_filename";
- public static final String RESULT_EXTRA_MESSAGE = "result_extra_message";
-
- private final Receiver receiver;
-
- public ImportServiceResultReceiver(Handler handler, @NonNull Receiver receiver) {
- super(handler);
- this.receiver = receiver;
- }
-
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- receiver.onReceiveResult(resultCode, resultData);
- }
-
- public interface Receiver {
- void onReceiveResult(int resultCode, Bundle resultData);
- }
-}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportViewModel.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportViewModel.java
deleted file mode 100644
index 39b0fa5d3..000000000
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportViewModel.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.dennisguse.opentracks.io.file.importer;
-
-import android.app.Application;
-import android.os.Bundle;
-import android.os.Handler;
-
-import androidx.annotation.NonNull;
-import androidx.documentfile.provider.DocumentFile;
-import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import de.dennisguse.opentracks.R;
-import de.dennisguse.opentracks.data.models.Track;
-import de.dennisguse.opentracks.util.FileUtils;
-
-public class ImportViewModel extends AndroidViewModel implements ImportServiceResultReceiver.Receiver {
-
- private static final String TAG = ImportViewModel.class.getSimpleName();
-
- private MutableLiveData importData;
- private final ImportServiceResultReceiver resultReceiver;
- private final Summary summary;
- private boolean cancel = false;
- private final List filesToImport = new ArrayList<>();
-
- public ImportViewModel(@NonNull Application application) {
- super(application);
- resultReceiver = new ImportServiceResultReceiver(new Handler(), this);
- summary = new Summary();
- }
-
- LiveData getImportData(List documentFiles) {
- if (importData == null) {
- importData = new MutableLiveData<>();
- loadData(documentFiles);
- }
- return importData;
- }
-
- void cancel() {
- cancel = true;
- }
-
- private void loadData(List documentFiles) {
- List> nestedFileList = documentFiles.stream()
- .map(FileUtils::getFiles)
- .collect(Collectors.toList());
-
- List fileList = new ArrayList<>();
- nestedFileList.forEach(fileList::addAll);
-
- summary.totalCount = fileList.size();
- filesToImport.addAll(fileList);
- importNextFile();
- }
-
- private void importNextFile() {
- if (cancel || filesToImport.isEmpty()) {
- return;
- }
- ImportService.enqueue(getApplication(), resultReceiver, filesToImport.get(0).getUri());
- filesToImport.remove(0);
- }
-
- @Override
- public void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultData == null) {
- throw new RuntimeException(TAG + ": onReceiveResult resultData NULL");
- }
-
- ArrayList trackIds = resultData.getParcelableArrayList(ImportServiceResultReceiver.RESULT_EXTRA_LIST_TRACK_ID);
- String fileName = resultData.getString(ImportServiceResultReceiver.RESULT_EXTRA_FILENAME);
- String message = resultData.getString(ImportServiceResultReceiver.RESULT_EXTRA_MESSAGE);
-
- switch (resultCode) {
- case ImportServiceResultReceiver.RESULT_CODE_ERROR -> {
- summary.errorCount++;
- summary.fileErrors.add(getApplication().getString(R.string.import_error_info, fileName, message));
- }
- case ImportServiceResultReceiver.RESULT_CODE_IMPORTED -> {
- summary.importedTrackIds.addAll(trackIds);
- summary.successCount++;
- }
- case ImportServiceResultReceiver.RESULT_CODE_ALREADY_EXISTS -> summary.existsCount++;
- default ->
- throw new RuntimeException(TAG + ": import service result code invalid: " + resultCode);
- }
-
- importData.postValue(summary);
- importNextFile();
- }
-
- static class Summary {
- private int totalCount;
- private int successCount;
- private int existsCount;
- private int errorCount;
- private final ArrayList importedTrackIds = new ArrayList<>();
- private final ArrayList fileErrors = new ArrayList<>();
-
- public int getTotalCount() {
- return totalCount;
- }
-
- public int getSuccessCount() {
- return successCount;
- }
-
- public int getExistsCount() {
- return existsCount;
- }
-
- public int getErrorCount() {
- return errorCount;
- }
-
- public ArrayList getImportedTrackIds() {
- return importedTrackIds;
- }
-
- public ArrayList getFileErrors() {
- return fileErrors;
- }
-
- public int getCount() {
- return getSuccessCount() + getExistsCount() + getErrorCount();
- }
-
- public boolean isDone() {
- return getTotalCount() == getCount();
- }
- }
-}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportWorker.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportWorker.java
new file mode 100644
index 000000000..9ee0fcfbc
--- /dev/null
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/ImportWorker.java
@@ -0,0 +1,100 @@
+package de.dennisguse.opentracks.io.file.importer;
+
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.work.Data;
+import androidx.work.Worker;
+import androidx.work.WorkerParameters;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import de.dennisguse.opentracks.R;
+import de.dennisguse.opentracks.data.ContentProviderUtils;
+import de.dennisguse.opentracks.data.models.Distance;
+import de.dennisguse.opentracks.data.models.Track;
+import de.dennisguse.opentracks.io.file.TrackFileFormat;
+import de.dennisguse.opentracks.settings.PreferencesUtils;
+import de.dennisguse.opentracks.util.FileUtils;
+
+public class ImportWorker extends Worker {
+
+ private static final String TAG = ImportWorker.class.getSimpleName();
+
+ static final String URI_KEY = "DIRECTORY_URI_KEY";
+
+ static final String RESULT_SUCCESS_LIST_TRACKIDS_KEY = "RESULT_TRACK_IDS";
+ static final String RESULT_URI_KEY = "RESULT_URI";
+ static final String RESULT_MESSAGE_KEY = "RESULT_MESSAGE";
+ static final String RESULT_FAILURE_IS_DUPLICATE = "RESULT_FAILURE_IS_DUPLICATE";
+
+ private final Uri uri;
+
+ public ImportWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+
+ uri = Uri.parse(getInputData().getString(URI_KEY));
+ }
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ ArrayList trackIds = new ArrayList<>();
+ Context context = getApplicationContext();
+
+ Distance maxRecordingDistance = PreferencesUtils.getMaxRecordingDistance();
+ boolean preventReimport = PreferencesUtils.getPreventReimportTracks();
+ TrackImporter trackImporter = new TrackImporter(context, new ContentProviderUtils(context), maxRecordingDistance, preventReimport);
+
+ Data.Builder data = new Data.Builder()
+ .putString(RESULT_URI_KEY, uri.toString());
+
+
+ String fileExtension = FileUtils.getExtension(uri);
+ try {
+ if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
+ trackIds.addAll(new XMLImporter(new GPXTrackImporter(getApplicationContext(), trackImporter)).importFile(context, uri));
+ } else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
+ trackIds.addAll(new XMLImporter(new KMLTrackImporter(getApplicationContext(), trackImporter)).importFile(context, uri));
+ } else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
+ trackIds.addAll(new KMZTrackImporter(context, trackImporter).importFile(uri));
+ } else {
+ Log.d(TAG, "Unsupported file format.");
+ return Result.failure(data
+ .putString(RESULT_MESSAGE_KEY, context.getString(R.string.import_unsupported_format))
+ .build());
+ }
+
+ if (!trackIds.isEmpty()) {
+ return Result.success(data
+ .putString(RESULT_MESSAGE_KEY, context.getString(R.string.import_file_imported, uri.toString())) //TODO unused?
+ .putLongArray(RESULT_SUCCESS_LIST_TRACKIDS_KEY, trackIds.stream().mapToLong(Track.Id::id).toArray())
+ .build());
+ }
+
+ return Result.failure(data
+ .putString(RESULT_MESSAGE_KEY, context.getString(R.string.import_unable_to_import_file, uri.toString()))
+ .build());
+
+ } catch (IOException e) {
+ Log.d(TAG, "Unable to import file", e);
+ return Result.failure(data
+ .putString(RESULT_MESSAGE_KEY, context.getString(R.string.import_unable_to_import_file, e.getMessage()))
+ .build());
+ } catch (ImportParserException e) {
+ Log.d(TAG, "Parser error: " + e.getMessage(), e);
+ return Result.failure(data
+ .putString(RESULT_MESSAGE_KEY, context.getString(R.string.import_parser_error, e.getMessage()))
+ .build());
+ } catch (ImportAlreadyExistsException e) {
+ Log.d(TAG, "Track already exists: " + e.getMessage(), e);
+ return Result.failure(data
+ .putString(RESULT_MESSAGE_KEY, e.getMessage()) //TODO This is not used
+ .putBoolean(RESULT_FAILURE_IS_DUPLICATE, true)
+ .build());
+ }
+ }
+}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/Importer.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/Importer.java
new file mode 100644
index 000000000..d91547c00
--- /dev/null
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/Importer.java
@@ -0,0 +1,151 @@
+package de.dennisguse.opentracks.io.file.importer;
+
+import androidx.documentfile.provider.DocumentFile;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import de.dennisguse.opentracks.R;
+import de.dennisguse.opentracks.data.models.Track;
+import de.dennisguse.opentracks.util.FileUtils;
+
+//TODO Cancel does not abort current import
+//TODO Provide some intermediate progress (not only when a file got imported)
+public class Importer {
+
+ private final MutableLiveData liveData = new MutableLiveData<>();
+ private final Summary summary = new Summary();
+ private final List filesToImport = new ArrayList<>();
+
+ private boolean cancel = false;
+
+ private final ImportActivity context;
+ private final WorkManager workManager;
+
+ //TODO Add summary callback
+ Importer(ImportActivity context, List documentFiles) {
+ this.context = context;
+ this.workManager = WorkManager.getInstance(context);
+
+ List> nestedFileList = documentFiles.stream()
+ .map(FileUtils::getFiles)
+ .collect(Collectors.toList());
+
+ List fileList = new ArrayList<>();
+ nestedFileList.forEach(fileList::addAll);
+
+ summary.totalCount = fileList.size();
+ filesToImport.addAll(fileList);
+ }
+
+ LiveData getLiveData() {
+ return liveData;
+ }
+
+ void startImport() {
+ liveData.postValue(summary);
+ importNextFile();
+ }
+
+ void cancel() {
+ cancel = true;
+ }
+
+ private void importNextFile() {
+ if (cancel || filesToImport.isEmpty()) {
+ return;
+ }
+
+ final DocumentFile documentFile = filesToImport.get(0);
+
+ WorkRequest importRequest = new OneTimeWorkRequest.Builder(ImportWorker.class)
+ .setInputData(new Data.Builder()
+ .putString(ImportWorker.URI_KEY, documentFile.getUri().toString())
+ .build())
+ .build();
+
+ workManager
+ .getWorkInfoByIdLiveData(importRequest.getId())
+ .observe(context, workInfo -> {
+ if (workInfo != null) {
+ WorkInfo.State state = workInfo.getState();
+ if (state.isFinished()) {
+ switch (state) {
+ case SUCCEEDED -> {
+ summary.importedTrackIds.addAll(
+ Arrays.stream(workInfo.getOutputData().getLongArray(ImportWorker.RESULT_SUCCESS_LIST_TRACKIDS_KEY))
+ .mapToObj(Track.Id::new)
+ .toList());
+
+ summary.successCount++;
+ }
+ case FAILED -> {
+ if (workInfo.getOutputData().getBoolean(ImportWorker.RESULT_FAILURE_IS_DUPLICATE, false)) {
+ summary.existsCount++;
+ } else {
+ // Some error happened
+ String errorMessage = workInfo.getOutputData().getString(ImportWorker.RESULT_MESSAGE_KEY);
+ summary.fileErrors.add(context.getString(R.string.import_error_info, documentFile.getName(), errorMessage));
+ }
+ }
+ }
+
+ liveData.postValue(summary);
+ importNextFile();
+ }
+ }
+ });
+
+ workManager.enqueue(importRequest);
+ filesToImport.remove(0);
+ }
+
+ static class Summary {
+ private int totalCount;
+ private int successCount;
+ private int existsCount;
+ private final ArrayList importedTrackIds = new ArrayList<>();
+ private final ArrayList fileErrors = new ArrayList<>();
+
+ public int getTotalCount() {
+ return totalCount;
+ }
+
+ public int getSuccessCount() {
+ return successCount;
+ }
+
+ public int getExistsCount() {
+ return existsCount;
+ }
+
+ public int getErrorCount() {
+ return fileErrors.size();
+ }
+
+ public ArrayList getImportedTrackIds() {
+ return importedTrackIds;
+ }
+
+ public ArrayList getFileErrors() {
+ return fileErrors;
+ }
+
+ public int getCount() {
+ return getSuccessCount() + getExistsCount() + getErrorCount();
+ }
+
+ public boolean isDone() {
+ return getTotalCount() == getCount();
+ }
+ }
+}