]> git.ktnx.net Git - mobile-ledger.git/commitdiff
migrate to a proper db helper class, sub-classed from SQLiteOpenHelper
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Thu, 13 Dec 2018 05:35:13 +0000 (05:35 +0000)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Thu, 13 Dec 2018 05:35:13 +0000 (05:35 +0000)
a small step from the quest of migrating to a ViewModel architecture,
avoiding context leaks

app/src/main/java/net/ktnx/mobileledger/AccountSummary.java
app/src/main/java/net/ktnx/mobileledger/MobileLedgerDB.java [deleted file]
app/src/main/java/net/ktnx/mobileledger/MobileLedgerDatabase.java [new file with mode: 0644]
app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java
app/src/main/java/net/ktnx/mobileledger/RetrieveAccountsTask.java

index fbdc89f2c659205a8ddaa39b5c0b54d0f202564d..829b00b1717bb7f7e72bf4230e59c7b3b0528561 100644 (file)
@@ -6,6 +6,7 @@ import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
 import android.graphics.Typeface;
 import android.os.Build;
 import android.os.Bundle;
@@ -34,8 +35,6 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import static android.view.View.GONE;
-import static net.ktnx.mobileledger.MobileLedgerDB.db;
-import static net.ktnx.mobileledger.MobileLedgerDB.set_option_value;
 
 public class AccountSummary extends AppCompatActivity {
     DrawerLayout drawer;
@@ -45,6 +44,7 @@ public class AccountSummary extends AppCompatActivity {
     MenuItem mShowHiddenAccounts;
     SharedPreferences.OnSharedPreferenceChangeListener sBindPreferenceSummaryToValueListener;
     private AccountRowLayout clickedAccountRow;
+    private MobileLedgerDatabase dbh;
 
     public static void preferences_changed() {
         account_list_needs_update = true;
@@ -58,6 +58,8 @@ public class AccountSummary extends AppCompatActivity {
         Toolbar toolbar = findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
 
+        dbh = new MobileLedgerDatabase(this);
+
         drawer = findViewById(R.id.drawer_layout);
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                 this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
@@ -188,17 +190,7 @@ public class AccountSummary extends AppCompatActivity {
     }
 
     private void prepare_db() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            MobileLedgerDB.setDb_filename(this.getApplicationInfo().deviceProtectedDataDir + "/" + MobileLedgerDB.DATABASE_NAME);
-        }
-        else {
-            MobileLedgerDB.setDb_filename(
-                    this.getApplicationInfo().dataDir + "/" + MobileLedgerDB.DATABASE_NAME);
-        }
-        MobileLedgerDB.initDB(getResources(), getPackageName());
-
-        account_list_last_updated = MobileLedgerDB.get_option_value("last_refresh", (long) 0);
-
+        account_list_last_updated = dbh.get_option_value("last_refresh", (long) 0);
     }
 
     private void update_accounts(boolean force) {
@@ -239,7 +231,7 @@ public class AccountSummary extends AppCompatActivity {
                     Snackbar.make(drawer, err_text, Snackbar.LENGTH_LONG ).show();
                 }
                 else {
-                    set_option_value("last_refresh", new Date().getTime() );
+                    dbh.set_option_value("last_refresh", new Date().getTime() );
                     update_account_table();
                 }
             }
@@ -271,8 +263,9 @@ public class AccountSummary extends AppCompatActivity {
     }
 
     public void hideAccountClicked(MenuItem item) {
-        db.execSQL("update accounts set hidden=1 where name=?",
-                new Object[]{clickedAccountRow.getAccountName()});
+        try(SQLiteDatabase db = dbh.getWritableDatabase()) {
+            db.execSQL("update accounts set hidden=1 where name=?", new Object[]{clickedAccountRow.getAccountName()});
+        }
         update_account_table();
     }
 
@@ -297,79 +290,89 @@ public class AccountSummary extends AppCompatActivity {
                 .getBoolean("show_hidden_accounts", false);
         Log.d("pref", "show_hidden_accounts is " + (showingHiddenAccounts ? "true" : "false"));
 
-        try (Cursor cursor = db
-                .rawQuery("SELECT name, hidden FROM accounts ORDER BY name;", null))
-        {
-            boolean even = false;
-            String skippingAccountName = null;
-            while (cursor.moveToNext()) {
-                String acc_name = cursor.getString(0);
-                if (skippingAccountName != null) {
-                    if (acc_name.startsWith(skippingAccountName + ":")) continue;
-
-                    skippingAccountName = null;
-                }
-
-                boolean is_hidden = cursor.getInt(1) == 1;
+        try(SQLiteDatabase db = dbh.getReadableDatabase()) {
+            try (Cursor cursor = db
+                    .rawQuery("SELECT name, hidden FROM accounts ORDER BY name;", null))
+            {
+                boolean even = false;
+                String skippingAccountName = null;
+                while (cursor.moveToNext()) {
+                    String acc_name = cursor.getString(0);
+                    if (skippingAccountName != null) {
+                        if (acc_name.startsWith(skippingAccountName + ":")) continue;
+
+                        skippingAccountName = null;
+                    }
 
-                if (!showingHiddenAccounts && is_hidden) {
-                    skippingAccountName = acc_name;
-                    continue;
-                }
+                    boolean is_hidden = cursor.getInt(1) == 1;
 
-                LinearLayout r = new AccountRowLayout(this, acc_name);
-                r.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
-                r.setGravity(Gravity.CENTER_VERTICAL);
-                r.setPadding(getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin), dp2px(3), getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin), dp2px(4));
-                r.setMinimumHeight(rowHeight);
+                    if (!showingHiddenAccounts && is_hidden) {
+                        skippingAccountName = acc_name;
+                        continue;
+                    }
 
-                if (even) {
-                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                        r.setBackgroundColor(
-                                getResources().getColor(R.color.table_row_even_bg, getTheme()));
+                    LinearLayout r = new AccountRowLayout(this, acc_name);
+                    r.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.WRAP_CONTENT));
+                    r.setGravity(Gravity.CENTER_VERTICAL);
+                    r.setPadding(getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin), dp2px(3),
+                            getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin),
+                            dp2px(4));
+                    r.setMinimumHeight(rowHeight);
+
+                    if (even) {
+                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                            r.setBackgroundColor(
+                                    getResources().getColor(R.color.table_row_even_bg, getTheme()));
+                        }
+                        else {
+                            r.setBackgroundColor(getResources().getColor(R.color.table_row_even_bg));
+                        }
                     }
-                    else {
-                        r.setBackgroundColor(getResources().getColor(R.color.table_row_even_bg));
+                    even = !even;
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                        r.setContextClickable(true);
                     }
-                }
-                even = !even;
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                    r.setContextClickable(true);
-                }
-                r.setOnCreateContextMenuListener(ccml);
-
-
-                TextView acc_tv = new TextView(this, null, R.style.account_summary_account_name);
-                acc_tv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 5f));
-                acc_tv.setGravity(Gravity.CENTER_VERTICAL);
-                int[] indent_level = new int[]{0};
-                String short_acc_name = strip_higher_accounts(acc_name, indent_level);
-                acc_tv.setPadding(indent_level[0] * getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin) / 2, 0, 0, 0);
-                acc_tv.setText(short_acc_name);
-                if (is_hidden) acc_tv.setTypeface(null, Typeface.ITALIC);
-                r.addView(acc_tv);
-
-                TextView amt_tv = new TextView(this, null, R.style.account_summary_amounts);
-                amt_tv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
-                amt_tv.setTextAlignment(EditText.TEXT_ALIGNMENT_VIEW_END);
-                amt_tv.setGravity(Gravity.CENTER_VERTICAL);
+                    r.setOnCreateContextMenuListener(ccml);
+
+
+                    TextView acc_tv = new TextView(this, null, R.style.account_summary_account_name);
+                    acc_tv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT, 5f));
+                    acc_tv.setGravity(Gravity.CENTER_VERTICAL);
+                    int[] indent_level = new int[]{0};
+                    String short_acc_name = strip_higher_accounts(acc_name, indent_level);
+                    acc_tv.setPadding(indent_level[0] * getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin) / 2, 0, 0,
+                            0);
+                    acc_tv.setText(short_acc_name);
+                    if (is_hidden) acc_tv.setTypeface(null, Typeface.ITALIC);
+                    r.addView(acc_tv);
+
+                    TextView amt_tv = new TextView(this, null, R.style.account_summary_amounts);
+                    amt_tv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT, 1f));
+                    amt_tv.setTextAlignment(EditText.TEXT_ALIGNMENT_VIEW_END);
+                    amt_tv.setGravity(Gravity.CENTER_VERTICAL);
 //                amt_tv.setGravity(Gravity.CENTER);
