【问题标题】:Copy Database from assets when there is a new database version有新数据库版本时从资产中复制数据库
【发布时间】:2012-11-15 14:25:34
【问题描述】:

我正在尝试解决以下问题。我有一个使用预先创建的数据库的应用程序。我将此数据库放在资产文件夹中。然后我在内部复制数据库。

我希望能够检查我的数据库的版本,因此当有新版本时,我会删除旧数据库并从 assets 文件夹中复制新数据库。我将数据库版本存储为共享偏好数据。

运行以下代码时出现错误,应用程序停止运行(意外停止)。 你能帮我找出问题所在吗?

   public class DatabaseConnector
     {
// database name
   private static final String DATABASE_NAME = "Recipes";
   private SQLiteDatabase database; // database object
   private DatabaseOpenHelper databaseOpenHelper; // database helper

   String selection;       

   // public constructor for DatabaseConnector
   public DatabaseConnector(Context context) 
   {
      // create a new DatabaseOpenHelper
      databaseOpenHelper = 
         new DatabaseOpenHelper(context, DATABASE_NAME, null, 1);
   } // end DatabaseConnector constructor

   // open the database connection
   // attempts to establish a connection to the db
   // and throws an exception if it fails
   public void open() throws SQLException 
   {
      // create or open a database for reading/writing
      database = databaseOpenHelper.getWritableDatabase();
   } // end method open

   // close the database connection
   public void close() 
   {
      if (database != null)
         database.close(); // close the database connection
   } // end method close

   // inserts a new esoda in the database
   public void insertEsoda(String title, String category, String ingredients, String process, 
      String notes, String image, String time, String calories, String difficulty) 
   {
....
   } // end method insertEsoda

   // updates a esoda in the database
   public void updateEsoda(long id, String title, String category, String ingredients, 
      String process, String notes, String image, String time, String calories, String difficulty) 
   {
      ....
   } // end method updateEsoda


// updates favorites in the database
   public Boolean updateFavorite(long id) 
   {
....
   } // end method update favorites


   // return a Cursor with all esoda information in the database
   public Cursor getAllEsoda() 
   {
     ....
   } // end method getAllEsoda


   // return a Cursor with all esoda information in the database
   public Cursor getRecipeCategory(int position) 
   {
      ....
   } // end method getAllEsoda


   // get a Cursor containing all information about the esoda specified
   // by the given id
   public Cursor getOneEsoda(long id) 
   {
     ....
   } // end method getOneEsoda


   // delete the contact specified by the given String name
   public void deleteEsoda(long id) 
   {
     ....
   } // end method deleteEsoda


   private class DatabaseOpenHelper extends SQLiteOpenHelper {
       public Context mContext;
       private static final int DATABASE_VERSION = 1;
       private static final String SP_KEY_DB_VER = "db_ver";

      // public constructor
      public DatabaseOpenHelper(Context context, String title,
         CursorFactory factory, int version) 
      {
         super(context, title, factory, version);
         mContext=context;
         initialize();
      } // end DatabaseOpenHelper constructor

      private void initialize() {

          if (databaseExists()) {
              SharedPreferences prefs = PreferenceManager
                      .getDefaultSharedPreferences(mContext);
              int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
              if (DATABASE_VERSION != dbVersion) {
                  File dbFile = mContext.getDatabasePath(DATABASE_NAME);
                  if (!dbFile.delete()) {
                      Log.w("TAG", "Unable to update database");
                  }
              }
          }
          if (!databaseExists()) {
              createDatabase();
          }
      }

      private boolean databaseExists() {
          File dbFile = mContext.getDatabasePath(DATABASE_NAME);
          return dbFile.exists();
      }

      private void createDatabase() {
          String parentPath = mContext.getDatabasePath(DATABASE_NAME).getParent();
          String path = mContext.getDatabasePath(DATABASE_NAME).getPath();

          File file = new File(parentPath);
          if (!file.exists()) {
              if (!file.mkdir()) {
                  Log.w("TAG", "Unable to create database directory");
                  return;
              }
          }

          InputStream is = null;
          OutputStream os = null;
          try {
              is = mContext.getAssets().open(DATABASE_NAME);
              os = new FileOutputStream(path);

              byte[] buffer = new byte[1024];
              int length;
              while ((length = is.read(buffer)) > 0) {
                  os.write(buffer, 0, length);
              }
              os.flush();
              SharedPreferences prefs = PreferenceManager
                      .getDefaultSharedPreferences(mContext);
              SharedPreferences.Editor editor = prefs.edit();
              editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
              editor.commit();
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              if (is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if (os != null) {
                  try {
                      os.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }



      // creates the contacts table when the database is created
      @Override
      public void onCreate(SQLiteDatabase db) 
      {
         // query to create a new table named contacts
         String createQuery = "CREATE TABLE recipes" +
            "(_id integer primary key autoincrement," +
            "title TEXT, category TEXT, ingredients TEXT, process TEXT, notes TEXT, image TEXT, " +
            "time TEXT, calories TEXT, difficulty TEXT);";

         db.execSQL(createQuery); // execute the query
      } // end method onCreate

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, 
          int newVersion) 
      {
      } // end method onUpgrade
   } // end class DatabaseOpenHelper
}

这是我的 LogCat 文本:

11-27 23:19:41.643: D/AndroidRuntime(297): Shutting down VM
11-27 23:19:41.643: W/dalvikvm(297): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
11-27 23:19:41.673: E/AndroidRuntime(297): FATAL EXCEPTION: main
11-27 23:19:41.673: E/AndroidRuntime(297): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{development.nk.cretanrecipes/development.nk.cretanrecipes.RecipesMainActivity}: java.lang.NullPointerException
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2585)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.os.Looper.loop(Looper.java:123)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread.main(ActivityThread.java:4627)
11-27 23:19:41.673: E/AndroidRuntime(297):  at java.lang.reflect.Method.invokeNative(Native Method)
11-27 23:19:41.673: E/AndroidRuntime(297):  at java.lang.reflect.Method.invoke(Method.java:521)
11-27 23:19:41.673: E/AndroidRuntime(297):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-27 23:19:41.673: E/AndroidRuntime(297):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-27 23:19:41.673: E/AndroidRuntime(297):  at dalvik.system.NativeStart.main(Native Method)
11-27 23:19:41.673: E/AndroidRuntime(297): Caused by: java.lang.NullPointerException
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.content.ContextWrapper.getResources(ContextWrapper.java:80)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.widget.Toast.<init>(Toast.java:89)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.widget.Toast.makeText(Toast.java:231)
11-27 23:19:41.673: E/AndroidRuntime(297):  at development.nk.cretanrecipes.DatabaseConnector$DatabaseOpenHelper.initialize(DatabaseConnector.java:191)
11-27 23:19:41.673: E/AndroidRuntime(297):  at development.nk.cretanrecipes.DatabaseConnector$DatabaseOpenHelper.<init>(DatabaseConnector.java:186)
11-27 23:19:41.673: E/AndroidRuntime(297):  at development.nk.cretanrecipes.DatabaseConnector.<init>(DatabaseConnector.java:35)
11-27 23:19:41.673: E/AndroidRuntime(297):  at development.nk.cretanrecipes.RecipesMainActivity.<init>(RecipesMainActivity.java:32)
11-27 23:19:41.673: E/AndroidRuntime(297):  at java.lang.Class.newInstanceImpl(Native Method)
11-27 23:19:41.673: E/AndroidRuntime(297):  at java.lang.Class.newInstance(Class.java:1429)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
11-27 23:19:41.673: E/AndroidRuntime(297):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2577)
11-27 23:19:41.673: E/AndroidRuntime(297):  ... 11 more

【问题讨论】:

  • 您需要包含来自 logcat 输出的错误。

标签: android database android-assets


【解决方案1】:

stacktrace 中的错误似乎与 toast 相关,但您粘贴的代码中并未出现该错误。

但是,这个库 sqllite asset helper 似乎解决了您要解决的完全相同的问题。

“使用应用程序的原始资产文件管理数据库创建和版本管理的 Android 帮助程序类。”

希望对你有帮助

【讨论】:

  • 感谢您的回答。没有与吐司有关的问题。我会研究图书馆..
  • 根据您发布的 logcat:11-27 23:19:41.673: E/AndroidRuntime(297): Caused by: java.lang.NullPointerException 11-27 23:19:41.673: E/ AndroidRuntime(297): 在 android.content.ContextWrapper.getResources(ContextWrapper.java:80) 11-27 23:19:41.673: E/AndroidRuntime(297): 在 android.widget.Toast.(Toast.java :89) 11-27 23:19:41.673: E/AndroidRuntime(297): 在 android.widget.Toast.makeText(Toast.java:231)
  • 我删除了所有的祝酒词,但问题仍然存在。我认为这与上下文有关......
  • 您是否在活动构造函数中使用上下文而不是在其 onCreate 方法中?这可能是问题所在(我很确定是这样)。
  • 这是因为您在 RecipesMainActivity 构造函数中调用 DatabaseConnector 而不是 onCreate:11-27 23:19:41.673: E/AndroidRuntime(297): at development.nk.cretanrecipes.DatabaseConnector.(DatabaseConnector.java:35) 11-27 23:19:41.673: E/AndroidRuntime(297): 在 development.nk.cretanrecipes.RecipesMainActivity.(RecipesMainActivity.java:32)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 2013-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多