2013-10-21 7 views
13

Nella mia applicazione Android c'è un database predefinito che si trova nella cartella delle risorse. Ho creato una tabella android_metadata con una colonna denominata locale e con un record en_US. Nella mia applicazione l'utente deve inserire i suoi dettagli e fare clic sul pulsante Salva. Quando fai clic sul pulsante Salva, ho ricevuto l'errore seguente.Impossibile cambiare la locale per db '/data/data/my.easymedi.controller/databases/EasyMediInfo.db' a 'en_US'

10-21 09:37:06.010: E/SQLiteLog(6278): (11) database corruption at line 50741 of  [00bb9c9ce4] 
10-21 09:37:06.010: E/SQLiteLog(6278): (11) database corruption at line 50780 of [00bb9c9ce4] 
10-21 09:37:06.010: E/SQLiteLog(6278): (11) statement aborts at 16: [SELECT locale FROM android_metadata UNION SELECT NULL ORDER BY locale DESC LIMIT 1] 
10-21 09:37:06.160: E/SQLiteDatabase(6278): Failed to open database '/data/data/my.easymedi.controller/databases/EasyMediInfo.db'. 
10-21 09:37:06.160: E/SQLiteDatabase(6278): android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/my.easymedi.controller/databases /EasyMediInfo.db' to 'en_US'. 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:386) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at my.easymedi.db.DBHelper.openDataBase(DBHelper.java:153) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at my.easymedi.controller.AddNewPerson.onClick(AddNewPerson.java:202) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.view.View.performClick(View.java:4202) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.view.View$PerformClick.run(View.java:17340) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.os.Handler.handleCallback(Handler.java:725) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.os.Handler.dispatchMessage(Handler.java:92) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.os.Looper.loop(Looper.java:137) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.app.ActivityThread.main(ActivityThread.java:5039) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at java.lang.reflect.Method.invokeNative(Native Method) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at java.lang.reflect.Method.invoke(Method.java:511) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at dalvik.system.NativeStart.main(Native Method) 
10-21 09:37:06.160: E/SQLiteDatabase(6278): Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed (code 11) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.nativeExecuteForString(Native Method) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:634) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:367) 
10-21 09:37:06.160: E/SQLiteDatabase(6278):  ... 22 more 

La mia classe DBHelper sta seguendo.

package my.easymedi.db; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import my.easymedi.entity.Person; 
import android.content.ContentValues; 
import android.content.Context; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteException; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 
import android.widget.Toast; 

public class DBHelper extends SQLiteOpenHelper { 

private static final String pkg = "my.easymedi.controller"; 
private static String DB_PATH = ""; 
private static String DB_NAME = "EasyMediInfo.db"; 
private static final int DB_VERSION = 1; 
private final Context myContext; 
private SQLiteDatabase myDatabase; 

public DBHelper(Context context) { 
    super(context, DB_NAME, null, DB_VERSION); 
    // this.myContext = context; 
    if (android.os.Build.VERSION.SDK_INT >= 4.2) { 
     DB_PATH = context.getApplicationInfo().dataDir + "/databases/"; 
    } else { 
     DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; 
    } 
    this.myContext = context; 
} 

public void createDataBase() { 
    boolean dbExist = checkDataBase(); 
    System.out.println("==="+dbExist+"==="); 
    if (dbExist) { 
     // do nothing - database already exist 
    } else { 

     this.getReadableDatabase(); 
     this.close(); 
     try { 
      copyDataBase(); 
      Log.d("CREATE_DB", "createDatabase database created"); 
     } catch (IOException e) { 
      Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT) 
        .show(); 
      Log.d("CREATE_DB", e.getMessage()); 
     } 
    } 
} 

private void copyDataBase() throws IOException { 
    System.out.println("***copy db***"); 
    InputStream databaseInput = null; 
    /* Path to copy the database */ 
    String outFileName = DB_PATH + DB_NAME; 
    /* open the empty database as an output stream */ 
    OutputStream databaseOutput = new FileOutputStream(outFileName); 
    /* open the local database as the input stream */ 
    databaseInput = myContext.getAssets().open(DB_NAME); 

    /* Transfer byte from byte from input file to output file */ 
    byte[] buffer = new byte[1024]; 
    int length = databaseInput.read(buffer); 
    while (length > 0) { 
     databaseOutput.write(buffer, 0, length); 
     //databaseOutput.flush(); 
    } 
    databaseOutput.flush(); 
    databaseInput.close(); 
    databaseOutput.close(); 
} 

