电池电量耗尽时丢失数据

时间:2013-01-16 17:10:29

标签: android

我们有一个奇怪的错误。如果电池电量耗尽,我们的应用程序将丢失它的数据(存储在SQLite中),但如果我们强行终止应用程序然后电池电量耗尽则不会。

我们不确定是什么原因引起的。

编辑1:

什么意味着放松数据?

  1. 当用户注册时,我们保存他的用户名等。
  2. 当应用关闭,强制关闭并且用户再次打开应用程序时,用户名就在那里
  3. 当电池电量耗尽且应用程序在前台运行时。电池充电后,用户再次打开应用程序,用户名就不见了。
  4. 如何存储对象:

    
     public Void perform(SQLiteDatabase db) {
                    final ConfigEntry entry = new ConfigEntry(property, value);
    
                    if(contains(property)) {
                        db.update(ConfigEntry.TABLE_NAME, databaseAdapter.convertToContentValues(entry), ConfigEntry.COLUMN_NAME + " = ?", new String[] { property });
                    } else {
                        db.insertOrThrow(ConfigEntry.TABLE_NAME, null, databaseAdapter.convertToContentValues(entry));
                    }
                    return null;
                }
            });
    
    

    所以基本上调用了db.insertOrThrow。

    这是我们初始化数据库的方式:

    
    public  S doInTransaction(TransactionTask task) {
            DatabaseHelper mDbHelper = DatabaseHelper.getInstance(mContext);
            SQLiteDatabase mDb = mDbHelper.getWritableDatabase();
            mDb.setLockingEnabled(true);
            mDb.beginTransaction();
            try {
                S result = task.perform(mDb);
                mDb.setTransactionSuccessful();
                return result;
            } finally {
                mDb.endTransaction();
            }
        }
    
    

3 个答案:

答案 0 :(得分:1)

问题是你正在使用beginTransaction()。如果您有来电beginTransaction(),则需要致电:

db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }

以下或您的数据将不会保存。原因在于sqlite manual

并且您的数据未保存的原因是,如果您启动了事务并且由于系统试图关闭它而未调用db.setTransactionSuccessful();,则不会保存数据。但是,finally{}可能仍会被调用,但这不会改变未调用db.setTransactionSuccessful();的事实。

答案 1 :(得分:1)

我不确定,但我希望我能提供一些问题或灵感来深入挖掘:

  1. 您是否监控过您的数据库是否经历了完整的初始创建过程,或者是否存在表格但只缺少用户名?您可以从设备下载数据库文件并在PC上的SQLite工具中查看内容吗?

  2. 您在doInTransaction()内打开数据库,但不要在那里关闭它:

    public S doInTransaction(TransactionTask task) {
        DatabaseHelper mDbHelper = DatabaseHelper.getInstance(mContext);
        SQLiteDatabase mDb = mDbHelper.getWritableDatabase();
        //mDb.setLockingEnabled(true); // true is default, so it can be removed
        mDb.beginTransaction();
        S result = null;
        try {
            result = task.perform(mDb);
            mDb.setTransactionSuccessful();
        } finally {
            // rolls back if setTransactionSuccessful() wasn't called
            mDb.endTransaction();
            mDb.close();
        }
        return result;
    }
    
  3. 您完全确定使用相同的数据库吗?我问,因为我曾经看到有人使用时间戳作为数据库名称的一部分。

  4. 您没有错误地创建in-memory database

  5. 设备有多种不同的方式可以使电池电量不足:它可能会死机或者设法实际关闭紧急电源。哪一个是这样的?您是否有任何日志记录可能会提供应用程序启动时的内容?

  6. 总结:我怀疑原因在于您提供的代码,正如您所提到的,代码仅在按下按钮时执行。这留下了上述问题需要进一步调查(当然,有些我可能会错过......)。

答案 2 :(得分:0)

非常感谢所有的帮助,我们终于找到了答案。

我们正在使用用户密码加密我们的数据库,并使用设备的 MAC地址来保存密码。

发生的事情是,当用户在启动后耗尽电池时,当我们的应用程序运行时,我们请求MAC地址失败,因为网卡仍处于禁用状态。在那种情况下,我们创建了一个新的盐,当尝试读取数据库时将失败。