Explorar el Código

Setup base Room configuration

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey hace 2 años
padre
commit
d0ab9ff67b

+ 4 - 1
app/build.gradle

@@ -354,6 +354,10 @@ dependencies {
     gplayImplementation "com.google.firebase:firebase-messaging:23.1.0"
 
     implementation 'com.github.nextcloud.android-common:ui:0.3.0'
+
+    implementation "androidx.room:room-runtime:$roomVersion"
+    kapt "androidx.room:room-compiler:$roomVersion"
+
 }
 
 configurations.all {
@@ -366,7 +370,6 @@ configurations.all {
             }
         }
     }
-
 }
 
 tasks.withType(Test) {

+ 65 - 0
app/src/main/java/com/nextcloud/client/database/NextcloudDatabase.kt

@@ -0,0 +1,65 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+import com.nextcloud.client.database.entity.ArbitraryDataEntity
+import com.nextcloud.client.database.entity.CapabilityEntity
+import com.nextcloud.client.database.entity.ExternalLinkEntity
+import com.nextcloud.client.database.entity.FileEntity
+import com.nextcloud.client.database.entity.FilesystemEntity
+import com.nextcloud.client.database.entity.ShareEntity
+import com.nextcloud.client.database.entity.SyncedFolderEntity
+import com.nextcloud.client.database.entity.UploadEntity
+import com.nextcloud.client.database.entity.VirtualEntity
+import com.owncloud.android.db.ProviderMeta
+
+@Database(
+    entities = [
+        ArbitraryDataEntity::class,
+        CapabilityEntity::class,
+        ExternalLinkEntity::class,
+        FileEntity::class,
+        FilesystemEntity::class,
+        ShareEntity::class,
+        SyncedFolderEntity::class,
+        UploadEntity::class,
+        VirtualEntity::class
+    ],
+    version = ProviderMeta.DB_VERSION
+)
+abstract class NextcloudDatabase : RoomDatabase() {
+    // companion object {
+    //     val MIGRATION_1_64 = object : Migration(1, 64) {
+    //         override fun migrate(database: SupportSQLiteDatabase) {
+    //             TODO("Not yet implemented, use legacy migrations")
+    //         }
+    //     }
+    //     val MIGRATION_64_65 = object : Migration(64, 65) {
+    //         override fun migrate(database: SupportSQLiteDatabase) {
+    //             // this is just for Room compatibility. No need for any migration
+    //         }
+    //     }
+    // }
+}

+ 41 - 0
app/src/main/java/com/nextcloud/client/database/entity/ArbitraryDataEntity.kt

@@ -0,0 +1,41 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME)
+data class ArbitraryDataEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_CLOUD_ID)
+    val cloudId: String?,
+    @ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_KEY)
+    val key: String?,
+    @ColumnInfo(name = ProviderTableMeta.ARBITRARY_DATA_VALUE)
+    val value: String?
+)

+ 129 - 0
app/src/main/java/com/nextcloud/client/database/entity/CapabilityEntity.kt

@@ -0,0 +1,129 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME)
+data class CapabilityEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)
+    val accountName: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)
+    val versionMajor: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MINOR)
+    val versionMinor: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_MICRO)
+    val versionMicro: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_STRING)
+    val versionString: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_VERSION_EDITION)
+    val versionEditor: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT)
+    val extendedSupport: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)
+    val corePollinterval: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED)
+    val sharingApiEnabled: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED)
+    val sharingPublicEnabled: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED)
+    val sharingPublicPasswordEnforced: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED)
+    val sharingPublicExpireDateEnabled: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)
+    val sharingPublicExpireDateDays: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED)
+    val sharingPublicExpireDateEnforced: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL)
+    val sharingPublicSendMail: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD)
+    val sharingPublicUpload: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL)
+    val sharingUserSendMail: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_RESHARING)
+    val sharingResharing: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING)
+    val sharingFederationOutgoing: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING)
+    val sharingFederationIncoming: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING)
+    val filesBigfilechunking: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_UNDELETE)
+    val filesUndelete: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_VERSIONING)
+    val filesVersioning: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS)
+    val externalLinks: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_NAME)
+    val serverName: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_COLOR)
+    val serverColor: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR)
+    val serverTextColor: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR)
+    val serverElementColor: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN)
+    val serverSlogan: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_LOGO)
+    val serverLogo: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL)
+    val serverBackgroundUrl: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)
+    val endToEndEncryption: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACTIVITY)
+    val activity: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)
+    val serverBackgroundDefault: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN)
+    val serverBackgroundPlain: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT)
+    val richdocument: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST)
+    val richdocumentMimetypeList: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING)
+    val richdocumentDirectEditing: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES)
+    val richdocumentTemplates: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST)
+    val richdocumentOptionalMimetypeList: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD)
+    val sharingPublicAskForOptionalPassword: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME)
+    val richdocumentProductName: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_DIRECT_EDITING_ETAG)
+    val directEditingEtag: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_USER_STATUS)
+    val userStatus: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_USER_STATUS_SUPPORTS_EMOJI)
+    val userStatusSupportsEmoji: Int,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ETAG)
+    val etag: String?,
+    @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_FILES_LOCKING_VERSION)
+    val filesLockingVersion: String?
+)