private boolean checkDataBase() { 
    File dbFile = new File(DB_PATH + DB_NAME); 
    return dbFile.exists(); 
    /*SQLiteDatabase checkDB = null; 
    try { 
     String myPath = DB_PATH + DB_NAME; 
     checkDB = SQLiteDatabase.openDatabase(myPath, null, 
       SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
    } catch (SQLiteException e) { 
     Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT) 
       .show(); 
     Log.d("Check_DB", e.getMessage()); 
    } 
    if (checkDB != null) { 
     String str = "checked"; 
     System.out.println("====" + str + "===="); 
     checkDB.close(); 
    } 
    return checkDB != null ? true : false;*/ 
} 

/* Open the database */ 
public boolean openDataBase() { 
    String myPath = DB_PATH + DB_NAME; 
    Toast.makeText(myContext, myPath, Toast.LENGTH_SHORT).show(); 
    myDatabase = SQLiteDatabase.openDatabase(myPath, null, 
      SQLiteDatabase.OPEN_READWRITE); 
    if (myDatabase != null) { 
     System.out.println("====database opened===="); 
    } else { 
     System.out.println("====error opening database===="); 
    } 
    return myDatabase != null ? true : false; 
} 

public void closeDatabase() { 
    if(myDatabase != null){ 
     myDatabase.close(); 
    } 
} 

@Override 
public void onCreate(SQLiteDatabase db) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    // TODO Auto-generated method stub 

} 

public boolean insertIntoDatabase(String table, ContentValues values) { 
    try { 
     myDatabase.insert(table, null, values); 
     Log.d("INSERT", "Information Saved"); 
     return true; 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     Log.d("INSERT", e.toString()); 
     return false; 
    } 
} 
} 

E questo è il mio segmento di codice per il pulsante di salvataggio.

case R.id.btnSave: 
     personName = etName.getText().toString(); 
     date_of_birth = tvDOB.getText().toString(); 
     age = tvAge.getText().toString(); 

     int selected_rb_ID = genderGrp.getCheckedRadioButtonId(); 
     RadioButton rb = (RadioButton) findViewById(selected_rb_ID); 
     gender = rb.getText().toString(); 
     bloodGrp = spiBloodGrp.getSelectedItem().toString(); 

     Person person = new Person(); 
     person.setName(personName); 
     person.setDate_of_birth(date_of_birth); 
     person.setAge(age); 
     person.setGender(gender); 
     person.setBloodGrp(bloodGrp); 

     ContentValues values = new ContentValues(); 
     values.put(COLUMN_PERSON_NAME, person.getName()); 
     values.put(COLUMN_DOB, person.getDate_of_birth()); 
     values.put(COLUMN_AGE, person.getAge()); 
     values.put(COLUMN_GENDER, person.getGender()); 
     values.put(COLUMN_BLOODGRP, person.getBloodGrp()); 

     DBHelper dbHelper = new DBHelper(this); 
     dbHelper.createDataBase(); 
     dbHelper.openDataBase(); 
     if(dbHelper.insertIntoDatabase("EMPerson", values)){ 
      Toast.makeText(getApplicationContext(), "Data has been saved successfully", Toast.LENGTH_SHORT).show(); 
     }else{ 
      Toast.makeText(getApplicationContext(), "Oops ! Try again", Toast.LENGTH_SHORT).show(); 
     } 
     dbHelper.closeDatabase(); 

     break; 

Nella mia attività principale ho creato il database chiamando questo segmento di codice.

final DBHelper helper = new DBHelper(this); 
helper.createDataBase(); 

Sarei molto grato se qualcuno potesse essere così gentile da spiegare qual è l'errore con questo.

Grazie in anticipo

+0

possibile duplicato del [SQLiteException Android: Impossibile cambiare locale per db a 'it \ _us'] (http: // StackOverflow .com/questions/14631316/android-sqliteexception-failed-to-change-locale-for-db-to-it-us) – rds

risposta

20

vostri copyDataBase() funzioni copie un db (EasyMediInfo.db) dalla cartella patrimonio. E sembra che il database sia stato creato utilizzando una diversa localizzazione rispetto a 'en_US'.

EDIT

Provare a cambiare:

myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); 

A:

myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE); 
+0

Grazie mille. Problema risolto :) – Rose18

+9

Cosa fare se non utilizzo il metodo SQLiteDatabase.openDatabase e invece dBHelper.getWritableDatabase()? –

+0

@AhesanaliMomin hai ricevuto una risposta? – user2520215

1

ho ottenuto lo stesso errore quando setLocale a zh_CN. Invece di scrivere nuovo codice da usare SQLiteDatabase direttamente, ho fatto una versione modificata SQLiteOpenHelper:

