diff --git a/src/main/java/de/dennisguse/opentracks/content/data/Track.java b/src/main/java/de/dennisguse/opentracks/content/data/Track.java index eb09da668..d4b8b5a57 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/Track.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/Track.java @@ -118,6 +118,10 @@ public class Track { this.id = id; } + protected Id(Parcel in) { + id = in.readLong(); + } + //TOOD Limit visibility to TrackRecordingService / ContentProvider public long getId() { return id; diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 406c180ba..6b9ad5ac1 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -25,6 +25,8 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.sqlite.SQLiteException; import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.PowerManager.WakeLock; import android.util.Log; @@ -46,12 +48,14 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.CustomContentProvider; import de.dennisguse.opentracks.content.provider.TrackPointIterator; import de.dennisguse.opentracks.content.sensor.SensorDataSet; +import de.dennisguse.opentracks.io.file.exporter.ExportServiceResultReceiver; import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.handlers.HandlerServer; import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager; import de.dennisguse.opentracks.services.sensors.ElevationSumManager; import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory; import de.dennisguse.opentracks.services.tasks.PeriodicTaskExecutor; +import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; import de.dennisguse.opentracks.util.ExportUtils; @@ -69,7 +73,7 @@ import de.dennisguse.opentracks.util.TrackPointUtils; * * @author Leif Hendrik Wilden */ -public class TrackRecordingService extends Service implements HandlerServer.HandlerServerInterface { +public class TrackRecordingService extends Service implements HandlerServer.HandlerServerInterface, ExportServiceResultReceiver.Receiver { private static final String TAG = TrackRecordingService.class.getSimpleName(); @@ -431,7 +435,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand } } - ExportUtils.postWorkoutExport(this, track); + ExportUtils.postWorkoutExport(this, track, new ExportServiceResultReceiver(new Handler(), this)); endRecording(true); } @@ -751,4 +755,16 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand public GpsStatusValue getGpsStatus() { return handlerServer.getGpsStatus(); } + + @Override + public void onReceiveResult(final int resultCode, final Bundle resultData) { + Log.w(TAG, "onReceiveResult: " + resultCode); + if (resultCode != ExportServiceResultReceiver.RESULT_CODE_SUCCESS) { + Intent intent = new Intent(this, SettingsActivity.class); + intent.putExtra(SettingsActivity.EXTRAS_CHECK_EXPORT_DIRECTORY, true); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + } + } diff --git a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java index 81652c04f..a7f425b6b 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java +++ b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java @@ -1,10 +1,12 @@ package de.dennisguse.opentracks.settings; +import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.documentfile.provider.DocumentFile; @@ -32,8 +34,10 @@ import de.dennisguse.opentracks.util.StringUtils; public class SettingsActivity extends AppCompatActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ResetDialogPreference.ResetCallback { private static final String TAG = SettingsActivity.class.getSimpleName(); + public static final String EXTRAS_CHECK_EXPORT_DIRECTORY = "Check Export Directory"; private PrefsFragment prefsFragment; + private boolean checkExportDirectory = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -45,9 +49,29 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit toolbar.setTitle(R.string.menu_settings); setSupportActionBar(toolbar); + Intent intent = getIntent(); + if (intent != null && intent.hasExtra(EXTRAS_CHECK_EXPORT_DIRECTORY)) { + checkExportDirectory = true; + } onReset(); } + @Override + protected void onResume() { + if (checkExportDirectory) { + checkExportDirectory = false; + new AlertDialog.Builder(this) + .setIcon(R.drawable.ic_logo_24dp) + .setTitle(R.string.app_name) + .setMessage(R.string.export_error_post_workout) + .setNeutralButton(R.string.generic_ok, null) + .create() + .show(); + } + + super.onResume(); + } + @Override public void onChooseActivityTypeDone(String iconValue) { prefsFragment.setDefaultActivity(iconValue); diff --git a/src/main/java/de/dennisguse/opentracks/util/ExportUtils.java b/src/main/java/de/dennisguse/opentracks/util/ExportUtils.java index 8982ff9f7..945415ce6 100644 --- a/src/main/java/de/dennisguse/opentracks/util/ExportUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/ExportUtils.java @@ -17,17 +17,20 @@ import java.util.List; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.io.file.TrackFileFormat; +import de.dennisguse.opentracks.io.file.exporter.ExportService; +import de.dennisguse.opentracks.io.file.exporter.ExportServiceResultReceiver; import de.dennisguse.opentracks.io.file.exporter.TrackExporter; public class ExportUtils { private static final String TAG = ExportUtils.class.getSimpleName(); - public static void postWorkoutExport(Context context, Track track) { + public static void postWorkoutExport(Context context, Track track, ExportServiceResultReceiver resultReceiver) { if (PreferencesUtils.shouldInstantExportAfterWorkout(context)) { TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(context); DocumentFile directory = PreferencesUtils.getDefaultExportDirectoryUri(context); + ExportService.enqueue(context, resultReceiver, track.getId(), trackFileFormat, directory.getUri()); exportTrack(context, trackFileFormat, directory, track); } } @@ -36,6 +39,10 @@ public class ExportUtils { TrackExporter trackExporter = trackFileFormat.newTrackExporter(context); Uri exportDocumentFileUri = getExportDocumentFileUri(context, track.getId(), trackFileFormat, directory); + if (exportDocumentFileUri == null) { + Log.e(TAG, "Couldn't create document file for export"); + return false; + } try (OutputStream outputStream = context.getContentResolver().openOutputStream(exportDocumentFileUri)) { if (trackExporter.writeTrack(track, outputStream)) { @@ -80,7 +87,10 @@ public class ExportUtils { String exportFileName = getExportFileNameByTrackId(trackId, trackFileFormat.getExtension()); Uri exportDocumentFileUri = findFile(context, directory.getUri(), exportFileName); if (exportDocumentFileUri == null) { - exportDocumentFileUri = directory.createFile(trackFileFormat.getMimeType(), exportFileName).getUri(); + final DocumentFile file = directory.createFile(trackFileFormat.getMimeType(), exportFileName); + if (file != null) { + exportDocumentFileUri = file.getUri(); + } } return exportDocumentFileUri; } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index c7bca868d..c6dce953d 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -212,6 +212,7 @@ limitations under the License. with photos without photos Exported %1$d of %2$s to %3$s + Post-workout export failed, please check the export directory. as %1$s to %2$s Exporting to %1$s… Exported %1$s to %2$s