close()方法从未被明确要求数据库 [英] close() was never explicitly called on database
问题描述
我需要存储短信SQLite数据库,在收到时之一。
我使用这些类:
DBHelper.java
公共类DBHelper扩展SQLiteOpenHelper {
私有静态最后弦乐DB_NAME =MY_DB;
私有静态最终诠释DB_VERSION = 1; 公共DBHelper(上下文的背景下,字符串名称,CursorFactory工厂,诠释的版本){
超(背景下,DB_NAME,工厂,DB_VERSION);
} 公共DBHelper(上下文的背景下){
超(背景下,DB_NAME,空,DB_VERSION);
} 公共字符串的getName(){
返回DB_NAME;
}
@覆盖
公共无效的onCreate(SQLiteDatabase DB){
SQL字符串=;
SQL + =CREATE TABLE SMS(;
SQL + =_ ID INTEGER PRIMARY KEY AUTOINCREMENT;
SQL + =TEXT麻省理工学院NOT NULL,;
SQL + =TEXT DEST NOT NULL,;
SQL + =TEXT文本NOT NULL,;
SQL + =日期DATETIME NOT NULL); db.execSQL(SQL);
}
DBManager.java
公共类DBManager {私人DBHelper胸径;
SQLiteDatabase DBR;
SQLiteDatabase DBW;DBManager(DBHelper胸径){
this.dbh =胸径;
DBR = dbh.getReadableDatabase(); //线24
DBW = dbh.getWritableDatabase();
}DBManager(上下文CTX){
this.dbh =新DBHelper(CTX);
DBR = dbh.getReadableDatabase();
DBW = dbh.getWritableDatabase();
}众长插入(字符串表,ContentValues值){
返回dbw.insert(表,空,价值);
}众长insertSMS(SMS短信){
如果(sms.getSender()长度()方式> 0&放大器;&放大器; sms.getReceiver()长度()方式> 0&放大器;&放大器; sms.getText()!= NULL){
SQL字符串=INSERT INTO短信VALUES(NULL,\\+ sms.getSender()+\\,\\+ sms.getReceiver()+\\,\\+ sms.getText()+ \\, 约会时间());
dbw.execSQL(SQL);
返回0;
}
返回-1;
}公共短信getSmsById(INT ID){
的String [] =列{麻省理工学院,目标,文本,日期},selectionArgs两个= {Integer.toString(ID)};
字符串选择=_ ID =?;
光标C = dbr.query(SMS,柱,选择,selectionArgs两个,NULL,NULL,_id ASC);
如果(c.moveToFirst())
返回新的SMS(c.getString(0),c.getString(1),c.getString(2),c.getString(3));
返回null;
}公众短信[] getAllSms(){
的String [] =列{mittente,destinatario,德图,dataora};
光标C = dbr.query(SMS,柱,NULL,NULL,NULL,NULL,_id ASC);
ArrayList的< SMS>人=新的ArrayList< SMS>();
如果(c.moveToFirst())
做{
al.add(新的SMS(c.getString(0),c.getString(1),c.getString(2),c.getString(3)));
}而(c.moveToNext());
返程(SMS [])al.toArray();
}公共无效的close(){
如果(胸径!= NULL)
dbh.close(); 如果(DBW!= NULL)
dbw.close(); 如果(DBR!= NULL)
dbr.close();
}}
SmsBR.java
公共类SmsBR扩展广播接收器{
@覆盖
公共无效的onReceive(上下文的背景下,意图意图){
捆绑包= intent.getExtras();
如果(捆绑!= NULL){
[对象]的PDU =(对象[])bundle.get(的PDU);
最后SmsMessage [] =邮件新SmsMessage [pdus.length]
的for(int i = 0; I< pdus.length;我++){
消息[I] = SmsMessage.createFromPdu((字节[])的PDU [I]);
}
如果(messages.length大于0){
的System.out.println(我收到短信的:+信息[0] .getOriginatingAddress());
DBManager DBM =新DBManager(背景);
dbm.insertSMS(讯息[0]);
dbm.close();
}}}}
但我得到这个错误:
close()方法从未被明确要求数据库/data/data/it.giox.sms/databases/my_db
android.database.sqlite.DatabaseObjectNotClosedException:应用程序没有关闭在这里打开游标或数据库对象
在android.database.sqlite.SQLiteDatabase<&初始化GT;(SQLiteDatabase.java:1847)
在android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
在android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
在android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:847)
在android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:549)
在android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
在android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:118)
在android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
在it.giox.sms.DBManager<&初始化GT;(DBManager.java:24)
在it.giox.sms.DroidClient<&初始化GT;(DroidClient.java:29)
在it.giox.sms.DroidWebServer.getClient(DroidWebServer.java:25)
在it.giox.sms.WebServer.startServer(WebServer.java:101)
在it.giox.sms.WebServer.run(WebServer.java:60)
在java.lang.Thread.run(Thread.java:1019)
我可以改变?
我做这个调整,但仍错误...
公共短信[] getAllSms(){
的String [] =列{mittente,destinatario,德图,dataora};
ArrayList的< SMS>人=新的ArrayList< SMS>();光标C = NULL;
尝试{
C = dbr.query(SMS,柱,NULL,NULL,NULL,NULL,_id ASC);
如果(c.moveToFirst())
做{
al.add(新的SMS(c.getString(0),c.getString(1),c.getString(2),c.getString(3)));
}而(c.moveToNext());}
最后{
c.close();
关();
} 返程(SMS [])al.toArray();
}
问题是,在 DBManager
构造函数创建一个新SQLiteDatabase
然后我应该关闭()
它。如果我把的close()
在构造函数中我没有这个错误,但系统告诉我,该数据库被关闭。
我解决了创建的 SQLiteDatabase
我需要它,最后关闭它每一次一个新实例的问题。它的工作原理,但我认为还有更好的解决方案!
公共短信[] getAllSms(){
SQLiteDatabase DBW;
...
尝试{
DBW = dbh.getWritableDatabase();
...
} {最后dbw.close();}}
您需要,一旦你与他们做关闭游标。使用尝试/终于
在 getAllSms()
和 getSmsById()
您读取数据后,关闭游标。
I need to store sms in a sqlite database, when one is received. I'm using these classes:
DBHelper.java
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);
}
DBManager.java
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()>0 && sms.getReceiver().length()>0 && 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<Sms> al=new ArrayList<Sms>();
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();
}}
SmsBR.java
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 < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > 0) {
System.out.println("I received an sms from: "+messages[0].getOriginatingAddress());
DBManager dbm = new DBManager(context);
dbm.insertSMS(messages[0]);
dbm.close();
}}}}
But I get this error:
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.<init>(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.<init>(DBManager.java:24)
at it.giox.sms.DroidClient.<init>(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)
What can I change?
[EDIT] I've done this correction, but the error remains...
public Sms[] getAllSms(){
String[] columns = { "mittente","destinatario","testo","dataora" };
ArrayList<Sms> al=new ArrayList<Sms>(); 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();
}
[EDIT 2]
The problem is that in DBManager
constructor I create a new SQLiteDatabase
and then I should close()
it. If I put close()
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 SQLiteDatabase
every time I need it, and finally closing it. It works, but I think there are better solutions!
public Sms[] getAllSms(){
SQLiteDatabase dbw;
...
try{
dbw=dbh.getWritableDatabase();
...
} finally {dbw.close();}}
You need to close your cursors once you are done with them. Use try/finally
in getAllSms()
and getSmsById()
to close the cursor after you read the data.
这篇关于close()方法从未被明确要求数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!