/** 
* A simplified version of SKD's SQLiteOpenHelper(only writable), original doc below 
* 
* A helper class to manage database creation and version management. 
* 
* <p>You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and 
* optionally {@link #onOpen}, and this class takes care of opening the database 
* if it exists, creating it if it does not, and upgrading it as necessary. 
* Transactions are used to make sure the database is always in a sensible state. 
* 
* <p>This class makes it easy for {@link android.content.ContentProvider} 
* implementations to defer opening and upgrading the database until first use, 
* to avoid blocking application startup with long-running database upgrades. 
* 
* <p>For an example, see the NotePadProvider class in the NotePad sample application, 
* in the <em>samples/</em> directory of the SDK.</p> 
* 
* <p class="note"><strong>Note:</strong> this class assumes 
* monotonically increasing version numbers for upgrades.</p> 
*/ 
public abstract class SQLiteOpenHelper { 
    private static final String TAG = SQLiteOpenHelper.class.getSimpleName(); 


    private final Context mContext; 
    private final String mName; 
    private final CursorFactory mFactory; 
    private final int mNewVersion; 

    private SQLiteDatabase mDatabase; 
    private boolean mIsInitializing; 
    private boolean mEnableWriteAheadLogging; 
    private final DatabaseErrorHandler mErrorHandler; 

    /** 
    * Create a helper object to create, open, and/or manage a database. 
    * This method always returns very quickly. The database is not actually 
    * created or opened until one of {@link #getWritableDatabase} or 
    * {@link #getReadableDatabase} is called. 
    * 
    * @param context to use to open or create the database 
    * @param name of the database file, or null for an in-memory database 
    * @param factory to use for creating cursor objects, or null for the default 
    * @param version number of the database (starting at 1); if the database is older, 
    *  {@link #onUpgrade} will be used to upgrade the database; if the database is 
    *  newer, {@link #onDowngrade} will be used to downgrade the database 
    */ 
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { 
     this(context, name, factory, version, null); 
    } 