-                amt_tv.setMinWidth(dp2px(60f));
-                StringBuilder amt_text = new StringBuilder();
-                try (Cursor cAmounts = db.rawQuery("SELECT currency, value FROM account_values WHERE account = ?", new String[]{acc_name})) {
-                    while (cAmounts.moveToNext()) {
-                        String curr = cAmounts.getString(0);
-                        Float amt = cAmounts.getFloat(1);
-                        if (amt_text.length() != 0) amt_text.append('\n');
-                        amt_text.append(String.format("%s %,1.2f", curr, amt));
+                    amt_tv.setMinWidth(dp2px(60f));
+                    StringBuilder amt_text = new StringBuilder();
+                    try (Cursor cAmounts = db.rawQuery(
+                            "SELECT currency, value FROM account_values WHERE account = ?", new String[]{acc_name}))
+                    {
+                        while (cAmounts.moveToNext()) {
+                            String curr = cAmounts.getString(0);
+                            Float amt = cAmounts.getFloat(1);
+                            if (amt_text.length() != 0) amt_text.append('\n');
+                            amt_text.append(String.format("%s %,1.2f", curr, amt));
+                        }
                     }
-                }
-                amt_tv.setText(amt_text.toString());
-                if (is_hidden) amt_tv.setTypeface(null, Typeface.ITALIC);
+                    amt_tv.setText(amt_text.toString());
+                    if (is_hidden) amt_tv.setTypeface(null, Typeface.ITALIC);
 
-                r.addView(amt_tv);
+                    r.addView(amt_tv);
 
-                root.addView(r);
+                    root.addView(r);
+                }
             }
         }
     }
