使用SQLiteAssetHelper无法打开数据库,点击购物车按钮崩溃求助
解决SQLiteAssetHelper引发的购物车添加崩溃问题
问题背景
我在实现Android应用的购物车功能时,每次点击添加到购物车按钮,应用就直接强制关闭了。相关代码和错误日志如下:
核心代码
public void addToCart(Order order){ SQLiteDatabase db = getReadableDatabase(); String query = String.format("INSERT INTO OrderDetail(Productid,ProductName,Quantity,Price) VALUES('%s','%s','%s','%s');", order.getProductid(), order.getProductName(), order.getQuantity(), order.getPrice()); db.execSQL(query); } // 按钮点击事件 btncart = (FloatingActionButton)findViewById(R.id.btncart); btncart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //line 49// new Database(FoodDetails.this).addToCart(new Order( foodId, currentFood.getName(), numberButton.getNumber(), currentFood.getPrice() )); Toast.makeText(FoodDetails.this,"Added to cart",Toast.LENGTH_SHORT).show(); } });
崩溃日志(Logcat)
1-19 19:43:14.767 9304-9304/com.k.menu E/AndroidRuntime: FATAL EXCEPTION: main Process: com.k.menu, PID: 9304 com.readystatesoftware.sqliteasset.SQLiteAssetHelper$SQLiteAssetException: assets目录中缺少databases/eatitDb.db文件(或.zip、.gz压缩包),或目标文件夹不可写入 at android.content.res.AssetManager.openAsset(Native Method) at android.content.res.AssetManager.open(AssetManager.java:347) at android.content.res.AssetManager.open(AssetManager.java:321) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.copyDatabaseFromAssets(SQLiteAssetHelper.java:436) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.createOrOpenDatabase(SQLiteAssetHelper.java:400) at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.getWritableDatabase(SQLiteAssetHelper.java:176) at com.k.menu.Database.Database.addToCart(Database.java:54) at com.k.menu.FoodDetails$1.onClick(FoodDetails.java:49) ...
问题诊断
从日志里的SQLiteAssetException可以直接定位到根源:
assets目录中缺少databases/eatitDb.db文件(或.zip、.gz压缩包),或目标文件夹不可写入
简单说,SQLiteAssetHelper在尝试从你的项目assets目录里复制预设的数据库文件到设备时失败了,导致数据库无法初始化,最终触发崩溃。
分步解决方案
1. 检查assets目录的文件结构
首先确认你的Android项目里存在正确的文件路径:src/main/assets/databases/eatitDb.db
- 如果你的数据库是压缩包格式(.zip或.gz),也要放在
databases子目录下,文件名保持一致(比如eatitDb.db.zip)。 - 注意Android Studio里的assets目录必须是在
main文件夹下,手动创建的话要确保目录名是全小写的assets。
2. 核对数据库文件名的拼写
检查你的Database类继承SQLiteAssetHelper时的构造参数,确保数据库名和assets里的完全一致(大小写敏感!):
public class Database extends SQLiteAssetHelper { public Database(Context context) { // 第二个参数必须和assets/databases/下的文件名完全匹配 super(context, "eatitDb.db", null, 1); } }
3. 修复SQL代码的两个潜在问题
你的addToCart方法还有两个隐藏问题,即使解决了数据库文件的问题,后续也可能出bug:
- 用
getWritableDatabase替代getReadableDatabase:插入操作需要可写的数据库连接,虽然getReadableDatabase()在某些情况下会自动转为可写,但直接用getWritableDatabase()更稳妥。 - 避免字符串拼接SQL:用
ContentValues和insert方法替代字符串拼接,能避免SQL注入风险,也不会因为字段里的单引号导致SQL语法错误:
public void addToCart(Order order){ SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("Productid", order.getProductid()); values.put("ProductName", order.getProductName()); values.put("Quantity", order.getQuantity()); values.put("Price", order.getPrice()); // 插入数据到OrderDetail表 db.insert("OrderDetail", null, values); db.close(); // 记得关闭数据库连接 }
4. 确认存储权限(针对自定义路径场景)
如果你的SQLiteAssetHelper配置了自定义的数据库存储路径(默认是应用内部存储,不需要额外权限),那要确保应用拥有WRITE_EXTERNAL_STORAGE权限,并且在Android 6.0+版本中完成了动态权限请求。不过大部分情况下用默认路径就不需要这一步。
内容的提问来源于stack exchange,提问作者Karthik N
相关产品推荐
相关产品推荐

