Я оставил этот вопрос в списке рассылки android-developer безуспешно.Итак, давайте попробуем здесь:)
То, чего я пытаюсь достичь здесь, очень просто.Используя подкласс SQLiteOpenHelper
Я пытаюсь создать новую новую БД, если она не существует, поэтому я полагаюсь на метод onCreate()
, предоставляемый этим классом.Вот мой код:
public class CurrencyStorageHelper extends SQLiteOpenHelper {
private static final String TAG = "CurrencyStorageHelper";
private static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "easycurrencyconverter.db";
public static final String COL_ID = "_id";
public static final String COL_CURRENCY_CODE = "currency_code";
public static final String COL_CURRENCY_VALUE = "currency_value";
public static final String COL_LAST_UPDATE = "last_update";
public static final String COL_LAST_DOWNLOADED = "last_downloaded";
public static final String COL_IS_TARGET_CURRENCY = "is_target_currency";
public static final String COL_CURRENCY_POSITION = "position";
public static final String TABLE_DEFAULT_CURRENCIES = "defaultcurrencies";
public static final String TABLE_CURRENCIES = "currencyhistory";
public static final String TABLE_CURRENCY_DEFINITION = "currencydefinition";
public static final String COL_DEFINITION_CODE = "code";
public static final String COL_DEFINITION_FULL_NAME = "full_name";
private static final String DATABASE_CREATE_1 =
"CREATE TABLE " + TABLE_CURRENCIES + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " +
", " + COL_CURRENCY_CODE + " TEXT NOT NULL" +
", " + COL_CURRENCY_VALUE + " REAL NOT NULL" +
", " + COL_LAST_UPDATE + " REAL NOT NULL" +
", " + COL_LAST_DOWNLOADED + " REAL NOT NULL); ";
private static final String DATABASE_CREATE_2 =
"CREATE TABLE " + TABLE_DEFAULT_CURRENCIES + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " +
", " + COL_CURRENCY_CODE + " TEXT NOT NULL" +
", " + COL_CURRENCY_VALUE + " REAL NOT NULL" +
", " + COL_CURRENCY_POSITION + " INTEGER NOT NULL" +
", " + COL_LAST_UPDATE + " REAL NOT NULL" +
", " + COL_LAST_DOWNLOADED + " REAL NOT NULL" +
", " + COL_IS_TARGET_CURRENCY + " NUMERIC ); ";
private static final String DATABASE_CREATE_3 =
"CREATE TABLE " + TABLE_CURRENCY_DEFINITION + " (" + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT " +
", " + COL_DEFINITION_CODE + " TEXT NOT NULL" +
", " + COL_DEFINITION_FULL_NAME + " TEXT NOT NULL); ";
private static final String DATABASE_DROP = "DROP TABLE IF EXISTS " + TABLE_CURRENCIES + "; " +
"DROP TABLE IF EXISTS " + TABLE_DEFAULT_CURRENCIES + ";" +
"DROP TABLE IF EXISTS " + TABLE_CURRENCY_DEFINITION + ";";
public CurrencyStorageHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
Log.d(TAG, "Opening the database... " + db.getPath() + " version " + db.getVersion());
db.setLockingEnabled(true);
}
@Override
public void onCreate(SQLiteDatabase database) {
if (database.isDbLockedByCurrentThread()){
Log.d(TAG, "Database locked by current thread...");
}
if (database.isDbLockedByOtherThreads()){
Log.e(TAG, "Database locked by OTHER thread...");
}
if (database.isOpen()){
Log.d(TAG, "OK.. Database open");
}
if (database.isReadOnly()){
Log.e(TAG, "The database is read only");
}
if (database.inTransaction()){
Log.e(TAG, "Why id the databse in transaction???");
}
Log.d(TAG, "Call to onCreate");
Log.d(TAG, "Creating table..." + DATABASE_CREATE_1);
database.beginTransaction();
database.execSQL(DATABASE_CREATE_1);
database.endTransaction();
Log.d(TAG, "Creating table..." + DATABASE_CREATE_2);
database.beginTransaction();
database.execSQL(DATABASE_CREATE_2);
database.endTransaction();
Log.d(TAG, "Creating table..." + DATABASE_CREATE_3);
database.beginTransaction();
database.execSQL(DATABASE_CREATE_3);
database.endTransaction();
insertInitialCurrencies(database);
}
/**
* Create the default values to be shown to the user main activity when the application
* is ran for the first time and no currencies have been downloaded yet.
* @param database
*/
private void insertInitialCurrencies(SQLiteDatabase database){
int i = 1;
//TODO The fact that USD is the target currency is arbitrary. Maybe we should read user's
//locale to get her currency
insertDefaultCurrency(database, "USD", "U.S. Dollar", 1, i++, true, (new Date()).getTime(), (new Date()).getTime(), true, false);
insertDefaultCurrency(database, "EUR", "Euro", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false);
insertDefaultCurrency(database, "GBP", "British Pound", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false);
insertDefaultCurrency(database, "JPY", "Japanese Yen", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false);
insertDefaultCurrency(database, "CNY", "Chinese Yuan", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, false);
insertDefaultCurrency(database, "CHF", "Swiss Franc", 1, i++, false, (new Date()).getTime(), (new Date()).getTime(), false, true);
}
/**
* Insert a new currency value which will be shown on the user main activity.
*
*/
private void insertDefaultCurrency(SQLiteDatabase database,
String currencyCode,
String currencyFullName,
double value,
int position,
boolean isTargetCurrency,
long lastModifiedDate,
long lastDownloadedDate,
boolean startTransaction,
boolean endTransaction){
ContentValues vals = new ContentValues();
vals.put(COL_CURRENCY_CODE, currencyCode);
vals.put(COL_CURRENCY_VALUE, value);
vals.put(COL_LAST_DOWNLOADED, lastDownloadedDate);
vals.put(COL_LAST_UPDATE, lastModifiedDate);
vals.put(COL_IS_TARGET_CURRENCY, (isTargetCurrency? 1 : 0));
vals.put(COL_CURRENCY_POSITION, position);
if (startTransaction){
database.beginTransaction();
}
Log.d(TAG, "Adding default currency..." + currencyCode);
database.insertOrThrow(TABLE_DEFAULT_CURRENCIES, null, vals);
if (endTransaction){
database.endTransaction();
}
}
Здесь происходит следующее: файл БД фактически создается (размер 3072 байта), но таблицы не создаются, поэтому, когда я запускаю метод для запроса БД, я получаю исключение
android.database.sqlite.SQLiteException: no such table.
Однако я не получаю никаких исключений SQL, поэтому понятия не имею, почему таблицы не создаются.
Кроме того, onCreate()
-метод выполняется каждый раз, когда язапустил мое приложение.Должно ли это выполняться только один раз, когда БД не существует?Почему он все время вызывается?
Отладка приложения Я заметил, что после открытия БД:
getVersion()
возвращает 0 isInTransaction()
возвращает true
- У экземпляра
SQLiteDatabase
есть закрытый атрибут mStackTrace
, установленный на DatabaseObjectNotClosedException
, но у меня еще нет открытого курсора.
Все это происходитс эмулятором, а также с моим мобильным телефоном (Samsung Galaxy S2), поэтому мне здесь чего-то не хватает.
Спасибо за любую помощь / подсказку, которую вы мне могли бы дать !!