android.database.sqlite.SQLiteCantOpenDatabaseException:未知错误(代码14):无法打开数据库 - 应用程序中的逻辑问题

时间:2017-11-01 05:24:09

标签: java android database sqlite

我正在学习机器人,而不是专家。我想在处理我的sqllite数据库时遇到了一些逻辑问题。让我解释一下我在做什么以及我得到了什么。

我有一个引用的应用程序。我也在线提供本地数据库。我在数据库中包含了数据库文件,并在用户从启动画面打开应用程序时首次从中复制数据库。之后,我检查存储在用户设备中的最后作者和本地数据库的最后一个引号,并与在线数据库进行比较。如果在线有新数据,那么我正在下载并将其存储在初始屏幕中。

现在我的启动画面代码如下所示

DAO database=DAO.getInstance(this);
int lastAuthor =database.getLastAuthor();
String  updatesUrl = constant.MainUrl + String.valueOf(lastAuthor)+ "/" + String.valueOf(lastQuote);

我的DAO课程看起来像这样

public class DAO {
    private SQLiteDatabase database;
    private DBHandler dbHandler;
    private static final String TABLE_QUOTES = "quotes";
    private static final String TABLE_AUTHORS = "authors";
    private static final String TABLE_SETTINGS = "settings";
    private static final String QU_ID = "_quid";
    private static final String QU_TEXT = "qu_text";
    private static final String QU_AUTHOR = "qu_author";
    private static final String QU_FAVORITE = "qu_favorite";
    private static final String QU_TIME = "qu_time";
    private static final String AU_NAME = "au_name";
    private static final String AU_PICTURE = "au_picture";
    private static final String AU_PICTURE_SDCARD = "au_picture_sdcard";
    private static final String AU_WEB_ID = "au_web_id";

    private static DAO dBObject;
    private final Object lockObj=new Object();

    public static DAO getInstance(Context context){

        if(dBObject==null)dBObject=new DAO(context);
        return  dBObject;

    }


    private DAO(Context context) {
        synchronized (lockObj) {
            dbHandler = new DBHandler(context);
            try {
                dbHandler.createDataBase();
            } catch (IOException e) {
                e.printStackTrace();
            }
            dbHandler.openDataBase();
            open();
        }
    }

    public int getLastAuthor() {

        String query = "SELECT " + AU_WEB_ID + " FROM " + TABLE_AUTHORS
                + " ORDER BY " + AU_WEB_ID + " DESC LIMIT 1";
        Cursor cursor = database.rawQuery(query, null);

        cursor.moveToFirst();
        int tmp = cursor.getInt(cursor.getColumnIndex(AU_WEB_ID));
        cursor.close();
        return tmp;

    }

    // ==============================================================================

    public int getLastQuote() {
        String query = "SELECT " + QU_ID + " FROM " + TABLE_QUOTES
                + " ORDER BY " + QU_ID + " DESC LIMIT 1";

        Cursor cursor = database.rawQuery(query, null);

        cursor.moveToFirst();
        int tmp = cursor.getInt(cursor.getColumnIndex(QU_ID));

        cursor.close();
        return tmp;
    }

    // ==============================================================================

    public void addAuthor(String au_name, String au_picture, int au_web_id) {
        open();
        ContentValues v = new ContentValues();
        v.put(AU_NAME, au_name);
        v.put(AU_PICTURE, au_picture);
        v.put(AU_PICTURE_SDCARD, 1);
        v.put(AU_WEB_ID, au_web_id);

        database.insert(TABLE_AUTHORS, null, v);

    }

    // ==============================================================================

    public void addQuote(String qu_text, int qu_author, int _quid, String qu_time) {
        open();
        ContentValues v = new ContentValues();
        v.put(QU_TEXT, qu_text);
        v.put(QU_AUTHOR, qu_author);
        v.put(QU_FAVORITE, "0");
        v.put(QU_ID, _quid);
        v.put(QU_TIME, qu_time);

        database.insert(TABLE_QUOTES, null, v);

    }



