如何在Android Studio模拟器上使用SQLite darabase启动应用程序?

时间:2018-06-15 21:10:19

标签: android sqlite android-sqlite

我正在使用Android Studio创建字典App。我试图使用SQlite数据库。

我无法在模拟器上启动它,因为我遇到了2个问题。

  1. 首先,我并没有真正了解如何创建目录,我这样编码.. "mydirectory"显示为红色,我不明白如何修复它
  2. : -

     public DBHelper(Context context) {
     super(context, DATABASE_NAME, null, DATABASE_VERSION);
     mContext = context;
        DATABASE_LOCATION = "data/data/" + mContext.getPackageName() + 
        "/database/";
        DATABASE_FULL_PATH = DATABASE_LOCATION + DATABASE_NAME;
        if (!isExistingfDB()) {
            try {
               File dbLocation = new File (DATABASE_LOCATION);
               dbLocation = mydirectory();
                extractAssetsToDatabaseDirectory(DATABASE_NAME);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_FULL_PATH, null);
    
    }
    
    1. 我尝试从我的SQLitedatabase中查询数据,但它不起作用,此处"SELECT * FROM "行并未显示绿色。
    2. : -

      public ArrayList<String> getWord(int dicType) {
          String tableName = getTableName(dicType);
          String q = "SELECT * FROM " + tableName;
          Cursor result = mDB.rawQuery(q, null);
          ArrayList<String> source = new ArrayList<>();
          while (result.moveToNext()) {
              source.add(result.getString(result.getColumnIndex(COL_KEY)));
          }
          return source;
      }
      

      这是SQLite数据库的结构 i just put it as image

      后续失败

      谢谢,我改变了代码,就像在第8步中一样,因为它看起来并不像它显示的那样,并且在Logcat中没有SQLite错误,除了这个:

      06-16 19:24:15.406 2925-2925/com.example.dimarozkin.diplomdict E/AndroidRuntime: FATAL EXCEPTION: main
      Process: com.example.dimarozkin.diplomdict, PID: 2925
      java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
          at com.example.dimarozkin.diplomdict.MainActivity.onPrepareOptionsMenu(MainActivity.java:194)
          at android.app.Activity.onPreparePanel(Activity.java:3406)
          at android.support.v4.app.FragmentActivity.onPrepareOptionsPanel(FragmentActivity.java:530)
          at android.support.v4.app.FragmentActivity.onPreparePanel(FragmentActivity.java:518)
          at android.support.v7.view.WindowCallbackWrapper.onPreparePanel(WindowCallbackWrapper.java:98)
          at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onPreparePanel(AppCompatDelegateImplBase.java:359)
          at android.support.v7.view.WindowCallbackWrapper.onPreparePanel(WindowCallbackWrapper.java:98)
          at android.support.v7.app.ToolbarActionBar$ToolbarCallbackWrapper.onPreparePanel(ToolbarActionBar.java:521)
          at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:455)
          at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:55)
          at android.os.Handler.handleCallback(Handler.java:790)
          at android.os.Handler.dispatchMessage(Handler.java:99)
          at android.os.Looper.loop(Looper.java:164)
          at android.app.ActivityThread.main(ActivityThread.java:6494)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
      

      据我所知错误在这里

      public boolean onPrepareOptionsMenu(Menu menu) {
          String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
          if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) {
              menuSettings.setVisible(false);
              toolbar.findViewById(R.id.edit_search).setVisibility(View.GONE);
              toolbar.setTitle("Bookmark");
          } else {
              menuSettings.setVisible(true);
              toolbar.findViewById(R.id.edit_search).setVisibility(View.VISIBLE);
              toolbar.setTitle("");
      
          }
          return true;
      }
      

      但我仍然不知道如何解决它......

1 个答案:

答案 0 :(得分:0)

