From 8ad3af0f2784876161b830508f4b0ed7c752db5e Mon Sep 17 00:00:00 2001 From: Casey D Date: Sun, 24 May 2015 23:01:10 +0100 Subject: [PATCH] Fixed a few bugs raised by the good folks on the internet. - MashStep list graphical bug - Timer counting down using wrong API. - MashStep default water-to-grain values not updated. --- AndroidManifest.xml | 4 +- BACKLOG | 5 +- res/layout/view_drag_drop_list.xml | 2 +- .../frontend/AddMashProfileActivity.java | 44 ++++++++++--- .../brews/frontend/MainActivity.java | 61 +++++++++++++++++-- .../brews/services/BrewTimerService.java | 35 ++++++++--- src/com/biermacht/brews/utils/Constants.java | 1 + 7 files changed, 125 insertions(+), 27 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fad64df..38707b0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionCode="8" + android:versionName="1.0.5"> parentView) { } public void updateMashStepList() { - // We have trouble setting the size in XML, so we dynamically do it here based on - // the number of steps. 149 is a magic number that seems to be the size of the mash step. - // Add two for each step to handle the borders added in the list. - int height = (mProfile.getMashStepList().size() * 150) + (2 * mProfile.getMashStepList().size()); - LinearLayout.LayoutParams params = - new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height); - // Drag list view dragDropAdapter = new MashStepArrayAdapter(this, mProfile.getMashStepList()); dragDropListView.setAdapter(dragDropAdapter); dragDropListView.setDropListener(onDrop); dragDropListView.setRemoveListener(onRemove); dragDropListView.setDragEnabled(true); - dragDropListView.setLayoutParams(params); + setListViewHeightBasedOnChildren(dragDropListView); + } + + /** + * This method adjusts the height of the given listView to match the combined height of all if its + * children and the dividers between list items. This is used to set the height of the mash step + * list such that it does not scroll, since it is encompassed by a ScrollView. + * + * @param listView + */ + public static void setListViewHeightBasedOnChildren(ListView listView) { + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter == null) { + return; + } + + int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED); + int totalHeight = 0; + View view = null; + for (int i = 0; i < listAdapter.getCount(); i++) { + view = listAdapter.getView(i, view, listView); + if (i == 0) { + view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT)); + } + + view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); + totalHeight += view.getMeasuredHeight(); + } + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); + listView.setLayoutParams(params); + listView.requestLayout(); } @Override diff --git a/src/com/biermacht/brews/frontend/MainActivity.java b/src/com/biermacht/brews/frontend/MainActivity.java index 6421163..d3ceaf1 100644 --- a/src/com/biermacht/brews/frontend/MainActivity.java +++ b/src/com/biermacht/brews/frontend/MainActivity.java @@ -36,6 +36,8 @@ import com.biermacht.brews.frontend.fragments.HydrometerTempCalculatorFragment; import com.biermacht.brews.frontend.fragments.RecipesFragment; import com.biermacht.brews.frontend.fragments.StrikeWaterCalculatorFragment; +import com.biermacht.brews.recipe.MashProfile; +import com.biermacht.brews.recipe.MashStep; import com.biermacht.brews.recipe.Recipe; import com.biermacht.brews.tasks.ImportXmlIngredientsTask; import com.biermacht.brews.tasks.InitializeTask; @@ -105,12 +107,12 @@ public void onCreate(Bundle savedInstanceState) { databaseInterface = new DatabaseInterface(getApplicationContext()); databaseInterface.open(); - // SHARED PREFERENCES JUNK ALL GOES HERE! - SharedPreferences preferences = this.getSharedPreferences(Constants.PREFERENCES, Context - .MODE_PRIVATE); + // Check for important shared preferences flags and perform any required actions. + SharedPreferences preferences = this.getSharedPreferences(Constants.PREFERENCES, Context.MODE_PRIVATE); usedBefore = preferences.getBoolean(Constants.PREF_USED_BEFORE, false); if (! usedBefore) { - // We've used the app! Woo! + // This is the first time the app has been used. Mark that the app has been opened, and + // perform first-time use setup task. preferences.edit().putBoolean(Constants.PREF_USED_BEFORE, true).commit(); new ImportXmlIngredientsTask(this).execute(""); @@ -118,10 +120,59 @@ public void onCreate(Bundle savedInstanceState) { Database.createRecipeWithName("Master Recipe"); } else { - // Async Initialize Assets on startup + // Async Initialize Assets on startup. new InitializeTask(ingredientHandler).execute(""); } + //////////////////////////////////////////////////////////////////////////////////////////////// + // BEGIN BAD HACKY TEMPORARY FIX. + //////////////////////////////////////////////////////////////////////////////////////////////// + // Temporary fix - initial mash profiles which came with early version of Biermacht had + // bad water-to-grain ratios for their Mash In steps. This procedure re-sets them to the correct + // values. This should be removed once enough of the user-base has upgraded to this SW version. + boolean fixedRatios = preferences.getBoolean(Constants.PREF_FIXED_RATIOS, false); + if (!fixedRatios) + { + // Get all profiles from the Custom database. Iterate through, change the water-to-grain + // ratio for those what are wrong, and save them. + preferences.edit().putBoolean(Constants.PREF_FIXED_RATIOS, true).commit(); + ArrayList l = new ArrayList(); + l.addAll(Database.getMashProfilesFromVirtualDatabase(Constants.DATABASE_CUSTOM)); + MashStep s; + Recipe masterRecipe; + try { + masterRecipe = Database.getRecipeWithId(Constants.MASTER_RECIPE_ID); + } catch (Exception e) + { + masterRecipe = new Recipe(); + } + ArrayList nameList = new ArrayList(); + nameList.add("Decoction Mash"); + nameList.add("Infusion, Full Body"); + nameList.add("Infusion, Light Body"); + nameList.add("Infusion, Medium Body"); + + for (MashProfile mp : l) { + masterRecipe.setMashProfile(mp); + if (nameList.contains(mp.getName())) + { + s = mp.getMashStepList().get(0); + if (s.getBeerXmlStandardWaterToGrainRatio() > 4.2) { + if (mp.getName().contains("Infusion")) { + s.setBeerXmlStandardWaterToGrainRatio(2.607); + } + else { + s.setBeerXmlStandardWaterToGrainRatio(4.1727); + } + mp.save(Constants.DATABASE_CUSTOM); + } + } + } + } + //////////////////////////////////////////////////////////////////////////////////////////////// + // END BAD HACKY TEMPORARY FIX. + //////////////////////////////////////////////////////////////////////////////////////////////// + // Initialize storage for imported recipes foundImportedRecipes = new ArrayList(); diff --git a/src/com/biermacht/brews/services/BrewTimerService.java b/src/com/biermacht/brews/services/BrewTimerService.java index 7337a73..5090e35 100644 --- a/src/com/biermacht/brews/services/BrewTimerService.java +++ b/src/com/biermacht/brews/services/BrewTimerService.java @@ -8,6 +8,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Build; import android.os.IBinder; import android.os.SystemClock; import android.support.v4.app.NotificationCompat; @@ -213,10 +214,10 @@ public void start(int seconds) { if (timerState != Constants.RUNNING) { timerState = Constants.RUNNING; remainingSeconds = seconds; - this.alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + 1000, - pendingTimerIntent); } + + // Schedule the first timer callback. + this.scheduleTimerTick(); } // Alternative to start(time) which just continues using the current @@ -258,11 +259,29 @@ public void onReceive(Context c, Intent i) { stop(); } - // If the timer is running, schedule a new tick - if (timerState == Constants.RUNNING) { - alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + 1000, - pendingTimerIntent); + // Schedule the next timer callback. + this.scheduleTimerTick(); + } + + /** + * Schedules a system alarm in 1000 milliseconds. This alarm is received by the Service and is + * used to update the timer. + */ + public void scheduleTimerTick() { + // For pre-KITKAT version of Android, AlarmManager.set() schedules an exact time in the future. + // For post-KITKAT version of Android, setExact() was added to perform this function, and set() + // is no-longer guaranteed to be exact (the OS may choose the reschedule in order to save + // battery life). We don't want to allow the OS to reschedule the timer, so make sure to use + // setExact() if it is available. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + this.alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + 1000, + pendingTimerIntent); + } + else { + this.alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + 1000, + pendingTimerIntent); } } } \ No newline at end of file diff --git a/src/com/biermacht/brews/utils/Constants.java b/src/com/biermacht/brews/utils/Constants.java index daa5e06..cfda728 100644 --- a/src/com/biermacht/brews/utils/Constants.java +++ b/src/com/biermacht/brews/utils/Constants.java @@ -63,6 +63,7 @@ public class Constants { public static final String PREF_LAST_OPENED = "com.biermacht.brews.lastOpened"; public static final String PREF_BREWER_NAME = "com.biermacht.brews.brewerName"; public static final String PREF_MEAS_SYSTEM = "com.biermacht.brews.measurementSystem"; + public static final String PREF_FIXED_RATIOS = "com.biermacht.brews.waterToGrainRatiosFixed"; // Activity for result return codes public static final int RESULT_DELETED = 1;