Android:SQLite使用方法 SQLiteOpenHelper操作 .

本文介绍如何利用SQLiteOpenHelper类创建和管理SQLite数据库,包括数据库的创建、版本升级及基本的CRUD操作。
    1. 程序内使用SQLite数据库是通过SQLiteOpenHelper进行操作  
    2. 1.       自己写个类继承SQLiteOpenHelper,重写以下3个方法  
    3. public void onCreate(SQLiteDatabase db)   
    4. {//创建数据库时的操作,如建表}   
    5.    
    6. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)   
    7.        {  
    8.            //版本更新的操作   
    9.        }  
    10. 2.    通过SQLiteOpenHelper的getWritableDatabase()获得一个SQLiteDatabase数据库,以后的操作都是对SQLiteDatabase进行操作。  
    11. 3.       对得到的SQLiteDatabase对象进行增,改,删,查等操作。  
    12. 代码  
    13. package cx.myNote;  
    14.    
    15. import android.content.ContentValues;  
    16. import android.content.Context;  
    17. import android.content.Intent;  
    18. import android.database.Cursor;  
    19. import android.database.sqlite.SQLiteDatabase;  
    20. import android.database.sqlite.SQLiteOpenHelper;  
    21.    
    22. //DBOptions for login   
    23. public class DBOptions {  
    24.        private static final String DB_NAME = "notes.db";  
    25.        private static final String DB_CREATE="create table logininf(name text,pwd text)";  
    26.        public class DBHelper extends SQLiteOpenHelper  
    27.        {  
    28.    
    29.               public DBHelper(Context context) {  
    30.                      super(context,DB_NAME, null1);  
    31.                      }  
    32.    
    33.               @Override  
    34.               public void onCreate(SQLiteDatabase db) {  
    35.                      // TODO Auto-generated method stub  
    36.                      //建表   
    37.                  db.execSQL(DB_CREATE);  
    38.               }  
    39.                 
    40.               @Override  
    41.               public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
    42.                      // TODO Auto-generated method stub  
    43.                      db.execSQL("drop table if exists logininf");  
    44.                      onCreate(db);  
    45.               }  
    46.                 
    47.        }  
    48.        private Context context;  
    49.        private SQLiteDatabase db;  
    50.        private DBHelper dbHelper;  
    51.        public  DBOptions(Context context)  
    52.        {  
    53.               this.context = context;  
    54.               dbHelper = new DBHelper(context);  
    55.               db=dbHelper.getReadableDatabase();  
    56.                 
    57.        }  
    58.   //自己写的方法,对数据库进行操作   
    59.        public String getName()  
    60.        {  
    61.                 
    62.               Cursor cursor = db.rawQuery("select name from logininf"null);  
    63.               cursor.moveToFirst();  
    64.               return cursor.getString(0);       
    65.        }  
    66.        public int changePWD(String oldP,String pwd)  
    67.        {  
    68.               ContentValues values = new ContentValues();  
    69.               values.put("pwd", pwd);  
    70.               return db.update("logininf", values,"pwd="+oldP, null);  
    71.        }  