diff --git a/app/src/main/java/net/ktnx/mobileledger/MobileLedgerDB.java b/app/src/main/java/net/ktnx/mobileledger/MobileLedgerDB.java
deleted file mode 100644 (file)
index 021ee45..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-package net.ktnx.mobileledger;
-
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
-import android.util.Log;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Locale;
-
-class MobileLedgerDB {
-    static final String DATABASE_NAME = "accounts";
-    static final String OPT_DB_REVISION = "db_revision";
-    static final String ACCOUNTS_TABLE = "accounts";
-    static final String DESCRIPTION_HISTORY_TABLE = "description_history";
-    private static String db_filename;
-    static SQLiteDatabase db;
-
-    static String getDb_filename() {
-        return db_filename;
-    }
-
-    static void setDb_filename(String db_filename) {
-        MobileLedgerDB.db_filename = db_filename;
-    }
-
-    static void initDB(Resources rm, String pkg_name) {
-        db = SQLiteDatabase.openOrCreateDatabase(db_filename, null);
-        int cur_ver = Integer.parseInt(get_option_value(OPT_DB_REVISION, "-1"));
-
-        Log.d("db", "Current DB revision is "+String.valueOf(cur_ver));
-
-        while (applyRevision(rm, pkg_name, cur_ver+1)) {
-            cur_ver++;
-        }
-
-        Log.d("db", "Database revision is "+String.valueOf(cur_ver)+" now");
-    }
-    private static boolean applyRevision(Resources rm, String pkg_name, int rev_no) {
-        String rev_file = String.format(Locale.US, "sql_%d", rev_no);
-
-        int res_id = rm.getIdentifier(rev_file, "raw", pkg_name);
-        if (res_id == 0) {
-            Log.d("db", String.format(Locale.US, "No resource for revision %d", rev_no));
-            return false;
-        }
-        db.beginTransaction();
-        try (InputStream res = rm.openRawResource(res_id)) {
-            Log.d("db", "Applying revision " + String.valueOf(rev_no));
-            InputStreamReader isr = new InputStreamReader(res);
-            BufferedReader reader = new BufferedReader(isr);
-
-            String line;
-            while ((line = reader.readLine()) != null) {
-                db.execSQL(line);
-            }
-
-            set_option_value(OPT_DB_REVISION, rev_no);
-            db.setTransactionSuccessful();
-        } catch (Resources.NotFoundException e) {
-            Log.d("db", "SQL revision "+String.valueOf(rev_no)+" not found");
-            return false;
-        }
-        catch (SQLException e) {
-            Log.e("db", String.format(Locale.US, "Error applying revision %d: %s", rev_no, e.getMessage()));
-            return false;
-        }
-        catch (Exception e) {
-            Log.w("db", "Error reading revision" + String.valueOf(rev_no)+": "+e.getMessage());
-            return false;
-        }
-        finally {
-            db.endTransaction();
-        }
-
-        return true;
-    }
-
-    static int get_option_value(String name, int default_value) {
-        String s = get_option_value(name, String.valueOf(default_value));
-        try {
-            return Integer.parseInt(s);
-        }
-        catch (Exception e) {
-            return default_value;
-        }
-    }
-
-    static long get_option_value(String name, long default_value) {
-        String s = get_option_value(name, String.valueOf(default_value));
-        try {
-            return Long.parseLong(s);
-        }
-        catch (Exception e) {
-            Log.d("db", "returning default long value of "+name, e);
-            return default_value;
-        }
-    }
-
-    static String get_option_value(String name, String default_value) {
-        Log.d("db", "about fo fetch option "+name);
-        try (Cursor cursor = db.rawQuery("select value from options where name=?", new String[]{name})) {
-            if (cursor.moveToFirst()) {
-                String result = cursor.getString(0);
-
-                if (result == null ) result = default_value;
-
-                Log.d("db", "option "+name+"="+result);
-                return result;
-            }
-            else return default_value;
-        }
-        catch(Exception e) {
-            Log.d("db", "returning default value for "+name, e);
-            return default_value;
-        }
-    }
-
-    static void set_option_value(String name, String value) {
-        Log.d("db", "setting option "+name+"="+value);
-        db.execSQL("insert or replace into options(name, value) values(?, ?);", new String[]{name, value});
-    }
-
-    static void set_option_value(String name, long value) {
-        set_option_value(name, String.valueOf(value));
-    }
-}
diff --git a/app/src/main/java/net/ktnx/mobileledger/MobileLedgerDatabase.java b/app/src/main/java/net/ktnx/mobileledger/MobileLedgerDatabase.java
new file mode 100644 (file)
index 0000000..301b946
--- /dev/null
@@ -0,0 +1,140 @@
+package net.ktnx.mobileledger;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Locale;
+
+class MobileLedgerDatabase extends SQLiteOpenHelper implements AutoCloseable {
+    static final String DB_NAME = "mobile-ledger.db";
+    static final String ACCOUNTS_TABLE = "accounts";
+    static final String DESCRIPTION_HISTORY_TABLE = "description_history";
+    static final int LATEST_REVISION = 4;
+
+    final Context mContext;
+
+    public
+    MobileLedgerDatabase(Context context) {
+        super(context, DB_NAME, null, LATEST_REVISION);
+        Log.d("db", "creating helper instance");
+        mContext = context;
+    }
+
+    @Override
+    public
+    void onCreate(SQLiteDatabase db) {
+        Log.d("db", "onCreate called");
+        onUpgrade(db, -1, LATEST_REVISION);
+    }
+
+    @Override
+    public
+    void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        Log.d("db", "onUpgrade called");
+        for(int i = oldVersion+1; i <= newVersion; i++) applyRevision(db, i);
+    }
+
+    private void applyRevision(SQLiteDatabase db, int
+            rev_no) {
+        final Resources rm = mContext.getResources();
+        String rev_file = String.format(Locale.US, "sql_%d", rev_no);
+
+        int res_id = rm.getIdentifier(rev_file, "raw", mContext.getPackageName());
+        if (res_id == 0)
+            throw new SQLException(String.format(Locale.US, "No resource for revision %d", rev_no));
+        db.beginTransaction();
+        try (InputStream res = rm.openRawResource(res_id)) {
+            Log.d("db", "Applying revision " + String.valueOf(rev_no));
+            InputStreamReader isr = new InputStreamReader(res);
+            BufferedReader reader = new BufferedReader(isr);
+
+            String line;
+            while ((line = reader.readLine()) != null) {
+                db.execSQL(line);
+            }
+
+            db.setTransactionSuccessful();
+        }
+        catch (IOException e) {
+            Log.e("db", String.format("Error opening raw resource for revision %d", rev_no));
+            e.printStackTrace();
+        }
+        finally {
+            db.endTransaction();
+        }
+    }
+    int get_option_value(String name, int default_value) {
+        String s = get_option_value(name, String.valueOf(default_value));
+        try {
+            return Integer.parseInt(s);
+        }
+        catch (Exception e) {
+            return default_value;
+        }
+    }
+
+    long get_option_value(String name, long default_value) {
+        String s = get_option_value(name, String.valueOf(default_value));
+        try {
+            return Long.parseLong(s);
+        }
+        catch (Exception e) {
+            Log.d("db", "returning default long value of "+name, e);
+            return default_value;
+        }
+    }
+
+    String get_option_value(String name, String default_value) {
+        Log.d("db", "about to fetch option "+name);
+        try(SQLiteDatabase db = getReadableDatabase()) {
+            try (Cursor cursor = db
+                    .rawQuery("select value from options where name=?", new String[]{name}))
+            {
+                if (cursor.moveToFirst()) {
+                    String result = cursor.getString(0);
+
+                    if (result == null) result = default_value;
+
+                    Log.d("db", "option " + name + "=" + result);
+                    return result;
+                }
+                else return default_value;
+            }
+            catch (Exception e) {
+                Log.d("db", "returning default value for " + name, e);
+                return default_value;
+            }
+        }
+    }
+
+     void set_option_value(String name, String value) {
+        Log.d("db", "setting option "+name+"="+value);
+        try(SQLiteDatabase db = getWritableDatabase()) {
+            db.execSQL("insert or replace into options(name, value) values(?, ?);",
+                    new String[]{name, value});
+        }
+    }
+
+    void set_option_value(String name, long value) {
+        set_option_value(name, String.valueOf(value));
+    }
+    static long get_option_value(Context context, String name, long default_value) {
+        try(MobileLedgerDatabase db = new MobileLedgerDatabase(context)) {
+            return db.get_option_value(name, default_value);
+        }
+    }
+    static void set_option_value(Context context, String name, String value) {
+        try(MobileLedgerDatabase db = new MobileLedgerDatabase(context)) {
+            db.set_option_value(name, value);
+        }
+    }
+}
index 93e6fe8dfaa7f12888ad180370f24b5b73260595..16feaaf1f33da9cca1b435d976820de3fdfdfd2e 100644 (file)
@@ -58,6 +58,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
     private AutoCompleteTextView text_descr;
     private static SaveTransactionTask saver;
     private MenuItem mSave;
