如何在Android Studio模拟器上启动带有SQLite数据库的APP? [英] how to launch app with SQLite darabase on Android Studio emulator?

查看:0
本文介绍了如何在Android Studio模拟器上启动带有SQLite数据库的APP?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Android Studio创建一个词典应用程序。我正在尝试使用SQLite数据库。

我无法在模拟器上启动它,因为我有两个问题。

  1. 首先,我真的不知道如何创建目录,我是这样编写的.."mydirectory"显示为红色,我不知道如何修复它

:-

 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. 我尝试从我的SQLite数据库中查询数据,但它不起作用,这里的"SELECT * FROM "行没有显示应有的绿色。

:-

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. 在SQLite工具中创建数据库和表,根据需要添加数据,然后保存。

  2. 关闭数据库,然后重新打开以检查表和数据是否符合预期。如果不匹配,请进行更改,然后重复%2,直到您确定保存的数据库匹配。

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

  4. 如果您尚未为应用程序创建项目,请执行此操作并保存该项目。

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

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

  7. 在Android Studio中打开项目。

  8. 新建一个名为DatabaseHelper的Java类,超类为SQLiteOpenHelper(将解析为android.database.sqlite.SQLiteOpenHelper),并选中显示选择覆盖对话框复选框。然后单击确定。

    /li>

它应该如下所示:-

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";
    
    • 请注意,引号内的值必须与复制到Assets文件夹中的文件名完全相同。

  1. 添加以下类变量

:-

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定义的表名/列名匹配。
    • DBVERSION将是存储在数据库的USER_VERSION字段中的版本号。
    • SQliteDatabase MDB是变量的声明,用于在打开SQLiteDatabase时保存它。注意:在设置它之前,它的值当前为空。

  1. 将Databasehelper类的构造函数从:-

    公共数据库帮助程序(上下文上下文,字符串名称,SQLiteDatabase.CursorFactory Factory,int版本){ SUPER(上下文、名称、工厂、版本); )

收件人:-

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

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

:-

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将资产文件复制到数据库

:-

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方法)

:-

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类的实例。然后运行该应用程序(如果该应用程序已经运行,最好在执行此操作之前删除该应用程序的数据,以防创建了一个可能为空的数据库。)

以下代码还包括一个查询,该查询将告诉您数据库中存在哪些表:-

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表、书签表、名为Android_METADATA的表(由存储区域设置的SDK为Android设备自动创建的表)和自动生成的书签表索引。

后续问题

该对象基本上没有一个名为getClass的方法,而是需要使用片段继承的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())) { ......

这篇关于如何在Android Studio模拟器上启动带有SQLite数据库的APP?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