Skip to content

Commit

Permalink
Open file for import in background thread
Browse files Browse the repository at this point in the history
Should fix crashes during import when opening from a network location
Fix crash when opening scheduled actions due to change in export params format
Upgrade database to version 11
Code refactoring
  • Loading branch information
codinguser committed Nov 18, 2015
1 parent 5411b4b commit 288717d
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 65 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/org/gnucash/android/db/DatabaseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
/*
* NOTE: In order to modify the database, create a new static method in the MigrationHelper class
* called upgradeDbToVersion<#>, e.g. int upgradeDbToVersion10(SQLiteDatabase) in order to upgrade to version 10.
* The upgrade method should return the current database version as the return value.
* Then all you need to do is incremend the DatabaseSchema.DATABASE_VERSION to the appropriate number.
* The upgrade method should return the upgraded database version as the return value.
* Then all you need to do is increment the DatabaseSchema.DATABASE_VERSION to the appropriate number.
*/
if (oldVersion > newVersion) {
throw new IllegalArgumentException("Database downgrades are not supported at the moment");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class DatabaseSchema {
* Database version.
* With any change to the database schema, this number must increase
*/
public static final int DATABASE_VERSION = 10;
public static final int DATABASE_VERSION = 11;

/**
* Database version where Splits were introduced
Expand Down
58 changes: 57 additions & 1 deletion app/src/main/java/org/gnucash/android/db/MigrationHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
import java.nio.channels.FileChannel;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
Expand Down Expand Up @@ -1068,7 +1070,7 @@ static int upgradeDbToVersion9(SQLiteDatabase db){
* <p>This method converts all saved scheduled export parameters to the new format using the
* timestamp of last export</p>
* @param db SQLite database
* @return New version number
* @return 10 if upgrade was successful, 9 otherwise
*/
static int upgradeDbToVersion10(SQLiteDatabase db){
Log.i(DatabaseHelper.LOG_TAG, "Upgrading database to version 9");
Expand Down Expand Up @@ -1107,11 +1109,65 @@ static int upgradeDbToVersion10(SQLiteDatabase db){
db.insert(ScheduledActionEntry.TABLE_NAME, null, contentValues);
}

cursor.close();

db.setTransactionSuccessful();
oldVersion = 10;
} finally {
db.endTransaction();
}
return oldVersion;
}

/**
* Upgrade database to version 11
* <p>
* Migrate scheduled backups and update export parameters to the new format
* </p>
* @param db SQLite database
* @return 11 if upgrade was successful, 10 otherwise
*/
static int upgradeDbToVersion11(SQLiteDatabase db){
Log.i(DatabaseHelper.LOG_TAG, "Upgrading database to version 9");
int oldVersion = 10;

db.beginTransaction();
try {
Cursor cursor = db.query(ScheduledActionEntry.TABLE_NAME, null,
ScheduledActionEntry.COLUMN_TYPE + "= ?",
new String[]{ScheduledAction.ActionType.BACKUP.name()}, null, null, null);

Map<String, String> uidToTagMap = new HashMap<>();
while (cursor.moveToNext()) {
String uid = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_UID));
String tag = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_TAG));
String[] tokens = tag.split(";");
try {
Timestamp timestamp = Timestamp.valueOf(tokens[2]);
} catch (IllegalArgumentException ex) {
tokens[2] = PreferenceManager.getDefaultSharedPreferences(GnuCashApplication.getAppContext())
.getString(Exporter.PREF_LAST_EXPORT_TIME, Exporter.TIMESTAMP_ZERO);
} finally {
tag = TextUtils.join(";", tokens);
}
uidToTagMap.put(uid, tag);
}

cursor.close();

ContentValues contentValues = new ContentValues();
for (Map.Entry<String, String> entry : uidToTagMap.entrySet()) {
contentValues.clear();
contentValues.put(ScheduledActionEntry.COLUMN_TAG, entry.getValue());
db.update(ScheduledActionEntry.TABLE_NAME, contentValues,
ScheduledActionEntry.COLUMN_UID + " = ?", new String[]{entry.getKey()});
}

db.setTransactionSuccessful();
oldVersion = 11;
} finally {
db.endTransaction();
}
return oldVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

package org.gnucash.android.export;

import android.preference.PreferenceManager;

import org.gnucash.android.BuildConfig;
import org.gnucash.android.R;
import org.gnucash.android.app.GnuCashApplication;
import org.gnucash.android.ui.export.ExportFormFragment;

import java.sql.Timestamp;
Expand Down
47 changes: 25 additions & 22 deletions app/src/main/java/org/gnucash/android/importer/ImportAsyncTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ProgressDialog;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
Expand All @@ -35,52 +36,54 @@
* Imports a GnuCash (desktop) account file and displays a progress dialog.
* The AccountsActivity is opened when importing is done.
*/
public class ImportAsyncTask extends AsyncTask<InputStream, Void, Boolean> {
private final Activity context;
public class ImportAsyncTask extends AsyncTask<Uri, Void, Boolean> {
private final Activity mContext;
private TaskDelegate mDelegate;
private ProgressDialog progressDialog;
private ProgressDialog mProgressDialog;

public ImportAsyncTask(Activity context){
this.context = context;
this.mContext = context;
}

public ImportAsyncTask(Activity context, TaskDelegate delegate){
this.context = context;
this.mContext = context;
this.mDelegate = delegate;
}

@TargetApi(11)
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setTitle(R.string.title_progress_importing_accounts);
progressDialog.setIndeterminate(true);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setTitle(R.string.title_progress_importing_accounts);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.show();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){
//these methods must be called after progressDialog.show()
progressDialog.setProgressNumberFormat(null);
progressDialog.setProgressPercentFormat(null);
mProgressDialog.setProgressNumberFormat(null);
mProgressDialog.setProgressPercentFormat(null);
}

}

