简体   繁体   English

Android SQLite,onCreate()未被调用

[英]Android SQLite, onCreate() not being called

I've been struggling to create a SQLite DB within my Android application. 我一直在努力在我的Android应用程序中创建一个SQLite数据库。 I've looked at numerous tutorials, and quite a few existing questions on stack overflow and other sites. 我看了很多教程,还有很多关于堆栈溢出和其他站点的问题。

Here is my DatabaseHelper class 这是我的DatabaseHelper类

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseHelper extends SQLiteOpenHelper {

public SQLiteDatabase db;
public static final String DATABASE_NAME = "user.db";

//Module table
public static final String MODULE_TABLE = "modules_table";
public static final String MODULE_COL_1 = "ID";
public static final String MODULE_COL_2 = "CODE";
public static final String MODULE_COL_3 = "TITLE";

public DatabaseHelper(Context context) {
    super(context, DATABASE_NAME, null, 1);
    Log.d("SQL", "SQLite dbhelper");
    db = getWritableDatabase();
}

@Override
public void onCreate(SQLiteDatabase db) {
    //db.execSQL("create table " + MODULE_TABLE + "(" + MODULE_COL_1 + " INTEGER PRIMARY KEY AUTOINCREMENT, " + MODULE_COL_2 + " TEXT, " + MODULE_COL_3 + " TEXT " +")");
    db.execSQL("create table modules_table (ID INTEGER PRIMARY KEY 
AUTOINCREMENT, CODE TEXT, TITLE TEXT)");
    Log.d("SQL", "SQLite onCreate");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + MODULE_TABLE);
    onCreate(db);
}
}

I've managed to get SQLite dbhelper to appear in logcat, but cannot get SQLite onCreate to appear, and cannot find the db anywhere in the file explorer or the device itself, both emulated and real device. 我已经设法让SQLite dbhelper出现在logcat中,但是无法让SQLite onCreate出现,并且无法在文件资源管理器或设备本身的任何地方找到数据库,无论是模拟设备还是真实设备。

Any help would be greatly appreciated, and apologies for the formatting of the code! 任何帮助将不胜感激,并为代码的格式化道歉!

I'd suggest using the following ( temporarily ) in the activity :- 我建议在活动中使用以下( 暂时 ): -

DatabaseHelper myDBHelper = new DatabaseHelper(this); //<<<<<<<<< you appear to already have the equivalent of this line (if so use whatever variable name you have given to the DatabaseHelper object)

Cursor csr = myDBHelper.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
DatabaseUtils.dumpCursor(csr);
csr.close();

