diff --git a/app/src/main/java/org/isoron/uhabits/MainActivity.java b/app/src/main/java/org/isoron/uhabits/MainActivity.java index 7dd2ed5be..1888d3773 100644 --- a/app/src/main/java/org/isoron/uhabits/MainActivity.java +++ b/app/src/main/java/org/isoron/uhabits/MainActivity.java @@ -31,7 +31,6 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Environment; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; @@ -43,7 +42,6 @@ import android.view.MenuItem; import org.isoron.helpers.DateHelper; import org.isoron.helpers.DialogHelper; import org.isoron.helpers.ReplayableActivity; -import org.isoron.uhabits.dialogs.FilePickerDialog; import org.isoron.uhabits.fragments.ListHabitsFragment; import org.isoron.uhabits.helpers.ReminderHelper; import org.isoron.uhabits.models.Habit; @@ -53,8 +51,6 @@ import org.isoron.uhabits.widgets.HistoryWidgetProvider; import org.isoron.uhabits.widgets.ScoreWidgetProvider; import org.isoron.uhabits.widgets.StreakWidgetProvider; -import java.io.File; - public class MainActivity extends ReplayableActivity implements ListHabitsFragment.OnHabitClickListener { @@ -65,6 +61,9 @@ public class MainActivity extends ReplayableActivity public static final String ACTION_REFRESH = "org.isoron.uhabits.ACTION_REFRESH"; + public static final int RESULT_IMPORT_DATA = 1; + public static final int RESULT_EXPORT_ALL_AS_CSV = 2; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -129,16 +128,10 @@ public class MainActivity extends ReplayableActivity { switch (item.getItemId()) { - case R.id.action_import: - { - onActionImportClicked(); - return true; - } - case R.id.action_settings: { Intent intent = new Intent(this, SettingsActivity.class); - startActivity(intent); + startActivityForResult(intent, 0); return true; } @@ -154,6 +147,21 @@ public class MainActivity extends ReplayableActivity } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + switch (resultCode) + { + case RESULT_IMPORT_DATA: + onActionImportClicked(); + break; + + case RESULT_EXPORT_ALL_AS_CSV: + listHabitsFragment.exportAllHabits(); + break; + } + } + private void onActionImportClicked() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != diff --git a/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java b/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java index f7c615353..8a577981b 100644 --- a/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java +++ b/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java @@ -21,13 +21,9 @@ package org.isoron.uhabits.dialogs; import android.app.AlertDialog; import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.AsyncTask; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.widget.ProgressBar; import com.android.colorpicker.ColorPickerDialog; @@ -42,11 +38,10 @@ import org.isoron.uhabits.commands.ChangeHabitColorCommand; import org.isoron.uhabits.commands.DeleteHabitsCommand; import org.isoron.uhabits.commands.UnarchiveHabitsCommand; import org.isoron.uhabits.fragments.EditHabitFragment; -import org.isoron.uhabits.io.HabitsExporter; +import org.isoron.uhabits.fragments.ExportHabitsTask; import org.isoron.uhabits.loaders.HabitListLoader; import org.isoron.uhabits.models.Habit; -import java.io.File; import java.util.LinkedList; import java.util.List; @@ -224,50 +219,6 @@ public class HabitSelectionCallback implements ActionMode.Callback private void onExportHabitsClick(final LinkedList selectedHabits) { - new AsyncTask() - { - String archiveFilename; - - @Override - protected void onPreExecute() - { - if(progressBar != null) - { - progressBar.setIndeterminate(true); - progressBar.setVisibility(View.VISIBLE); - } - } - - @Override - protected void onPostExecute(Void aVoid) - { - if(archiveFilename != null) - { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_SEND); - intent.setType("application/zip"); - intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(archiveFilename))); - - activity.startActivity(intent); - } - else - { - activity.showToast(R.string.could_not_export); - } - - if(progressBar != null) - progressBar.setVisibility(View.GONE); - } - - @Override - protected Void doInBackground(Void... params) - { - String dirName = String.format("%s/export/", activity.getExternalCacheDir()); - HabitsExporter exporter = new HabitsExporter(selectedHabits, dirName); - archiveFilename = exporter.writeArchive(); - - return null; - } - }.execute(); + new ExportHabitsTask(activity, selectedHabits, progressBar).execute(); } } diff --git a/app/src/main/java/org/isoron/uhabits/fragments/ExportHabitsTask.java b/app/src/main/java/org/isoron/uhabits/fragments/ExportHabitsTask.java new file mode 100644 index 000000000..4431fcc3d --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/fragments/ExportHabitsTask.java @@ -0,0 +1,72 @@ +package org.isoron.uhabits.fragments; + +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.view.View; +import android.widget.ProgressBar; + +import org.isoron.helpers.ReplayableActivity; +import org.isoron.uhabits.R; +import org.isoron.uhabits.io.HabitsExporter; +import org.isoron.uhabits.models.Habit; + +import java.io.File; +import java.util.List; + +public class ExportHabitsTask extends AsyncTask +{ + private final ReplayableActivity activity; + private ProgressBar progressBar; + private final List selectedHabits; + String archiveFilename; + + public ExportHabitsTask(ReplayableActivity activity, List selectedHabits, + ProgressBar progressBar) + { + this.selectedHabits = selectedHabits; + this.progressBar = progressBar; + this.activity = activity; + } + + @Override + protected void onPreExecute() + { + if(progressBar != null) + { + progressBar.setIndeterminate(true); + progressBar.setVisibility(View.VISIBLE); + } + } + + @Override + protected void onPostExecute(Void aVoid) + { + if(archiveFilename != null) + { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.setType("application/zip"); + intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(archiveFilename))); + + activity.startActivity(intent); + } + else + { + activity.showToast(R.string.could_not_export); + } + + if(progressBar != null) + progressBar.setVisibility(View.GONE); + } + + @Override + protected Void doInBackground(Void... params) + { + String dirName = String.format("%s/export/", activity.getExternalCacheDir()); + HabitsExporter exporter = new HabitsExporter(selectedHabits, dirName); + archiveFilename = exporter.writeArchive(); + + return null; + } +} diff --git a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java index 58e8a7170..05c95cbc4 100644 --- a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java @@ -466,4 +466,9 @@ public class ListHabitsFragment extends Fragment break; } } + + public void exportAllHabits() + { + new ExportHabitsTask(activity, Habit.getAll(true), progressBar).execute(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/fragments/SettingsFragment.java b/app/src/main/java/org/isoron/uhabits/fragments/SettingsFragment.java index fb5c04f60..20b5ce28d 100644 --- a/app/src/main/java/org/isoron/uhabits/fragments/SettingsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/fragments/SettingsFragment.java @@ -22,8 +22,10 @@ package org.isoron.uhabits.fragments; import android.app.backup.BackupManager; import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.Preference; import android.preference.PreferenceFragment; +import org.isoron.uhabits.MainActivity; import org.isoron.uhabits.R; public class SettingsFragment extends PreferenceFragment @@ -34,6 +36,24 @@ public class SettingsFragment extends PreferenceFragment { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); + + setResultOnPreferenceClick("importData", MainActivity.RESULT_IMPORT_DATA); + setResultOnPreferenceClick("exportCSV", MainActivity.RESULT_EXPORT_ALL_AS_CSV); + } + + private void setResultOnPreferenceClick(String key, final int result) + { + Preference exportCSV = findPreference(key); + exportCSV.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() + { + @Override + public boolean onPreferenceClick(Preference preference) + { + getActivity().setResult(result); + getActivity().finish(); + return true; + } + }); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/io/HabitsExporter.java b/app/src/main/java/org/isoron/uhabits/io/HabitsExporter.java index c3674220e..32aad256d 100644 --- a/app/src/main/java/org/isoron/uhabits/io/HabitsExporter.java +++ b/app/src/main/java/org/isoron/uhabits/io/HabitsExporter.java @@ -58,7 +58,7 @@ public class HabitsExporter private void writeHabits() throws IOException { - String filename = "habits.csv"; + String filename = "Habits.csv"; new File(exportDirName).mkdirs(); FileWriter out = new FileWriter(exportDirName + filename); generateFilenames.add(filename); @@ -67,7 +67,7 @@ public class HabitsExporter for(Habit h : habits) { - String habitDirName = String.format("%s/", h.name); + String habitDirName = String.format("%03d %s/", h.position, h.name); new File(exportDirName + habitDirName).mkdirs(); generateDirs.add(habitDirName); @@ -78,7 +78,7 @@ public class HabitsExporter private void writeScores(String habitDirName, ScoreList scores) throws IOException { - String path = habitDirName + "scores.csv"; + String path = habitDirName + "Scores.csv"; FileWriter out = new FileWriter(exportDirName + path); generateFilenames.add(path); scores.writeCSV(out); @@ -87,7 +87,7 @@ public class HabitsExporter private void writeCheckmarks(String habitDirName, CheckmarkList checkmarks) throws IOException { - String filename = habitDirName + "checkmarks.csv"; + String filename = habitDirName + "Checkmarks.csv"; FileWriter out = new FileWriter(exportDirName + filename); generateFilenames.add(filename); checkmarks.writeCSV(out); @@ -98,7 +98,7 @@ public class HabitsExporter { SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat(); String date = dateFormat.format(DateHelper.getStartOfToday()); - String zipFilename = String.format("%s/habits-%s.zip", exportDirName, date); + String zipFilename = String.format("%s/Loop-Habits-%s.zip", exportDirName, date); FileOutputStream fos = new FileOutputStream(zipFilename); ZipOutputStream zos = new ZipOutputStream(fos); diff --git a/app/src/main/java/org/isoron/uhabits/models/Habit.java b/app/src/main/java/org/isoron/uhabits/models/Habit.java index e93d73abc..b40b7a012 100644 --- a/app/src/main/java/org/isoron/uhabits/models/Habit.java +++ b/app/src/main/java/org/isoron/uhabits/models/Habit.java @@ -481,13 +481,16 @@ public class Habit extends Model public static void writeCSV(List habits, Writer out) throws IOException { + String header[] = { "Name", "Description", "FrequencyNumerator", "FrequencyDenominator", "Color" }; + CSVWriter csv = new CSVWriter(out); + csv.writeNext(header, false); for(Habit habit : habits) { String[] cols = { habit.name, habit.description, Integer.toString(habit.freqNum), Integer.toString(habit.freqDen), ColorHelper.toHTML(habit.color) }; - csv.writeAll(Collections.singletonList(cols)); + csv.writeNext(cols, false); } csv.close(); diff --git a/app/src/main/res/menu/list_habits_menu.xml b/app/src/main/res/menu/list_habits_menu.xml index 06a5c3fe8..320dc357a 100644 --- a/app/src/main/res/menu/list_habits_menu.xml +++ b/app/src/main/res/menu/list_habits_menu.xml @@ -28,12 +28,6 @@ android:enabled="true" android:title="@string/show_archived"/> - - Monday to Friday Any day of the week Select days - Export data + Export as CSV Done Clear @@ -142,4 +142,9 @@ Failed to import habits from file. File type not recognized. Habits imported successfully. + Supports files exported by Loop, Tickmate, HabitBull or Rewire. See FAQ for more information. + Import data + This archive contains files that can be opened by spreadsheet software such as Microsoft Excel or OpenOffice Calc, but cannot be imported back. + Export full backup + This file contains all your data and can be imported back. \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 82a733f67..b1bbf36f6 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -36,7 +36,8 @@ android:entries="@array/snooze_interval_names" android:entryValues="@array/snooze_interval_values" android:key="pref_snooze_interval" - android:title="@string/pref_snooze_interval_title"/> + android:title="@string/pref_snooze_interval_title" + android:summary="%s"/> @@ -44,17 +45,21 @@ android:key="pref_key_links" android:title="Database"> - - + - - + + + +