在Android App和网络服务器之间同步数据[关闭]


262

我想在Android应用程序和服务器之间同步数据(例如db记录,媒体)。如果您看过Evernote或类似的应用程序,那么您肯定理解我的意思。

我有一个问题(想像我们要同步数据库记录):

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

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

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


1
首先,您需要弄清楚(决定)与服务器的通信协议,因此,可以传输哪些数据以及如何传输。
hovanessyan

这对我很重要,传输SQLlite数据。但我会知道如何传输其他数据。我不明白您对协议的卑鄙。请更多解释。
奥米德·纳齐菲


1
试试konysync,这是konylabs的产品,可提供跨各种平台(android,windows,ios),网络服务器,数据提供程序(salesforce,sap提供程序),数据库(sqlserver,mysql ...)的端到端解决方案
saimadan

Answers:


311

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


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

永久存储:

这是电话实际存储从网络服务器接收的数据的方式。实现此目的的一种可能方法是编写由Sqlite数据库支持的自定义ContentProvider。可以在以下位置找到有关内容提供商的不错的教程:http : //thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/

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

虽然我当然建议将ContentProvider与Sqlite数据库一起使用,但是您可以使用所需的任何基于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”之类的列属性,以确保始终获取最新数据,或者不会意外覆盖新写入的数据。


3
大量数据呢?我该如何同步?
Pratik Butani 2014年

4
很好地解释了,我只是有一个注释... SyncAdapter->“执行很多魔术”。我希望您将其称为黑魔法……这完全是邪恶的。
MRodrigues 2015年

@MRodrigues:对于开发人员而言,SyncAdapter可能是不可思议的,但对于稳定性和功能性来说,它仍然是不可思议的,它比其他库要好得多
Milad Metias 2015年

2
Web服务本身需要什么才能将其与android设备同步?Spring有可能吗?
jublikon

58

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

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

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

  • 领域:领域是一个移动数据库:SQLite和核心数据的替代。

  • 改造类型安全的针对Android和Java的广场HTTP客户端,公司必须学会一个智能双向使用的,改造

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

祝所有新手学习顺利。:)


链接到智能使用方式的改装已失效
Greg Holst,

@GregHolst已更新。
Pratik Butani

3
还没下来 还是需要登录?Archive.org拥有它:web.archive.org/web/20160316222227/https
//futurestud.io/blog/…– bobpaul

24

如果您自己写这些,这些是要记住的一些要点

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

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

选择您的有效载荷格式。我建议将基于SyncML的XML与基于JSON的格式混合以表示实际数据。因此,SyncML用于协议,而JSON用于交换实际数据。始终首选使用JSON Array来处理数据,因为使用JSON Array可以轻松访问数据。

跟踪客户端和服务器上的数据更改。您可以维护ID的更改日志,这些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正确对话,这将使事情持久化(是的,它将DB与应用程序其他部分的直接访问隔离开来)。

另外,如果您想看一下2015年的代码,请访问:https : //github.com/google/iosched


IMO的Google IO应用程序的源代码非常有用!
Richeek

10

例如,您要将表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


1
您的想法很棒,但仍然无法正确理解表格设计。它与休息服务和适当的同步服务一起起作用
Ahesanali Suthar,2017年


3

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


如何查看本地App和服务器中更新的数据?以及如何合并在一起?我将所有记录通过JSON或其他方式发送到应用程序以合并它们是不好的。你怎么看?
奥米德·纳齐菲

2
您可以使用带有int / bool 1/0的标志(例如“在服务器上”)表示是或否。发送记录/文件/数据块时,请在服务器上检查是否成功,然后将其翻转为“是”。那么,如果您使用的是类似SQLite的工具,则可以执行“ SELECT * FROM my_table WHERE sended = 0”类型的操作以发送任何新记录
Evan R.

1

我建议使用类似于Hessian的二进制Web服务协议。它运作良好,并且确实有android实现。它可能会有点沉重,但是取决于您正在构建的应用程序。希望这可以帮助。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.