[英]Why isn't my SQLite database loading from Assets in Android Studio?
我正在嘗試將現有的 SQLite 數據庫加載到 Android Studio 中。 但是,數據庫適配器返回一個空數據庫,而不是給我已填充數據庫的副本。
我有我的權限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我的數據庫適配器
package com.example.testbed;
import android.app.SearchManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
public class DBAdapter extends SQLiteOpenHelper{
public static final String TAG = DBAdapter.class.getSimpleName();
public static int flag;
private static SQLiteDatabase db;
private static String DB_NAME = "recipes.db";
public static String TABLE_NAME = "DrinkRecipes_Loaded";
public static String DB_PATH = "";
public static String COL_WORD = "WORD";
String outFileName = "";
public static Context myContext;
private String loadedTable = "DrinkRecipes_Loaded";
private String specialtyTable = "DrinkRecipes_Specialty";
private String beautyTable = "DrinkRecipes_Beauty";
private String kidsTable = "DrinkRecipes_Kids";
private String shakesTable = "DrinkRecipes_Shakes";
public DBAdapter(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
ContextWrapper cw = new ContextWrapper(context);
DB_PATH = "/data/data" + BuildConfig.APPLICATION_ID + "/databases/";
Log.e(TAG, "Databasehelper: DB_PATH " + DB_PATH);
outFileName = DB_PATH + DB_NAME;
File file = new File(DB_PATH);
Log.e(TAG, "Databasehelper: " + file.exists());
if (!file.exists()) {
file.mkdir();
}
}
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* 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() {
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(outFileName, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
try {
copyDataBase();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* 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 transfering bytestream.
*/
private void copyDataBase() throws IOException {
Log.i("Database",
"New database is being copied to device!");
byte[] buffer = new byte[1024];
OutputStream myOutput = null;
int length;
// Open your local db as the input stream
InputStream myInput = null;
try {
myInput = myContext.getAssets().open(DB_NAME);
// transfer bytes from the inputfile to the
// outputfile
myOutput = new FileOutputStream(DB_PATH + DB_NAME);
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.close();
myOutput.flush();
myInput.close();
Log.i("Database",
"New database has been copied to device!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Log.e(TAG, "openDataBase: Open " + db.isOpen());
}
// we have created a new method for reading loaded recipes.
public ArrayList<recipeModal> readLoadedRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor cursorRecipes = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
// on below line we are creating a new array list.
ArrayList<recipeModal> recipeModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (cursorRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
recipeModalArrayList.add(new recipeModal(cursorRecipes.getString(0),
cursorRecipes.getString(1),
cursorRecipes.getString(2),
cursorRecipes.getString(3),
cursorRecipes.getString(4),
cursorRecipes.getString(5),
cursorRecipes.getString(6),
cursorRecipes.getString(7),
cursorRecipes.getString(8)));
} while (cursorRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
cursorRecipes.close();
return recipeModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<beautyModal> readBeautyRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor beautyRecipes = db.rawQuery("SELECT * FROM " + beautyTable, null);
// on below line we are creating a new array list.
ArrayList<beautyModal> beautyModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (beautyRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
beautyModalArrayList.add(new beautyModal(beautyRecipes.getString(0),
beautyRecipes.getString(1),
beautyRecipes.getString(2),
beautyRecipes.getString(3),
beautyRecipes.getString(4),
beautyRecipes.getString(5)));
} while (beautyRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
beautyRecipes.close();
return beautyModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<specialtyModal> readSpecialtyRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor specialtyRecipes = db.rawQuery("SELECT * FROM " + specialtyTable, null);
// on below line we are creating a new array list.
ArrayList<specialtyModal> specialtyModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (specialtyRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
specialtyModalArrayList.add(new specialtyModal(specialtyRecipes.getString(0),
specialtyRecipes.getString(1),
specialtyRecipes.getString(2),
specialtyRecipes.getString(3),
specialtyRecipes.getString(4),
specialtyRecipes.getString(5),
specialtyRecipes.getString(6),
specialtyRecipes.getString(7)));
} while (specialtyRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
specialtyRecipes.close();
return specialtyModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<kidsModal> readKidsRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor kidsRecipes = db.rawQuery("SELECT * FROM " + kidsTable, null);
// on below line we are creating a new array list.
ArrayList<kidsModal> kidsModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (kidsRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
kidsModalArrayList.add(new kidsModal(kidsRecipes.getString(0),
kidsRecipes.getString(1),
kidsRecipes.getString(2),
kidsRecipes.getString(3),
kidsRecipes.getString(4)));
} while (kidsRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
kidsRecipes.close();
return kidsModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<shakesModal> readShakesRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor shakesRecipes = db.rawQuery("SELECT * FROM " + shakesTable, null);
// on below line we are creating a new array list.
ArrayList<shakesModal> shakesModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (shakesRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
shakesModalArrayList.add(new shakesModal(shakesRecipes.getString(0),
shakesRecipes.getString(1),
shakesRecipes.getString(2),
shakesRecipes.getString(3),
shakesRecipes.getString(4)));
} while (shakesRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
shakesRecipes.close();
return shakesModalArrayList;
}
@Override
public synchronized void close() {
if (db != null)
db.close();
super.close();
}
public void onCreate(SQLiteDatabase arg0) {
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
}
}
當我調用它時,我唯一得到的是一個崩潰的應用程序和一個寫入正確路徑的空數據庫。 我非常渴望找到解決此問題的方法,並希望得到任何反饋。
我嘗試了幾種在 Google 上看起來很有前途的不同解決方案,但沒有成功。
編輯:錯誤的堆棧跟蹤
E/SQLiteLog: (1) no such table: DrinkRecipes_Loaded in "SELECT * FROM DrinkRecipes_Loaded"
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.testbed, PID: 4732
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testbed/com.example.testbed.ViewRecipes}: android.database.sqlite.SQLiteException: no such table: DrinkRecipes_Loaded (code 1 SQLITE_ERROR[1]): , while compiling: SELECT * FROM DrinkRecipes_Loaded
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3851)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4027)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:247)
at android.app.ActivityThread.main(ActivityThread.java:8676)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: android.database.sqlite.SQLiteException: no such table: DrinkRecipes_Loaded (code 1 SQLITE_ERROR[1]): , while compiling: SELECT * FROM DrinkRecipes_Loaded
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1463)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:901)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:62)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:2063)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:2002)
at com.example.testbed.DBAdapter.readLoadedRecipes(DBAdapter.java:128)
at com.example.testbed.ViewRecipes.onCreate(ViewRecipes.java:84)
at android.app.Activity.performCreate(Activity.java:8215)
at android.app.Activity.performCreate(Activity.java:8199)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3824)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4027)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2336)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:247)
at android.app.ActivityThread.main(ActivityThread.java:8676)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
您的代碼存在一些問題。
您正在嘗試將數據庫文件設為目錄而不是將父目錄設為目錄。
您不適合后來的 android 版本,這些版本默認使用 WAL(預寫日志記錄),而不是在創建(復制資產)時使用getReabableDatabase
進行日志記錄。
getReadableDatabase
將按照它所說的那樣創建數據庫。 然后副本會覆蓋它(如果有效)。 使用getReadableDatabase
只是為了繞過不存在的數據庫目錄是矯枉過正/效率低下的,因為創建新數據庫的所有處理都已進行。
這是您的代碼的重寫,請注意:-
createDatabase
和checkDatabase
方法已被注釋掉。 它們已被getDatabase
方法取代。CopyDatabase
方法已更改為返回 false(getDatabase 然后拋出 runTimeException) getDatabase
方法
CopyDatabase
方法所以代碼(大部分原始代碼被注釋掉了)是:-
public class DBAdapter extends SQLiteOpenHelper {
public static final String TAG = DBAdapter.class.getSimpleName();
public static int flag;
private static SQLiteDatabase db;
private static String DB_NAME = "recipes.db";
public static String TABLE_NAME = "DrinkRecipes_Loaded";
public static String DB_PATH = "";
public static String COL_WORD = "WORD";
String outFileName = "";
public static Context myContext;
private String loadedTable = "DrinkRecipes_Loaded";
private String specialtyTable = "DrinkRecipes_Specialty";
private String beautyTable = "DrinkRecipes_Beauty";
private String kidsTable = "DrinkRecipes_Kids";
private String shakesTable = "DrinkRecipes_Shakes";
public DBAdapter(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
//ContextWrapper cw = new ContextWrapper(context); Not used
DB_PATH = context.getDatabasePath(DB_NAME).getPath(); // no need to hard code anything bar the DB name
/*
//DB_PATH = "/data/data" + BuildConfig.APPLICATION_ID + "/databases/";
Log.e(TAG, "Databasehelper: DB_PATH " + DB_PATH);
outFileName = DB_PATH + DB_NAME;
File file = new File(DB_PATH);
Log.e(TAG, "Databasehelper: " + file.exists());
if (!file.exists()) {
file.getParentFile().mkdirs(); // CHANGED you don't want the database to be a directory
}
*/
getDatabase(context);
}
/*<<<<< ADDED >>>>>*/
private void getDatabase(Context context) {
File dbFile = new File(context.getDatabasePath((DB_NAME)).getPath());
if (dbFile.exists()) return; // Database found so all done
// Otherwise ensure that the database directory exists (does not by default until later versions)
if (!dbFile.getParentFile().exists()) {
dbFile.getParentFile().mkdirs();
}
if (!copyDataBase()) {
throw new RuntimeException("Unable to copy database from the asset (check the stack-trace).");
}
}
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
/* NOTE NEEDED/UNSAFE as getDatabase create a database and for later version of Android it will be in WAL mode
thus the additional WAL files are created. When the database is then opened SQLite see that the WAL files are not
for the copied database and thus the open fails. Android's API then creates an new empty database file
*/
/*
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase(); // Causes issues if in WAL mode and result in database
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
*/
/**
* 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() {
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(outFileName, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
try {
copyDataBase();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
*/
/**
* 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 transfering bytestream.
*/
private boolean /* <<<<< CHANGED SIGNATURE */ copyDataBase() {
Log.i("Database",
"New database is being copied to device!");
byte[] buffer = new byte[4096]; //Probably more efficient as default page size will be 4k
OutputStream myOutput = null;
int length;
// Open your local db as the input stream
InputStream myInput = null;
try {
myInput = myContext.getAssets().open(DB_NAME);
// transfer bytes from the inputfile to the
// outputfile
myOutput = new FileOutputStream(DB_PATH);
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.close();
myOutput.flush();
myInput.close();
Log.i("Database",
"New database has been copied to device!");
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Log.e(TAG, "openDataBase: Open " + db.isOpen());
}
/*
// we have created a new method for reading loaded recipes.
public ArrayList<recipeModal> readLoadedRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor cursorRecipes = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
// on below line we are creating a new array list.
ArrayList<recipeModal> recipeModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (cursorRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
recipeModalArrayList.add(new recipeModal(cursorRecipes.getString(0),
cursorRecipes.getString(1),
cursorRecipes.getString(2),
cursorRecipes.getString(3),
cursorRecipes.getString(4),
cursorRecipes.getString(5),
cursorRecipes.getString(6),
cursorRecipes.getString(7),
cursorRecipes.getString(8)));
} while (cursorRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
cursorRecipes.close();
return recipeModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<beautyModal> readBeautyRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor beautyRecipes = db.rawQuery("SELECT * FROM " + beautyTable, null);
// on below line we are creating a new array list.
ArrayList<beautyModal> beautyModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (beautyRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
beautyModalArrayList.add(new beautyModal(beautyRecipes.getString(0),
beautyRecipes.getString(1),
beautyRecipes.getString(2),
beautyRecipes.getString(3),
beautyRecipes.getString(4),
beautyRecipes.getString(5)));
} while (beautyRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
beautyRecipes.close();
return beautyModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<specialtyModal> readSpecialtyRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor specialtyRecipes = db.rawQuery("SELECT * FROM " + specialtyTable, null);
// on below line we are creating a new array list.
ArrayList<specialtyModal> specialtyModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (specialtyRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
specialtyModalArrayList.add(new specialtyModal(specialtyRecipes.getString(0),
specialtyRecipes.getString(1),
specialtyRecipes.getString(2),
specialtyRecipes.getString(3),
specialtyRecipes.getString(4),
specialtyRecipes.getString(5),
specialtyRecipes.getString(6),
specialtyRecipes.getString(7)));
} while (specialtyRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
specialtyRecipes.close();
return specialtyModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<kidsModal> readKidsRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor kidsRecipes = db.rawQuery("SELECT * FROM " + kidsTable, null);
// on below line we are creating a new array list.
ArrayList<kidsModal> kidsModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (kidsRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
kidsModalArrayList.add(new kidsModal(kidsRecipes.getString(0),
kidsRecipes.getString(1),
kidsRecipes.getString(2),
kidsRecipes.getString(3),
kidsRecipes.getString(4)));
} while (kidsRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
kidsRecipes.close();
return kidsModalArrayList;
}
// we have created a new method for reading loaded recipes.
public ArrayList<shakesModal> readShakesRecipes() {
// on below line we are creating a
// database for reading our database.
SQLiteDatabase db = this.getReadableDatabase();
// on below line we are creating a cursor with query to read data from database.
Cursor shakesRecipes = db.rawQuery("SELECT * FROM " + shakesTable, null);
// on below line we are creating a new array list.
ArrayList<shakesModal> shakesModalArrayList = new ArrayList<>();
// moving our cursor to first position.
if (shakesRecipes.moveToFirst()) {
do {
// on below line we are adding the data from cursor to our array list.
shakesModalArrayList.add(new shakesModal(shakesRecipes.getString(0),
shakesRecipes.getString(1),
shakesRecipes.getString(2),
shakesRecipes.getString(3),
shakesRecipes.getString(4)));
} while (shakesRecipes.moveToNext());
// moving our cursor to next.
}
// at last closing our cursor
// and returning our array list.
shakesRecipes.close();
return shakesModalArrayList;
}
*/
@Override
public synchronized void close() {
if (db != null)
db.close();
super.close();
}
public void onCreate(SQLiteDatabase arg0) {
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
}
}
以上已經過測試,但使用重命名為 recipes.db 的替代數據庫(NorthWind,因為它非常大)新安裝的日志:-
2022-03-27 10:22:11.223 I/Database: New database is being copied to device!
2022-03-27 10:22:11.455 I/Database: New database has been copied to device!
AppInspection 確認數據庫已成功復制(盡管不是您的數據庫):-
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.