解
我正面临着一种独特的问题。
到目前为止,我已经编写了Android应用程序,它们在手机内存中内部使用了一个SQLite数据库,并且运行正常。现在我想添加另一个数据库,并希望将其存储在SD卡上。我通过修改我们通常使用的DatabaseHelper类来做到这一点。我还编写了一个脚本,将db从assets文件夹转移到一个DB的SD卡和另一个DB的内部存储器位置。
现在我遇到的问题是,当我尝试访问外部数据库时,android在/ data / data / package_name / databases文件夹中创建了一个内部数据库,因此我最终得到没有这样的表异常
有人可以告诉我为什么会收到此错误!
修改1 我的DB Helper Class
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) {
}
}
* 我的内部记忆DB的类的构造函数*
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
外部DB的助手类中导致错误的函数:
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());
}
}
如果我尝试将外部数据库用作内部数据库,则没有错误导致我认为我为外部数据库做错了。
答案 0 :(得分:1)
你能提供一些代码吗?
我通过修改我们通常使用的DatabaseHelper类
来做到这一点
您能描述一下您做了哪些修改?
如果您正在使用SQLiteOpenHelper
,请注意传递给它的构造函数的DB路径是相对于/ data / data / package / databases /文件夹的,因此您无法在那里传递SD路径。如果您仍然需要这个 - 我建议您使用ContextWrapper
并重新定义它的getDatabasePath
方法以指向您的SD数据库。