title: Downloaded SQLite database and leak warnings
body: <p>I've made an application that uses a downloaded SQLite database. To retrieve data in it I'm using a <code>ContentProvider</code>. When I need to read the database, I always (I've checked at least five times) use a code like this:</p>
  
  <pre><code>Cursor c = getContext().getContentResolver().query(MyContentProvider.ITEMSURI,
          projection,where,null,null);
  if(c.moveToFirst()){
      while(!c.isAfterLast()){
          itemsList.add(cursorToItem(c));
          c.moveToNext();
      }
  }
  if(c!=null) c.close();
  </code></pre>
  
  <p>But I keep getting many errors like this (I make a sequence of queries in a for loop):</p>
  
  <pre><code>10-18 13:16:01.709: W/SQLiteConnectionPool(27704): A SQLiteConnection object 
  for database '/storage/emulated/0/MyAPP/mydb.sqlite' was leaked!  
  Please fix your application to end transactions in progress properly and to 
  close the database when it is no longer needed.
  </code></pre>
  
  <p>What could cause all these warnings? Cursor is always closed and in <code>ContentProvider</code> there's no need to close database. </p>
  
  <p><strong>Code:</strong></p>
  
  <p>This is the class that manages the database:</p>
  
  <pre><code>public class OpenMyDBHelper{
  
      private static final String DB_NAME = "mydb.sqlite";
      private static final File DB_PATH = new File(
              MyAppFolderManager.getInternalMemoryFolder(), DB_NAME);
  
      private SQLiteDatabase db;
  
      public SQLiteDatabase open() {
          db = SQLiteDatabase.openDatabase(DB_PATH.getAbsolutePath(), null,
                  SQLiteDatabase.OPEN_READONLY);
          return db;
      }
  
      public void close() {
          db.close();
      }
  
  }
  </code></pre>
  
  <p>And this is my <code>ContentProvider</code> subclass:</p>
  
  <pre><code>public class MyContentProvider extends ContentProvider {
  
      private OpenMyDBHelper db;
      //static paths/Uri definitions....
  
  
      private final static int ITEMS = 1;
      private static final UriMatcher sURIMatcher = new UriMatcher(
              UriMatcher.NO_MATCH);
      static {
          sURIMatcher.addURI(AUTHORITY, ITEMS_PATH, ITEMS);
      }
  
      @Override
      public boolean onCreate() {
          db = new OpenMyDBHelper();
          return false;
      }
  
      @Override
      public Cursor query(Uri uri, String[] projection, String selection,
              String[] selectionArgs, String sortOrder) {
          Cursor cursor = null;
          SQLiteDatabase database = db.open();
          int uriType = sURIMatcher.match(uri);
          switch (uriType) {
          case ITEMS:
              cursor = database.query(Constants.TABLE_ITEMS,
                      projection, selection, selectionArgs, null,null,
                      null);
              cursor.setNotificationUri(getContext().getContentResolver(), ITEMSURI);
              break;
          default:
              throw new IllegalArgumentException("Unknown URI (" + uri + ")");
          }
          return cursor;
      }
  
      @Override
      public String getType(Uri uri) {
          return null;
      }
  
      //It's just a read-only db, I don't need the CUD operations...
  
      @Override
      public Uri insert(Uri uri, ContentValues values) {
          return null;
      }
  
      @Override
      public int delete(Uri uri, String selection, String[] selectionArgs) {
          return 0;
      }
  
      @Override
      public int update(Uri uri, ContentValues values, String selection,
              String[] selectionArgs) {
          return 0;
      }
  }
  </code></pre>