    // ==============================================================================

    //method changed
    private void open() throws SQLException {
        if(database!=null&&database.isOpen())return; //changed line
        database = dbHandler.getWritableDatabase();

    }

    // ==============================================================================

    public void closeDAO(){
        synchronized (lockObj){
            if(dbHandler!=null)dbHandler.close();
            dbHandler=null;
            database=null;
        }
    }



    public static void dispose(){

        if(dBObject!=null){
            dBObject.closeDAO();
        }
        dBObject=null;
    }

}

我的数据库处理程序类看起来像这样

public class DBHandler extends SQLiteOpenHelper {
    private static String DB_PATH;
    private static String DB_NAME = "xxx";
    private SQLiteDatabase myDataBase;
    private final Context myContext;
    public DBHandler(Context context) {

        super(context, DB_NAME, null, constant.DATABASE_VERSION);
        this.myContext = context;
        DB_PATH = context.getDatabasePath(DB_NAME).toString();
    }
    public void createDataBase() throws IOException {

        boolean dbExist = checkDataBase();

        if (dbExist) {
        } else {

            this.getReadableDatabase();

            try {
                copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");

            }
        }

    }

    // ==============================================================================

    /**
     * Check if the database already exist to avoid re-copying the file each
     * time you open the application.
     *
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        } catch (SQLiteException e) {

            // database does't exist yet.

        }

        if (checkDB != null) {

            checkDB.close();

        }

        return checkDB != null ? true : false;
    }


    private void copyDataBase() throws IOException {

        InputStream myInput = myContext.getAssets().open(DB_NAME);

        String outFileName = DB_PATH;

        OutputStream myOutput = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    // ==============================================================================

    public void openDataBase() throws SQLException {


        // Open the database
        String myPath = DB_PATH;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }

    // ==============================================================================

    @Override
    public synchronized void close() {

        if (myDataBase != null)
            myDataBase.close();

        super.close();

    }

    // ==============================================================================

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    // ==============================================================================

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }


}

我在logcat中遇到这样的错误

Failed to open database '/data/user/0/com.newdeveloper.test/databases/xxx'.
 android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
 at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:835)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:820)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:723)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:692)
at com.newdeveloper.test.utility.DBHandler.checkDataBase(DBHandler.java:69)
at com.newdeveloper.test.utility.DBHandler.createDataBase(DBHandler.java:32)
at com.newdeveloper.test.utility.DAO.<init>(DAO.java:41)
at com.newdeveloper.test.utility.DAO.getInstance(DAO.java:31)
at com.newdeveloper.test.activities.SplashScreensActivity.checkForUpdate(SplashScreensActivity.java:111)
at com.newdeveloper.test.activities.SplashScreensActivity.access$000(SplashScreensActivity.java:41)
at com.newdeveloper.test.activities.SplashScreensActivity$1.onAnimationEnd(SplashScreensActivity.java:98)
at android.view.animation.AnimationSet.getTransformation(AnimationSet.java:400)
  

然而,应用程序不会崩溃并且正常工作   需要。但是这个错误让我感到困惑,我需要改变它   解决这个错误。我想从最近两天解决但不是   找到任何有效的解决方案。如果有高级开发人员,请告诉我   可以帮助我从这里出来。感谢

1 个答案:

答案 0 :(得分:0)

如果您尚未在apk中使用捆绑数据库,则实际上并未在代码中创建数据库。

 @Override
    public void onCreate(SQLiteDatabase db) {
       //you must create the database here
    }

    // ==============================================================================

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     //Handle the database update here
    } 

你需要做这样的事情。

 @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.execSQL(CREATE_STRING);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Log.e(TAG, "Table Created");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_STRING);
        onCreate(db);
        Log.d(TAG, "Table upgraded to Version :" + newVersion);
    }

我还建议开始使用ROOM Android Architecture Component,它为模式使用的Sqlite提供了更好的抽象级别。