title: close() was never explicitly called on database
body: <p>I need to store sms in a sqlite database, when one is received.
  I'm using these classes:</p>
  
  <p><strong>DBHelper.java</strong></p>
  
  <pre><code>public class DBHelper extends SQLiteOpenHelper {
      private static final String DB_NAME = "my_db";
      private static final int DB_VERSION = 1;
  
      public DBHelper(Context context, String name, CursorFactory factory, int version) {
          super(context, DB_NAME, factory, DB_VERSION);
      }
  
      public DBHelper(Context context) {
          super(context, DB_NAME, null, DB_VERSION);
      }
  
      public String getName(){
          return DB_NAME;
      }
      @Override
      public void onCreate(SQLiteDatabase db) {
          String sql="";
          sql+="CREATE TABLE sms ( ";
              sql+="_id INTEGER PRIMARY KEY AUTOINCREMENT, ";
          sql+="mit TEXT NOT NULL, ";
          sql+="dest TEXT NOT NULL, ";
          sql+="text TEXT NOT NULL, ";
          sql+="date DATETIME NOT NULL )";
  
          db.execSQL(sql);
      }
  </code></pre>
  
  <p><strong>DBManager.java</strong></p>
  
  <pre><code>public class DBManager {
  
  private DBHelper dbh;
  SQLiteDatabase dbr;
  SQLiteDatabase dbw;
  
  DBManager(DBHelper dbh){
      this.dbh=dbh;
      dbr=dbh.getReadableDatabase(); //line 24
      dbw=dbh.getWritableDatabase();
  }
  
  DBManager(Context ctx){
      this.dbh=new DBHelper(ctx);
      dbr=dbh.getReadableDatabase();
      dbw=dbh.getWritableDatabase();
  }
  
  public long insert(String table, ContentValues values){
      return dbw.insert(table, null, values);
  }
  
  public long insertSMS(Sms sms){
      if(sms.getSender().length()&gt;0 &amp;&amp; sms.getReceiver().length()&gt;0 &amp;&amp; sms.getText()!=null){
      String sql="INSERT INTO sms VALUES ( null, \""+sms.getSender()+"\", \""+sms.getReceiver()+"\", \""+sms.getText()+"\", datetime())";
      dbw.execSQL(sql);
      return 0;
      }
      return -1;
  }
  
  public Sms getSmsById(int id){
      String[] columns = { "mit","dest","text","date" }, selectionArgs={ Integer.toString(id) };
      String selection="_id = ?";
      Cursor c=dbr.query("sms", columns, selection, selectionArgs, null, null, "_id ASC");
      if(c.moveToFirst())
      return new Sms(c.getString(0),c.getString(1), c.getString(2),c.getString(3));
      return null;
  }
  
  public Sms[] getAllSms(){
          String[] columns = { "mittente","destinatario","testo","dataora" };
          Cursor c=dbr.query("sms", columns, null, null, null, null, "_id ASC");
          ArrayList&lt;Sms&gt; al=new ArrayList&lt;Sms&gt;();
          if(c.moveToFirst())
          do{
              al.add(new Sms(c.getString(0),c.getString(1),c.getString(2),c.getString(3)));
          }while(c.moveToNext());
          return (Sms[]) al.toArray();
      }
  
  public void close(){
          if(dbh!=null)
          dbh.close();
  
          if(dbw!=null)
          dbw.close();
  
          if(dbr!=null)
          dbr.close();
      }}
  </code></pre>
  
  <p><strong>SmsBR.java</strong></p>
  
  <pre><code>public class SmsBR extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {               
                      Bundle bundle = intent.getExtras();
                      if (bundle != null) {
                          Object[] pdus = (Object[])bundle.get("pdus");
                          final SmsMessage[] messages = new SmsMessage[pdus.length];
                          for (int i = 0; i &lt; pdus.length; i++) {
                              messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
                          }
                          if (messages.length &gt; 0) {
                              System.out.println("I received an sms from: "+messages[0].getOriginatingAddress());
                              DBManager dbm = new DBManager(context);
                              dbm.insertSMS(messages[0]);
                              dbm.close();
                          }}}}
  </code></pre>
  
  <p>But I get this error:</p>
  
  <pre><code>close() was never explicitly called on database '/data/data/it.giox.sms/databases/my_db' 
  android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
       at android.database.sqlite.SQLiteDatabase.&lt;init&gt;(SQLiteDatabase.java:1847)
       at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
       at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
       at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847)
       at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:549)
       at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
       at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
       at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
       at it.giox.sms.DBManager.&lt;init&gt;(DBManager.java:24)
       at it.giox.sms.DroidClient.&lt;init&gt;(DroidClient.java:29)
       at it.giox.sms.DroidWebServer.getClient(DroidWebServer.java:25)
       at it.giox.sms.WebServer.startServer(WebServer.java:101)
       at it.giox.sms.WebServer.run(WebServer.java:60)
       at java.lang.Thread.run(Thread.java:1019)
  </code></pre>
  
  <p>What can I change?</p>
  
  <p><strong>[EDIT]</strong>
  I've done this correction, but the error remains...</p>
  
  <pre><code>public Sms[] getAllSms(){
          String[] columns = { "mittente","destinatario","testo","dataora" };
          ArrayList&lt;Sms&gt; al=new ArrayList&lt;Sms&gt;(); Cursor c = null;
          try{
          c=dbr.query("sms", columns, null, null, null, null, "_id ASC");
                  if(c.moveToFirst())
          do{
              al.add(new Sms(c.getString(0),c.getString(1),c.getString(2),c.getString(3)));
          }while(c.moveToNext());}
          finally{
          c.close();
          close();
          }
  
          return (Sms[]) al.toArray();
          }
  </code></pre>
  
  <p><strong>[EDIT 2]</strong></p>
  
  <p>The problem is that in <code>DBManager</code> constructor I create a <code>new SQLiteDatabase</code> and then I should <code>close()</code> it. If I put <code>close()</code> in the constructor I've no that error, but the system tell me that the database is closed.
  I solved the problem creating a new instance of <code>SQLiteDatabase</code> every time I need it, and finally closing it. It works, but I think there are better solutions!</p>
  
  <pre><code>public Sms[] getAllSms(){
          SQLiteDatabase dbw;
                  ...
                  try{
                  dbw=dbh.getWritableDatabase();
                  ...
                  } finally {dbw.close();}}
  </code></pre>