当你遇到困难时,下面是一个匆忙整理的教程和代码。

  1. 在SQLite工具中创建数据库和表,根据需要添加数据,然后保存。

  2. 关闭数据库并重新打开它以检查表和数据是否符合预期。如果没有进行更改,则重复2,直到您确定保存的数据库匹配为止。

  3. 获取已保存数据库的文件名并记录,包括文件扩展名。

  4. 如果您还没有为应用创建项目,请执行此操作并保存项目。

  5. 在IDE外部导航到项目app / src / main文件夹并创建名为 assets 的文件夹(如果它尚不存在)。

  6. 将数据库文件复制到assets文件夹中。

  7. 在Android Studio中打开项目。

  8. 使用SuperClass创建一个名为 DatabaseHelper 的新Java类作为 SQLiteOpenHelper (将解析为android.database.sqlite.SQLiteOpenHelper)并勾选显示选择覆盖对话框复选框。单击确定。

  9. 应该如下: -

    public class DatabaseHelper extends SQLiteOpenHelper {
        public Databasehelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
    
        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
    
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    
        }
    }
    
    1. public class DatabaseHelper extends SQLiteOpenHelper {之后添加一行作为类变量,如下所示: -

      public static final String DBNAME = "my_dic.db";
      
      • 请注意引号中的值与复制到资源文件夹中的文件名完全相同非常重要。
      1. 添加以下类变量
      2. : -

        public static final int DBVERSION = 1;
        public static final String TB_BOOKMARK = "Bookmark";
        public static final String COL_BOOKMARK_KEY = "key";
        public static final String COL_BOOKMARK_VALUE = "value";
        public static final String COL_BOOKMARK_DATE = "date";
        SQLiteDatabase mDB;
        
        • 注意引号中的值需要匹配TB_BOOKMARK,COL_BOOKMARK_KEY,COL_BOOKMARK_VALUE和COl_BOOKMARK_DATE数据库中定义的respetice表/列名称。
          • DBVERSION将是存储在数据库的user_version字段中的版本号。
          • SQliteDatabase mDB是一个变量的声明,用于在SQLiteDatabase打开时保存它。注意当前它的值在设置之前为空。

        1. 从以下位置更改Databasehelper类的构造函数: -

          public DatabaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){     超级(上下文,名称,工厂,版本); }

        2. 来: -

          public DatabaseHelper(Context context) {
              super(context, DBNAME, null, DBVERSION);
          }
          
          • 这样就可以使用一个参数(即上下文)创建Databasehelper类的实例。其他值已定义,或者在出厂时不使用任何值,因此null表示此。

          1. 向DatabaseHelper类添加方法 ifDBExists 以检查数据库是否存在(您只想从资产文件中复制一次)
          2. : -

            private boolean ifDBExists(Context context) {
                String dbparent = context.getDatabasePath(DBNAME).getParent();
                File f = context.getDatabasePath(DBNAME);
                if (!f.exists()) {
                    Log.d("NODB MKDIRS","Database file not found, making directories."); //<<<< remove before the App goes live.
                    File d = new File(dbparent);
                    d.mkdirs();
                    //return false;
                }
                return f.exists();
            }
            
            • 除了检查数据库文件是否存在(注意它被认为是有效的数据库文件),
            • 此外,如果数据库不存在,那么可能是数据库目录不存在,如果它不存在则会创建它。

            1. 添加其他方法 copyDBFromAssets 将资产文件复制到数据库
            2. : -

              private boolean copyDBFromAssets(Context context) {
                  Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
                  String DBPATH = context.getDatabasePath(DBNAME).getPath();
                  InputStream is;
                  OutputStream os;
                  int length = 8192;
                  long bytes_read = 0;
                  long bytes_written = 0;
                  byte[] buffer = new byte[length];
              
                  try {
              
                      is = context.getAssets().open(DBNAME);
                  } catch (IOException e) {
                      Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
                      e.printStackTrace();
                      return false;
                  }
              
                  try {
                      os = new FileOutputStream(DBPATH);
                  } catch (IOException e) {
                      Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
                      e.printStackTrace();
                      return false;
                  }
                  Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
                  while (length >= 8192) {
                      try {
                          length = is.read(buffer,0,length);
                      } catch (IOException e) {
                          Log.e("CPYDB FAIL - RD ASSET",
                                  "Failed while reading in data from the Asset. " +
                                          String.valueOf(bytes_read) +
                                          " bytes read ssuccessfully."
                          );
                          e.printStackTrace();
                          return false;
                      }
                      bytes_read = bytes_read + length;
                      try {
                          os.write(buffer,0,length);
                      } catch (IOException e) {
                          Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                                  DBPATH +
                                  ". " +
                          String.valueOf(bytes_written) +
                                  " bytes written successfully.");
                          e.printStackTrace();
                          return false;
              
                      }
                      bytes_written = bytes_written + length;
                  }
                  Log.d("CPYDBINFO",
                          "Read " + String.valueOf(bytes_read) + " bytes. " +
                                  "Wrote " + String.valueOf(bytes_written) + " bytes."
                  );
                  try {
                      os.flush();
                      is.close();
                      os.close();
                  } catch (IOException e ) {
                      Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                              String.valueOf(bytes_read) +
                              " bytes read." +
                              String.valueOf(bytes_written) +
                              " bytes written."
                      );
                      e.printStackTrace();
                      return false;
                  }
                  return true;
              }
              
              • 请注意,这是故意啰嗦,因此任何失败都可能是针对性的。

              完整的DatabaseHelper类现在是: -

              public class DatabaseHelper extends SQLiteOpenHelper {
              
                  public static final String DBNAME = "my_dic.db"; // <<<< VERY IMPORTANT THAT THIS MATCHES DATABASE FILE NAME
                  public static final int DBVERSION = 1;
                  public static final String TB_BOOKMARK = "Bookmark";
                  public static final String COL_BOOKMARK_KEY = "key";
                  public static final String COL_BOOKMARK_VALUE = "value";
                  public static final String COL_BOOKMARK_DATE = "date";
                  SQLiteDatabase mDB;
              
                  public DatabaseHelper(Context context) {
                      super(context, DBNAME, null, DBVERSION);
                      if (!ifDBExists(context)) {
                          if (!copyDBFromAssets(context)) {
                              throw new RuntimeException("Failed to Copy Database From Assets Folder");
                          }
                      }
                      mDB = this.getWritableDatabase();
                  }
              
                  @Override
                  public void onCreate(SQLiteDatabase sqLiteDatabase) {
              
                  }
              
                  @Override
                  public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
                  }
              
                  private boolean ifDBExists(Context context) {
                      String dbparent = context.getDatabasePath(DBNAME).getParent();
                      File f = context.getDatabasePath(DBNAME);
                      if (!f.exists()) {
                          Log.d("NODB MKDIRS","Database file not found, making directories.");
                          File d = new File(dbparent);
                          d.mkdirs();
                          //return false;
                      }
                      return f.exists();
                  }
              
                  private boolean copyDBFromAssets(Context context) {
                      Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
                      String DBPATH = context.getDatabasePath(DBNAME).getPath();
                      InputStream is;
                      OutputStream os;
                      int length = 8192;
                      long bytes_read = 0;
                      long bytes_written = 0;
                      byte[] buffer = new byte[length];
              
                      try {
              
                          is = context.getAssets().open(DBNAME);
                      } catch (IOException e) {
                          Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
                          e.printStackTrace();
                          return false;
                      }
              
                      try {
                          os = new FileOutputStream(DBPATH);
                      } catch (IOException e) {
                          Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
                          e.printStackTrace();
                          return false;
                      }
                      Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
                      while (length >= 8192) {
                          try {
                              length = is.read(buffer,0,length);
                          } catch (IOException e) {
                              Log.e("CPYDB FAIL - RD ASSET",
                                      "Failed while reading in data from the Asset. " +
                                              String.valueOf(bytes_read) +
                                              " bytes read ssuccessfully."
                              );
                              e.printStackTrace();
                              return false;
                          }
                          bytes_read = bytes_read + length;
                          try {
                              os.write(buffer,0,length);
                          } catch (IOException e) {
                              Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                                      DBPATH +
                                      ". " +
                              String.valueOf(bytes_written) +
                                      " bytes written successfully.");
                              e.printStackTrace();
                              return false;
              
                          }
                          bytes_written = bytes_written + length;
                      }
                      Log.d("CPYDBINFO",
                              "Read " + String.valueOf(bytes_read) + " bytes. " +
                                      "Wrote " + String.valueOf(bytes_written) + " bytes."
                      );
                      try {
                          os.flush();
                          is.close();
                          os.close();
                      } catch (IOException e ) {
                          Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                                  String.valueOf(bytes_read) +
                                  " bytes read." +
                                  String.valueOf(bytes_written) +
                                  " bytes written."
                          );
                          e.printStackTrace();
                          return false;
                      }
                      return true;
                  }
              }
              

              1. 如果数据库不存在(使用 copyDBFromAssets 方法),则更改构造函数以运行 ifDBExists 方法
              2. : -

                public DatabaseHelper(Context context) {
                    super(context, DBNAME, null, DBVERSION);
                    if (!ifDBExists(context)) {
                        if (!copyDBFromAssets(context)) {
                            throw new RuntimeException("Failed to Copy Database From Assets Folder");
                        }
                    }
                    mDB = this.getWritableDatabase();
                }
                
                • 请注意,如果复制数据库时出现问题,则应用程序将因RunTimeExcpetion已发布而停止。

                1. 最后修改一个活动的onCreate方法(通常是主要活动)来创建DatabaseHelper类的实例。然后运行App(如果App已经运行,最好在这样做之前删除App的数据,以防万一创建了一个数据库,可能是空的。)
                2. 以下代码还包含一个查询,告诉您数据库中存在哪些表: -

                  public class MainActivity extends AppCompatActivity {
                  
                      @Override
                      protected void onCreate(Bundle savedInstanceState) {
                          super.onCreate(savedInstanceState);
                          setContentView(R.layout.activity_main);
                          DatabaseHelper mDBHlpr = new DatabaseHelper(this);
                          Cursor csr = mDBHlpr.getWritableDatabase().query(
                                  "sqlite_master",
                                  null,null,null,null,null,null
                          );
                          while (csr.moveToNext()) {
                              Log.d("DB TABLES", csr.getString(csr.getColumnIndex("name")));
                          }
                          csr.close();
                      }
                  }
                  

                  基于屏幕截图和名为 my_dic.db 的数据库文件。日志中的输出是: -

                  06-16 02:28:45.208 4467-4467/? D/NODB MKDIRS: Database file not found, making directories.
                  06-16 02:28:45.208 4467-4467/? D/CPYDBINFO: Starting attemtpt to cop database from the assets file.
                      Initiating copy from asset filemy_dic.db to /data/data/com.mydictionaryapp.mydictionaryapp/databases/my_dic.db
                      Read 12288 bytes. Wrote 12288 bytes.
                  06-16 02:28:45.224 4467-4467/? D/DB TABLES: Bookmark
                      sqlite_autoindex_Bookmark_1
                      android_metadata
                  
                  • 这表明: -
                    • 数据库不存在且数据库目录已创建(即data/data/<package name>/databases
                    • 12288字节从资产文件复制到数据库文件(即成功复制)。
                    • 结果数据库在sqlite_master表中有三个条目,BookMark表,一个名为android_metadata的表(一个表由SDK存储区域设置自动为Android设备创建)和一个自动生成的BookMark表索引。

                  后续问题

                  基本上,对象没有一个名为getClass的方法,而是需要使用Fragment的继承getClass方法。因此,您需要将返回的片段括在括号中。

                  所以而不是: -

                  String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
                  

                  您可以使用: -

                  String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();
                  

                  或者你可以使用: -

                  Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
                  

                  以及使用: -

                  if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code
                  

                  而不是使用if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......