Второй WorkRequest of Work Продолжение не работает - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь запустить два рабочих запроса, один рабочий отправляет запрос на сервер для генерации файла Excel и получает URL для загрузки. Другая работа начинается после предыдущей и должна загрузить этот файл. Первая работа начинается и возвращается Result.SUCCESS. Проблема в другом WorkRequest просто не выполняется. LoadInvoiceFileWorker ничего не делать. Что мне нужно делать или что я делаю неправильно?

Вот мой код: InvoiceDetailsViewModel

class InvoiceDetailsViewModel : ViewModel() {
    private val mWorkManager: WorkManager = WorkManager.getInstance()

    fun generateAndLoadExcel(invoiceId: Int, invoiceName: String, enterpriseId: Int) {
        val genInvoiceWorkerBuilder = OneTimeWorkRequest.Builder(GenerateExcelWorker::class.java)
        genInvoiceWorkerBuilder.setInputData(createInputDataForGenerateExcel(invoiceId, invoiceName, enterpriseId))

        val constraintBuilder = Constraints.Builder()
        //constraintBuilder.setRequiredNetworkType(NetworkType.CONNECTED)
        genInvoiceWorkerBuilder.setConstraints(constraintBuilder.build())

        val continuation = mWorkManager.beginWith(
                genInvoiceWorkerBuilder.build()
        )

        val loadFileWorkerBuilder = OneTimeWorkRequest.Builder(LoadInvoiceFileWorker::class.java)
        //loadFileWorkerBuilder.setConstraints(Constraints.NONE)
        continuation.then(loadFileWorkerBuilder.build())

        continuation.enqueue()
    }

    private fun createInputDataForGenerateExcel(invoiceId: Int, invoiceName: String, enterpriseId: Int): Data {
        val builder = Data.Builder()
        builder.putInt(WorkerConstants.INVOICE_ID, invoiceId)
        builder.putString(WorkerConstants.INVOICE_NAME, invoiceName)
        builder.putInt(WorkerConstants.ENTERPRISE_ID, enterpriseId)
        return builder.build()
    }
}

GenerateExcelWorker :

class GenerateExcelWorker : Worker() {
    companion object {
        private val TAG = GenerateExcelWorker::class.java.simpleName
    }

    override fun doWork(): Result {
        val appCont = applicationContext
        val tokenType = PreferenceUtil.getString(TOKEN_TYPE, appCont, R.string.shared_pref_name)
        val accessToken = PreferenceUtil.getString(ACCESS_TOKEN, appCont, R.string.shared_pref_name)
        val enterpriseId = inputData.getInt(WorkerConstants.ENTERPRISE_ID, 0)
        val invoiceId = inputData.getInt(WorkerConstants.INVOICE_ID, 0)
        val invoiceName = inputData.getString(WorkerConstants.INVOICE_NAME)

        makeStatusNotification(applicationContext, invoiceId, invoiceName
                ?: ("Invoice ${invoiceId.str()}"))
        try {
            val rd = RequestData()
            rd.putValue("authorization", "$tokenType $accessToken", RequestData.TYPE_HEADER)
            rd.putValue(FTUrls.SendingParameters.ENTERPRISE_ID, enterpriseId, RequestData.TYPE_PATH)
            rd.putValue(FTUrls.SendingParameters.INVOICE_ID, invoiceId, RequestData.TYPE_PATH)
            val excelUrl = InvoiceManager().generateIncomeInvoiceExcel(rd)
            outputData = Data.Builder().putString(WorkerConstants.FILE_URL, excelUrl).build()
            return Result.SUCCESS
        } catch (t: Throwable) {
            Log.e(TAG, "Error generating excel file for invoice $invoiceName ($invoiceId)", t)
            if (t is UnauthenticatedException) {
                outputData = Data.Builder().putBoolean(WorkerConstants.FILE_URL, true).build()
            } else {
                ExceptionLogger.logException(t)
                Toast.makeText(applicationContext, t.message, Toast.LENGTH_SHORT).show()
            }
            return Result.FAILURE
        }
    }