Run and then check the log. 运行,然后检查日志。 You should see output for your modules_table and also sqlite_sequence (the latter because you have coded autoincrement. 您应该看到modules_tablesqlite_sequence的输出(后者因为您已编码自动增量。

sqlite_master is a system table that stores system information, such as table and index names ie the schema. sqlite_master是一个存储系统信息的系统表,例如表和索引名称,即模式。

Additional - access to the database file 附加 - 访问数据库文件

On a device that isn't rooted each applications data (data/data) is protected so you won't be able to see the database file. 在未植根的设备上,每个应用程序数据(数据/数据)都受到保护,因此您将无法看到数据库文件。

On an emulator, it depends upon the emulator. 在模拟器上,它取决于模拟器。 I believe later versions of Android studio do now allow access eg :- 我相信Android工作室的更高版本现在允许访问,例如: -

在此输入图像描述

  • Note the above is Android 10.1 Pie (API 28) and hence the database has Write-Ahead Logging (WAL) and thus the -shm and -wal files also exist. 请注意,上面是Android 10.1 Pie(API 28),因此数据库具有预写日志记录(WAL),因此-shm和-wal文件也存在。

  • The package is mjt.pvcheck. 包是mjt.pvcheck。 The full path is data/data/mjt.pvcheck/databases. 完整路径是data / data / mjt.pvcheck / databases。

    • As you can see cache directory, then I'd suggest that for some reason, perhaps a failure, the database doesn't exist, but you do appear to have access as per however upon checking through the virtual device file explorer the only sub folder I have within my package is the cache . 正如你可以看到缓存目录,那么我建议由于某种原因,也许是失败,数据库不存在,但是你确实看起来有权访问虚拟设备文件资源管理器中唯一的子文件夹我的包里面有缓存
    • Perhaps, try rerunning on the device (note in device explorer re-select the device as it doesn't refresh), which may be another reason why you didn't see the database. 也许,尝试在设备上重新运行(注意设备浏览器重新选择设备,因为它不刷新),这可能是您没有看到数据库的另一个原因。

I don't use SQL query like 我不喜欢使用SQL查询

db.execSQL("create table modules_table (ID INTEGER PRIMARY KEY 
AUTOINCREMENT, CODE TEXT, TITLE TEXT)");
    Log.d("SQL", "SQLite onCreate");

instead, I'm using my own implementation of SQLiteOpenHelper class 相反,我正在使用我自己的SQLiteOpenHelper类实现

import android.content.Context;
import android.content.res.AssetManager;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.zip.GZIPOutputStream;

public class DbProvider extends SQLiteOpenHelper {

    private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock(true);
    private static final int VERSION = 0;
    private final String DB_NAME = "mydb";

    private final AssetManager assets;

    private DbProvider(Context context) {
        super(context, DB_NAME, null, VERSION);
        assets = context.getAssets();
    }

    @NonNull
    public static DbProvider getInstance() {
        return new DbProvider(App.getContext());
    }

    @NonNull
    public static ReentrantReadWriteLock.WriteLock writeLock() {
        return LOCK.writeLock();
    }

    @NonNull
    public static ReentrantReadWriteLock.ReadLock readLock() {
        return LOCK.readLock();
    }

    @NonNull
    public static ReentrantReadWriteLock getLock() {
        return LOCK;
    }

    public static void close(DbProvider instance) {
        try {
            instance.close();
        } catch (Exception ex) {

        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        executeQuery(db, "db-scripts/database.sql", false);
        Log.w("database", "database create");
        executeQuery(db, "db-scripts/database_updates.sql", true);
        Log.w("database", "database update");
    }

    private void executeQuery(SQLiteDatabase db, String sql, boolean shouldHandleExceptions) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(assets.open(sql)));
            String line;
            File tempDbScript = new File(Environment.getExternalStorageDirectory(), "iErunt/dbBackup");
            tempDbScript.getParentFile().mkdirs();
            tempDbScript.createNewFile();
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(tempDbScript));
            while ((line = bufferedReader.readLine()) != null) {
                line = line.replaceAll("\t+", " ").replaceAll("\n+", " ").replaceAll(" +", " ").replaceAll(";", ";\n");
                if (line.startsWith("--") || line.isEmpty()) {
                    continue;
                }
                bufferedWriter.write(line);
                bufferedWriter.flush();
            }
            bufferedWriter.close();
            bufferedReader.close();
            bufferedReader = new BufferedReader(new FileReader(tempDbScript));
            db.beginTransaction();
            while ((line = bufferedReader.readLine()) != null) {
                if (!(line = line.trim().replace(";", "")).isEmpty()) {
                    if (shouldHandleExceptions) {
                        try {
                            db.execSQL(line);
                        } catch (SQLException ex) {
                            Log.e("database", ex.getMessage(), ex);
                        }
                    } else {
                        db.execSQL(line);
                    }
                }
            }
            db.setTransactionSuccessful();
            db.endTransaction();
            tempDbScript.delete();
        } catch (IOException ex) {
            Log.e("database", ex.getMessage(), ex);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {

                }
            }
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        executeQuery(db, "db-scripts/database_updates.sql", true);
    }
}

and put initial DB schema of your database in assets/db-scripts/database.sql and whenever you make DB modifications put your alter queries in assets/db-scripts/database_updates.sql . 并将数据库的初始数据库模式放在assets/db-scripts/database.sql ,无论何时进行数据库修改,都要将您的alter查询放在assets/db-scripts/database_updates.sql Be sure to increase VERSION of the database when updating the database. 更新数据库时,请务必增加数据库的VERSION

What this class does is read your entire SQL script and executes one by one . 这个类的作用是读取整个SQL脚本并逐个执行 which significantly reduces development time . 这显着缩短了开发时间

Note: You'll need android.permission.WRITE_EXTERNAL_STORAGE permission, as this creates a temp file and deletes it at the end 注意:您需要android.permission.WRITE_EXTERNAL_STORAGE权限,因为这会创建一个临时文件并在最后删除它

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM