272

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

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

  1. 每个用户都有自己的服务器空间的一部分(例如EvernoteDropbox)。也许用户通过手机创建新记录并在服务器中创建新记录。我怎样才能将这些记录匹配在一起?如果有相同 ID 的记录你建议我什么算法?

  2. 除了JSON还有什么方法可以在手机设备和服务器之间发送数据?

  3. 如果SyncAdapterContentProvider可以解决我的问题,请为我解释清楚。(如果您可以向我提供一些示例或教程,或者任何有助于扩大/指导我的搜索的建议或关键字也将不胜感激)。

4

9 回答 9

312

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


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

持久存储:

这就是您的手机实际存储从网络服务器接收到的数据的方式。实现此目的的一种可能方法是编写您自己的由 Sqlite 数据库支持的自定义ContentProvider 。可以在此处找到内容提供者的体面教程:http: //thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/

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

虽然我当然会推荐使用带有 Sqlite 数据库的ContentProvider,但您可以使用任何您想要的基于 java 的存储机制。

数据交换格式:

这是您用于在网络服务器和 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”之类的列属性,以确保您始终获得最新数据,或者您不会意外覆盖新写入的数据。

于 2012-07-07T01:38:43.273 回答
61

如果我们今天想想,接受的答案太老了。正如我们所知,我们有许多新的库可以帮助您制作这种类型的应用程序。

您应该学习以下肯定会对您有所帮助的主题:

您的数据库同步逻辑如下:如何将 Android 手机上的 SQLite 数据库与服务器上的 MySQL 数据库同步?

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

于 2016-04-25T04:58:03.157 回答
24

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

设备和同步服务器之间的正确身份验证

设备和服务器之间的同步协议。它通常分为 3 个阶段,身份验证、数据交换、状态交换(哪些操作有效,哪些失败)

选择您的有效负载格式。我建议将基于 SyncML 的 XML 与基于 JSON 的格式混合来表示实际数据。因此,SyncML 用于协议,而 JSON 用于正在交换的实际数据。在处理数据时使用 JSON 数组总是首选,因为使用 JSON 数组很容易访问数据。

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

当服务器上的数据发生变化时,需要有一种从服务器到设备的通信方式来启动同步会话。您可以使用 C2DM 或编写自己的基于 tcp 的持久通信。tcp 方法非常无缝

一种跨多个设备复制数据更改的方法

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

希望这有助于作为一个好的起点。

于 2012-05-31T22:07:16.620 回答
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 正确对话,这将使事情变得持久(是的,它将数据库与应用程序其他部分的直接访问隔离开来)。

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

于 2015-05-15T02:51:40.493 回答
11

例如,您要将表todoTable从同步MySqlSqlite

version (type INT)首先,todoTable为两者创建一个列SqliteMySql 在此处输入图像描述

二、创建database_version一列名的表名currentVersion(INT)
在此处输入图像描述

MySql中,当您添加新项目todoTable或更新项目时,您必须将该项目的版本升级+1,同时升级currentVersion 在此处输入图像描述

Android中,当您要同步时(通过手动按下同步按钮或​​使用周期时间运行的服务):

您将带有SqlitecurrentVersion(当前为 1)的请求发送到服务器。
然后在服务器中,您会发现MySql版本值大于SqlitecurrentVersion(1) 的项目然后响应 Android(在此示例中,版本 2 的项目 3 将响应 Android)

SQLite中,您将添加或更新新项目todoTable并升级 currentVersion

于 2016-07-20T10:46:07.887 回答
6

查看parseplatform.org。它是开源项目。

(您也可以在back4app.com上购买商业包。)

这是一个非常直接且用户友好的服务器端数据库服务,它提供了一个很棒的 android 客户端 API

于 2012-07-06T17:37:12.587 回答
3

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

于 2012-05-31T08:49:56.297 回答
1

我建议使用类似于Hessian的二进制 web 服务协议。它工作得很好,他们确实有一个 android 实现。它可能有点重,但取决于您正在构建的应用程序。希望这可以帮助。

于 2012-07-07T00:40:43.277 回答
1

@Grantismo 很好地概述了 Android 同步组件。

SyncManagerAndroid 库提供了一个简单的 2 路同步实现以插入 Android 同步框架 (AbstractThreadedSyncAdapter.OnPerformSync)。

https://github.com/sschendel/SyncManagerAndroid

于 2014-10-26T15:25:41.127 回答