+ 47 - 0
app/src/main/java/com/nextcloud/client/database/entity/ExternalLinkEntity.kt

@@ -0,0 +1,47 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME)
+data class ExternalLinkEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_ICON_URL)
+    val iconUrl: String?,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_LANGUAGE)
+    val language: String?,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_TYPE)
+    val type: Int,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_NAME)
+    val name: String?,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_URL)
+    val url: String,
+    @ColumnInfo(name = ProviderTableMeta.EXTERNAL_LINKS_REDIRECT)
+    val redirect: Int
+)

+ 119 - 0
app/src/main/java/com/nextcloud/client/database/entity/FileEntity.kt

@@ -0,0 +1,119 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.FILE_TABLE_NAME)
+data class FileEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_NAME)
+    val name: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_ENCRYPTED_NAME)
+    val encryptedName: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_PATH)
+    val path: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_PATH_DECRYPTED)
+    val pathDecrypted: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_PARENT)
+    val parent: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_CREATION)
+    val creation: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_MODIFIED)
+    val modified: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_CONTENT_TYPE)
+    val contentType: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_CONTENT_LENGTH)
+    val contentLength: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_STORAGE_PATH)
+    val storagePath: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_ACCOUNT_OWNER)
+    val accountOwner: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LAST_SYNC_DATE)
+    val lastSyncDate: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)
+    val lastSyncDateForData: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)
+    val modifiedAtLastSyncForData: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_ETAG)
+    val etag: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_ETAG_ON_SERVER)
+    val etagOnServer: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_SHARED_VIA_LINK)
+    val sharedViaLink: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_PERMISSIONS)
+    val permissions: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_REMOTE_ID)
+    val remoteId: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_UPDATE_THUMBNAIL)
+    val updateThumbnail: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_IS_DOWNLOADING)
+    val isDownloading: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_FAVORITE)
+    val favorite: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_IS_ENCRYPTED)
+    val isEncrypted: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_ETAG_IN_CONFLICT)
+    val etagInConflict: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_SHARED_WITH_SHAREE)
+    val sharedWithSharee: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_MOUNT_TYPE)
+    val mountType: Int?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_HAS_PREVIEW)
+    val hasPreview: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT)
+    val unreadCommentsCount: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_OWNER_ID)
+    val ownerId: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_OWNER_DISPLAY_NAME)
+    val ownerDisplayName: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_NOTE)
+    val note: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_SHAREES)
+    val sharees: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_RICH_WORKSPACE)
+    val richWorkspace: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_METADATA_SIZE)
+    val metadataSize: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCKED)
+    val locked: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TYPE)
+    val lockType: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER)
+    val lockOwner: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER_DISPLAY_NAME)
+    val lockOwnerDisplayName: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_OWNER_EDITOR)
+    val lockOwnerEditor: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TIMESTAMP)
+    val lockTimestamp: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TIMEOUT)
+    val lockTimeout: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILE_LOCK_TOKEN)
+    val lockToken: String?
+)

+ 49 - 0
app/src/main/java/com/nextcloud/client/database/entity/FilesystemEntity.kt

@@ -0,0 +1,49 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.FILESYSTEM_TABLE_NAME)
+data class FilesystemEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_LOCAL_PATH)
+    val localPath: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_IS_FOLDER)
+    val fileIsFolder: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_FOUND_RECENTLY)
+    val fileFoundRecently: Long,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_SENT_FOR_UPLOAD)
+    val fileSentForUpload: Int,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_SYNCED_FOLDER_ID)
+    val syncedFolderId: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_CRC32)
+    val crc32: String?,
+    @ColumnInfo(name = ProviderTableMeta.FILESYSTEM_FILE_MODIFIED)
+    val fileModified: Long
+)