+    private MobileLedgerDatabase dbh;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -66,6 +67,8 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
         Toolbar toolbar = findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
 
+        dbh = new MobileLedgerDatabase(this);
+
         text_date = findViewById(R.id.new_transaction_date);
         text_date.setOnFocusChangeListener(new View.OnFocusChangeListener() {
             @Override
@@ -75,7 +78,8 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
             }
         });
         text_descr = findViewById(R.id.new_transaction_description);
-        hook_autocompletion_adapter(text_descr, MobileLedgerDB.DESCRIPTION_HISTORY_TABLE, "description");
+        hook_autocompletion_adapter(text_descr, MobileLedgerDatabase
+                .DESCRIPTION_HISTORY_TABLE, "description");
         hook_text_change_listener(text_descr);
 
         progress = findViewById(R.id.save_transaction_progress);
@@ -87,7 +91,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
             AutoCompleteTextView acc_name_view = (AutoCompleteTextView) row.getChildAt(0);
             TextView amount_view = (TextView) row.getChildAt(1);
             hook_swipe_listener(row);
-            hook_autocompletion_adapter(acc_name_view, MobileLedgerDB.ACCOUNTS_TABLE, "name");
+            hook_autocompletion_adapter(acc_name_view, MobileLedgerDatabase.ACCOUNTS_TABLE, "name");
             hook_text_change_listener(acc_name_view);
             hook_text_change_listener(amount_view);
 //            Log.d("swipe", "hooked to row "+i);
