mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Allow user to export a full copy of the database
This commit is contained in:
@@ -24,7 +24,7 @@ import android.app.Application;
|
|||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.ActiveAndroid;
|
||||||
import com.activeandroid.Configuration;
|
import com.activeandroid.Configuration;
|
||||||
|
|
||||||
import java.io.File;
|
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||||
|
|
||||||
public class HabitsApplication extends Application
|
public class HabitsApplication extends Application
|
||||||
{
|
{
|
||||||
@@ -41,14 +41,6 @@ public class HabitsApplication extends Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteDB(String databaseFilename)
|
|
||||||
{
|
|
||||||
File databaseFile = new File(String.format("%s/../databases/%s",
|
|
||||||
getApplicationContext().getFilesDir().getPath(), databaseFilename));
|
|
||||||
|
|
||||||
if(databaseFile.exists()) databaseFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate()
|
public void onCreate()
|
||||||
{
|
{
|
||||||
@@ -58,7 +50,7 @@ public class HabitsApplication extends Application
|
|||||||
if (isTestMode())
|
if (isTestMode())
|
||||||
{
|
{
|
||||||
databaseFilename = "test.db";
|
databaseFilename = "test.db";
|
||||||
deleteDB(databaseFilename);
|
DatabaseHelper.deleteDatabase(this, databaseFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration dbConfig = new Configuration.Builder(this)
|
Configuration dbConfig = new Configuration.Builder(this)
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ public class MainActivity extends ReplayableActivity
|
|||||||
public static final String ACTION_REFRESH = "org.isoron.uhabits.ACTION_REFRESH";
|
public static final String ACTION_REFRESH = "org.isoron.uhabits.ACTION_REFRESH";
|
||||||
|
|
||||||
public static final int RESULT_IMPORT_DATA = 1;
|
public static final int RESULT_IMPORT_DATA = 1;
|
||||||
public static final int RESULT_EXPORT_ALL_AS_CSV = 2;
|
public static final int RESULT_EXPORT_CSV = 2;
|
||||||
|
public static final int RESULT_EXPORT_DB = 3;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState)
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
@@ -155,9 +156,13 @@ public class MainActivity extends ReplayableActivity
|
|||||||
onActionImportClicked();
|
onActionImportClicked();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESULT_EXPORT_ALL_AS_CSV:
|
case RESULT_EXPORT_CSV:
|
||||||
listHabitsFragment.exportAllHabits();
|
listHabitsFragment.exportAllHabits();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RESULT_EXPORT_DB:
|
||||||
|
listHabitsFragment.exportDB();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import org.isoron.uhabits.helpers.ReminderHelper;
|
|||||||
import org.isoron.uhabits.loaders.HabitListLoader;
|
import org.isoron.uhabits.loaders.HabitListLoader;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.tasks.ExportCSVTask;
|
import org.isoron.uhabits.tasks.ExportCSVTask;
|
||||||
|
import org.isoron.uhabits.tasks.ExportDBTask;
|
||||||
import org.isoron.uhabits.tasks.ImportDataTask;
|
import org.isoron.uhabits.tasks.ImportDataTask;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -472,4 +473,9 @@ public class ListHabitsFragment extends Fragment
|
|||||||
{
|
{
|
||||||
new ExportCSVTask(activity, Habit.getAll(true), progressBar).execute();
|
new ExportCSVTask(activity, Habit.getAll(true), progressBar).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void exportDB()
|
||||||
|
{
|
||||||
|
new ExportDBTask(activity, progressBar).execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ public class SettingsFragment extends PreferenceFragment
|
|||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
|
|
||||||
setResultOnPreferenceClick("importData", MainActivity.RESULT_IMPORT_DATA);
|
setResultOnPreferenceClick("importData", MainActivity.RESULT_IMPORT_DATA);
|
||||||
setResultOnPreferenceClick("exportCSV", MainActivity.RESULT_EXPORT_ALL_AS_CSV);
|
setResultOnPreferenceClick("exportCSV", MainActivity.RESULT_EXPORT_CSV);
|
||||||
|
setResultOnPreferenceClick("exportDB", MainActivity.RESULT_EXPORT_DB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setResultOnPreferenceClick(String key, final int result)
|
private void setResultOnPreferenceClick(String key, final int result)
|
||||||
|
|||||||
@@ -1,9 +1,32 @@
|
|||||||
package org.isoron.uhabits.helpers;
|
package org.isoron.uhabits.helpers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.ActiveAndroid;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.BuildConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
public class DatabaseHelper
|
public class DatabaseHelper
|
||||||
{
|
{
|
||||||
|
public static void copy(File src, File dst) throws IOException
|
||||||
|
{
|
||||||
|
FileInputStream inStream = new FileInputStream(src);
|
||||||
|
FileOutputStream outStream = new FileOutputStream(dst);
|
||||||
|
FileChannel inChannel = inStream.getChannel();
|
||||||
|
FileChannel outChannel = outStream.getChannel();
|
||||||
|
inChannel.transferTo(0, inChannel.size(), outChannel);
|
||||||
|
inStream.close();
|
||||||
|
outStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
public interface Command
|
public interface Command
|
||||||
{
|
{
|
||||||
void execute();
|
void execute();
|
||||||
@@ -22,4 +45,31 @@ public class DatabaseHelper
|
|||||||
ActiveAndroid.endTransaction();
|
ActiveAndroid.endTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
|
public static String saveDatabaseCopy(Context context, File dir) throws IOException
|
||||||
|
{
|
||||||
|
File db = getDatabaseFile(context, BuildConfig.databaseFilename);
|
||||||
|
|
||||||
|
SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat();
|
||||||
|
String date = dateFormat.format(DateHelper.getStartOfToday());
|
||||||
|
File dbCopy = new File(String.format("%s/Loop-Habits-Backup-%s.db", dir.getAbsolutePath(), date));
|
||||||
|
|
||||||
|
copy(db, dbCopy);
|
||||||
|
|
||||||
|
return dbCopy.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteDatabase(Context context, String databaseFilename)
|
||||||
|
{
|
||||||
|
File db = getDatabaseFile(context, databaseFilename);
|
||||||
|
if(db.exists()) db.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static File getDatabaseFile(Context context, String databaseFilename)
|
||||||
|
{
|
||||||
|
return new File(String.format("%s/../databases/%s",
|
||||||
|
context.getApplicationContext().getFilesDir().getPath(), databaseFilename));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public class HabitsCSVExporter
|
|||||||
{
|
{
|
||||||
SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat();
|
SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat();
|
||||||
String date = dateFormat.format(DateHelper.getStartOfToday());
|
String date = dateFormat.format(DateHelper.getStartOfToday());
|
||||||
String zipFilename = String.format("%s/Loop-Habits-%s.zip", exportDirName, date);
|
String zipFilename = String.format("%s/Loop-Habits-CSV-%s.zip", exportDirName, date);
|
||||||
|
|
||||||
FileOutputStream fos = new FileOutputStream(zipFilename);
|
FileOutputStream fos = new FileOutputStream(zipFilename);
|
||||||
ZipOutputStream zos = new ZipOutputStream(fos);
|
ZipOutputStream zos = new ZipOutputStream(fos);
|
||||||
|
|||||||
94
app/src/main/java/org/isoron/uhabits/tasks/ExportDBTask.java
Normal file
94
app/src/main/java/org/isoron/uhabits/tasks/ExportDBTask.java
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.tasks;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.ReplayableActivity;
|
||||||
|
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ExportDBTask extends AsyncTask<Void, Void, Void>
|
||||||
|
{
|
||||||
|
private final ReplayableActivity activity;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
public ExportDBTask(ReplayableActivity activity, ProgressBar progressBar)
|
||||||
|
{
|
||||||
|
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(filename != null)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
|
intent.setType("application/octet-stream");
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename)));
|
||||||
|
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activity.showToast(R.string.could_not_export);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(progressBar != null)
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params)
|
||||||
|
{
|
||||||
|
filename = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filename = DatabaseHelper.saveDatabaseCopy(activity, activity.getExternalCacheDir());
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -142,9 +142,10 @@
|
|||||||
<string name="could_not_import">Failed to import habits from file.</string>
|
<string name="could_not_import">Failed to import habits from file.</string>
|
||||||
<string name="file_not_recognized">File type not recognized.</string>
|
<string name="file_not_recognized">File type not recognized.</string>
|
||||||
<string name="habits_imported">Habits imported successfully.</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_summary">Supports full backups exported by this app, as well as files generated by Tickmate, HabitBull or Rewire. See FAQ for more information.</string>
|
||||||
<string name="import_data">Import data</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_as_csv_summary">Generates 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">Export full backup</string>
|
||||||
<string name="export_full_backup_summary">This file contains all your data and can be imported back.</string>
|
<string name="export_full_backup_summary">Generates a file that contains all your data, and that can be imported back.</string>
|
||||||
|
<string name="full_backup_success">Full backup successfully exported.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
android:title="Database">
|
android:title="Database">
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
|
android:key="exportDB"
|
||||||
android:summary="@string/export_full_backup_summary"
|
android:summary="@string/export_full_backup_summary"
|
||||||
android:title="@string/export_full_backup">
|
android:title="@string/export_full_backup">
|
||||||
</Preference>
|
</Preference>
|
||||||
|
|||||||
Reference in New Issue
Block a user