Line 1366: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: java.lang.IllegalStateException: The file system on the device is in a bad state. WorkManager cannot access the app's internal data store. Line 1367: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:80) Line 1368: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:3) Line 1369: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156) Line 1370: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:651) Line 1371: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at java.lang.Thread.run(Thread.java:1119) Line 1372: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/data/user/0/com.kiloo.subwaysurf/no_backup/androidx.work.workdb' with flags 0x30000000: Directory /data/user/0/com.kiloo.subwaysurf/no_backup doesn't exist Line 1373: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:289) Line 1374: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:232) Line 1375: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:535) Line 1376: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:222) Line 1377: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:214) Line 1378: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:1163) Line 1379: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:1143) Line 1380: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007) Line 1381: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:996) Line 1382: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:373) Line 1383: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316) Line 1384: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableOrReadableDatabase(FrameworkSQLiteOpenHelper.kt:5) Line 1385: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.innerGetDatabase(FrameworkSQLiteOpenHelper.kt:132) Line 1386: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getSupportDatabase(FrameworkSQLiteOpenHelper.kt:22) Line 1387: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.kt:6) Line 1388: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.room.RoomDatabase.inTransaction(RoomDatabase.kt:5) Line 1389: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.kt:1) Line 1390: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.model.SystemIdInfoDao_Impl.getWorkSpecIds(SystemIdInfoDao_Impl.java:10) Line 1391: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.background.systemjob.SystemJobScheduler.reconcileJobs(SystemJobScheduler.java:17) Line 1392: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.utils.ForceStopRunnable.cleanUp(ForceStopRunnable.java:9) Line 1393: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.utils.ForceStopRunnable.forceStopRunnable(ForceStopRunnable.java:1) Line 1394: 07-18 13:13:46.039998 29707 29809 E AndroidRuntime: at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:29)
最新发布
08-22
<think>我们有一个崩溃日志,显示WorkManager在尝试访问其内部数据库时失败,原因是目录不存在。 具体错误信息: java.lang.IllegalStateException: The file system on the device is in a bad state. WorkManager cannot access the app's internal data store. 然后由以下异常引起: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/data/user/0/com.kiloo.subwaysurf/no_backup/androidx.work.workdb' with flags 0x30000000: Directory /data/user/0/com.kiloo.subwaysurf/no_backup doesn't exist 分析: WorkManager在启动时(ForceStopRunnable)尝试打开数据库,但发现数据库所在的目录(/data/user/0/com.kiloo.subwaysurf/no_backup)不存在,导致无法打开数据库。 可能的原因: 1. 应用在安装后第一次启动时,系统尚未创建应用的数据目录(但这种情况很少见,通常系统会创建好)。 2. 用户或某些清理工具删除了应用的数据目录中的部分内容(特别是no_backup目录)。 3. 应用在启动过程中被中断(例如强制停止),导致目录创建失败。 4. 设备存储问题,如存储空间不足或文件系统损坏。 从堆栈跟踪看,WorkManager在初始化时尝试访问数据库,但目录不存在。这个no_backup目录是Android为每个应用提供的,用于存储不希望被自动备份的数据(使用Context.getNoBackupFilesDir()获取)。 解决方案: 1. 在尝试使用WorkManager之前,确保数据目录存在。可以在Application的onCreate中检查并创建必要的目录。 2. 捕获这个异常并尝试重新创建目录,然后重试WorkManager的初始化。 具体步骤: 在Application类中,我们可以添加以下代码: ```java @Override public void onCreate() { super.onCreate(); // 确保no_backup目录存在 File noBackupDir = new File(getApplicationInfo().dataDir, "no_backup"); if (!noBackupDir.exists()) { noBackupDir.mkdirs(); // 设置目录权限(如果需要) noBackupDir.setReadable(true, false); noBackupDir.setWritable(true, false); } // 然后初始化WorkManager WorkManager.initialize(this, new Configuration.Builder().build()); } ``` 但是,注意:WorkManager在2.1.0版本之后会自动创建这个目录。因此,如果使用的WorkManager版本较旧,建议升级到最新版本。 另外,也可以考虑在WorkManager初始化时捕获此异常,然后尝试修复目录问题,再重新初始化。 然而,根据堆栈,这个错误发生在WorkManager内部初始化时(ForceStopRunnable),所以我们在WorkManager初始化之前确保目录存在即可。 如果问题仍然存在,可以检查存储权限,尽管对于内部存储,应用通常具有权限。 总结:这个崩溃是由于WorkManager的数据库所在目录不存在导致的。我们可以在应用启动时确保该目录被创建。 §§相关问题§§ 1.Android中,如何安全地创建应用数据目录下的子目录? 2. WorkManager初始化过程中可能遇到哪些常见异常? 3. 如何通过升级WorkManager版本来避免已知的数据库问题? 4. 当应用内部存储目录被意外删除时,如何设计恢复机制?</think>### WorkManager数据库崩溃分析 #### **根本原因:内部存储目录缺失导致数据库无法打开** 这个崩溃发生在《地铁跑酷》(com.kiloo.subwaysurf)应用的WorkManager初始化过程中,核心问题是**应用内部存储目录被破坏**,导致WorkManager无法访问其数据库。以下是详细分析: --- ### **关键错误链解析** ```plaintext 1. 文件系统异常: IllegalStateException: "The file system on the device is in a bad state" 2. 数据库打开失败: SQLiteCantOpenDatabaseException: "Cannot open database ... Directory doesn't exist" → 路径: /data/user/0/com.kiloo.subwaysurf/no_backup/androidx.work.workdb → 缺失目录: /data/user/0/com.kiloo.subwaysurf/no_backup 3. 触发点: ForceStopRunnable.run() // WorkManager的强制停止恢复例程 SystemIdInfoDao_Impl.getWorkSpecIds() // 工作ID查询操作 ``` --- ### **根本原因分层诊断** | 层级 | 问题 | 技术细节 | |------|------|----------| | **存储系统** | no_backup目录缺失 | • Android为每个应用自动创建的`no_backup`目录消失<br>• 该目录存储不可备份的敏感数据(WorkDB)<br>• 路径:`/data/user/0/{package}/no_backup` | | **文件操作** | 目录验证缺失 | • WorkManager未检查目录存在性<br>• `SQLiteOpenHelper`直接尝试打开数据库<br>• 缺乏对`getNoBackupFilesDir()`返回值的空检查 | | **设备状态** | 文件系统异常 | • 可能由存储空间耗尽引起(100%占用)<br>• 用户手动删除应用数据目录<br>• 设备ROOT后误删系统目录 | | **WorkManager** | 错误恢复机制 | • `ForceStopRunnable`尝试恢复作业时未处理存储异常<br>• 未实现存储状态检查的fallback机制 | --- ### **解决方案** #### 1. 紧急修复(目录验证) 在`Application.onCreate()`中添加存储验证: ```java public void onCreate() { super.onCreate(); validateStorageIntegrity(); } private void validateStorageIntegrity() { File noBackupDir = new File(getNoBackupFilesDir(), "androidx.work"); if (!noBackupDir.exists()) { // 重建目录结构 noBackupDir.mkdirs(); // 设置正确权限 (rwx------) noBackupDir.setReadable(true, false); noBackupDir.setWritable(true, false); noBackupDir.setExecutable(true, false); } } ``` #### 2. WorkManager初始化保护 ```java Configuration config = new Configuration.Builder() .setInitializationExceptionHandler((throwable) -> { // 捕获初始化异常 if (throwable instanceof SQLiteCantOpenDatabaseException) { repairWorkManagerStorage(); } }) .build(); WorkManager.initialize(this, config); ``` #### 3. 存储状态监控 添加定期存储检查: ```java new FileObserver(getNoBackupFilesDir().getPath()) { @Override public void onEvent(int event, String path) { if (event == FileObserver.DELETE_SELF) { // 关键目录被删除时紧急恢复 rebuildNoBackupStructure(); } } }.startWatching(); ``` --- ### **预防措施** 1. **添加存储验证钩子** ```java // 在WorkManager 2.7+中使用新的初始化API WorkManager.initialize(context, new Configuration.Builder() .setStoragePath(getVerifiedStorageDir()) // 自定义路径验证 .build()); ``` 2. **磁盘空间监控** ```java // 在Application中监控存储空间 registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context ctx, Intent i) { if (Environment.MEDIA_CHECKING.equals(i.getAction())) { if (getStorageFreeSpace() < 100 * 1024 * 1024) { // <100MB WorkManager.cancelAllWork(); // 防止写入操作 } } } }, new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW)); ``` 3. **异常恢复机制** ```java // 在ForceStopRunnable中插入修复逻辑 public void run() { try { cleanUp(); } catch (SQLiteCantOpenDatabaseException e) { repairDatabaseStructure(); // 先修复目录 cleanUp(); // 重试操作 } } ``` --- ### **根本原因总结** WorkManager在初始化时尝试访问`no_backup`目录下的数据库文件(`workdb`),但该目录已被删除或损坏。这通常由**设备存储空间耗尽**或**用户手动清除应用数据**导致。由于WorkManager缺乏对存储状态的验证机制,且`ForceStopRunnable`恢复流程未处理目录缺失异常,最终引发崩溃。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值