|
@@ -2,7 +2,7 @@
|
|
* Nextcloud Talk application
|
|
* Nextcloud Talk application
|
|
*
|
|
*
|
|
* @author Marcel Hibbe
|
|
* @author Marcel Hibbe
|
|
- * Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
|
|
|
|
|
+ * Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
|
*
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* it under the terms of the GNU General Public License as published by
|
|
@@ -21,46 +21,50 @@
|
|
package com.nextcloud.talk.jobs
|
|
package com.nextcloud.talk.jobs
|
|
|
|
|
|
import android.Manifest
|
|
import android.Manifest
|
|
|
|
+import android.app.Notification
|
|
|
|
+import android.app.NotificationManager
|
|
|
|
+import android.app.PendingIntent
|
|
import android.content.Context
|
|
import android.content.Context
|
|
|
|
+import android.content.Intent
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import android.os.Build
|
|
|
|
+import android.os.Bundle
|
|
|
|
+import android.os.SystemClock
|
|
import android.util.Log
|
|
import android.util.Log
|
|
|
|
+import androidx.core.app.NotificationCompat
|
|
import androidx.core.content.PermissionChecker
|
|
import androidx.core.content.PermissionChecker
|
|
import androidx.work.Data
|
|
import androidx.work.Data
|
|
|
|
+import androidx.work.ExistingWorkPolicy
|
|
import androidx.work.OneTimeWorkRequest
|
|
import androidx.work.OneTimeWorkRequest
|
|
import androidx.work.WorkManager
|
|
import androidx.work.WorkManager
|
|
import androidx.work.Worker
|
|
import androidx.work.Worker
|
|
import androidx.work.WorkerParameters
|
|
import androidx.work.WorkerParameters
|
|
import autodagger.AutoInjector
|
|
import autodagger.AutoInjector
|
|
import com.bluelinelabs.conductor.Controller
|
|
import com.bluelinelabs.conductor.Controller
|
|
|
|
+import com.nextcloud.talk.R
|
|
|
|
+import com.nextcloud.talk.activities.MainActivity
|
|
import com.nextcloud.talk.api.NcApi
|
|
import com.nextcloud.talk.api.NcApi
|
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
import com.nextcloud.talk.data.user.model.User
|
|
import com.nextcloud.talk.data.user.model.User
|
|
-import com.nextcloud.talk.models.json.generic.GenericOverall
|
|
|
|
|
|
+import com.nextcloud.talk.upload.chunked.ChunkedFileUploader
|
|
|
|
+import com.nextcloud.talk.upload.chunked.OnDataTransferProgressListener
|
|
|
|
+import com.nextcloud.talk.upload.normal.FileUploader
|
|
import com.nextcloud.talk.users.UserManager
|
|
import com.nextcloud.talk.users.UserManager
|
|
-import com.nextcloud.talk.utils.ApiUtils
|
|
|
|
-import com.nextcloud.talk.utils.UriUtils
|
|
|
|
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FILE_PATHS
|
|
|
|
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
|
|
|
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_META_DATA
|
|
|
|
|
|
+import com.nextcloud.talk.utils.FileUtils
|
|
|
|
+import com.nextcloud.talk.utils.NotificationUtils
|
|
|
|
+import com.nextcloud.talk.utils.RemoteFileUtils
|
|
|
|
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL
|
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
|
|
|
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
|
|
|
|
+import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
|
-import io.reactivex.Observer
|
|
|
|
-import io.reactivex.android.schedulers.AndroidSchedulers
|
|
|
|
-import io.reactivex.disposables.Disposable
|
|
|
|
-import io.reactivex.schedulers.Schedulers
|
|
|
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
-import okhttp3.RequestBody
|
|
|
|
-import retrofit2.Response
|
|
|
|
-import java.io.File
|
|
|
|
-import java.io.FileNotFoundException
|
|
|
|
-import java.io.FileOutputStream
|
|
|
|
-import java.io.InputStream
|
|
|
|
|
|
+import okhttp3.OkHttpClient
|
|
import javax.inject.Inject
|
|
import javax.inject.Inject
|
|
|
|
|
|
@AutoInjector(NextcloudTalkApplication::class)
|
|
@AutoInjector(NextcloudTalkApplication::class)
|
|
class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerParameters) :
|
|
class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerParameters) :
|
|
- Worker(context, workerParameters) {
|
|
|
|
|
|
+ Worker(context, workerParameters), OnDataTransferProgressListener {
|
|
|
|
|
|
@Inject
|
|
@Inject
|
|
lateinit var ncApi: NcApi
|
|
lateinit var ncApi: NcApi
|
|
@@ -71,6 +75,21 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
|
@Inject
|
|
@Inject
|
|
lateinit var appPreferences: AppPreferences
|
|
lateinit var appPreferences: AppPreferences
|
|
|
|
|
|
|
|
+ @Inject
|
|
|
|
+ lateinit var okHttpClient: OkHttpClient
|
|
|
|
+
|
|
|
|
+ lateinit var fileName: String
|
|
|
|
+
|
|
|
|
+ private var mNotifyManager: NotificationManager? = null
|
|
|
|
+ private var mBuilder: NotificationCompat.Builder? = null
|
|
|
|
+ private lateinit var notification: Notification
|
|
|
|
+ private var notificationId: Int = 0
|
|
|
|
+
|
|
|
|
+ lateinit var roomToken: String
|
|
|
|
+ lateinit var conversationName: String
|
|
|
|
+ lateinit var currentUser: User
|
|
|
|
+
|
|
|
|
+ @Suppress("Detekt.TooGenericExceptionCaught")
|
|
override fun doWork(): Result {
|
|
override fun doWork(): Result {
|
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
|
|
|
|
|
@@ -85,139 +104,173 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
|
}
|
|
}
|
|
|
|
|
|
return try {
|
|
return try {
|
|
- val currentUser = userManager.currentUser.blockingGet()
|
|
|
|
- val sourcefiles = inputData.getStringArray(DEVICE_SOURCEFILES)
|
|
|
|
- val ncTargetpath = inputData.getString(NC_TARGETPATH)
|
|
|
|
- val roomToken = inputData.getString(ROOM_TOKEN)
|
|
|
|
|
|
+ currentUser = userManager.currentUser.blockingGet()
|
|
|
|
+ val sourceFile = inputData.getString(DEVICE_SOURCE_FILE)
|
|
|
|
+ roomToken = inputData.getString(ROOM_TOKEN)!!
|
|
|
|
+ conversationName = inputData.getString(CONVERSATION_NAME)!!
|
|
val metaData = inputData.getString(META_DATA)
|
|
val metaData = inputData.getString(META_DATA)
|
|
|
|
|
|
checkNotNull(currentUser)
|
|
checkNotNull(currentUser)
|
|
- checkNotNull(sourcefiles)
|
|
|
|
- require(sourcefiles.isNotEmpty())
|
|
|
|
- checkNotNull(ncTargetpath)
|
|
|
|
|
|
+ checkNotNull(sourceFile)
|
|
|
|
+ require(sourceFile.isNotEmpty())
|
|
checkNotNull(roomToken)
|
|
checkNotNull(roomToken)
|
|
|
|
|
|
- for (index in sourcefiles.indices) {
|
|
|
|
- val sourceFileUri = Uri.parse(sourcefiles[index])
|
|
|
|
- uploadFile(
|
|
|
|
- currentUser!!,
|
|
|
|
- UploadItem(
|
|
|
|
- sourceFileUri,
|
|
|
|
- UriUtils.getFileName(sourceFileUri, context),
|
|
|
|
- createRequestBody(sourceFileUri)
|
|
|
|
- ),
|
|
|
|
- ncTargetpath,
|
|
|
|
|
|
+ val sourceFileUri = Uri.parse(sourceFile)
|
|
|
|
+ fileName = FileUtils.getFileName(sourceFileUri, context)
|
|
|
|
+ val file = FileUtils.getFileFromUri(context, sourceFileUri)
|
|
|
|
+ val remotePath = getRemotePath(currentUser)
|
|
|
|
+ val uploadSuccess: Boolean
|
|
|
|
+
|
|
|
|
+ if (file != null && file.length() > CHUNK_UPLOAD_THRESHOLD_SIZE) {
|
|
|
|
+ Log.d(TAG, "starting chunked upload because size is " + file.length())
|
|
|
|
+
|
|
|
|
+ initNotification()
|
|
|
|
+ val mimeType = context.contentResolver.getType(sourceFileUri)?.toMediaTypeOrNull()
|
|
|
|
+
|
|
|
|
+ uploadSuccess = ChunkedFileUploader(
|
|
|
|
+ okHttpClient!!,
|
|
|
|
+ currentUser,
|
|
roomToken,
|
|
roomToken,
|
|
- metaData
|
|
|
|
|
|
+ metaData,
|
|
|
|
+ this
|
|
|
|
+ ).upload(
|
|
|
|
+ file,
|
|
|
|
+ mimeType,
|
|
|
|
+ remotePath
|
|
)
|
|
)
|
|
|
|
+ } else {
|
|
|
|
+ Log.d(TAG, "starting normal upload (not chunked)")
|
|
|
|
+
|
|
|
|
+ uploadSuccess = FileUploader(
|
|
|
|
+ context,
|
|
|
|
+ currentUser,
|
|
|
|
+ roomToken,
|
|
|
|
+ ncApi
|
|
|
|
+ ).upload(
|
|
|
|
+ sourceFileUri,
|
|
|
|
+ fileName,
|
|
|
|
+ remotePath,
|
|
|
|
+ metaData
|
|
|
|
+ ).blockingFirst()
|
|
}
|
|
}
|
|
- Result.success()
|
|
|
|
- } catch (e: IllegalStateException) {
|
|
|
|
- Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
|
|
|
- Result.failure()
|
|
|
|
- } catch (e: IllegalArgumentException) {
|
|
|
|
- Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
|
|
|
|
- Result.failure()
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
|
|
- @Suppress("Detekt.TooGenericExceptionCaught")
|
|
|
|
- private fun createRequestBody(sourcefileUri: Uri): RequestBody? {
|
|
|
|
- var requestBody: RequestBody? = null
|
|
|
|
- try {
|
|
|
|
- val input: InputStream = context.contentResolver.openInputStream(sourcefileUri)!!
|
|
|
|
- val buf = ByteArray(input.available())
|
|
|
|
- while (input.read(buf) != -1)
|
|
|
|
- requestBody = RequestBody.create("application/octet-stream".toMediaTypeOrNull(), buf)
|
|
|
|
|
|
+ if (uploadSuccess) {
|
|
|
|
+ mNotifyManager?.cancel(notificationId)
|
|
|
|
+ return Result.success()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Log.e(TAG, "Something went wrong when trying to upload file")
|
|
|
|
+ showFailedToUploadNotification()
|
|
|
|
+ return Result.failure()
|
|
} catch (e: Exception) {
|
|
} catch (e: Exception) {
|
|
- Log.e(javaClass.simpleName, "failed to create RequestBody for $sourcefileUri", e)
|
|
|
|
|
|
+ Log.e(TAG, "Something went wrong when trying to upload file", e)
|
|
|
|
+ showFailedToUploadNotification()
|
|
|
|
+ return Result.failure()
|
|
}
|
|
}
|
|
- return requestBody
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- private fun uploadFile(
|
|
|
|
- currentUser: User,
|
|
|
|
- uploadItem: UploadItem,
|
|
|
|
- ncTargetPath: String?,
|
|
|
|
- roomToken: String?,
|
|
|
|
- metaData: String?
|
|
|
|
- ) {
|
|
|
|
- ncApi.uploadFile(
|
|
|
|
- ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
|
|
|
- ApiUtils.getUrlForFileUpload(currentUser.baseUrl, currentUser.userId, ncTargetPath, uploadItem.fileName),
|
|
|
|
- uploadItem.requestBody
|
|
|
|
|
|
+ private fun getRemotePath(currentUser: User): String {
|
|
|
|
+ var remotePath = CapabilitiesUtilNew.getAttachmentFolder(currentUser)!! + "/" + fileName
|
|
|
|
+ remotePath = RemoteFileUtils.getNewPathIfFileExists(
|
|
|
|
+ ncApi,
|
|
|
|
+ currentUser,
|
|
|
|
+ remotePath
|
|
)
|
|
)
|
|
- .subscribeOn(Schedulers.io())
|
|
|
|
- .observeOn(AndroidSchedulers.mainThread())
|
|
|
|
- .subscribe(object : Observer<Response<GenericOverall>> {
|
|
|
|
- override fun onSubscribe(d: Disposable) {
|
|
|
|
- // unused atm
|
|
|
|
- }
|
|
|
|
|
|
+ return remotePath
|
|
|
|
+ }
|
|
|
|
|
|
- override fun onNext(t: Response<GenericOverall>) {
|
|
|
|
- // unused atm
|
|
|
|
- }
|
|
|
|
|
|
+ override fun onTransferProgress(
|
|
|
|
+ percentage: Int
|
|
|
|
+ ) {
|
|
|
|
+ notification = mBuilder!!
|
|
|
|
+ .setProgress(HUNDRED_PERCENT, percentage, false)
|
|
|
|
+ .setContentText(getNotificationContentText(percentage))
|
|
|
|
+ .build()
|
|
|
|
|
|
- override fun onError(e: Throwable) {
|
|
|
|
- Log.e(TAG, "failed to upload file ${uploadItem.fileName}")
|
|
|
|
- }
|
|
|
|
|
|
+ mNotifyManager!!.notify(notificationId, notification)
|
|
|
|
+ }
|
|
|
|
|
|
- override fun onComplete() {
|
|
|
|
- shareFile(roomToken, currentUser, ncTargetPath, uploadItem.fileName, metaData)
|
|
|
|
- copyFileToCache(uploadItem.uri, uploadItem.fileName)
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
|
|
+ private fun initNotification() {
|
|
|
|
+ mNotifyManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
|
|
+ mBuilder = NotificationCompat.Builder(context, NotificationUtils.NOTIFICATION_CHANNEL_UPLOADS)
|
|
|
|
+
|
|
|
|
+ notification = mBuilder!!
|
|
|
|
+ .setContentTitle(context.resources.getString(R.string.nc_upload_in_progess))
|
|
|
|
+ .setContentText(getNotificationContentText(ZERO_PERCENT))
|
|
|
|
+ .setSmallIcon(R.drawable.upload_white)
|
|
|
|
+ .setOngoing(true)
|
|
|
|
+ .setProgress(HUNDRED_PERCENT, ZERO_PERCENT, false)
|
|
|
|
+ .setPriority(NotificationCompat.PRIORITY_LOW)
|
|
|
|
+ .setContentIntent(getIntentToOpenConversation())
|
|
|
|
+ .build()
|
|
|
|
+
|
|
|
|
+ notificationId = SystemClock.uptimeMillis().toInt()
|
|
|
|
+ mNotifyManager!!.notify(notificationId, notification)
|
|
}
|
|
}
|
|
|
|
|
|
- private fun copyFileToCache(sourceFileUri: Uri, filename: String) {
|
|
|
|
- val cachedFile = File(context.cacheDir, filename)
|
|
|
|
|
|
+ private fun getNotificationContentText(percentage: Int): String {
|
|
|
|
+ return String.format(
|
|
|
|
+ context.resources.getString(R.string.nc_upload_notification_text),
|
|
|
|
+ getShortenedFileName(),
|
|
|
|
+ conversationName,
|
|
|
|
+ percentage
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
|
|
- if (cachedFile.exists()) {
|
|
|
|
- Log.d(TAG, "file is already in cache")
|
|
|
|
|
|
+ private fun getShortenedFileName(): String {
|
|
|
|
+ return if (fileName.length > NOTIFICATION_FILE_NAME_MAX_LENGTH) {
|
|
|
|
+ THREE_DOTS + fileName.takeLast(NOTIFICATION_FILE_NAME_MAX_LENGTH)
|
|
} else {
|
|
} else {
|
|
- val outputStream = FileOutputStream(cachedFile)
|
|
|
|
- try {
|
|
|
|
- val inputStream: InputStream? = context.contentResolver.openInputStream(sourceFileUri)
|
|
|
|
- inputStream?.use { input ->
|
|
|
|
- outputStream.use { output ->
|
|
|
|
- input.copyTo(output)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } catch (e: FileNotFoundException) {
|
|
|
|
- Log.w(TAG, "failed to copy file to cache", e)
|
|
|
|
- }
|
|
|
|
|
|
+ fileName
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private fun shareFile(
|
|
|
|
- roomToken: String?,
|
|
|
|
- currentUser: User,
|
|
|
|
- ncTargetpath: String?,
|
|
|
|
- filename: String?,
|
|
|
|
- metaData: String?
|
|
|
|
- ) {
|
|
|
|
- val paths: MutableList<String> = ArrayList()
|
|
|
|
- paths.add("$ncTargetpath/$filename")
|
|
|
|
-
|
|
|
|
- val data = Data.Builder()
|
|
|
|
- .putLong(KEY_INTERNAL_USER_ID, currentUser.id!!)
|
|
|
|
- .putString(KEY_ROOM_TOKEN, roomToken)
|
|
|
|
- .putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
|
|
|
|
- .putString(KEY_META_DATA, metaData)
|
|
|
|
- .build()
|
|
|
|
- val shareWorker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
|
|
|
- .setInputData(data)
|
|
|
|
|
|
+ private fun getIntentToOpenConversation(): PendingIntent? {
|
|
|
|
+ val bundle = Bundle()
|
|
|
|
+ val intent = Intent(context, MainActivity::class.java)
|
|
|
|
+ intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
|
|
|
+
|
|
|
|
+ bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
|
|
|
+ bundle.putParcelable(KEY_USER_ENTITY, currentUser)
|
|
|
|
+ bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, false)
|
|
|
|
+
|
|
|
|
+ intent.putExtras(bundle)
|
|
|
|
+
|
|
|
|
+ val requestCode = System.currentTimeMillis().toInt()
|
|
|
|
+ val intentFlag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
|
|
+ PendingIntent.FLAG_MUTABLE
|
|
|
|
+ } else {
|
|
|
|
+ 0
|
|
|
|
+ }
|
|
|
|
+ return PendingIntent.getActivity(context, requestCode, intent, intentFlag)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private fun showFailedToUploadNotification() {
|
|
|
|
+ val failureTitle = context.resources.getString(R.string.nc_upload_failed_notification_title)
|
|
|
|
+ val failureText = String.format(
|
|
|
|
+ context.resources.getString(R.string.nc_upload_failed_notification_text),
|
|
|
|
+ fileName
|
|
|
|
+ )
|
|
|
|
+ notification = mBuilder!!
|
|
|
|
+ .setContentTitle(failureTitle)
|
|
|
|
+ .setContentText(failureText)
|
|
.build()
|
|
.build()
|
|
- WorkManager.getInstance().enqueue(shareWorker)
|
|
|
|
|
|
+
|
|
|
|
+ mNotifyManager!!.notify(notificationId, notification)
|
|
}
|
|
}
|
|
|
|
|
|
companion object {
|
|
companion object {
|
|
- const val TAG = "UploadFileWorker"
|
|
|
|
|
|
+ private val TAG = UploadAndShareFilesWorker::class.simpleName
|
|
|
|
+ private const val DEVICE_SOURCE_FILE = "DEVICE_SOURCE_FILE"
|
|
|
|
+ private const val ROOM_TOKEN = "ROOM_TOKEN"
|
|
|
|
+ private const val CONVERSATION_NAME = "CONVERSATION_NAME"
|
|
|
|
+ private const val META_DATA = "META_DATA"
|
|
|
|
+ private const val CHUNK_UPLOAD_THRESHOLD_SIZE: Long = 1024000
|
|
|
|
+ private const val NOTIFICATION_FILE_NAME_MAX_LENGTH = 20
|
|
|
|
+ private const val THREE_DOTS = "…"
|
|
|
|
+ private const val HUNDRED_PERCENT = 100
|
|
|
|
+ private const val ZERO_PERCENT = 0
|
|
const val REQUEST_PERMISSION = 3123
|
|
const val REQUEST_PERMISSION = 3123
|
|
- const val DEVICE_SOURCEFILES = "DEVICE_SOURCEFILES"
|
|
|
|
- const val NC_TARGETPATH = "NC_TARGETPATH"
|
|
|
|
- const val ROOM_TOKEN = "ROOM_TOKEN"
|
|
|
|
- const val META_DATA = "META_DATA"
|
|
|
|
|
|
|
|
fun isStoragePermissionGranted(context: Context): Boolean {
|
|
fun isStoragePermissionGranted(context: Context): Boolean {
|
|
return when {
|
|
return when {
|
|
@@ -276,11 +329,23 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- private data class UploadItem(
|
|
|
|
- val uri: Uri,
|
|
|
|
- val fileName: String,
|
|
|
|
- val requestBody: RequestBody?
|
|
|
|
- )
|
|
|
|
|
|
+ fun upload(
|
|
|
|
+ fileUri: String,
|
|
|
|
+ roomToken: String,
|
|
|
|
+ conversationName: String,
|
|
|
|
+ metaData: String?
|
|
|
|
+ ) {
|
|
|
|
+ val data: Data = Data.Builder()
|
|
|
|
+ .putString(DEVICE_SOURCE_FILE, fileUri)
|
|
|
|
+ .putString(ROOM_TOKEN, roomToken)
|
|
|
|
+ .putString(CONVERSATION_NAME, conversationName)
|
|
|
|
+ .putString(META_DATA, metaData)
|
|
|
|
+ .build()
|
|
|
|
+ val uploadWorker: OneTimeWorkRequest = OneTimeWorkRequest.Builder(UploadAndShareFilesWorker::class.java)
|
|
|
|
+ .setInputData(data)
|
|
|
|
+ .build()
|
|
|
|
+ WorkManager.getInstance().enqueueUniqueWork(fileUri, ExistingWorkPolicy.KEEP, uploadWorker)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|