尝试连接到 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 查询并插入数据库