    private fun makeStatusNotification(context: Context, invoiceId: Int, invoiceTitle: String) {
        // Make a channel if necessary
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create the NotificationChannel, but only on API 26+ because
            // the NotificationChannel class is new and not in the support library
            val name = WorkerConstants.NOTIFICATION_CHANNEL_NAME
            val description = WorkerConstants.NOTIFICATION_CHANNEL_DESCRIPTION
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel = NotificationChannel(WorkerConstants.CHANNEL_ID, name, importance)
            channel.description = description

            // Add the channel
            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }

        val builder = NotificationCompat.Builder(context, WorkerConstants.CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_autorenew_blue)
                .setContentTitle(WorkerConstants.NOTIFICATION_TITLE)
                .setContentText(String.format(WorkerConstants.NOTIFICATION_TEXT, invoiceTitle))
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setVibrate(LongArray(0))

        NotificationManagerCompat.from(context).notify(invoiceId, builder.build())
    }
}

LoadInvoiceFileWorker

class LoadInvoiceFileWorker : Worker() {
    companion object {
        private val TAG = LoadInvoiceFileWorker::class.java.simpleName
    }

    override fun doWork(): Result {
        try {
            val fileUrl = inputData.getString(WorkerConstants.FILE_URL)
            val invoiceId = inputData.getInt(WorkerConstants.INVOICE_ID, 0)
            val invoiceName = inputData.getString(WorkerConstants.INVOICE_NAME)
            val r = DownloadManager.Request(Uri.parse(fileUrl))
            // This put the download in the same Download dir the browser uses
            r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, invoiceName
                    ?: ("Invoice ${invoiceId.str()}"))
            // Notify user when download is completed
            r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            // Start download
            val dm = applicationContext.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager?
            if (dm != null) {
                dm.enqueue(r)
            } else {
                Log.w(TAG, "Download manager not exists for load invoice excel file")
                ToastError(applicationContext, R.string.download_manager_not_found, Toast.LENGTH_SHORT)
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse(fileUrl))
                try {
                    applicationContext.startActivity(intent)
                } catch (e: ActivityNotFoundException) {
                    Log.e(TAG, "Error open browser for view invoice excel file", e)
                    ToastError(applicationContext, R.string.browser_not_found, Toast.LENGTH_SHORT)
                }
            }
            clearGenerateFileNotification(invoiceId)
            return Result.SUCCESS
        } catch (t: Throwable) {
            Log.e(TAG, "Error loading excel generated file", t)
            ExceptionLogger.logException(t)
            ToastError(applicationContext, R.string.error_during_loading_file, Toast.LENGTH_SHORT)
            return Result.FAILURE
        }
    }

    private fun clearGenerateFileNotification(invoiceId: Int) {
        val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.cancel(invoiceId)
    }
}

WorkerConstants

object WorkerConstants {
    const val ENTERPRISE_ID = "enterprise_id"
    const val INVOICE_ID = "invoice_id"
    const val INVOICE_NAME = "invoice_name"
    const val FILE_URL = "file_url"

    const val UNIQUE_WORK_NAME_FOR_INVOICE = "generate_and_load_excel_for_invoice"

    const val NOTIFICATION_CHANNEL_NAME = "GenerateExcelWorker Notifications"
    const val NOTIFICATION_CHANNEL_DESCRIPTION = "Shows notifications whenever work starts"
    const val NOTIFICATION_TITLE = "Генерація ексель файла"
    const val NOTIFICATION_TEXT = "Генерація ексель файла накладної %s"
    const val CHANNEL_ID = "GENERATE_INVOICE_NOTIFICATION"
}

1 Ответ

0 голосов
/ 28 августа 2018

Хорошо, я нашел свою ошибку. Вместо этого: ...

continuation.then(loadFileWorkerBuilder.build())
continuation.enqueue()

Мне нужно сделать это: ...

continuation = continuation.then(loadFileWorkerBuilder.build())
continuation.enqueue()

Я запрашивал enqueue () для первого продолжения одного запроса. Метод WorkContinuation.then () возвращает новый объект, который содержит старое продолжение с новым добавленным запросом.

...