+ 73 - 0
app/src/main/java/com/nextcloud/client/database/entity/ShareEntity.kt

@@ -0,0 +1,73 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.OCSHARES_TABLE_NAME)
+data class ShareEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_FILE_SOURCE)
+    val fileSource: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_ITEM_SOURCE)
+    val itemSource: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_TYPE)
+    val shareType: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_WITH)
+    val shareWith: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_PATH)
+    val path: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_PERMISSIONS)
+    val permissions: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARED_DATE)
+    val sharedDate: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_EXPIRATION_DATE)
+    val expirationDate: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_TOKEN)
+    val token: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME)
+    val shareWithDisplayName: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_IS_DIRECTORY)
+    val isDirectory: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_USER_ID)
+    val userId: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)
+    val idRemoteShared: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
+    val accountOwner: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED)
+    val isPasswordProtected: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_NOTE)
+    val note: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD)
+    val hideDownload: Int,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_LINK)
+    val shareLink: String?,
+    @ColumnInfo(name = ProviderTableMeta.OCSHARES_SHARE_LABEL)
+    val shareLabel: String?
+)

+ 61 - 0
app/src/main/java/com/nextcloud/client/database/entity/SyncedFolderEntity.kt

@@ -0,0 +1,61 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME)
+data class SyncedFolderEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH)
+    val localPath: String?,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH)
+    val remotePath: String?,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY)
+    val wifiOnly: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY)
+    val chargingOnly: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_EXISTING)
+    val existing: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ENABLED)
+    val enabled: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS)
+    val enabledTimestampMs: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE)
+    val subfolderByDate: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_ACCOUNT)
+    val account: String?,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION)
+    val uploadAction: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY)
+    val nameCollisionPolicy: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_TYPE)
+    val type: Int,
+    @ColumnInfo(name = ProviderTableMeta.SYNCED_FOLDER_HIDDEN)
+    val hidden: Int
+)

+ 65 - 0
app/src/main/java/com/nextcloud/client/database/entity/UploadEntity.kt

@@ -0,0 +1,65 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.UPLOADS_TABLE_NAME)
+data class UploadEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_LOCAL_PATH)
+    val localPath: String?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_REMOTE_PATH)
+    val remotePath: String?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_ACCOUNT_NAME)
+    val accountName: String?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_FILE_SIZE)
+    val fileSize: Long?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_STATUS)
+    val status: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_LOCAL_BEHAVIOUR)
+    val localBehaviour: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_UPLOAD_TIME)
+    val uploadTime: Int?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_NAME_COLLISION_POLICY)
+    val nameCollisionPolicy: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_CREATE_REMOTE_FOLDER)
+    val isCreateRemoteFolder: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP)
+    val uploadEndTimestamp: Int?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_LAST_RESULT)
+    val lastResult: Int?,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_WHILE_CHARGING_ONLY)
+    val isWhileChargingOnly: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_IS_WIFI_ONLY)
+    val isWifiOnly: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_CREATED_BY)
+    val createdBy: Int,
+    @ColumnInfo(name = ProviderTableMeta.UPLOADS_FOLDER_UNLOCK_TOKEN)
+    val folderUnlockToken: String?
+)

+ 39 - 0
app/src/main/java/com/nextcloud/client/database/entity/VirtualEntity.kt

