简体   繁体   中英

Android SQLite, onCreate() not being called

I've been struggling to create a SQLite DB within my Android application. I've looked at numerous tutorials, and quite a few existing questions on stack overflow and other sites.

Here is my DatabaseHelper class

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.

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.

sqlite_master is a system table that stores system information, such as table and index names ie the schema.

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 :-

在此输入图像描述

  • 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.

  • The package is mjt.pvcheck. The full path is 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

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

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 . Be sure to increase VERSION of the database when updating the database.

What this class does is read your entire SQL script and executes one by one . 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

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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