Skip to content

Commit d1c3103

Browse files
committed
Merge branch 'hotfix/patches'
2 parents 66b3d0c + 5642de8 commit d1c3103

File tree

20 files changed

+345
-122
lines changed

20 files changed

+345
-122
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
Change Log
22
===============================================================================
3+
Version 2.1.3 *(2016-10-20)*
4+
----------------------------
5+
* Fixed: Scheduled exports execute too often or not at all in some cases
6+
* Fixed: Crash if device is rotated during first-run wizard execution
7+
* Fixed: Negative values displayed as green on homescreen widget
8+
* Improved: Homescreen widget now allows to select the book to use
9+
* Improved: Update Russian translation
10+
311
Version 2.1.2 *(2016-09-21)*
412
----------------------------
513
* Fixed: Scheduled exports always run daily (no matter the actual schedule)

CONTRIBUTORS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,11 @@ The following (incomplete list of) people (in no particular order) contributed (
3030
* Terry Chung <[email protected]>
3131
* Caesar Wirth <[email protected]>
3232
* Alceu Rodrigues Neto <[email protected]>
33+
* Carlo Zancanaro <[email protected]>
34+
* Eric Daly <[email protected]>
35+
* Weslly Oliveira <[email protected]>
36+
* Felipe Morato <[email protected]>
37+
* Alceu Rodrigues Neto <[email protected]>
38+
* Salama AB <[email protected]>
3339

3440
Please visit https://crowdin.com/project/gnucash-android for a more complete list of translation contributions

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ apply plugin: 'io.fabric'
77

88
def versionMajor = 2
99
def versionMinor = 1
10-
def versionPatch = 2
11-
def versionBuild = 0
10+
def versionPatch = 3
11+
def versionBuild = 1
1212

1313
def buildTime() {
1414
def df = new SimpleDateFormat("yyyyMMdd HH:mm 'UTC'")

app/src/main/java/org/gnucash/android/app/GnuCashApplication.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public void onCreate(){
126126
BookDbHelper bookDbHelper = new BookDbHelper(getApplicationContext());
127127
mBooksDbAdapter = new BooksDbAdapter(bookDbHelper.getWritableDatabase());
128128

129-
initDatabaseAdapters();
129+
initializeDatabaseAdapters();
130130
setDefaultCurrencyCode(getDefaultCurrencyCode());
131131

132132
if (BuildConfig.DEBUG && !isRoboUnitTest())
@@ -137,7 +137,7 @@ public void onCreate(){
137137
* Initialize database adapter singletons for use in the application
138138
* This method should be called every time a new book is opened
139139
*/
140-
private static void initDatabaseAdapters() {
140+
private static void initializeDatabaseAdapters() {
141141
if (mDbHelper != null){ //close if open
142142
mDbHelper.getReadableDatabase().close();
143143
}
@@ -205,15 +205,23 @@ public static BooksDbAdapter getBooksDbAdapter(){
205205
}
206206

207207
/**
208-
* Loads the book with GUID {@code bookUID}
208+
* Loads the book with GUID {@code bookUID} and opens the AccountsActivity
209209
* @param bookUID GUID of the book to be loaded
210210
*/
211211
public static void loadBook(@NonNull String bookUID){
212-
mBooksDbAdapter.setActive(bookUID);
213-
initDatabaseAdapters();
212+
activateBook(bookUID);
214213
AccountsActivity.start(getAppContext());
215214
}
216215

216+
/**
217+
* Activates the book with unique identifer {@code bookUID}, and refreshes the database adapters
218+
* @param bookUID GUID of the book to be activated
219+
*/
220+
public static void activateBook(@NonNull String bookUID){
221+
mBooksDbAdapter.setActive(bookUID);
222+
initializeDatabaseAdapters();
223+
}
224+
217225
/**
218226
* Returns the currently active database in the application
219227
* @return Currently active {@link SQLiteDatabase}

app/src/main/java/org/gnucash/android/db/BookDbHelper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ public void onCreate(SQLiteDatabase db) {
124124

125125
}
126126

127+
/**
128+
* Returns the database for the book
129+
* @param bookUID GUID of the book
130+
* @return SQLiteDatabase of the book
131+
*/
132+
public static SQLiteDatabase getDatabase(String bookUID){
133+
DatabaseHelper dbHelper = new DatabaseHelper(GnuCashApplication.getAppContext(), bookUID);
134+
return dbHelper.getWritableDatabase();
135+
}
136+
127137
/**
128138
* Inserts the book into the database
129139
* @param db Book database

app/src/main/java/org/gnucash/android/db/adapter/BooksDbAdapter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.gnucash.android.ui.settings.PreferenceActivity;
3232
import org.gnucash.android.util.TimestampHelper;
3333

34+
import java.util.List;
35+
3436
/**
3537
* Database adapter for creating/modifying book entries
3638
*/

app/src/main/java/org/gnucash/android/model/ScheduledAction.java

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,35 +173,64 @@ public long getTimeOfLastSchedule(){
173173
}
174174

175175
/**
176-
* Computes the next time that this scheduled action is supposed to be executed
176+
* Computes the next time that this scheduled action is supposed to be
177+
* executed based on the execution count.
178+
*
177179
* <p>This method does not consider the end time, or number of times it should be run.
178-
* It only considers when the next execution would theoretically be due</p>
180+
* It only considers when the next execution would theoretically be due.</p>
181+
*
179182
* @return Next run time in milliseconds
180183
*/
181-
public long computeNextScheduledExecutionTime(){
182-
int multiplier = mRecurrence.getPeriodType().getMultiplier();
183-
//this is the last planned time for the action to occur, not the last run time
184-
long lastActionTime = getTimeOfLastSchedule(); //mStartDate + ((mExecutionCount-1)*getPeriod());
185-
if (lastActionTime < 0){
184+
public long computeNextCountBasedScheduledExecutionTime(){
185+
return computeNextScheduledExecutionTimeStartingAt(getTimeOfLastSchedule());
186+
}
187+
188+
/**
189+
* Computes the next time that this scheduled action is supposed to be
190+
* executed based on the time of the last run.
191+
*
192+
* <p>This method does not consider the end time, or number of times it should be run.
193+
* It only considers when the next execution would theoretically be due.</p>
194+
*
195+
* @return Next run time in milliseconds
196+
*/
197+
public long computeNextTimeBasedScheduledExecutionTime() {
198+
return computeNextScheduledExecutionTimeStartingAt(getLastRunTime());
199+
}
200+
201+
/**
202+
* Computes the next time that this scheduled action is supposed to be
203+
* executed starting at startTime.
204+
*
205+
* <p>This method does not consider the end time, or number of times it should be run.
206+
* It only considers when the next execution would theoretically be due.</p>
207+
*
208+
* @param startTime time in milliseconds to use as start to compute the next schedule.
209+
*
210+
* @return Next run time in milliseconds
211+
*/
212+
private long computeNextScheduledExecutionTimeStartingAt(long startTime) {
213+
if (startTime <= 0){ // has never been run
186214
return mStartDate;
187215
}
188216

189-
LocalDateTime localDate = LocalDateTime.fromDateFields(new Date(lastActionTime));
217+
int multiplier = mRecurrence.getPeriodType().getMultiplier();
218+
LocalDateTime nextScheduledExecution = LocalDateTime.fromDateFields(new Date(startTime));
190219
switch (mRecurrence.getPeriodType()) {
191220
case DAY:
192-
localDate = localDate.plusDays(multiplier);
221+
nextScheduledExecution = nextScheduledExecution.plusDays(multiplier);
193222
break;
194223
case WEEK:
195-
localDate = localDate.plusWeeks(multiplier);
224+
nextScheduledExecution = nextScheduledExecution.plusWeeks(multiplier);
196225
break;
197226
case MONTH:
198-
localDate = localDate.plusMonths(multiplier);
227+
nextScheduledExecution = nextScheduledExecution.plusMonths(multiplier);
199228
break;
200229
case YEAR:
201-
localDate = localDate.plusYears(multiplier);
230+
nextScheduledExecution = nextScheduledExecution.plusYears(multiplier);
202231
break;
203232
}
204-
return localDate.toDate().getTime();
233+
return nextScheduledExecution.toDate().getTime();
205234
}
206235

207236
/**

app/src/main/java/org/gnucash/android/receivers/TransactionAppWidgetProvider.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import android.content.SharedPreferences.Editor;
2222
import android.preference.PreferenceManager;
2323

24+
import org.gnucash.android.db.adapter.BooksDbAdapter;
25+
import org.gnucash.android.model.Book;
2426
import org.gnucash.android.ui.common.UxArgument;
2527
import org.gnucash.android.ui.homescreen.WidgetConfigurationActivity;
28+
import org.gnucash.android.ui.settings.PreferenceActivity;
2629

2730
/**
2831
* {@link AppWidgetProvider} which is responsible for managing widgets on the homescreen
@@ -43,13 +46,13 @@ public void onUpdate(Context context, AppWidgetManager appWidgetManager,
4346
for (int i=0; i<N; i++) {
4447
int appWidgetId = appWidgetIds[i];
4548

46-
String accountUID = PreferenceManager
47-
.getDefaultSharedPreferences(context)
49+
String accountUID = PreferenceActivity.getActiveBookSharedPreferences()
4850
.getString(UxArgument.SELECTED_ACCOUNT_UID + appWidgetId, null);
4951
if (accountUID == null)
5052
return;
5153

52-
WidgetConfigurationActivity.updateWidget(context, appWidgetId, accountUID);
54+
WidgetConfigurationActivity.updateWidget(context, appWidgetId, accountUID,
55+
BooksDbAdapter.getInstance().getActiveBookUID());
5356
}
5457
}
5558

@@ -62,11 +65,11 @@ public void onEnabled(Context context) {
6265
@Override
6366
public void onDeleted(Context context, int[] appWidgetIds) {
6467
super.onDeleted(context, appWidgetIds);
65-
Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
68+
Editor editor = PreferenceActivity.getActiveBookSharedPreferences().edit();
6669

6770
for (int appWidgetId : appWidgetIds) {
6871
editor.remove(UxArgument.SELECTED_ACCOUNT_UID + appWidgetId);
6972
}
70-
editor.commit();
73+
editor.apply();
7174
}
7275
}

app/src/main/java/org/gnucash/android/service/ScheduledActionService.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,17 @@ private static void executeScheduledEvent(ScheduledAction scheduledAction, SQLit
142142
//the last run time is computed instead of just using "now" so that if the more than
143143
// one period has been skipped, all intermediate transactions can be created
144144

145+
scheduledAction.setLastRun(System.currentTimeMillis());
146+
//set the execution count in the object because it will be checked for the next iteration in the calling loop
147+
scheduledAction.setExecutionCount(executionCount); //this call is important, do not remove!!
145148
//update the last run time and execution count
146149
ContentValues contentValues = new ContentValues();
147-
contentValues.put(DatabaseSchema.ScheduledActionEntry.COLUMN_LAST_RUN, System.currentTimeMillis());
148-
contentValues.put(DatabaseSchema.ScheduledActionEntry.COLUMN_EXECUTION_COUNT, executionCount);
150+
contentValues.put(DatabaseSchema.ScheduledActionEntry.COLUMN_LAST_RUN,
151+
scheduledAction.getLastRunTime());
152+
contentValues.put(DatabaseSchema.ScheduledActionEntry.COLUMN_EXECUTION_COUNT,
153+
scheduledAction.getExecutionCount());
149154
db.update(DatabaseSchema.ScheduledActionEntry.TABLE_NAME, contentValues,
150155
DatabaseSchema.ScheduledActionEntry.COLUMN_UID + "=?", new String[]{scheduledAction.getUID()});
151-
152-
//set the execution count in the object because it will be checked for the next iteration in the calling loop
153-
scheduledAction.setExecutionCount(executionCount); //this call is important, do not remove!!
154156
}
155157

156158
/**
@@ -161,26 +163,31 @@ private static void executeScheduledEvent(ScheduledAction scheduledAction, SQLit
161163
* @return Number of times backup is executed. This should either be 1 or 0
162164
*/
163165
private static int executeBackup(ScheduledAction scheduledAction, SQLiteDatabase db) {
164-
int executionCount = 0;
165-
long now = System.currentTimeMillis();
166-
long endTime = scheduledAction.getEndTime();
167-
168-
if (endTime > 0 && endTime < now)
169-
return executionCount;
170-
171-
if (scheduledAction.computeNextScheduledExecutionTime() > now)
166+
if (!shouldExecuteScheduledBackup(scheduledAction))
172167
return 0;
173168

174169
ExportParams params = ExportParams.parseCsv(scheduledAction.getTag());
175170
try {
176171
//wait for async task to finish before we proceed (we are holding a wake lock)
177172
new ExportAsyncTask(GnuCashApplication.getAppContext(), db).execute(params).get();
178-
scheduledAction.setExecutionCount(++executionCount);
179173
} catch (InterruptedException | ExecutionException e) {
180174
Crashlytics.logException(e);
181175
Log.e(LOG_TAG, e.getMessage());
182176
}
183-
return executionCount;
177+
return 1;
178+
}
179+
180+
private static boolean shouldExecuteScheduledBackup(ScheduledAction scheduledAction) {
181+
long now = System.currentTimeMillis();
182+
long endTime = scheduledAction.getEndTime();
183+
184+
if (endTime > 0 && endTime < now)
185+
return false;
186+
187+
if (scheduledAction.computeNextTimeBasedScheduledExecutionTime() > now)
188+
return false;
189+
190+
return true;
184191
}
185192

186193
/**
@@ -214,7 +221,7 @@ private static int executeTransactions(ScheduledAction scheduledAction, SQLiteDa
214221

215222
//we may be executing scheduled action significantly after scheduled time (depending on when Android fires the alarm)
216223
//so compute the actual transaction time from pre-known values
217-
long transactionTime = scheduledAction.computeNextScheduledExecutionTime();
224+
long transactionTime = scheduledAction.computeNextCountBasedScheduledExecutionTime();
218225
while (transactionTime <= endTime) {
219226
Transaction recurringTrxn = new Transaction(trxnTemplate, true);
220227
recurringTrxn.setTime(transactionTime);
@@ -224,7 +231,7 @@ private static int executeTransactions(ScheduledAction scheduledAction, SQLiteDa
224231

225232
if (totalPlannedExecutions > 0 && executionCount >= totalPlannedExecutions)
226233
break; //if we hit the total planned executions set, then abort
227-
transactionTime = scheduledAction.computeNextScheduledExecutionTime();
234+
transactionTime = scheduledAction.computeNextCountBasedScheduledExecutionTime();
228235
}
229236

230237
transactionsDbAdapter.bulkAddRecords(transactions, DatabaseAdapter.UpdateMethod.insert);

app/src/main/java/org/gnucash/android/ui/common/BaseDrawerActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ protected void onCreate(Bundle savedInstanceState) {
102102
super.onCreate(savedInstanceState);
103103
setContentView(getContentView());
104104

105+
//if a parameter was passed to open an account within a specific book, then switch
106+
String bookUID = getIntent().getStringExtra(UxArgument.BOOK_UID);
107+
if (bookUID != null && !bookUID.equals(BooksDbAdapter.getInstance().getActiveBookUID())){
108+
GnuCashApplication.activateBook(bookUID);
109+
}
110+
105111
ButterKnife.bind(this);
106112
setSupportActionBar(mToolbar);
107113
final ActionBar actionBar = getSupportActionBar();

0 commit comments

Comments
 (0)