@@ -228,43 +232,43 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
     private void hook_autocompletion_adapter(final AutoCompleteTextView view, final String table, final String field) {
         String[] from = {field};
         int[] to = {android.R.id.text1};
-        SQLiteDatabase db = MobileLedgerDB.db;
-
-        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_dropdown_item_1line, null, from, to, 0);
+        SimpleCursorAdapter adapter =
+                new SimpleCursorAdapter(this, android.R.layout.simple_dropdown_item_1line, null,
+                        from, to, 0);
         adapter.setStringConversionColumn(1);
 
         FilterQueryProvider provider = new FilterQueryProvider() {
             @Override
-            public Cursor runQuery(CharSequence constraint) {
+            public
+            Cursor runQuery(CharSequence constraint) {
                 if (constraint == null) return null;
 
                 String str = constraint.toString().toUpperCase();
-                Log.d("autocompletion", "Looking for "+str);
+                Log.d("autocompletion", "Looking for " + str);
                 String[] col_names = {FontsContract.Columns._ID, field};
                 MatrixCursor c = new MatrixCursor(col_names);
 
-                Cursor matches = db.rawQuery(String.format(
-                        "SELECT %s as a, case when %s_upper LIKE ?||'%%' then 1 " +
-                                "WHEN %s_upper LIKE '%%:'||?||'%%' then 2 " +
-                                "WHEN %s_upper LIKE '%% '||?||'%%' then 3 " + "else 9 end " +
-                                "FROM %s " + "WHERE %s_upper LIKE '%%'||?||'%%' " +
-                                "ORDER BY 2, 1;", field, field, field, field, table, field),
-                        new String[]{str, str, str, str});
-
-                try {
-                    int i = 0;
-                    while (matches.moveToNext()) {
-                        String match = matches.getString(0);
-                        int order = matches.getInt(1);
-                        Log.d("autocompletion", String.format("match: %s |%d", match, order));
-                        c.newRow().add(i++).add(match);
+                try (SQLiteDatabase db = dbh.getReadableDatabase()) {
+
+                    try (Cursor matches = db.rawQuery(String.format(
+                            "SELECT %s as a, case when %s_upper LIKE ?||'%%' then 1 "
+                                    + "WHEN %s_upper LIKE '%%:'||?||'%%' then 2 "
+                                    + "WHEN %s_upper LIKE '%% '||?||'%%' then 3 " + "else 9 end "
+                                    + "FROM %s " + "WHERE %s_upper LIKE '%%'||?||'%%' "
+                                    + "ORDER BY 2, 1;", field, field, field, field, table, field),
+                            new String[]{str, str, str, str}))
+                    {
+                        int i = 0;
+                        while (matches.moveToNext()) {
+                            String match = matches.getString(0);
+                            int order = matches.getInt(1);
+                            Log.d("autocompletion", String.format("match: %s |%d", match, order));
+                            c.newRow().add(i++).add(match);
+                        }
                     }
-                }
-                finally {
-                    matches.close();
-                }
 
-                return c;
+                    return c;
+                }
 
             }
         };
@@ -332,7 +336,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal
         if (focus) acc.requestFocus();
 
         hook_swipe_listener(row);
-        hook_autocompletion_adapter(acc, MobileLedgerDB.ACCOUNTS_TABLE, "name");
+        hook_autocompletion_adapter(acc, MobileLedgerDatabase.ACCOUNTS_TABLE, "name");
         hook_text_change_listener(acc);
         hook_text_change_listener(amt);
     }
index 16919b336b62fac88f73489492924c0178c35dfd..21963dd6b37abbbe0b85cc68af4682ab6cbdaf37 100644 (file)
@@ -1,6 +1,8 @@
 package net.ktnx.mobileledger;
 
+import android.content.Context;
 import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
 import android.util.Log;
 
 import java.io.BufferedReader;
@@ -14,14 +16,14 @@ import java.net.URLDecoder;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static net.ktnx.mobileledger.MobileLedgerDB.db;
-
 abstract public class RetrieveAccountsTask extends android.os.AsyncTask<Void, Integer, Void> {
     int error;
 
     private SharedPreferences pref;
+    private final Context mContext;
 
-    RetrieveAccountsTask() {
+    RetrieveAccountsTask(Context context) {
+        mContext = context;
         error = 0;
     }
 
@@ -35,104 +37,111 @@ abstract public class RetrieveAccountsTask extends android.os.AsyncTask<Void, In
             http.setAllowUserInteraction(false);
             http.setRequestProperty("Accept-Charset", "UTF-8");
             publishProgress(0);
-            InputStream resp = http.getInputStream();
-            try {
-                Log.d("update_accounts", String.valueOf(http.getResponseCode()));
-                if (http.getResponseCode() != 200) {
-                    throw new IOException(String.format("HTTP error: %d %s", http.getResponseCode(), http.getResponseMessage()));
-                }
-                else {
-                    if (db.inTransaction()) throw new AssertionError();
-
-                    db.beginTransaction();
-
-                    try {
-                        db.execSQL("update account_values set keep=0;");
-                        db.execSQL("update accounts set keep=0;");
-
-                        String line;
-                        String last_account_name = null;
-                        BufferedReader buf = new BufferedReader(new InputStreamReader(resp, "UTF-8"));
-                        // %3A is '='
-                        Pattern account_name_re = Pattern.compile("/register\\?q=inacct%3A([a-zA-Z0-9%]+)\"");
-                        Pattern value_re = Pattern.compile("<span class=\"[^\"]*\\bamount\\b[^\"]*\">\\s*([-+]?[\\d.,]+)(?:\\s+(\\S+))?</span>");
-                        Pattern tr_re = Pattern.compile("</tr>");
-                        Pattern descriptions_line_re = Pattern.compile("\\bdescriptionsSuggester\\s*=\\s*new\\b");
-                        Pattern description_items_re = Pattern.compile("\"value\":\"([^\"]+)\"");
-                        int count = 0;
-                        while ((line = buf.readLine()) != null) {
-                            Matcher m = account_name_re.matcher(line);
-                            if (m.find()) {
-                                String acct_encoded = m.group(1);
-                                String acct_name = URLDecoder.decode(acct_encoded, "UTF-8");
-                                acct_name = acct_name.replace("\"", "");
-                                Log.d("account-parser", acct_name);
-
-                                db.execSQL("insert or replace into accounts(name, name_upper, " +
-                                                "keep) values(?, ?, 1)",
-                                        new Object[]{acct_name, acct_name.toUpperCase()});
-                                publishProgress(++count);
-
-                                last_account_name = acct_name;
-
-                                continue;
-                            }
-
-                            Matcher tr_m = tr_re.matcher(line);
-                            if (tr_m.find()) {
-                                Log.d("account-parser", "<tr> - another account expected");
-                                last_account_name = null;
-                                continue;
-                            }
-
-                            if (last_account_name != null) {
-                                m = value_re.matcher(line);
-                                boolean match_found = false;
-                                while (m.find()) {
-                                    match_found = true;
-                                    String value = m.group(1);
-                                    String currency = m.group(2);
-                                    if (currency == null) currency = "";
-                                    value = value.replace(',', '.');
-                                    Log.d("db", "curr=" + currency + ", value=" + value);
-                                    db.execSQL("insert or replace into account_values(account, currency, value, keep) values(?, ?, ?, 1);",
-                                            new Object[]{last_account_name, currency, Float.valueOf(value)});
+            try(MobileLedgerDatabase dbh = new MobileLedgerDatabase(mContext)) {
+                try(SQLiteDatabase db = dbh.getWritableDatabase()) {
+                    try (InputStream resp = http.getInputStream()) {
+                        Log.d("update_accounts", String.valueOf(http.getResponseCode()));
+                        if (http.getResponseCode() != 200) {
+                            throw new IOException(
+                                    String.format("HTTP error: %d %s", http.getResponseCode(), http.getResponseMessage()));
+                        }
+                        else {
+                            if (db.inTransaction()) throw new AssertionError();
+
+                            db.beginTransaction();
+
+                            try {
+                                db.execSQL("update account_values set keep=0;");
+                                db.execSQL("update accounts set keep=0;");
+
+                                String line;
+                                String last_account_name = null;
+                                BufferedReader buf =
+                                        new BufferedReader(new InputStreamReader(resp, "UTF-8"));
+                                // %3A is '='
+                                Pattern account_name_re = Pattern.compile("/register\\?q=inacct%3A([a-zA-Z0-9%]+)\"");
+                                Pattern value_re = Pattern.compile(
+                                        "<span class=\"[^\"]*\\bamount\\b[^\"]*\">\\s*([-+]?[\\d.,]+)(?:\\s+(\\S+))?</span>");
+                                Pattern tr_re = Pattern.compile("</tr>");
+                                Pattern descriptions_line_re = Pattern.compile("\\bdescriptionsSuggester\\s*=\\s*new\\b");
+                                Pattern description_items_re = Pattern.compile("\"value\":\"([^\"]+)\"");
+                                int count = 0;
+                                while ((line = buf.readLine()) != null) {
+                                    Matcher m = account_name_re.matcher(line);
+                                    if (m.find()) {
+                                        String acct_encoded = m.group(1);
+                                        String acct_name = URLDecoder.decode(acct_encoded, "UTF-8");
+                                        acct_name = acct_name.replace("\"", "");
+                                        Log.d("account-parser", acct_name);
+
+                                        db.execSQL(
+                                                "insert or replace into accounts(name, name_upper, "
+                                                        + "keep) values(?, ?, 1)",
+                                                new Object[]{acct_name, acct_name.toUpperCase()});
+                                        publishProgress(++count);
+
+                                        last_account_name = acct_name;
+
+                                        continue;
+                                    }
+
+                                    Matcher tr_m = tr_re.matcher(line);
+                                    if (tr_m.find()) {
+                                        Log.d("account-parser", "<tr> - another account expected");
+                                        last_account_name = null;
+                                        continue;
+                                    }
+
+                                    if (last_account_name != null) {
+                                        m = value_re.matcher(line);
+                                        boolean match_found = false;
+                                        while (m.find()) {
+                                            match_found = true;
+                                            String value = m.group(1);
+                                            String currency = m.group(2);
+                                            if (currency == null) currency = "";
+                                            value = value.replace(',', '.');
+                                            Log.d("db", "curr=" + currency + ", value=" + value);
+                                            db.execSQL(
+                                                    "insert or replace into account_values(account, currency, value, keep) values(?, ?, ?, 1);",
+                                                    new Object[]{last_account_name, currency, Float.valueOf(value)
+                                                    });
+                                        }
+
+                                        if (match_found) continue;
+                                    }
+
+                                    m = descriptions_line_re.matcher(line);
+                                    if (m.find()) {
+                                        db.execSQL("update description_history set keep=0;");
+                                        m = description_items_re.matcher(line);
+                                        while (m.find()) {
+                                            String description = m.group(1);
+                                            if (description.isEmpty()) continue;
+
+                                            Log.d("db", String.format("Stored description: %s",
+                                                    description));
+                                            db.execSQL("insert or replace into description_history"
+                                                            + "(description, description_upper, keep) " + "values(?, ?, 1);",
+                                                    new Object[]{description, description.toUpperCase()
+                                                    });
+                                        }
+                                    }
                                 }
 
-                                if (match_found) continue;
+                                db.execSQL("delete from account_values where keep=0;");
+                                db.execSQL("delete from accounts where keep=0;");
+//                        db.execSQL("delete from description_history where keep=0;");
+                                db.setTransactionSuccessful();
                             }
-
-                            m = descriptions_line_re.matcher(line);
-                            if (m.find()) {
-                                db.execSQL("update description_history set keep=0;");
-                                m = description_items_re.matcher(line);
-                                while(m.find()) {
-                                    String description = m.group(1);
-                                    if (description.isEmpty()) continue;
-
-                                    Log.d("db", String.format("Stored description: %s", description));
-                                    db.execSQL("insert or replace into description_history" +
-                                                    "(description, description_upper, keep) " +
-                                                    "values(?, ?, 1);",
-                                            new Object[]{description, description.toUpperCase()});
-                                }
+                            finally {
+                                db.endTransaction();
                             }
-                        }
 
-                        db.execSQL("delete from account_values where keep=0;");
-                        db.execSQL("delete from accounts where keep=0;");
-//                        db.execSQL("delete from description_history where keep=0;");
-                        db.setTransactionSuccessful();
-                    }
-                    finally {
-                        db.endTransaction();
+                        }
                     }
-
                 }
             }
-            finally {
-                resp.close();
-            }
         } catch (MalformedURLException e) {
             error = R.string.err_bad_backend_url;
             e.printStackTrace();