@@ -0,0 +1,39 @@
+/*
+ * Nextcloud Android client application
+ *
+ *  @author Álvaro Brey
+ *  Copyright (C) 2022 Álvaro Brey
+ *  Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.nextcloud.client.database.entity
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta
+
+@Entity(tableName = ProviderTableMeta.VIRTUAL_TABLE_NAME)
+data class VirtualEntity(
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = ProviderTableMeta._ID)
+    val id: Int,
+    @ColumnInfo(name = ProviderTableMeta.VIRTUAL_TYPE)
+    val type: String,
+    @ColumnInfo(name = ProviderTableMeta.VIRTUAL_OCFILE_ID)
+    val ocFileId: Int
+)

+ 9 - 0
app/src/main/java/com/nextcloud/client/di/AppModule.java

@@ -39,6 +39,7 @@ import com.nextcloud.client.core.AsyncRunner;
 import com.nextcloud.client.core.Clock;
 import com.nextcloud.client.core.ClockImpl;
 import com.nextcloud.client.core.ThreadPoolAsyncRunner;
+import com.nextcloud.client.database.NextcloudDatabase;
 import com.nextcloud.client.device.DeviceInfo;
 import com.nextcloud.client.logger.FileLogHandler;
 import com.nextcloud.client.logger.Logger;
@@ -57,6 +58,7 @@ import com.owncloud.android.authentication.PassCodeManager;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.UploadsStorageManager;
+import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository;
 import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi;
 import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl;
@@ -75,6 +77,7 @@ import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.room.Room;
 import dagger.Module;
 import dagger.Provides;
 
@@ -91,6 +94,12 @@ class AppModule {
         return application;
     }
 
+    @Provides
+    @Singleton
+    NextcloudDatabase database(Context context) {
+        return Room.databaseBuilder(context, NextcloudDatabase.class, ProviderMeta.DB_NAME).build();
+    }
+
     @Provides
     PackageManager packageManager(Application application) {
         return application.getPackageManager();

+ 1 - 1
app/src/main/java/com/owncloud/android/db/ProviderMeta.java

@@ -35,7 +35,7 @@ import java.util.List;
  */
 public class ProviderMeta {
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 64;
+    public static final int DB_VERSION = 65;
 
     private ProviderMeta() {
         // No instance

+ 73 - 55
app/src/main/java/com/owncloud/android/providers/FileContentProvider.java

@@ -37,12 +37,12 @@ import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Binder;
 import android.text.TextUtils;
 
 import com.nextcloud.client.core.Clock;
+import com.nextcloud.client.database.NextcloudDatabase;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
@@ -68,6 +68,10 @@ import javax.inject.Inject;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+import androidx.sqlite.db.SupportSQLiteOpenHelper;
+import androidx.sqlite.db.SupportSQLiteQuery;
+import androidx.sqlite.db.SupportSQLiteQueryBuilder;
 import dagger.android.AndroidInjection;
 import third_parties.aosp.SQLiteTokenizer;
 
@@ -118,7 +122,7 @@ public class FileContentProvider extends ContentProvider {
     private static final Map<String, String> FILE_PROJECTION_MAP;
 
     static {
-        HashMap<String,String> tempMap = new HashMap<>();
+        HashMap<String, String> tempMap = new HashMap<>();
         for (String projection : ProviderTableMeta.FILE_ALL_COLUMNS) {
             tempMap.put(projection, projection);
         }
@@ -127,7 +131,8 @@ public class FileContentProvider extends ContentProvider {
 
 
     @Inject protected Clock clock;
-    private DataBaseHelper mDbHelper;
+    @Inject NextcloudDatabase database;
+    private SupportSQLiteOpenHelper mDbHelper;
     private Context mContext;
     private UriMatcher mUriMatcher;
 
@@ -138,7 +143,7 @@ public class FileContentProvider extends ContentProvider {
         }
 
         int count;
-        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
         db.beginTransaction();
         try {
             count = delete(db, uri, where, whereArgs);
@@ -150,7 +155,7 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
 
-    private int delete(SQLiteDatabase db, Uri uri, String where, String... whereArgs) {
+    private int delete(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
         if (isCallerNotAllowed(uri)) {
             return -1;
         }
@@ -205,7 +210,7 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
 
-    private int deleteDirectory(SQLiteDatabase db, Uri uri, String where, String... whereArgs) {
+    private int deleteDirectory(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
         int count = 0;
 
         Cursor children = query(uri, PROJECTION_CONTENT_TYPE, null, null, null);
@@ -238,7 +243,7 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
 
-    private int deleteSingleFile(SQLiteDatabase db, Uri uri, String where, String... whereArgs) {
+    private int deleteSingleFile(SupportSQLiteDatabase db, Uri uri, String where, String... whereArgs) {
         int count = 0;
 
         try (Cursor c = query(db, uri, PROJECTION_REMOTE_ID, where, whereArgs, null)) {
@@ -255,7 +260,7 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
 
-    private int deleteWithUri(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
+    private int deleteWithUri(SupportSQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
         final String[] argsWithUri = VerificationUtils.prependUriFirstSegmentToSelectionArgs(whereArgs, uri);
         return db.delete(ProviderTableMeta.FILE_TABLE_NAME,
                          ProviderTableMeta._ID + "=?"
@@ -281,7 +286,7 @@ public class FileContentProvider extends ContentProvider {
         }
 
         Uri newUri;
-        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
         db.beginTransaction();
         try {
             newUri = insert(db, uri, values);
@@ -293,7 +298,7 @@ public class FileContentProvider extends ContentProvider {
         return newUri;
     }
 
-    private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
+    private Uri insert(SupportSQLiteDatabase db, Uri uri, ContentValues values) {
         // verify only for those requests that are not internal (files table)
         switch (mUriMatcher.match(uri)) {
             case ROOT_DIRECTORY:
@@ -318,7 +323,7 @@ public class FileContentProvider extends ContentProvider {
                 // FileDataStorageManager and bring it to FileContentProvider
                 if (!doubleCheck.moveToFirst()) {
                     doubleCheck.close();
-                    long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
+                    long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                     if (rowId > 0) {
                         return ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
                     } else {
@@ -337,7 +342,7 @@ public class FileContentProvider extends ContentProvider {
 
             case SHARES:
                 Uri insertedShareUri;
-                long idShares = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
+                long idShares = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (idShares > 0) {
                     insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, idShares);
                 } else {
@@ -350,7 +355,7 @@ public class FileContentProvider extends ContentProvider {
 
             case CAPABILITIES:
                 Uri insertedCapUri;
-                long idCapabilities = db.insert(ProviderTableMeta.CAPABILITIES_TABLE_NAME, null, values);
+                long idCapabilities = db.insert(ProviderTableMeta.CAPABILITIES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (idCapabilities > 0) {
                     insertedCapUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_CAPABILITIES, idCapabilities);
                 } else {
@@ -360,7 +365,7 @@ public class FileContentProvider extends ContentProvider {
 
             case UPLOADS:
                 Uri insertedUploadUri;
-                long uploadId = db.insert(ProviderTableMeta.UPLOADS_TABLE_NAME, null, values);
+                long uploadId = db.insert(ProviderTableMeta.UPLOADS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (uploadId > 0) {
                     insertedUploadUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_UPLOADS, uploadId);
                 } else {
@@ -370,7 +375,7 @@ public class FileContentProvider extends ContentProvider {
 
             case SYNCED_FOLDERS:
                 Uri insertedSyncedFolderUri;
-                long syncedFolderId = db.insert(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, null, values);
+                long syncedFolderId = db.insert(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (syncedFolderId > 0) {
                     insertedSyncedFolderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
                                                                          syncedFolderId);
@@ -381,7 +386,7 @@ public class FileContentProvider extends ContentProvider {
 
             case EXTERNAL_LINKS:
                 Uri insertedExternalLinkUri;
-                long externalLinkId = db.insert(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME, null, values);
+                long externalLinkId = db.insert(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (externalLinkId > 0) {
                     insertedExternalLinkUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_EXTERNAL_LINKS,
                                                                          externalLinkId);
@@ -392,7 +397,7 @@ public class FileContentProvider extends ContentProvider {
 
             case ARBITRARY_DATA:
                 Uri insertedArbitraryDataUri;
-                long arbitraryDataId = db.insert(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, null, values);
+                long arbitraryDataId = db.insert(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (arbitraryDataId > 0) {
                     insertedArbitraryDataUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_ARBITRARY_DATA,
                                                                           arbitraryDataId);
@@ -402,7 +407,7 @@ public class FileContentProvider extends ContentProvider {
                 return insertedArbitraryDataUri;
             case VIRTUAL:
                 Uri insertedVirtualUri;
-                long virtualId = db.insert(ProviderTableMeta.VIRTUAL_TABLE_NAME, null, values);
+                long virtualId = db.insert(ProviderTableMeta.VIRTUAL_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
 
                 if (virtualId > 0) {
                     insertedVirtualUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_VIRTUAL, virtualId);
@@ -413,7 +418,7 @@ public class FileContentProvider extends ContentProvider {
                 return insertedVirtualUri;
             case FILESYSTEM:
                 Uri insertedFilesystemUri;
-                long filesystemId = db.insert(ProviderTableMeta.FILESYSTEM_TABLE_NAME, null, values);
+                long filesystemId = db.insert(ProviderTableMeta.FILESYSTEM_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values);
                 if (filesystemId > 0) {
                     insertedFilesystemUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILESYSTEM,
                                                                        filesystemId);
@@ -426,7 +431,7 @@ public class FileContentProvider extends ContentProvider {
         }
     }
 
-    private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, ContentValues newShare) {
+    private void updateFilesTableAccordingToShareInsertion(SupportSQLiteDatabase db, ContentValues newShare) {
         ContentValues fileValues = new ContentValues();
         ShareType newShareType = ShareType.fromValue(newShare.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE));
 
@@ -456,14 +461,14 @@ public class FileContentProvider extends ContentProvider {
             newShare.getAsString(ProviderTableMeta.OCSHARES_PATH),
             newShare.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
         };
-        db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, where, whereArgs);
+        db.update(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, fileValues, where, whereArgs);
     }
 
 
     @Override
     public boolean onCreate() {
         AndroidInjection.inject(this);
-        mDbHelper = new DataBaseHelper(getContext());
+        mDbHelper = database.getOpenHelper();
         mContext = getContext();
 
         if (mContext == null) {
@@ -510,7 +515,7 @@ public class FileContentProvider extends ContentProvider {
         }
 
         Cursor result;
-        SQLiteDatabase db = mDbHelper.getReadableDatabase();
+        SupportSQLiteDatabase db = mDbHelper.getReadableDatabase();
         db.beginTransaction();
         try {
             result = query(db, uri, projection, selection, selectionArgs, sortOrder);
@@ -521,7 +526,7 @@ public class FileContentProvider extends ContentProvider {
         return result;
     }
 
-    private Cursor query(SQLiteDatabase db,
+    private Cursor query(SupportSQLiteDatabase db,
                          Uri uri,
                          String[] projectionArray,
                          String selection,
@@ -531,49 +536,49 @@ public class FileContentProvider extends ContentProvider {
         // verify only for those requests that are not internal
         final int uriMatch = mUriMatcher.match(uri);
 
-        SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
-
-
+        String tableName;
         switch (uriMatch) {
             case ROOT_DIRECTORY:
             case DIRECTORY:
             case SINGLE_FILE:
                 VerificationUtils.verifyWhere(selection); // prevent injection in public paths
-                sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
+                tableName = ProviderTableMeta.FILE_TABLE_NAME;
                 break;
             case SHARES:
-                sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME);
+                tableName = ProviderTableMeta.OCSHARES_TABLE_NAME;
                 break;
             case CAPABILITIES:
-                sqlQuery.setTables(ProviderTableMeta.CAPABILITIES_TABLE_NAME);
+                tableName = ProviderTableMeta.CAPABILITIES_TABLE_NAME;
                 break;
             case UPLOADS:
-                sqlQuery.setTables(ProviderTableMeta.UPLOADS_TABLE_NAME);
+                tableName = ProviderTableMeta.UPLOADS_TABLE_NAME;
                 break;
             case SYNCED_FOLDERS:
-                sqlQuery.setTables(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME);
+                tableName = ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME;
                 break;
             case EXTERNAL_LINKS:
-                sqlQuery.setTables(ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME);
+                tableName = ProviderTableMeta.EXTERNAL_LINKS_TABLE_NAME;
                 break;
             case ARBITRARY_DATA:
-                sqlQuery.setTables(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME);
+                tableName = ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME;
                 break;
             case VIRTUAL:
-                sqlQuery.setTables(ProviderTableMeta.VIRTUAL_TABLE_NAME);
+                tableName = ProviderTableMeta.VIRTUAL_TABLE_NAME;
                 break;
             case FILESYSTEM:
-                sqlQuery.setTables(ProviderTableMeta.FILESYSTEM_TABLE_NAME);
+                tableName = ProviderTableMeta.FILESYSTEM_TABLE_NAME;
                 break;
             default:
                 throw new IllegalArgumentException("Unknown uri id: " + uri);
         }
 
+        SupportSQLiteQueryBuilder queryBuilder = SupportSQLiteQueryBuilder.builder(tableName);
+
 
         // add ID to arguments if Uri has more than one segment
-        if (uriMatch != ROOT_DIRECTORY && uri.getPathSegments().size() > SINGLE_PATH_SEGMENT ) {
+        if (uriMatch != ROOT_DIRECTORY && uri.getPathSegments().size() > SINGLE_PATH_SEGMENT) {
             String idColumn = uriMatch == DIRECTORY ? ProviderTableMeta.FILE_PARENT : ProviderTableMeta._ID;
-            sqlQuery.appendWhere(idColumn + "=?");
+            selection = idColumn + "=? AND " + selection;
             selectionArgs = VerificationUtils.prependUriFirstSegmentToSelectionArgs(selectionArgs, uri);
         }
 
@@ -619,11 +624,12 @@ public class FileContentProvider extends ContentProvider {
         // DB case_sensitive
         db.execSQL("PRAGMA case_sensitive_like = true");
 
-        // only file list is accessible via content provider, so only this has to be protected with projectionMap
-        if ((uriMatch == ROOT_DIRECTORY || uriMatch == SINGLE_FILE ||
-            uriMatch == DIRECTORY) && projectionArray != null) {
-            sqlQuery.setProjectionMap(FILE_PROJECTION_MAP);
-        }
+        // TODO
+//        // only file list is accessible via content provider, so only this has to be protected with projectionMap
+//        if ((uriMatch == ROOT_DIRECTORY || uriMatch == SINGLE_FILE ||
+//            uriMatch == DIRECTORY) && projectionArray != null) {
+//            sqlQuery.setProjectionMap(FILE_PROJECTION_MAP);
+//        }
 
         // if both are null, let them pass to query
         if (selectionArgs == null && selection != null) {
@@ -631,8 +637,20 @@ public class FileContentProvider extends ContentProvider {
             selection = "(?)";
         }
 
-        sqlQuery.setStrict(true);
-        Cursor c = sqlQuery.query(db, projectionArray, selection, selectionArgs, null, null, order);
+        // TODO
+//        sqlQuery.setStrict(true);
+
+        if (!TextUtils.isEmpty(selection)) {
+            queryBuilder.selection(selection, selectionArgs);
+        }
+        if (!TextUtils.isEmpty(order)) {
+            queryBuilder.orderBy(order);
+        }
+        if (projectionArray != null && projectionArray.length > 0) {
+            queryBuilder.columns(projectionArray);
+        }
+        final SupportSQLiteQuery supportSQLiteQuery = queryBuilder.create();
+        final Cursor c = db.query(supportSQLiteQuery);
         c.setNotificationUri(mContext.getContentResolver(), uri);
         return c;
     }
@@ -644,7 +662,7 @@ public class FileContentProvider extends ContentProvider {
         }
 
         int count;
-        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        SupportSQLiteDatabase db = mDbHelper.getWritableDatabase();
         db.beginTransaction();
         try {
             count = update(db, uri, values, selection, selectionArgs);
@@ -656,7 +674,7 @@ public class FileContentProvider extends ContentProvider {
         return count;
     }
 
-    private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String... selectionArgs) {
+    private int update(SupportSQLiteDatabase db, Uri uri, ContentValues values, String selection, String... selectionArgs) {
         // verify contentValues and selection for public paths to prevent injection
         switch (mUriMatcher.match(uri)) {
             case ROOT_DIRECTORY:
@@ -670,19 +688,19 @@ public class FileContentProvider extends ContentProvider {
             case DIRECTORY:
                 return 0;
             case SHARES:
-                return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             case CAPABILITIES:
-                return db.update(ProviderTableMeta.CAPABILITIES_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.CAPABILITIES_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             case UPLOADS:
-                return db.update(ProviderTableMeta.UPLOADS_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.UPLOADS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             case SYNCED_FOLDERS:
-                return db.update(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             case ARBITRARY_DATA:
-                return db.update(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.ARBITRARY_DATA_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             case FILESYSTEM:
-                return db.update(ProviderTableMeta.FILESYSTEM_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.FILESYSTEM_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
             default:
-                return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs);
+                return db.update(ProviderTableMeta.FILE_TABLE_NAME, SQLiteDatabase.CONFLICT_REPLACE, values, selection, selectionArgs);
         }
     }
 
@@ -695,7 +713,7 @@ public class FileContentProvider extends ContentProvider {
         ContentProviderResult[] results = new ContentProviderResult[operations.size()];
         int i = 0;
 
-        SQLiteDatabase database = mDbHelper.getWritableDatabase();
+        SupportSQLiteDatabase database = mDbHelper.getWritableDatabase();
         database.beginTransaction();  // it's supposed that transactions can be nested
         try {
             for (ContentProviderOperation operation : operations) {

+ 1 - 0
build.gradle

@@ -16,6 +16,7 @@ buildscript {
         checkerVersion = "3.21.2"
         exoplayerVersion = "2.18.1"
         documentScannerVersion = "1.0.1"
+        roomVersion = "2.4.3"
 
         ciBuild = System.getenv("CI") == "true"
     }