2012-12-09 38 views
9

我有一个应用程序使用sqlite数据库,首先安装我检查数据库文件夹和db文件是否存在如果没有调用updateDB函数。但有些情况下,例如在银河注10.1它给了我错误。Android Sqlite单例数据库文件流更新失败

on load;

this.dhn = DataHelper.getDataHelper(this); 

    File directory = new File(Environment.getDataDirectory() + File.separator + "data" + File.separator + "XXX" + File.separator + "databases"); 
    if(!directory.exists()) 
    { 
     directory.mkdirs(); 
     updateDB(); 
    } 

    try { 
     androidCheckout = this.dhn.Guid(); 

     if(this.dhn.getSettings("dbVersion") == null || Integer.parseInt(this.dhn.getSettings("dbVersion")) != Version || !this.dhn.isTableExists("UserInfo")) 
     { 
      updateDB(); 
     } 
    } 
    catch (SQLiteException e) 
    {    
    try { 
      updateDB(); 
      androidCheckout = this.dhn.Guid(); 
     } 
    catch (SQLiteException e11) 
     { 
      ManuelYukle(); 
     } 

    } 



    public void updateDB() 
    { 
     this.dhn.close(); 

     try { 
      InputStream myInput; 

       myInput = getAssets().open("XXX.db"); 

      // Path to the just created empty db 
      String outFileName = "/data/data/XXX/databases/" 
        + "XXX.db"; 

      // Open the empty db as the output stream 
      FileOutputStream myOutput = new FileOutputStream(outFileName); 

      // transfer bytes from the inputfile to the outputfile 
      byte[] buffer = new byte[1024]; 
      int length; 
      while ((length = myInput.read(buffer)) > 0) { 
       myOutput.write(buffer, 0, length); 
      } 

      myOutput.flush(); 
      myOutput.close(); 
      myInput.close(); 
      buffer = null; 
      outFileName = null; 
      this.dhn.close(); 
      this.dhn = null; 
      this.dhn = DataHelper.getDataHelper(this); <<<<<<<< HERE IT CRUSHS 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 

DBHELPER CLASS>

private static DataHelper singleton; 

    public static DataHelper getDataHelper(Context context) { 
      if (singleton == null) { 
        singleton = new DataHelper(context); 
        OpenHelper openHelper = new OpenHelper(singleton.context); 
        singleton.db = openHelper.getWritableDatabase(); 
      } 
      if(!singleton.db.isOpen()){ 
        OpenHelper openHelper = new OpenHelper(singleton.context); 
        singleton.db = openHelper.getWritableDatabase(); 
      } 
      singleton.context = context; 
      return singleton; 
    } 

    private DataHelper(Context context) { 
     this.context = context; 
} 

错误日志文件>

12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database corruption at line 48171 of [ed759d5a9e], db=/data/data/XXX/databases/XXX_db 
12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database disk image is malformed, db=/data/data/XXX/databases/XXX_db 
12-09 19:11:15.772: E/SqliteDatabaseCpp(6271): sqlite3_exec - Failed to set synchronous mode = 1(Normal) 
12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database corruption at line 48171 of [ed759d5a9e], db=/data/data/XXX/databases/XXX_db 
12-09 19:11:15.772: I/SqliteDatabaseCpp(6271): sqlite returned: error code = 11, msg = database disk image is malformed, db=/data/data/XXX/databases/XXX_db 
12-09 19:11:15.772: E/SqliteDatabaseCpp(6271): CREATE TABLE android_metadata failed 
12-09 19:11:15.777: E/DefaultDatabaseErrorHandler(6271): Corruption reported by sqlite on database: /data/data/XXX/databases/XXX.db 
12-09 19:11:15.782: E/DefaultDatabaseErrorHandler(6271): deleting the database file: /data/data/XXX/databases/XXX.db 
+0

嗨Mert,在这里与星系笔记10.1一样的问题。得到的解决方案! – 2013-05-02 09:47:42

+0

这可能是一个权限问题吗?你可以写入(和读取)任何'XXX'目录? – Tigger

回答

3

我面临同样的问题database disk image is malformed当我试图访问数据库,当它被更新本身。所以,我遵循下面的方式。

  1. DataBaseHelper

    import java.io.File; 
    import java.io.FileOutputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import android.content.Context; 
    import android.database.SQLException; 
    import android.database.sqlite.SQLiteDatabase; 
    import android.database.sqlite.SQLiteException; 
    import android.database.sqlite.SQLiteOpenHelper; 
    import android.util.Log; 
    
    public class DataBaseHelper extends SQLiteOpenHelper { 
    
         private static final String TAG = DataBaseHelper.class.getSimpleName(); 
         private static String DB_PATH = "/data/data/YOUR_PACKAGE/databases/"; 
         private static String DB_NAME = "XXX"; 
         private SQLiteDatabase mDataBase; 
         private final Context mContext; 
    
         public DataBaseHelper(Context context) { 
          super(context, DB_NAME, null, 1); 
          DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; 
          this.mContext = context; 
         } 
    
         public void createDataBase() throws IOException { 
          boolean mDataBaseExist = checkDataBase(); 
          if (!mDataBaseExist) { 
           this.getReadableDatabase(); 
           try { 
            copyDataBase(); 
           } catch (IOException mIOException) { 
            throw new Error("ErrorCopyingDataBase"); 
           } 
          } 
         } 
    
        private boolean checkDataBase() { 
         SQLiteDatabase mCheckDataBase = null; 
         try { 
          String mPath = DB_PATH + DB_NAME; 
          File pathFile = new File(mPath); 
          if(pathFile.exists()) { 
           mCheckDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
          } 
         } catch (SQLiteException mSQLiteException) { 
          Log.e(TAG, "DatabaseNotFound " + mSQLiteException.toString()); 
         } 
    
         if (mCheckDataBase != null) { 
          mCheckDataBase.close(); 
         } 
         return mCheckDataBase != null; 
        } 
    
        private void copyDataBase() throws IOException { 
         final InputStream mInput = mContext.getAssets().open(DB_NAME); 
         final String outFileName = DB_PATH + DB_NAME; 
         OutputStream mOutput = new FileOutputStream(outFileName); 
         byte[] mBuffer = new byte[1024]; 
         int mLength; 
         while ((mLength = mInput.read(mBuffer)) > 0) { 
          mOutput.write(mBuffer, 0, mLength); 
         } 
         mOutput.flush(); 
         mOutput.close(); 
         mInput.close(); 
        } 
    
        public boolean openDataBase() throws SQLException { 
         final String mPath = DB_PATH + DB_NAME; 
         mDataBase = SQLiteDatabase.openDatabase(mPath, null, 
         SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
         return mDataBase != null; 
        } 
    
        @Override 
        public synchronized void close() { 
         if (mDataBase != null) 
          mDataBase.close(); 
         super.close(); 
        } 
    
        @Override 
        public void onCreate(SQLiteDatabase db) {} 
    
        @Override 
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} 
    } 
    
  2. DBAdapter

    public class DBAdapter { 
    
        private static final String TAG = DBAdapter.class.getSimpleName(); 
        private final Context mContext; 
        private SQLiteDatabase mDb; 
        private final DataBaseHelper mDbHelper; 
    
        public DBAdapter(Context context) { 
         this.mContext = context; 
         mDbHelper = new DataBaseHelper(mContext); 
        } 
    
        public DBAdapter createDatabase() throws SQLException { 
         try { 
          mDbHelper.createDataBase(); 
         } catch (IOException mIOException) { 
          throw new Error("UnableToCreateDatabase"); 
         } 
         return this; 
        } 
    
        public DBAdapter open() throws SQLException { 
         try { 
          mDbHelper.openDataBase(); 
          mDbHelper.close(); 
          mDb = mDbHelper.getReadableDatabase(); 
         } catch (SQLException mSQLException) { 
          Log.e(TAG, mSQLException.toString()); 
          throw mSQLException; 
         } 
         return this; 
        } 
    
        public void close() { 
         mDbHelper.close(); 
        } 
    } 
    
  3. Abhan扩展应用类

    public class Abhan extends Application { 
    
        public static final String TAG = Abhan.class.getSimpleName(); 
        public static final boolean DEBUG = true; 
        private int androidVersion = 4; 
        private DBAdapter dbAdapter = null; 
    
        @Override 
        public void onCreate() { 
         super.onCreate(); 
         setAndroidVersion(android.os.Build.VERSION.SDK_INT); 
    
         if(dbAdapter == null) { 
          dbAdapter = new DBAdapter(getBaseContext()); 
          dbAdapter.createDatabase(); 
         } 
        } 
    
        public int getAndroidVersion() { 
         return androidVersion; 
        } 
    
        public void setAndroidVersion(int androidVersion) { 
         this.androidVersion = androidVersion; 
        } 
    
        public DBAdapter getDBInstatnce() { 
         dbAdapter.open(); 
         return dbAdapter; 
        } 
    
        public void closeDataBase() { 
         dbAdapter.close(); 
         if(DEBUG) { 
          android.util.Log.d(TAG, "DataBase closed."); 
         } 
        } 
    } 
    
  4. 在你AndroidManifest,声明Abhan

    <application 
        android:name=".Abhan" 
        android:allowBackup="false" 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" 
        android:theme="@style/AppTheme" > 
    
  5. 在你Activity,使用访问您的数据库Application

    private Abhan abhan; 
    

onCreate

abhan = (Abhan) this.getApplication(); 

现在访问数据库事务方法就像这样。

int currentDay = abhan.getDBInstatnce().getCurrentDay(); 

这里,abhan.getDBInstatnce()返回您Database实例,它是在你的整个应用程序实例,并getCurrentDay()是我的方法,在DBAdpater宣布它返回我当前的一天。

我希望这个人能解决你的问题。谢谢。

1

我在使用预填充数据库时遇到了类似的问题。我就是这样解决的。

问题出在sqlite数据库中,我认为这是sqlite3旧版本中的bug,也许是3.6之前的版本。我做的是,我用sqlite3 v3.7.11重新创建了数据库,它的工作原理就像一个魅力 - 并且,不要忘记创建android_metadata table

它对我有效,那么我希望这会对您有所帮助。