昨天項目剛發版,測試的時候一切正常,模擬線上更新測試的時候,在模擬下載完新包後安裝,出現了閃退現象,當時就嚇尿了!。。。java
進過一番排查,發現是找不到province表(在新版本開發過程當中在數據庫手動建立並添加了信息的一個表),可是我明明有把新的數據拷貝進項目,非常奇怪。android
先整理下思路:sql
首先在Application中執行靜態代碼塊,在oncreate()中執行數據庫
//初始化數據庫 CarDatabaseHelper.initDatabase(getApplicationContext()); ExtendsDataBase.initPhoneDb(this); // 若是當前的版本號>1,刪除舊的的車型庫 if (Utils.getCurrentVersion(getApplicationContext()) > 1) { ExtendsDataBase.deleteOldDB(getApplication()); }
1.0版本後,每次版本更新都會進行數據庫的刪除和從新寫入操做,具體代碼以下測試
package cn.car273.db; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import cn.car273.R; /** * 內置數據庫操做文件 * * @author ... * */ public class ExtendsDataBase { public final static String DATABASE_NAME_OLD = "car273_db.db"; private final static String DATABASE_NAME_NEW = "car273_new.db"; private static ExtendsDataBase _instance; private static Context context; private static SQLiteDatabase mDb; private static String getDBDir() { return context.getFilesDir().getAbsolutePath() + File.separator; //return Utils.getCacheDir(context).getAbsolutePath() + File.separator; } private static String getDBPath() { String path = getDBDir() + DATABASE_NAME_NEW; return path; } /** * 刪除舊的車型庫 */ public static void deleteOldDB(Context ctx){ if(context == null){ context = ctx; } File oldDb = new File(getDBDir() + DATABASE_NAME_OLD); if (!oldDb.exists()) { return; } File dirDir = new File(getDBDir()); File[] files = dirDir.listFiles(); for(File f : files){ if (f.getName().contains(DATABASE_NAME_OLD)) { f.delete(); } } } private static void createPhoneDB() { File dirFile = new File(getDBPath()); if (dirFile.exists()) { return; } File dirDir = new File(getDBDir()); if (!dirDir.exists()) { dirDir.mkdirs(); } try { InputStream in = ExtendsDataBase.context.getResources().openRawResource(R.raw.car273_db); File myCaptureFile = new File(getDBPath()); writeToFile(in, myCaptureFile); } catch (Exception e) { e.printStackTrace(); } } private static void writeToFile(InputStream ins, File file) throws Exception { OutputStream os = new FileOutputStream(file); int bytesRead = 0; byte[] buffer = new byte[8192]; while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); } private ExtendsDataBase() { mDb = SQLiteDatabase.openOrCreateDatabase(getDBPath(), null); } public static ExtendsDataBase getInstance() { if (_instance == null) { _instance = new ExtendsDataBase(); } return _instance; } public static void initPhoneDb(Context context) { ExtendsDataBase.context = context; ExtendsDataBase.createPhoneDB(); } public static void close() { if (ExtendsDataBase.mDb != null && ExtendsDataBase.mDb.isOpen()) { ExtendsDataBase.mDb.close(); } } public SQLiteDatabase getExtendsDB() { return mDb; } }
首先initPhoneDb()建立數據庫,若是car273_new數據庫(car273_db的複製數據庫)不存在,則將數據庫文件寫進輸入流,再刪除car273_db,再讀出輸出流獲得新的car273_new數據庫;若是存在則直接return,不作任何處理。問題就出在了這裏!this
在升級的前,car273_new和car273_db都是存在的,那就會直接return掉,而不會去執行覆蓋操做,因此,須要把紅色代碼替換成dirFile.delete();即:有須要更新數據庫的,直接把舊版本的car273_new刪掉,再次複製就能夠決絕此問題。spa