【发布时间】:2013-11-25 09:53:25
【问题描述】:
在我的内容提供程序中,我创建并维护了 3 个 SQLiteDatabase 对象。它们是这样创建的:
private ContentProviderHelper helper;
@Override
public boolean onCreate() { // that's the ContentProvider onCreate()
SQLiteDatabase dbLog = new DbLog(getContext()).getWritableDatabase();
SQLiteDatabase dbSession = new DbSession(getContext()).getWritableDatabase();
SQLiteDatabase dbLocation = new DbLocation(getContext()).getWritableDatabase();
helper = new ContentProviderHelper(UriManager.getAuthority(getContext()));
helper.addDb(dbLog, DbLog.TABLE_NAME, UriManager.LOG, SQLiteDatabase.CONFLICT_REPLACE);
helper.addDb(dbSession, DbSession.TABLE_NAME, UriManager.SESSION, SQLiteDatabase.CONFLICT_REPLACE);
helper.addDb(dbLocation, DbLocation.TABLE_NAME, UriManager.LOCATION, SQLiteDatabase.CONFLICT_REPLACE);
ContentProviderHelper 将这些 SQLiteDatabase 存储在一个用 UriMatcher 索引的 ArrayList 中。
<provider> 已在清单中正确注册,并且我的应用具有 SD 卡权限。
对于我们 500,000 名用户群中的大多数人来说,它运行良好,但每隔一段时间我就会从 Google Play 收到 SQLiteCantOpenDatabaseException: unable to open database file
相关的堆栈轨迹是:
Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file
at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1013)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:787)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
这些错误报告通常来自普通的无品牌劣质设备。
任何有关如何正确避免这些错误的帮助将不胜感激。
编辑:
我在相同代码上遇到的不同 SQL 异常。
Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error: COMMIT;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1763)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:583)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:137)
at ***.***.***.data.ContentManager.onCreate(ContentManager.java:26)
除了try{} catch(){},还有其他方法可以解决这个问题吗?
编辑:
关于游标使用的额外信息:
一般来说,游标保持打开的时间尽可能短。所有 3 个 SQLiteDatabase 都有一个 Wrapper,它执行实际的 Cursor 调用,从中读取数据并关闭它们。只有 1 个实例将光标传递回调用对象,但它是一个 IntentService,同样,单线程、单实例、单进程(就像 ContentProvider)循环通过光标并关闭它。
【问题讨论】:
-
如在其他线程中所见,可能与数据库的路径(在android文件系统内部)有关。 stackoverflow.com/questions/4651797/… 也许情况是有人将应用程序移至 SD 并在卸载 SD 时访问/使用您的应用程序(在 Windows 中使用)。只是一个理论!也许试试看:)
标签: android sqlite android-sqlite android-contentprovider