0
我有一個靜態的sqlite數據庫。我怎麼能把它包含到應用程序中?我應該把它放在我的項目文件夾中?我應該如何從DatabaseHandler訪問它?如何使用我的自定義SQLite數據庫與Android應用程序?
我在網上發現的所有東西都是使用sqlite創建一個新的數據庫,並在其中存儲用戶或臨時數據,但沒有使用預定義數據的現有數據庫。
Official Google docs不知道該怎麼做。
我有一個靜態的sqlite數據庫。我怎麼能把它包含到應用程序中?我應該把它放在我的項目文件夾中?我應該如何從DatabaseHandler訪問它?如何使用我的自定義SQLite數據庫與Android應用程序?
我在網上發現的所有東西都是使用sqlite創建一個新的數據庫,並在其中存儲用戶或臨時數據,但沒有使用預定義數據的現有數據庫。
Official Google docs不知道該怎麼做。
處理這種情況基本上只是做一個文件複製。
棘手的部分是
我寫了一個示例助手類,演示如何當從資產中加載數據庫。
public abstract class SQLiteAssetHelper extends SQLiteOpenHelper {
// ----------------------------------
// CONSTANTS
// ----------------------------------
private static final String DATABASE_DIR_NAME = "databases";
// ----------------------------------
// ATTRIBUTES
// ----------------------------------
private final Context mContext;
private final CursorFactory mFactory;
private SQLiteDatabase mDatabase;
private String mDatabaseName;
private String mDatabaseAssetPath;
private String mDatabaseDiskPath;
private boolean mIsProcessingDatabaseCreation; // Database creation may take some time
// ----------------------------------
// CONSTRUCTORS
// ----------------------------------
public SQLiteAssetHelper(Context context, String name, CursorFactory factory, String destinationPath, int version) {
super(context, name, factory, version);
mContext = context;
mFactory = factory;
mDatabaseName = name;
mDatabaseAssetPath = DATABASE_DIR_NAME + "/" + name;
if (destinationPath == null) {
mDatabaseDiskPath = context.getApplicationInfo().dataDir + "/" + DATABASE_DIR_NAME;
} else {
mDatabaseDiskPath = destinationPath;
}
}
// ----------------------------------
// OVERRIDEN METHODS
// ----------------------------------
@Override
public synchronized SQLiteDatabase getWritableDatabase() {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
// the database is already open and writable
return mDatabase;
}
if (mIsProcessingDatabaseCreation) {
throw new IllegalStateException("getWritableDatabase is still processing");
}
SQLiteDatabase db = null;
boolean isDatabaseLoaded = false;
try {
mIsProcessingDatabaseCreation = true;
db = createOrOpenDatabase();
// you should probably check for database new version and process upgrade if necessary
onOpen(db);
isDatabaseLoaded = true;
return db;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
mIsProcessingDatabaseCreation = false;
if (isDatabaseLoaded) {
if (mDatabase != null) {
try {
mDatabase.close();
} catch (Exception e) {
e.printStackTrace();
}
}
mDatabase = db;
} else {
if (db != null) db.close();
}
}
}
@Override
public final void onCreate(SQLiteDatabase db) {
// getWritableDatabase() actually handles database creation so nothing to code here
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO implement your upgrade logic here
}
// ----------------------------------
// PRIVATE METHODS
// ----------------------------------
private void copyDatabaseFromAssets() throws IOException {
String dest = mDatabaseDiskPath + "/" + mDatabaseName;
String path = mDatabaseAssetPath;
InputStream is = mContext.getAssets().open(path);
File databaseDestinationDir = new File(mDatabaseDiskPath + "/");
if (!databaseDestinationDir.exists()) {
databaseDestinationDir.mkdir();
}
IOUtils.copy(is, new FileOutputStream(dest));
}
private SQLiteDatabase createOrOpenDatabase() throws IOException {
SQLiteDatabase db = null;
File file = new File (mDatabaseDiskPath + "/" + mDatabaseName);
if (file.exists()) {
db = openDatabase();
}
if (db != null) {
return db;
} else {
copyDatabaseFromAssets();
db = openDatabase();
return db;
}
}
private SQLiteDatabase openDatabase() {
try {
SQLiteDatabase db = SQLiteDatabase.openDatabase(
mDatabaseDiskPath + "/" + mDatabaseName, mFactory, SQLiteDatabase.OPEN_READWRITE);
return db;
} catch (SQLiteException e) {
e.printStackTrace();
return null;
}
}
// ----------------------------------
// NESTED CLASSES
// ----------------------------------
private static class IOUtils {
private static final int BUFFER_SIZE = 1024;
public static void copy(InputStream in, OutputStream outs) throws IOException {
int length;
byte[] buffer = new byte[BUFFER_SIZE];
while ((length = in.read(buffer)) > 0) {
outs.write(buffer, 0, length);
}
outs.flush();
outs.close();
in.close();
}
}; // IOUtils
}
然後你只需要創建從一個以上這樣的擴展類:
public class MyDbHelper extends SQLiteAssetHelper {
// ----------------------------------
// CONSTANTS
// ----------------------------------
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_FILE_NAME = "test.db";
// ----------------------------------
// CONSTRUCTORS
// ----------------------------------
public MyDbHelper(Context context) {
super(context, DATABASE_FILE_NAME, null, context.getFilesDir().getAbsolutePath(), DATABASE_VERSION);
}
}
每次會從你的MyDbHelper實例調用getWritableDatabase(),它會做所有的副本/爲你打開東西並返回可寫數據庫。
正如我之前所說的,我沒有在這個示例中實現upgrade()方法,您將不得不這樣做。 我也沒有實現getReadableDatabase(),因爲我通常只使用getWritableDatabase()。你可能需要這樣做。
如果你想測試它,只需做到以下幾點:以上
希望這對我有所幫助。
只需將它放在您的'assets'文件夾中即可。然後將其複製到您的應用程序數據庫路徑(如果不存在)。用它。要開心。 –