Created
April 17, 2024 12:35
-
-
Save stakancheck/f8dbc666ef97b97bf680e8605e28b587 to your computer and use it in GitHub Desktop.
GeneratePDFWorker example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@HiltWorker | |
class GeneratePDFWorker @AssistedInject constructor( | |
@Assisted context: Context, | |
@Assisted params: WorkerParameters, | |
private val repository: Repository | |
) : CoroutineWorker(context, params) { | |
private val notificationBuilder: NotificationCompat.Builder | |
private var pdfGenerator: PdfGenerator? = null | |
init { | |
Log.d(TAG, "initialize: GeneratePDFWorker") | |
notificationBuilder = NotificationCompat.Builder( | |
applicationContext, | |
applicationContext.getString(R.string.notification_channel_name) | |
) | |
Handler(Looper.getMainLooper()).post { | |
pdfGenerator = PdfGenerator( | |
applicationContext | |
) | |
} | |
} | |
override suspend fun doWork(): Result { | |
Log.d(TAG, "doWork: before generating act") | |
return generateData() | |
} | |
override suspend fun getForegroundInfo(): ForegroundInfo { | |
createNotificationChannel() | |
return ForegroundInfo(NOTIFICATION_ID_WORKER, foregroundNotification()) | |
} | |
private suspend fun generateData(): Result { | |
Log.d(TAG, "generateData: start generate data function") | |
// Подготавливаем к работе (чистим пустые директории в internal storage) | |
repository.checkAndClearDirs() | |
// Получаем список уже готовых документов | |
val alreadyGeneratedIds = repository.getLocalPdfsIds() | |
// Получаем список данных для генерации и убираем уже сгенерированные. | |
// Делаем это, потому что мы не удаляем информацию, так как при ошибке генерации, данные могут снова понадобится. | |
val actIds = repository.getLocalActsIds().filter { act -> !alreadyGeneratedIds.contains(act) } | |
Log.d(TAG, "generateData: ACTS TO GENERATE: $actIds") | |
if (actIds.isEmpty()) { | |
if (alreadyGeneratedIds.isNotEmpty()) { | |
SendDataWorker.startSendDataWorker(applicationContext) | |
} | |
return Result.success() | |
} | |
// Начинаем работу, отправляем уведомление с прогрессом и кол-вом задач | |
sendNotification(progressNotification(0, actIds.size)) | |
// Будем записывать успешные операции | |
val successOperations: MutableList<String> = mutableListOf() | |
var progress = 0 // Всего проверено данных | |
var retry = false // Нужно ли перевыполнить worker | |
for (id: String in actIds) { | |
Log.d(TAG, "generateData: save act $id") | |
// Получаем данные из internal storage | |
val act = repository.getLocalAct(id) | |
if (act == null) { | |
Log.e(TAG, "generateData: can't get act -> $id") | |
retry = true | |
} else { | |
try { | |
// Вызываем генерацию | |
generateAndSavePdf( | |
act = act, | |
id = id | |
).onSuccess { | |
Log.d(TAG, "generateData: successfully created $id") | |
successOperations.add(id) | |
}.onFailure { | |
Log.e(TAG, "generateData: save", it) | |
retry = true | |
} | |
} catch (e: Exception) { | |
Log.e(TAG, "generateData: generate or save error", e) | |
retry = true | |
} | |
} | |
// Обновляем прогресс | |
progress += 1 | |
sendNotification(progressNotification(progress, actIds.size)) | |
} | |
if (successOperations.isNotEmpty()) { | |
// Вызываем Worker отправки данных | |
SendDataWorker.startSendDataWorker(applicationContext) | |
} | |
// Заканчиваем работу, уведомляем о результате | |
return if (retry) { | |
sendNotification(errorNotification("Не удалось сгенерировать акты, произошла ошибка. Задача будет отложена.")) | |
Result.retry() // Worker сам перезапустится | |
} else { | |
sendNotification(successNotification("Акты сгенерированы успешно. Кол-во: ${successOperations.size}/$progress")) | |
Result.success() | |
} | |
} | |
private suspend fun generateAndSavePdf( | |
act: ActSave, | |
id: String | |
): kotlin.Result<Unit> { | |
pdfGenerator | |
?: return kotlin.Result.failure(IllegalStateException("PDF generator is not initialized")) | |
Log.d(TAG, "createPDF: type ${act.type}") | |
return pdfGenerator!!.generateExpertAct( | |
act = act, | |
images = repository.getImagesForAct(id), // Получаем файлы изображений для акта | |
outFile = repository.preparePdfFile(id) // Создаем файл для сохранения PDF | |
) | |
} | |
private fun sendNotification(notification: Notification) { | |
val notificationManager = | |
getSystemService(applicationContext, NotificationManager::class.java) | |
createNotificationChannel() | |
notificationManager?.notify(NOTIFICATION_ID_PROGRESS, notification) | |
} | |
private fun foregroundNotification(): Notification { | |
return notificationBuilder | |
.setContentTitle("Приложение - Генерация отчетов") | |
.setProgress(0, 0, false) | |
.setSilent(true) | |
.setSmallIcon(R.drawable.ic_time_min) | |
.build() | |
} | |
private fun createNotificationChannel() { | |
val notificationManager = | |
getSystemService(applicationContext, NotificationManager::class.java) | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
val channel = NotificationChannel( | |
applicationContext.getString(R.string.notification_channel_name), | |
applicationContext.getString(R.string.notification_channel_generate_description), | |
NotificationManager.IMPORTANCE_DEFAULT | |
) | |
notificationManager?.createNotificationChannel(channel) | |
} | |
} | |
private fun successNotification(message: String = "Все отчеты успешно сгенерированы"): Notification { | |
return notificationBuilder | |
.setContentTitle("Приложение - Генерация отчетов") | |
.setContentText(message) | |
.setProgress(0, 0, false) | |
.setSilent(false) | |
.setColor(Color.GREEN) | |
.setSmallIcon(R.drawable.ic_check) | |
.build() | |
} | |
private fun errorNotification(message: String): Notification { | |
return notificationBuilder | |
.setContentTitle("Приложение - Генерация отчетов") | |
.setContentText(message) | |
.setColor(Color.RED) | |
.setProgress(0, 0, false) | |
.setSilent(true) | |
.setSmallIcon(R.drawable.ic_cancel) | |
.build() | |
} | |
private fun progressNotification( | |
progress: Int, | |
goal: Int, | |
message: String = "Генерация отчетов" | |
): Notification { | |
return notificationBuilder | |
.setContentTitle("Приложение - Генерация отчетов") | |
.setContentText(message) | |
.setSilent(true) | |
.setProgress(goal, progress, false) | |
.setSmallIcon(R.drawable.ic_upload) | |
.build() | |
} | |
companion object { | |
private const val WORK_NAME = "example.background.worker.GeneratePDFWorker" | |
private const val TAG: String = "GeneratePDFWorker" | |
private const val NOTIFICATION_ID_WORKER = 13 | |
private const val NOTIFICATION_ID_PROGRESS = 24 | |
fun startGeneratePDFWorker( | |
context: Context, | |
policy: ExistingWorkPolicy = ExistingWorkPolicy.REPLACE | |
) { | |
Log.d(TAG, "startGeneratePDFWorker: start enqueue work") | |
val generateDataWorkRequest = OneTimeWorkRequestBuilder<GeneratePDFWorker>() | |
.build() | |
val workManager: WorkManager = WorkManager.getInstance(context) | |
workManager.enqueueUniqueWork( | |
WORK_NAME, | |
policy, | |
generateDataWorkRequest | |
) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment