在Android应用程序和Web服务器之间同步数据

272

我想在Android应用程序和服务器之间同步数据(例如数据库记录、媒体文件)。如果你见过Evernote或类似的应用程序,你肯定明白我的意思。

我有一些问题(假设我们想同步数据库记录):

  1. 每个用户都有自己的一部分服务器空间(例如Evernote或Dropbox)。也许用户使用手机创建了新的记录并在服务器上创建了新的记录。 如何将这些记录匹配起来? 如果存在具有相同ID的记录,你建议我使用什么算法?

  2. 除了JSON,有没有其他方法可以发送数据到手机设备和服务器之间?

  3. 如果SyncAdapter和ContentProvider能够解决我的问题,请为我详细解释一下。(如果您可以向我提供一些示例或教程,或者提供任何建议或关键词来帮助扩大/指导我的搜索,我将不胜感激)。


1
首先,您需要确定与服务器的通信协议 - 因此 - 您可以传输哪些数据以及如何传输。 - hovanessyan
这对我很重要,需要转移SQLlite数据。但我想知道如何转移其他数据。我不明白您所说的协议是什么意思,请再解释一下。 - Omid Nazifi
我所说的协议是指这个:http://simple.wikipedia.org/wiki/Internet_Protocol - hovanessyan
1
尝试使用Konysync,这是Konylabs的产品,可在各种平台(Android、Windows、iOS)、Web服务器、数据提供程序(Salesforce、SAP提供程序)和数据库(SQL Server、MySQL等)上提供端到端解决方案。 - saimadan
9个回答

315

我将尝试通过回答更大的问题来回应您的所有问题:如何在Web服务器和Android应用程序之间同步数据?


在Web服务器和Android应用程序之间同步数据需要您的Android设备上使用几个不同的组件。

持久存储:

这是您的手机实际上存储从Web服务器接收到的数据的方式。一种可能的方法是编写自己的自定义ContentProvider,由Sqlite数据库支持。有一个不错的内容提供程序教程可以在这里找到:http://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/

ContentProvider定义了与存储的数据交互的一致接口。如果您希望,它还可以允许其他应用程序与您的数据交互。在ContentProvider背后可能是Sqlite数据库、缓存或任何任意存储机制。

虽然我肯定会建议使用带有Sqlite数据库的ContentProvider,但您也可以使用任何基于Java的存储机制。

数据交换格式:

这是您在Web服务器和Android应用程序之间发送数据所使用的格式。如今最流行的两种格式是XML和JSON。在选择格式时,您应考虑可用的序列化库类型。我知道json序列化有一个非常棒的库叫gson:https://github.com/google/gson,尽管我相信类似的库也适用于XML。

同步服务:

您需要一种异步任务,可以从服务器获取新数据并刷新移动内容以反映服务器内容。您还需要在本地更改内容并希望反映这些更改时通知服务器。Android提供了"SyncAdapter"模式来轻松解决此问题。您需要注册用户帐户,然后Android将为您执行许多操作,使您能够自动同步。以下是一个很好的教程:http://www.c99.org/2010/01/23/writing-an-android-sync-provider-part-1/ 至于如何确定记录是否相同,通常您将使用唯一ID创建项目,将其存储在Android设备和服务器上,并使用它来确保引用相同。此外,您可以存储列属性,例如“updated_at”,以确保始终获得最新数据或不会意外覆盖新编写的数据。

3
大量数据怎么办?如何同步? - Pratik Butani
4
非常清楚易懂的解释,我只有一个注释...SyncAdapter被称作“执行许多魔法”。我希望你指的是黑魔法...它完全是邪恶的。 - MRodrigues
@MRodrigues:对于开发人员来说,SyncAdapter可能是黑魔法,但它仍然可以通过稳定性和功能实现魔法,它比其他库要好得多。 - Milad Metias
3
需要同步与安卓设备的Web服务本身需要什么?使用Spring框架可以实现吗? - jublikon

64

如果我们考虑今天,那么被接受的答案太旧了。我们知道有很多新的库可以帮助您制作这种类型的应用程序。

您应该学习以下主题,这些主题一定会对您有所帮助:

  • SyncAdapter:您的应用程序中的同步适配器组件封装了在设备和服务器之间传输数据的任务的代码。根据您在应用程序中提供的安排和触发器,同步适配器框架运行同步适配器组件中的代码。

  • Realm:Realm是移动数据库:SQLite和Core Data的替代品。

  • Retrofit:由Square Inc.开发的Android和Java的类型安全HTTP客户端。必须学习a-smart-way-to-use-retrofit

并且您的数据库同步逻辑可以参考:如何在Android手机上将SQLite数据库与服务器上的MySQL数据库同步?

祝所有新学习者好运。 :)


a-smart-way-to-use-retrofit 的链接已失效。 - Greg Holst
@GregHolst 已更新。 - Pratik Butani
4
还是失效了,或者需要登录?Archive.org有这个页面:https://web.archive.org/web/20160316222227/https://futurestud.io/blog/retrofit-getting-started-and-android-client - bobpaul