@Override
protected Boolean doInBackground(InputStream... inputStreams) {
protected Boolean doInBackground(Uri... uris) {
try {
GncXmlImporter.parse(inputStreams[0]);
InputStream accountInputStream = mContext.getContentResolver().openInputStream(uris[0]);
GncXmlImporter.parse(accountInputStream);
} catch (Exception exception){
Log.e(ImportAsyncTask.class.getName(), "" + exception.getMessage());
Crashlytics.logException(exception);
exception.printStackTrace();

final String err_msg = exception.getLocalizedMessage();
context.runOnUiThread(new Runnable() {
Crashlytics.log(err_msg);
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context,
context.getString(R.string.toast_error_importing_accounts) + "\n" + err_msg,
Toast.makeText(mContext,
mContext.getString(R.string.toast_error_importing_accounts) + "\n" + err_msg,
Toast.LENGTH_LONG).show();
}
});
Expand All @@ -96,18 +99,18 @@ protected void onPostExecute(Boolean importSuccess) {
mDelegate.onTaskComplete();

try {
if (progressDialog != null && progressDialog.isShowing())
progressDialog.dismiss();
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
} catch (IllegalArgumentException ex){
//TODO: This is a hack to catch "View not attached to window" exceptions
//FIXME by moving the creation and display of the progress dialog to the Fragment
} finally {
progressDialog = null;
mProgressDialog = null;
}

int message = importSuccess ? R.string.toast_success_importing_accounts : R.string.toast_error_importing_accounts;
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();

AccountsActivity.start(context);
AccountsActivity.start(mContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,18 +295,9 @@ private void handleOpenFileIntent(Intent intent) {
Uri data = intent.getData();
if (data != null){
GncXmlExporter.createBackup();

intent.setData(null);
InputStream accountInputStream = null;
try {
accountInputStream = getContentResolver().openInputStream(data);
new ImportAsyncTask(this).execute(accountInputStream);
} catch (FileNotFoundException e) {
Crashlytics.logException(e);
Log.e(LOG_TAG, "Error opening file for import - " + e.getMessage());
} finally {
removeFirstRunFlag();
}
new ImportAsyncTask(this).execute(data);
removeFirstRunFlag();
}
}

Expand Down Expand Up @@ -496,8 +487,8 @@ public void onTaskComplete() {
};
}

InputStream accountFileInputStream = activity.getResources().openRawResource(R.raw.default_accounts);
new ImportAsyncTask(activity, delegate).execute(accountFileInputStream);
Uri uri = Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + R.raw.default_accounts);
new ImportAsyncTask(activity, delegate).execute(uri);
}

/**
Expand Down Expand Up @@ -536,14 +527,8 @@ public static void startXmlFileChooser(Activity activity) {
* @param data Intent data containing the XML uri
*/
public static void importXmlFileFromIntent(Activity context, Intent data) {
try {
GncXmlExporter.createBackup();
InputStream accountInputStream = context.getContentResolver().openInputStream(data.getData());
new ImportAsyncTask(context).execute(accountInputStream);
} catch (FileNotFoundException e) {
Crashlytics.logException(e);
Toast.makeText(context, R.string.toast_error_importing_accounts, Toast.LENGTH_SHORT).show();
}
GncXmlExporter.createBackup();
new ImportAsyncTask(context).execute(data.getData());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
Expand Down Expand Up @@ -565,15 +566,7 @@ public void onClick(DialogInterface dialog, int which) {
@Override
public void onClick(DialogInterface dialog, int which) {
File backupFile = sortedBackupFiles[which];

try {
FileInputStream inputStream = new FileInputStream(backupFile);
new ImportAsyncTask(SettingsActivity.this).execute(inputStream);
} catch (FileNotFoundException e) {
Crashlytics.logException(e);
Log.e(LOG_TAG, "Error restoring backup: " + backupFile.getName());
Toast.makeText(SettingsActivity.this, R.string.toast_error_importing_accounts, Toast.LENGTH_LONG).show();
}
new ImportAsyncTask(SettingsActivity.this).execute(Uri.fromFile(backupFile));
}
});

Expand Down
16 changes: 7 additions & 9 deletions app/src/main/res/layout/activity_transaction_detail.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,27 +133,25 @@
style="@style/TransactionInfo" />
</TableRow>

<TableRow android:id="@+id/row_trn_recurrence"
<TableRow android:id="@+id/row_trn_notes"
style="@style/FormRow">

<ImageView style="@style/FormIcon"
android:src="@drawable/ic_action_rotate_right"/>
android:src="@drawable/ic_action_sort_by_size"/>

<TextView android:id="@+id/trn_recurrence"
<TextView android:id="@+id/trn_notes"
style="@style/TransactionInfo" />

</TableRow>

<TableRow android:id="@+id/row_trn_notes"
<TableRow android:id="@+id/row_trn_recurrence"
style="@style/FormRow">

<ImageView style="@style/FormIcon"
android:src="@drawable/ic_action_sort_by_size"/>
android:src="@drawable/ic_action_rotate_right"/>

<TextView android:id="@+id/trn_notes"
<TextView android:id="@+id/trn_recurrence"
style="@style/TransactionInfo" />
</TableRow>


</TableLayout>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>

0 comments on commit 288717d

Please sign in to comment.