尝试连接到 SQLite 数据库时,Android 应用程序崩溃

Posted

技术标签:

【中文标题】尝试连接到 SQLite 数据库时,Android 应用程序崩溃【英文标题】:Android app crashes when trying to connect to SQLite database 【发布时间】:2017-12-23 19:08:07 【问题描述】:

我的 android 应用程序崩溃并显示此错误。

package com.example.sanket.databaseexample;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.StrictMode;

/**
 * Created by sanket on 18-07-2017.
 */

public class DBHandler extends SQLiteOpenHelper
    private static  final int DATABASE_VERSION =1;
    private static final String DATABASE_NAME = "products.db";
    public static final String TABLE_PRODUCTS = "products";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_PRODUCTNAME = "product_name";

    public DBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) 
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        String query ="CREATE TABLE " + TABLE_PRODUCTS + "("  +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT ,"+
                COLUMN_PRODUCTNAME + " TEXT "+
                ")";
        db.execSQL(query);
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
            db.execSQL("DROP  TABLE IF EXISTS " + TABLE_PRODUCTS );
            onCreate(db);
    
    public void addProduct(Products product)
        ContentValues values = new ContentValues();
        values.put(COLUMN_PRODUCTNAME,product.getProduct_name());
        SQLiteDatabase db = getWritableDatabase();
        db.insert(TABLE_PRODUCTS,null,values);
        db.close();
    
    public void deleteProduct(String prductName)
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_PRODUCTS + " WHERE " + COLUMN_PRODUCTNAME+ " =\"" + prductName + "\";");
    
    public String databaseToString()
        String dbString = "";
        SQLiteDatabase db = getWritableDatabase();
        String query = "SELECT * FROM " + TABLE_PRODUCTS +" WHERE 1";
        Cursor c = db.rawQuery(query,null);
        if(c.getCount() > 0) 
            c.moveToFirst();
            while (!c.isAfterLast()) 
                if (c.getString(c.getColumnIndex("productname")) != null) 
                    dbString += c.getString(c.getColumnIndex("productname"));
                    dbString += "\n";
                
            
        
        db.close();
        return dbString;
    

日志:

07-19 00:13:34.764 18415-18415/?我/艺术:不延迟启用 -Xcheck:jni (已经开启)07-19 00:13:34.765 18415-18415/? W/art:意外的 CPU 使用默认值的 X86 变体:x86 07-19 00:13:35.243 18415-18415/com.example.sanket.databaseexample W/系统:类加载器 引用的未知路径: /data/app/com.example.sanket.databaseexample-2/lib/x86 07-19 00:13:35.501 18415-18422/com.example.sanket.databaseexample W/艺术: 暂停所有线程耗时:7.283ms 07-19 00:13:35.506 18415-18415/com.example.sanket.databaseexample W/art:在 Android 之前 4.1、方法android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) 会错误地覆盖 package-private 方法 android.graphics.drawable.Drawable 07-19 00:13:35.992 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:7.732ms 07-19 00:13:36.142 18415-18415/com.example.sanket.databaseexample E/CursorWindow:失败 从具有 1 行 2 的 CursorWindow 读取第 0 行第 -1 列 列。 07-19 00:13:36.143 18415-18415/com.example.sanket.databaseexample D/AndroidRuntime: 关闭虚拟机

--------- 崩溃开始 07-19 00:13:36.148 18415-18415/com.example.sanket.databaseexample E/AndroidRuntime: FATAL 例外:主要 进程:com.example.sanket.databaseexample,PID:18415 java.lang.RuntimeException:无法启动活动 组件信息com.example.sanket.databaseexample/com.example.sanket.databaseexample.MainActivity: java.lang.IllegalStateException:无法读取第 0 行,列 -1 光标窗口。确保光标在之前正确初始化 从中访问数据。 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 在 android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6077) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 引起:java.lang.IllegalStateException:无法读取第 0 行,col -1 来自光标窗口。确保在从光标访问数据之前正确初始化光标。 在 android.database.CursorWindow.nativeGetString(Native Method) 在 android.database.CursorWindow.getString(CursorWindow.java:438) 在 android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51) 在 com.example.sanket.databaseexample.DBHandler.databaseToString(DBHandler.java:57) 在 com.example.sanket.databaseexample.MainActivity.printDatabase(MainActivity.java:37) 在 com.example.sanket.databaseexample.MainActivity.onCreate(MainActivity.java:24) 在 android.app.Activity.performCreate(Activity.java:6662) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 在 android.app.ActivityThread.-wrap12(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6077) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) 07-19 00:13:42.576 18415-18422/com.example.sanket.databaseexample W/艺术: 暂停所有线程花费:16.982ms 07-19 00:13:45.084 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:16.342ms 07-19 00:13:46.553 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:5.273ms 07-19 00:13:49.082 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:14.783ms 07-19 00:13:55.105 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:17.910ms 07-19 00:13:55.594 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:5.317ms 07-19 00:14:04.126 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:6.876ms 07-19 00:14:05.626 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:6.402ms 07-19 00:14:07.622 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程占用:5.339ms 07-19 00:14:16.655 18415-18422/com.example.sanket.databaseexample W/art:暂停所有 线程耗时:6.749ms

【问题讨论】:

【参考方案1】:

看看这个错误信息:

无法从具有 1 行 2 列的 CursorWindow 读取第 0 行第 -1 列。

第-1列...这怎么可能?原因是这样的:

if (c.getString(c.getColumnIndex("productname")) != null) 

表中没有名为“productname”的列。 有一个名为“product_name”。 当请求列名不存在时, getColumnIndex 方法返回 -1。

您在创建表时使用了此常量:

public static final String COLUMN_PRODUCTNAME = "product_name";

最好将表格元素名称放在常量中, 你应该在任何地方始终如一地使用它们, 正是为了避免这种错别字, 并使维护更容易。

if (c.getString(c.getColumnIndex(COLUMN_PRODUCTNAME)) != null) 

【讨论】:

以上是关于尝试连接到 SQLite 数据库时,Android 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android Studio 和 Database Navigator 连接到正在运行的应用的 SQLite 数据库

PyCharm 无法连接到 SQLite:SQLITE_BUSY,(数据库已锁定)

如何将 SQLite 数据库(SQLite Firefox 扩展)连接到 Android 应用程序,以便 android 2.1 查询并插入数据库

QSqlDatabase 并连接到 .sqlite 文件

Netbeans 连接到 SQLite 时出现 SQLite 错误或缺少数据库(没有这样的表)

Android:在 SQLite 中使用 UUID 作为主键