24

如果您自己编写代码,请记住以下几点:

设备和同步服务器之间需要进行适当的身份验证。

设备和服务器之间需要一种同步协议。通常分为三个阶段:身份验证、数据交换、状态交换(哪些操作成功了,哪些失败了)

选择有效载荷格式。建议使用基于SyncML的XML与基于JSON的格式来表示实际数据。因此,使用SyncML作为协议,JSON用于交换实际数据。在操作数据时,始终首选使用JSON数组,因为它可以轻松访问数据。

在客户端和服务器上跟踪数据变化。可以维护一个更改日志,记录更改id,并在同步会话期间获取它们。还可以在对象成功同步后清除更改日志。还可以使用布尔变量来确认同步状态,即上次同步的时间。这将有助于最终用户确定上次同步的时间。

需要一种方式从服务器到设备进行通信,以在服务器上更改数据时启动同步会话。可以使用C2DM或编写自己的持久性TCP基础通信。TCP方法非常流畅。

一种在多个设备之间复制数据更改的方法。

最后但并非最不重要的是,需要一种检测和处理冲突的方法。

希望这作为一个良好的起点能够有所帮助。


14

@Grantismo提供了一个全面的解释。如果你想知道人们实际上是如何做这些事情的,我建议你看看Google在2014年Google IO应用程序上的做法(深入查看它们发布的这些应用程序的源代码总是值得学习的)。

这里有一篇关于此的博客文章:http://android-developers.blogspot.com.br/2014/09/conference-data-sync-gcm-google-io.html

基本上,在应用程序方面:GCM用于信令,Sync Adapter用于数据获取并与Content Provider适当通信,Content Provider将使事物持久化(是的,它将数据库与应用程序的其他部分隔离开来,以防止直接访问)。

此外,如果您想查看2015年的代码:https://github.com/google/iosched


Google IO 应用程序的源代码在我看来非常有用! - Richeek

11
例如,您想要将MySql中的表todoTableSqlite同步。
首先,在todoTable中为SqliteMySql创建一个名为version(类型INT)的列。 enter image description here 其次,创建一个名为database_version的表,其中包含一个名为currentVersion(INT)的列。 enter image description hereMySql 中,当你向 todoTable 添加一个新项目或更新项目时,必须将该项目的版本号升级 +1,并且还要升级 currentVersionenter image description hereAndroid 中,当你想要同步(通过手动按同步按钮或定期运行的服务):
你将使用当前 Sqlite 版本(当前为 1)向服务器发送请求。 然后在服务器中,找到版本值大于 Sqlite 当前版本(1)的 MySql 中的项,然后响应给 Android(在此示例中,版本为 2 的第 3 项将响应给 Android)。
SQLite 中,您将添加或更新新项目到 todoTable 并升级当前版本。

1
你的想法非常棒,但是还是不能正确地理解表格设计。配合REST服务和适当的同步服务,它会很好地工作。 - Ahesanali Suthar

6

请看parseplatform.org,这是一个开源项目。

(你也可以选择在back4app.com上购买商业套餐。)

它是一个非常简单易用的服务端数据库服务,提供了出色的安卓客户端API。


他们提供哪些免费计划? - praxmon
12
Parse.com已经关闭。 - Chintan Rathod
4
你仍然可以使用Parse.com的功能,但需要在自己的服务器上进行操作,因为它们已经开源。 - geniushkg

3

实现这一点的一种方法是拥有一个等待数据的服务器端应用程序。可以使用Java中的HttpRequest对象发送数据,也可以编写自己的TCP/IP数据传输实用程序。数据可以使用JSON格式或您认为合适的任何其他格式发送。如果数据包含敏感信息,则可以在发送到服务器之前对其进行加密。所有服务器应用程序需要做的就是等待HttpRequests进来并解析数据并将其存储在任何您想要的位置。


如何检查本地应用程序和服务器中的数据更新?如何合并它们?我不想通过JSON或其他方式将所有记录发送到应用程序以进行合并,这样做不好。你怎么看? - Omid Nazifi
2
你可以使用一个标志,比如“在服务器上”,用一个整数/布尔值1/0表示是或否。当一条记录/文件/数据块被发送时,在服务器上检查是否成功,并将位翻转为“是”。然后,如果你正在使用类似SQLite的东西,你可以做一个“SELECT * FROM my_table WHERE sent = 0”的类型来发送任何新记录。 - Evan R.

1

@Grantismo提供了关于Android同步组件的优秀概述。

SyncManagerAndroid库提供了一个简单的双向同步实现,可插入到Android同步框架中(AbstractThreadedSyncAdapter.OnPerformSync)。

https://github.com/sschendel/SyncManagerAndroid


1
我建议使用类似于Hessian的二进制Web服务协议。它运行非常良好,并且他们有一个Android实现。它可能会有点重,但这取决于您正在构建的应用程序。希望这可以帮助到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接