解决方案
我必须在我的自定义 DBHelper 类中覆盖 getReadableDatabase() 和 getWritableDatabase()。
我面临着一种独特的问题。
到目前为止,我编写的 Android 应用程序在手机内存内部使用了一个 SQLite DB,并且运行良好。现在我想添加另一个数据库并将其存储在 SD 卡上。我通过修改我们通常使用的 DatabaseHelper 类来做到这一点。我还编写了一个脚本,将 db 从 assets 文件夹传输到 SD 卡用于一个 DB,并将内部存储器位置用于另一个。
现在我面临的问题是,当我尝试访问外部数据库时,android 在 /data/data/package_name/databases 文件夹中创建了一个内部数据库,因此我最终没有得到这样的表异常。
有人可以告诉我为什么会收到此错误!
编辑 1 我的数据库助手类
public class DBHelper extends SQLiteOpenHelper {
private Context myContext;
private String DB_PATH;
private String DB_NAME;
private boolean isExternal;
private SQLiteDatabase myDataBase;
private final String TAG = "ERROR";
public DBHelper(Context AppC, String DB_NAME, boolean isExternal,
int DB_VERSION) {
super(AppC, DB_NAME + ".sqlite", null, DB_VERSION);
this.myContext = AppC;
this.isExternal = isExternal;
this.DB_NAME = DB_NAME;
setDbPath();
}
private void setDbPath() {
if (this.isExternal) {
try {
DB_PATH = Environment.getExternalStorageDirectory()
+ "/myappname/";
} catch (Exception e) {
DB_PATH = "/mnt/sdcard/myappname/";
}
} else {
try {
DB_PATH = Environment.getDataDirectory()
+ "/data/my.app.package/databases/";
} catch (Exception e) {
DB_PATH = "data/data/my.app.package/databases/";
}
}
}
/**
* Creates a empty database on the system and rewrites it with your own
* database.
* */
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (!dbExist) {
try {
copyDataBase();
} catch (Exception E) {
// MRC
}
}
}
/**
* Copies your database from your local assets-folder to the just created
* empty database in the system folder, from where it can be accessed and
* handled. This is done by transferring byte streams.
* */
private void copyDataBase() throws IOException {
String filePath = DB_PATH + this.DB_NAME + ".sqlite";
if (this.isExternal) {
File file = new File(filePath);
if (!file.exists()) {
File dir = new File(DB_PATH);
if (dir.exists() || dir.mkdirs()) {
transferFromAssets(this.DB_NAME + ".zip", filePath);
} else {
Log.d(TAG, "Unable to create dir " + DB_PATH);
}
}
} else {
// By calling this method and empty database will be created
// into the default system path of your application so we
// will be able to overwrite that database with our
// database.
SQLiteDatabase db_Read = this.getReadableDatabase();
db_Read.close();
transferFromAssets(this.DB_NAME + ".zip", filePath);
}
}
private void transferFromAssets(String from, String to) throws IOException {
ZipInputStream myInput = new ZipInputStream(myContext.getAssets().open(
from));
myInput.getNextEntry(); // Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(to);
// transfer bytes from the inputfile to the outputfile
AndroidUtil.copyStream(myInput, myOutput);
}
/**
* Check if the database already exist to avoid re-copying the file each
* time you open the application.
*
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase() {
File dbFile = new File(DB_PATH + this.DB_NAME + ".sqlite");
return dbFile.exists();
}
public void openDataBase() throws SQLException {
String myPath = DB_PATH + this.DB_NAME + ".sqlite";
Log.d(TAG, "Opening DB:" + myPath);
myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
}
@Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
*我的内存数据库类的构造函数 *
public WordsDB(Context AppC) {
DBAPI = new DBHelper(AppC, "DB_NAME", false, 11);
this.AppC = AppC;
try {
DBAPI.createDataBase();
DBAPI.openDataBase();
} catch (IOException e) {
CustomToast.Toast(AppC, "", TCategory_E.CRITICAL_ERROR,
TDuration_E.LONG, TPosition_E.CENTER);
// MRC
}
}
** 我的外部数据库类的构造函数 **
public BackupDB(Context AppC) {
DBAPI = new DBHelper(AppC, "/mnt/sdcard/myapp/backup-db",
true, 11);
this.AppC = AppC;
try {
DBAPI.createDataBase();
DBAPI.openDataBase();
} catch (IOException e) {
CustomToast.Toast(AppC, "", TCategory_E.CRITICAL_ERROR,
TDuration_E.LONG, TPosition_E.CENTER);
// MRC
}
}
编辑 2
导致错误的外部数据库助手类中的函数:
public void setValue(int No, int Stars) {
try {
ContentValues update = new ContentValues();
update.put(COL_STARRED, Stars);
String args[] = { No + "" };
SQLDB = DBAPI.getWritableDatabase();
SQLDB.acquireReference();
SQLDB.update(TABLE_NAME, update, COL_ID + "=?", args);
SQLDB.releaseReference();
SQLDB.close();
} catch (Exception E) {
Log.d(TAG, E.getMessage());
}
}
如果我尝试将外部数据库用作内部数据库,则没有错误导致我认为我为外部数据库做错了什么。