Android:如何在同一用户的设备之间同步存储在Room数据库中的应用程序数据?

问题描述 投票:2回答:2

我正在开发一个在本地存储用户数据的应用。我已经使用Room数据库将用户创建的数据存储在Android设备中。现在,如果用户拥有多于一台设备,则数据应该在所有(Android)设备上都可用,而无需任何中央数据库或Web服务。

注意:对于iOS端,我使用CloudKit在iOS设备之间同步数据。有什么方法可以对Android设备执行相同操作吗?请注意,我不想将数据存储在任何中央数据库或Web服务器或任何中央云存储中。它应仅归用户所有。 (即应通过用户的Google帐户进行同步)。注意:我想要本机android解决方案,并且不需要跨平台(Android到iOS)同步。

更新:到目前为止,我发现了一些选项,例如FirestoreRealtime database,并且某些AWS服务还提供了同步功能,但所有这些的问题在于它们都将用户数据存储在中央云位置。

所以我的问题仍然保持不变-是否有一种方法可以使用Google Drive或类似方法在android设备之间同步数据,我们可以利用用户自己的云存储而不是将用户数据存储在中央数据库中。

android google-cloud-firestore android-room cloudkit
2个回答
4
投票

编辑

no本机/默认/开箱即用的机制可以在Android

上实时同步数据

虽然有代理人。

在Android中出现两个主要选项:

  • 具有一些持久性存储的套接字-您可以实现对sockets的支持的后端服务器,并为您的android(ios / web / desktop)应用添加此支持。这是在设备之间实现实时同步的最常见且相当低级的机制。 Pros:跨平台通用,行业标准和许多在线信息。 Cons:由于它是较低级别的东西,因此需要很多代码,如果有很多同步偶数,需要后端,需要单独的持久性,则可能会变得相当复杂。主要实现:Socket.io

  • FirebaseRealtime Database/ Cloud Firestore-基本上与某些数据库一起围绕套接字包装。 “优点”:既不需要后端,也不需要数据库,对于原型/低负载应用程序免费,非常直接的实现,跨平台,效果很好。 缺点:如果您想以“简洁的方式”使用很多样板文件,则无法控制内部流程,无法在高负载情况下进行非常明显的付款计算,可以将自己链接到具有特定API的第三方后端-如果您想从其他地方迁移而无需重新构建应用程序,则需要定义明确的架构。 comparison: firebase cloud firestore vs realtime database

我将不详细介绍实现,因为在这种情况下,官方文档非常简单(与Google驱动器不同)

Cloud Firestore文档

Cloud Firestore文档

编辑结束

是。可以使用Realtime Database私下存储数据。只有您的应用程序才能访问它。而且,它不会在用户Realtime Database中占据任何方便的空间。在这种情况下,可以使用跨平台,但需要针对iO和Android单独实施(SDK不提供现成的支持)。

因此该解决方案基于Google Drive,更具体地基于Google Drive部分。

对此用户可见的唯一操作是google登录提示。

Google Drive API是Java的详细快速入门

因此,您需要:

  • 添加依赖项;

  • 实施Google身份验证,如Store application-specific dataHere

  • 非常重要使用herehere范围对用户进行身份验证。也是drive.appdata Google Cloud Console中的Google Drive API。所有这些都描述为drive.file

  • 找出enable文件的位置,例如:here

  • 将文件上传到Google云端硬盘应用文件夹,如Room SQLite

  • 所述

基本上看起来像这样

  • [String currentDBPath = context.getDatabasePath("your_database_name.db").getAbsolutePath();控制台中的Google Dive API

  • 添加依赖项(可能需要更新到相关版本)

here
implementation 'com.google.android.gms:play-services-auth:17.0.0'// for google sign in

// for drive integration
implementation 'com.google.android.gms:play-services-auth:16.0.1'
implementation 'com.google.http-client:google-http-client-gson:1.26.0'
implementation('com.google.api-client:google-api-client-android:1.26.0') {
exclude group: 'org.apache.httpcomponents'
}
implementation('com.google.apis:google-api-services-drive:v3-rev136-1.25.0') 
{
exclude group: 'org.apache.httpcomponents'
} 
  • 清单
android
  • 具有所需范围的Google身份验证
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
}
  • 设置Google Drive客户服务(在上下文中)
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 创建和发送文件
       val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(
                 Scope(Scopes.DRIVE_FILE),
                 Scope(Scopes.DRIVE_APPFOLDER)
            )
            .requestEmail()
            .build()
        googleSingInClient = GoogleSignIn.getClient(this, gso)
        val signInIntent = googleSingInClient.signInIntent
        startActivityForResult(signInIntent, RC_SIGN_IN)
        ... // handle sign in result
  • 在其他设备上搜索文件
        val mAccount = GoogleSignIn.getLastSignedInAccount(this)

        val credential =
            GoogleAccountCredential.usingOAuth2(
                applicationContext, Collections.singleton(Scopes.DRIVE_FILE)
            )
        credential.setSelectedAccount(mAccount.getAccount())
        val googleDriveService =
            Drive.Builder(
                AndroidHttp.newCompatibleTransport(),
                GsonFactory(),
                credential
            )
                .setApplicationName("Your app name")
                .build()

[您可能会得到 val fileMetadata = File() fileMetadata.setName("your_database_name.db") fileMetadata.setParents(Collections.singletonList("appDataFolder")) val databasePath = context.getDatabasePath("your_database_name.db").absolutePath val filePath = File(databasePath) val mediaContent = FileContent("application/sqlite", filePath) val file = driveService.files().create(fileMetadata, mediaContent) .setFields("id") .execute() 的更多信息

希望有帮助。


0
投票

您可以为此使用Firebase中的Cloud FireStore val files = driveService.files().list() .setSpaces("appDataFolder") .setFields("nextPageToken, files(id, name)") .setPageSize(10) .execute() for (file in files.getFiles()) { // get file here }

© www.soinside.com 2019 - 2024. All rights reserved.