show postworkout error messages, #1669

This commit is contained in:
Peter Storch
2023-08-26 19:17:04 +02:00
committed by Dennis Guse
parent 326da494eb
commit f83c23e450
4 changed files with 35 additions and 42 deletions
@@ -19,6 +19,7 @@ package de.dennisguse.opentracks.io.file.exporter;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@@ -340,7 +341,7 @@ public class ExportActivity extends FragmentActivity implements ExportService.Ex
} }
@Override @Override
public void onExportError(ExportTask exportTask) { public void onExportError(ExportTask exportTask, String errorMessage) {
trackExportErrorCount++; trackExportErrorCount++;
String name; String name;
if (exportTask.isMultiExport()) { if (exportTask.isMultiExport()) {
@@ -348,6 +349,7 @@ public class ExportActivity extends FragmentActivity implements ExportService.Ex
} else { } else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName(); name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName();
} }
Log.e(TAG, "Error exporting " + name + ": " + errorMessage);
trackErrors.add(name); trackErrors.add(name);
nextExport(exportTask); nextExport(exportTask);
@@ -7,12 +7,12 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService; import androidx.core.app.JobIntentService;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.ExportUtils; import de.dennisguse.opentracks.util.ExportUtils;
public class ExportService extends JobIntentService { public class ExportService extends JobIntentService {
@@ -22,7 +22,6 @@ public class ExportService extends JobIntentService {
private static final String EXTRA_RECEIVER = "extra_receiver"; private static final String EXTRA_RECEIVER = "extra_receiver";
private static final String EXTRA_EXPORT_TASK = "export_task"; private static final String EXTRA_EXPORT_TASK = "export_task";
private static final String EXTRA_DIRECTORY_URI = "extra_directory_uri"; 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, ExportTask exportTask, Uri directoryUri) { public static void enqueue(Context context, ExportServiceResultReceiver receiver, ExportTask exportTask, Uri directoryUri) {
Intent intent = new Intent(context, JobService.class); Intent intent = new Intent(context, JobService.class);
@@ -46,17 +45,19 @@ public class ExportService extends JobIntentService {
// Build directory file. // Build directory file.
DocumentFile directoryFile = DocumentFile.fromTreeUri(this, directoryUri); DocumentFile directoryFile = DocumentFile.fromTreeUri(this, directoryUri);
if (directoryFile == null || !directoryFile.canWrite()) { if (directoryFile == null || !directoryFile.canWrite()) {
Log.e(TAG, "Can't write to directory: " + directoryFile); bundle.putString(ExportServiceResultReceiver.EXTRA_EXPORT_ERROR_MESSAGE, getString(R.string.export_cannot_write_to_dir) + ": " + directoryFile);
resultReceiver.send(ExportServiceResultReceiver.RESULT_CODE_ERROR, bundle); resultReceiver.send(ExportServiceResultReceiver.RESULT_CODE_ERROR, bundle);
return; return;
} }
// Export. // Export and send result
boolean success = ExportUtils.exportTrack(this, directoryFile, exportTask); try {
ExportUtils.exportTrack(this, directoryFile, exportTask);
// Send result to the receiver. resultReceiver.send(ExportServiceResultReceiver.RESULT_CODE_SUCCESS, bundle);
int resultCode = success ? ExportServiceResultReceiver.RESULT_CODE_SUCCESS : ExportServiceResultReceiver.RESULT_CODE_ERROR; } catch (Exception e) {
resultReceiver.send(resultCode, bundle); bundle.putString(ExportServiceResultReceiver.EXTRA_EXPORT_ERROR_MESSAGE, e.getMessage());
resultReceiver.send(ExportServiceResultReceiver.RESULT_CODE_ERROR, bundle);
}
} }
public static class ExportServiceResultReceiver extends ResultReceiver { public static class ExportServiceResultReceiver extends ResultReceiver {
@@ -66,6 +67,8 @@ public class ExportService extends JobIntentService {
public static final String RESULT_EXTRA_EXPORT_TASK = "result_extra_export_task"; public static final String RESULT_EXTRA_EXPORT_TASK = "result_extra_export_task";
public static final String EXTRA_EXPORT_ERROR_MESSAGE = "extra_export_error_message";
private final Receiver receiver; private final Receiver receiver;
public ExportServiceResultReceiver(Handler handler, @NonNull Receiver receiver) { public ExportServiceResultReceiver(Handler handler, @NonNull Receiver receiver) {
@@ -75,10 +78,10 @@ public class ExportService extends JobIntentService {
@Override @Override
protected void onReceiveResult(int resultCode, Bundle resultData) { protected void onReceiveResult(int resultCode, Bundle resultData) {
ExportTask exportTask = resultData.getParcelable(ExportServiceResultReceiver.RESULT_EXTRA_EXPORT_TASK); ExportTask exportTask = resultData.getParcelable(RESULT_EXTRA_EXPORT_TASK);
switch (resultCode) { switch (resultCode) {
case RESULT_CODE_SUCCESS -> receiver.onExportSuccess(exportTask); case RESULT_CODE_SUCCESS -> receiver.onExportSuccess(exportTask);
case RESULT_CODE_ERROR -> receiver.onExportError(exportTask); case RESULT_CODE_ERROR -> receiver.onExportError(exportTask, resultData.getString(EXTRA_EXPORT_ERROR_MESSAGE));
default -> throw new RuntimeException("Unknown resultCode."); default -> throw new RuntimeException("Unknown resultCode.");
} }
} }
@@ -87,7 +90,7 @@ public class ExportService extends JobIntentService {
default void onExportSuccess(ExportTask exportTask) { default void onExportSuccess(ExportTask exportTask) {
} }
default void onExportError(ExportTask exportTask) { default void onExportError(ExportTask exportTask, String errorMessage) {
} }
} }
} }
@@ -16,8 +16,9 @@ import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
public class SettingsActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller { public class SettingsActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
public static final String EXTRAS_CHECK_EXPORT_DIRECTORY = "Check Export Directory"; public static final String EXTRAS_EXPORT_ERROR_MESSAGE = "Export error message";
private boolean checkExportDirectory = false;
private String exportErrorMessage = null;
public static final String FRAGMENT_KEY = "fragmentKey"; public static final String FRAGMENT_KEY = "fragmentKey";
@@ -30,8 +31,8 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = getIntent(); Intent intent = getIntent();
if (intent != null && intent.hasExtra(EXTRAS_CHECK_EXPORT_DIRECTORY)) { if (intent != null) {
checkExportDirectory = true; exportErrorMessage = intent.getStringExtra(EXTRAS_EXPORT_ERROR_MESSAGE);
} }
if (savedInstanceState != null) { if (savedInstanceState != null) {
@@ -48,15 +49,15 @@ public class SettingsActivity extends AbstractActivity implements ChooseActivity
@Override @Override
protected void onResume() { protected void onResume() {
if (checkExportDirectory) { if (exportErrorMessage != null) {
checkExportDirectory = false;
new AlertDialog.Builder(this) new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_logo_24dp) .setIcon(R.drawable.ic_logo_24dp)
.setTitle(R.string.app_name) .setTitle(R.string.app_name)
.setMessage(R.string.export_error_post_workout) .setMessage(getString(R.string.export_error_post_workout) + "\n" + exportErrorMessage)
.setNeutralButton(android.R.string.ok, null) .setNeutralButton(android.R.string.ok, null)
.create() .create()
.show(); .show();
exportErrorMessage = null;
} }
super.onResume(); super.onResume();
@@ -8,7 +8,6 @@ import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
@@ -19,7 +18,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
@@ -40,17 +38,12 @@ public class ExportUtils {
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(); TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat();
DocumentFile directory = IntentUtils.toDocumentFile(context, PreferencesUtils.getDefaultExportDirectoryUri()); DocumentFile directory = IntentUtils.toDocumentFile(context, PreferencesUtils.getDefaultExportDirectoryUri());
if (directory == null || !directory.canWrite()) {
Toast.makeText(context, R.string.export_cannot_write_to_dir, Toast.LENGTH_LONG).show();
return;
}
ExportServiceResultReceiver resultReceiver = new ExportServiceResultReceiver(new Handler(), new ExportServiceResultReceiver.Receiver() { ExportServiceResultReceiver resultReceiver = new ExportServiceResultReceiver(new Handler(), new ExportServiceResultReceiver.Receiver() {
@Override @Override
public void onExportError(ExportTask unused) { public void onExportError(ExportTask unused, String errorMessage) {
Intent intent = new Intent(context, SettingsActivity.class); Intent intent = new Intent(context, SettingsActivity.class);
intent.putExtra(SettingsActivity.EXTRAS_CHECK_EXPORT_DIRECTORY, true);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(SettingsActivity.EXTRAS_EXPORT_ERROR_MESSAGE, errorMessage);
context.startActivity(intent); context.startActivity(intent);
} }
}); });
@@ -59,7 +52,7 @@ public class ExportUtils {
} }
} }
public static boolean exportTrack(Context context, DocumentFile directory, ExportTask exportTask) { public static void exportTrack(Context context, DocumentFile directory, ExportTask exportTask) {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context);
List<Track> tracks = exportTask.getTrackIds().stream().map(contentProviderUtils::getTrack).collect(Collectors.toList()); List<Track> tracks = exportTask.getTrackIds().stream().map(contentProviderUtils::getTrack).collect(Collectors.toList());
Uri exportDocumentFileUri; Uri exportDocumentFileUri;
@@ -71,27 +64,21 @@ public class ExportUtils {
} }
if (exportDocumentFileUri == null) { if (exportDocumentFileUri == null) {
Log.e(TAG, "Couldn't create document file for export"); throw new RuntimeException("Couldn't create document file for export");
return false;
} }
TrackExporter trackExporter = exportTask.getTrackFileFormat().createTrackExporter(context, contentProviderUtils); TrackExporter trackExporter = exportTask.getTrackFileFormat().createTrackExporter(context, contentProviderUtils);
try (OutputStream outputStream = context.getContentResolver().openOutputStream(exportDocumentFileUri)) { try (OutputStream outputStream = context.getContentResolver().openOutputStream(exportDocumentFileUri)) {
if (trackExporter.writeTrack(tracks, outputStream)) { if (!trackExporter.writeTrack(tracks, outputStream)) {
return true;
} else {
if (!DocumentFile.fromSingleUri(context, exportDocumentFileUri).delete()) { if (!DocumentFile.fromSingleUri(context, exportDocumentFileUri).delete()) {
Log.e(TAG, "Unable to delete exportDocumentFile"); throw new RuntimeException("Unable to delete exportDocumentFile");
} }
Log.e(TAG, "Unable to export track"); throw new RuntimeException("Unable to export track");
return false;
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Log.e(TAG, "Unable to open exportDocumentFile " + exportDocumentFileUri, e); throw new RuntimeException("Unable to open exportDocumentFile " + exportDocumentFileUri, e);
return false;
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Unable to close exportDocumentFile output stream", e); throw new RuntimeException("Unable to close exportDocumentFile output stream", e);
return false;
} }
} }