From f71c75f180d472451cdd1b8c0365ad2a846ccd1f Mon Sep 17 00:00:00 2001 From: jannis Date: Thu, 9 Jan 2020 16:25:46 +0100 Subject: [PATCH] #29 Option to save backup to internal storage --- app/build.gradle | 3 + app/src/main/AndroidManifest.xml | 1 + .../fitness/activity/FitoTrackActivity.java | 37 ++++----- .../activity/FitoTrackSettingsActivity.java | 22 ------ .../fitness/activity/SettingsActivity.java | 10 ++- .../fitness/activity/ShowWorkoutActivity.java | 10 ++- .../fitness/export/BackupController.java | 1 + .../de/tadris/fitness/util/FileUtils.java | 78 +++++++++++++++++++ app/src/main/res/values/strings.xml | 5 ++ 9 files changed, 118 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/de/tadris/fitness/util/FileUtils.java diff --git a/app/build.gradle b/app/build.gradle index 93a1715..4dcd3da 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -82,6 +82,9 @@ dependencies { implementation 'stax:stax-api:1.0.1' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8' + // File Utils + implementation 'commons-io:commons-io:2.6' + // Upload to OSM implementation('de.westnordost:osmapi-traces:1.0') configurations { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c6c3c40..79648e4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ + { try{ String file= getFilesDir().getAbsolutePath() + "/shared/backup.ftb"; - if (!new File(file).getParentFile().mkdirs()) { + File parent = new File(file).getParentFile(); + if (!parent.exists() && !parent.mkdirs()) { throw new IOException("Cannot write"); } Uri uri= FileProvider.getUriForFile(getBaseContext(), "de.tadris.fitness.fileprovider", new File(file)); @@ -123,7 +129,7 @@ public class SettingsActivity extends FitoTrackSettingsActivity { mHandler.post(() -> { dialogController.cancel(); - shareFile(uri); + FileUtils.saveOrShareFile(this, uri, "ftb"); }); }catch (Exception e){ e.printStackTrace(); diff --git a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java index 02cdb4a..d336847 100644 --- a/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java +++ b/app/src/main/java/de/tadris/fitness/activity/ShowWorkoutActivity.java @@ -48,6 +48,7 @@ import de.tadris.fitness.data.WorkoutSample; import de.tadris.fitness.osm.OAuthAuthentication; import de.tadris.fitness.osm.OsmTraceUploader; import de.tadris.fitness.util.DialogUtils; +import de.tadris.fitness.util.FileUtils; import de.tadris.fitness.util.gpx.GpxExporter; import de.tadris.fitness.util.unit.UnitUtils; import de.tadris.fitness.view.ProgressDialogController; @@ -202,20 +203,25 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils. } private void exportToGpx(){ + if (!hasStoragePermission()) { + requestStoragePermissions(); + return; + } ProgressDialogController dialogController= new ProgressDialogController(this, getString(R.string.exporting)); dialogController.setIndeterminate(true); dialogController.show(); new Thread(() -> { try{ String file= getFilesDir().getAbsolutePath() + "/shared/workout.gpx"; - if (!new File(file).getParentFile().mkdirs()) { + File parent = new File(file).getParentFile(); + if (!parent.exists() && !parent.mkdirs()) { throw new IOException("Cannot write to " + file); } Uri uri= FileProvider.getUriForFile(getBaseContext(), "de.tadris.fitness.fileprovider", new File(file)); GpxExporter.exportWorkout(getBaseContext(), workout, new File(file)); dialogController.cancel(); - mHandler.post(() -> shareFile(uri)); + mHandler.post(() -> FileUtils.saveOrShareFile(this, uri, "gpx")); }catch (Exception e){ e.printStackTrace(); mHandler.post(() -> showErrorDialog(e, R.string.error, R.string.errorGpxExportFailed)); diff --git a/app/src/main/java/de/tadris/fitness/export/BackupController.java b/app/src/main/java/de/tadris/fitness/export/BackupController.java index 65cf498..546ffe3 100644 --- a/app/src/main/java/de/tadris/fitness/export/BackupController.java +++ b/app/src/main/java/de/tadris/fitness/export/BackupController.java @@ -65,6 +65,7 @@ public class BackupController { private void init(){ database= Instance.getInstance(context).db; UnitUtils.setUnit(context); // Ensure unit system is correct + newContainer(); } private void newContainer(){ diff --git a/app/src/main/java/de/tadris/fitness/util/FileUtils.java b/app/src/main/java/de/tadris/fitness/util/FileUtils.java new file mode 100644 index 0000000..f541e25 --- /dev/null +++ b/app/src/main/java/de/tadris/fitness/util/FileUtils.java @@ -0,0 +1,78 @@ +package de.tadris.fitness.util; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.util.Log; +import android.widget.Toast; + +import org.apache.commons.io.IOUtils; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import de.tadris.fitness.R; + +public class FileUtils { + + public static void saveOrShareFile(Activity activity, Uri uri, String suffix) { + String[] colors = {activity.getString(R.string.share), activity.getString(R.string.save)}; + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setItems(colors, (dialog, which) -> { + if (which == 0) { + shareFile(activity, uri); + } else { + try { + saveFile(activity, uri, suffix); + Toast.makeText(activity, R.string.savedToDownloads, Toast.LENGTH_LONG).show(); + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(activity, R.string.savingFailed, Toast.LENGTH_LONG).show(); + } + } + }); + builder.show(); + } + + private static void saveFile(Activity activity, Uri fileUri, String suffix) throws IOException { + File target = new File(Environment.getExternalStorageDirectory(), "Download/fitotrack" + System.currentTimeMillis() + "." + suffix); + if (!target.createNewFile()) { + throw new IOException("Cannot write to file " + target); + } + copyFile(activity, fileUri, Uri.fromFile(target)); + } + + private static void copyFile(Activity activity, Uri sourceUri, Uri targetUri) throws IOException { + InputStream input = activity.getContentResolver().openInputStream(sourceUri); + if (input == null) { + throw new IOException("Source file not found"); + } + OutputStream output = activity.getContentResolver().openOutputStream(targetUri); + IOUtils.copy(input, output); + } + + private static void shareFile(Activity activity, Uri uri) { + Intent intentShareFile = new Intent(Intent.ACTION_SEND); + intentShareFile.setDataAndType(uri, activity.getContentResolver().getType(uri)); + intentShareFile.putExtra(Intent.EXTRA_STREAM, uri); + intentShareFile.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + + activity.startActivity(Intent.createChooser(intentShareFile, activity.getString(R.string.shareFile))); + + Log.d("Export", uri.toString()); + Log.d("Export", activity.getContentResolver().getType(uri)); + try { + Log.d("Export", new BufferedInputStream(activity.getContentResolver().openInputStream(uri)).toString()); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 17e626f..a55932e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -150,4 +150,9 @@ TextToSpeech is not available Edit Comment Announcement Mode + + Save + Share + Saved to Downloads + Saving failed