Android Cursor:数据库在被读取时被修改

时间:2015-07-01 16:19:34

标签: java android database bluetooth android-contentprovider

我的应用程序是SMS应用程序发送和接收短信但有以下区别:所有消息都通过蓝牙发送到您的PC,我的其他应用程序(在C#和WPF中)将允许用户编写和接收短信。

我的应用未设置为默认短信应用,并且可以追溯到 API Lv 9

当用户需要加载所有短信以将其发送到PC时,我使用Cursor从内部 SMS数据库中读取:

final Uri uriSMSInbox = Uri.parse("content://sms/inbox");
final Uri uriSMSSent = Uri.parse("content://sms/sent");
final Cursor cursorInbox = this.context.getContentResolver()
       .query(uriSMSInbox, null, null, null, null);
final Cursor cursorSent = this.context.getContentResolver()
       .query(uriSMSSent, null, null, null, null);

我创建了一个Message类来表示一个SMS(主要是ID,内容,地址,时间戳的不可变的最终字段)。在使用cursor.moveNext()时,我填写了一个Message列表,它将代表所有存储的SMS。

截至目前,我可以发送和接收消息,一切正常。

但问题是,当PC应用程序发送消息时,它会创建消息对象并通过蓝牙将其发送到Android应用程序。但是如何设置其不可变ID?它应该匹配内部SMS数据库中的那个!

所以每次发送消息时我都会尝试查询数据库...问题是内部数据库并不总是立即更新。所以"我的"消息不存在... 尚未更新所需的时间可能会有很大差异,具体取决于最终用户设备(硬件,Android版本等)

所以我可以自己设置ID 。我可以问数据库最后一个ID是什么,但如果用户交换了很多短信怎么办?如果有十几条短信收到或发送怎么办...我怎样才能确定我设置的ID是否会在数据库中存在?

我需要在手机和PC之间同步SMS数据库,以便用户每次启动Android应用时都不必发送所有短信:他应该能够同步丢失的消息(如果他在我的应用程序外聊天)。

比使用ID快速比较和检查更好更快的方法?

所以这是我的问题:

  1. Android(或4.4+中的SMS默认应用程序)是否以异步方式更新内部SMS数据库,或者是否锁定它以防止多线程访问(更重要的是)修改它以防止竞争条件

  2. 使用Content Provider是否会返回Cursor代表某种"副本"因此,如果发生修改,数据库会在给定时刻忽略任何修改?

  3. 或者它是否锁定了数据库,这意味着Android(或默认的SMS应用程序)会等到我完成阅读以更新它?

  4. 一种解决方案是设置一个定时器,该定时器将不时定期检查SMS数据库并正确设置ID。这是一个好方法吗?

1 个答案:

答案 0 :(得分:1)

回答你的问题:

    在4.4+中
  1. ,Android不会执行更新,它只会创建允许允许执行更新的应用程序的权限。可以想象,应用程序创建者可以编写不安全的多线程代码,就像4.4之前一样。这是不常见的,但是可能。

  2. ContentProvider确实返回Cursor并且随之而来,它可以让观察者无效并重新查询基础数据是否更新。因此,如果您愿意,您可以注册接收这些更新的通知。假设您确实希望ID与数据库匹配,那么在插入数据之前您无法知道ID - 这意味着您需要等到这种情况发生。这可能意味着某些消息不能以您想要的速度同步,但它们会在某个时刻出现。

  3. 当您打开Cursor并正在读取数据库时,数据库未锁定。可能会发生可能导致Cursor失效的更新。通常,您应该在读取行之前注册以更新Cursor,然后删除它,然后Cursor将抛出异常。