Export all habits as CSV from the settings menu

Closes #28
pull/77/merge
Alinson S. Xavier 10 years ago
parent 2d675ed9b0
commit e6b7b8b590

@ -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) !=

@ -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<Habit> selectedHabits)
{
new AsyncTask<Void, Void, Void>()
{
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();
}
}

@ -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<Void, Void, Void>
{
private final ReplayableActivity activity;
private ProgressBar progressBar;
private final List<Habit> selectedHabits;
String archiveFilename;
public ExportHabitsTask(ReplayableActivity activity, List<Habit> 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;
}
}

@ -466,4 +466,9 @@ public class ListHabitsFragment extends Fragment
break;
}
}
public void exportAllHabits()
{
new ExportHabitsTask(activity, Habit.getAll(true), progressBar).execute();
}
}

@ -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

@ -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);

@ -481,13 +481,16 @@ public class Habit extends Model
public static void writeCSV(List<Habit> 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();

@ -28,12 +28,6 @@
android:enabled="true"
android:title="@string/show_archived"/>
<item
android:id="@+id/action_import"
android:orderInCategory="50"
android:title="Import data"
app:showAsAction="never"/>
<item
android:id="@+id/action_settings"
android:orderInCategory="100"

@ -106,7 +106,7 @@
<string name="any_weekday">Monday to Friday</string>
<string name="any_day">Any day of the week</string>
<string name="select_weekdays">Select days</string>
<string name="export_to_csv">Export data</string>
<string name="export_to_csv">Export as CSV</string>
<string name="done_label">Done</string>
<string name="clear_label">Clear</string>
@ -142,4 +142,9 @@
<string name="could_not_import">Failed to import habits from file.</string>
<string name="file_not_recognized">File type not recognized.</string>
<string name="habits_imported">Habits imported successfully.</string>
<string name="import_data_summary">Supports files exported by Loop, Tickmate, HabitBull or Rewire. See FAQ for more information.</string>
<string name="import_data">Import data</string>
<string name="export_as_csv_summary">This archive contains files that can be opened by spreadsheet software such as Microsoft Excel or OpenOffice Calc, but cannot be imported back.</string>
<string name="export_full_backup">Export full backup</string>
<string name="export_full_backup_summary">This file contains all your data and can be imported back.</string>
</resources>

@ -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"/>
</PreferenceCategory>
@ -44,17 +45,21 @@
android:key="pref_key_links"
android:title="Database">
<Preference android:title="Export data">
<intent
android:action="android.intent.action.VIEW"
android:data="@string/helpURL"/>
<Preference
android:summary="@string/export_full_backup_summary"
android:title="@string/export_full_backup">
</Preference>
<Preference android:title="Import data"
android:summary="Supports files exported by Loop, Tickmate, HabitBull or Rewire. This feature is currently experimental.">
<intent
android:action="android.intent.action.VIEW"
android:data="@string/helpURL"/>
<Preference
android:key="exportCSV"
android:summary="@string/export_as_csv_summary"
android:title="@string/export_to_csv">
</Preference>
<Preference
android:key="importData"
android:summary="@string/import_data_summary"
android:title="@string/import_data">
</Preference>
</PreferenceCategory>

Loading…
Cancel
Save