    /** 
    * Create a helper object to create, open, and/or manage a database. 
    * The database is not actually created or opened until one of 
    * {@link #getWritableDatabase} or {@link #getReadableDatabase} is called. 
    * 
    * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be 
    * used to handle corruption when sqlite reports database corruption.</p> 
    * 
    * @param context to use to open or create the database 
    * @param name of the database file, or null for an in-memory database 
    * @param factory to use for creating cursor objects, or null for the default 
    * @param version number of the database (starting at 1); if the database is older, 
    *  {@link #onUpgrade} will be used to upgrade the database; if the database is 
    *  newer, {@link #onDowngrade} will be used to downgrade the database 
    * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database 
    * corruption, or null to use the default error handler. 
    */ 
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, 
      DatabaseErrorHandler errorHandler) { 
     if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version); 

     mContext = context; 
     mName = name; 
     mFactory = factory; 
     mNewVersion = version; 
     mErrorHandler = errorHandler; 
    } 

    /** 
    * Return the name of the SQLite database being opened, as given to 
    * the constructor. 
    */ 
    public String getDatabaseName() { 
     return mName; 
    } 

    /** 
    * Enables or disables the use of write-ahead logging for the database. 
    * 
    * Write-ahead logging cannot be used with read-only databases so the value of 
    * this flag is ignored if the database is opened read-only. 
    * 
    * @param enabled True if write-ahead logging should be enabled, false if it 
    * should be disabled. 
    * 
    * @see SQLiteDatabase#enableWriteAheadLogging() 
    */ 
    public void setWriteAheadLoggingEnabled(boolean enabled) { 
     synchronized (this) { 
      if (mEnableWriteAheadLogging != enabled) { 
       if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { 
        if (enabled) { 
         mDatabase.enableWriteAheadLogging(); 
        } else { 
         mDatabase.disableWriteAheadLogging(); 
        } 
       } 
       mEnableWriteAheadLogging = enabled; 
      } 
     } 
    } 

    /** 
     Simplified getWritableDatabase from SDK source 
    */ 
    public SQLiteDatabase getWritableDatabase() { 
     synchronized (this) { 
      return getDatabaseLocked(); 
     } 
    } 

    private SQLiteDatabase getDatabaseLocked() { 
     // always get writable database 
     if (mDatabase != null) { 
      if (!mDatabase.isOpen()) { 
       // Darn! The user closed the database by calling mDatabase.close(). 
       mDatabase = null; 
      } else if (!mDatabase.isReadOnly()) { 
       // The database is already open for business. 
       return mDatabase; 
      } 
     } 

     if (mIsInitializing) { 
      throw new IllegalStateException("getDatabase called recursively"); 
     } 

     SQLiteDatabase db = mDatabase; 
     try { 
      mIsInitializing = true; 

      if (db == null && mName == null) { 
       db = SQLiteDatabase.create(null); 
      } else if (db == null) { 
       try { 
        final String path = mContext.getDatabasePath(mName).getPath(); 
        db = SQLiteDatabase.openDatabase(path, mFactory, 
          (SQLiteDatabase.CREATE_IF_NECESSARY 
          | SQLiteDatabase.OPEN_READWRITE 
          | SQLiteDatabase.NO_LOCALIZED_COLLATORS), 
          mErrorHandler); 
       } catch (SQLiteException ex) { 
        throw ex; 
       } 
      } 

      onConfigure(db); 

      final int version = db.getVersion(); 
      if (version != mNewVersion) { 

       db.beginTransaction(); 
       try { 
        if (version == 0) { 
         onCreate(db); 
        } else { 
         if (version > mNewVersion) { 
          onDowngrade(db, version, mNewVersion); 
         } else { 
          onUpgrade(db, version, mNewVersion); 
         } 
        } 
        db.setVersion(mNewVersion); 
        db.setTransactionSuccessful(); 
       } finally { 
        db.endTransaction(); 
       } 
      } 

      onOpen(db); 

      mDatabase = db; 
      return db; 
     } finally { 
      mIsInitializing = false; 
      if (db != null && db != mDatabase) { 
       db.close(); 
      } 
     } 
    } 

    /** 
    * Close any open database object. 
    */ 
    public synchronized void close() { 
     if (mIsInitializing) throw new IllegalStateException("Closed during initialization"); 

     if (mDatabase != null && mDatabase.isOpen()) { 
      mDatabase.close(); 
      mDatabase = null; 
     } 
    } 

    /** 
    * Called when the database connection is being configured, to enable features 
    * such as write-ahead logging or foreign key support. 
    * <p> 
    * This method is called before {@link #onCreate}, {@link #onUpgrade}, 
    * {@link #onDowngrade}, or {@link #onOpen} are called. It should not modify 
    * the database except to configure the database connection as required. 
    * </p><p> 
    * This method should only call methods that configure the parameters of the 
    * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging} 
    * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, 
    * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize}, 
    * or executing PRAGMA statements. 
    * </p> 
    * 
    * @param db The database. 
    */ 
    public void onConfigure(SQLiteDatabase db) {} 

    /** 
    * Called when the database is created for the first time. This is where the 
    * creation of tables and the initial population of the tables should happen. 
    * 
    * @param db The database. 
    */ 
    public abstract void onCreate(SQLiteDatabase db); 

    /** 
    * Called when the database needs to be upgraded. The implementation 
    * should use this method to drop tables, add tables, or do anything else it 
    * needs to upgrade to the new schema version. 
    * 
    * <p> 
    * The SQLite ALTER TABLE documentation can be found 
    * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns 
    * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns 
    * you can use ALTER TABLE to rename the old table, then create the new table and then 
    * populate the new table with the contents of the old table. 
    * </p><p> 
    * This method executes within a transaction. If an exception is thrown, all changes 
    * will automatically be rolled back. 
    * </p> 
    * 
    * @param db The database. 
    * @param oldVersion The old database version. 
    * @param newVersion The new database version. 
    */ 
    public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); 

    /** 
    * Called when the database needs to be downgraded. This is strictly similar to 
    * {@link #onUpgrade} method, but is called whenever current version is newer 
    * than requested one. 
    * However, this method is not abstract, so it is not mandatory for a customer to 
    * implement it. If not overridden, default implementation will reject downgrade and 
    * throws SQLiteException 
    * 
    * <p> 
    * This method executes within a transaction. If an exception is thrown, all changes 
    * will automatically be rolled back. 
    * </p> 
    * 
    * @param db The database. 
    * @param oldVersion The old database version. 
    * @param newVersion The new database version. 
    */ 
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     throw new SQLiteException("Can't downgrade database from version " 
       + oldVersion + " to " + newVersion); 
    } 

    /** 
    * Called when the database has been opened. The implementation 
    * should check {@link SQLiteDatabase#isReadOnly} before updating the 
    * database. 
    * <p> 
    * This method is called after the database connection has been configured 
    * and after the database schema has been created, upgraded or downgraded as necessary. 
    * If the database connection must be configured in some way before the schema 
    * is created, upgraded, or downgraded, do it in {@link #onConfigure} instead. 
    * </p> 
    * 
    * @param db The database. 
    */ 
    public void onOpen(SQLiteDatabase db) {} 
} 
+0

Great ~ La maggior parte del tempo usiamo 'SQLiteOpenHelper' per creare db. – Autobots

Problemi correlati