Fix WorkManager crash on android 11 and below

This commit is contained in:
Mohamed
2024-07-06 16:36:40 +03:00
parent e3ae94513a
commit f384cdd1c9
2 changed files with 88 additions and 40 deletions

View File

@ -14,6 +14,8 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.BottomCenter
import androidx.compose.ui.Alignment.Companion.TopCenter import androidx.compose.ui.Alignment.Companion.TopCenter
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -56,7 +58,7 @@ class SaveSheetActivity : AppCompatActivity() {
if (intent.type?.startsWith("text/plain") == true) { if (intent.type?.startsWith("text/plain") == true) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
extractedText = it extractedText = it
workManager.enqueueSaveWorker(this, it) workManager.enqueueSaveWorker(it)
Log.d(ContentValues.TAG, "Extracted text: $extractedText") Log.d(ContentValues.TAG, "Extracted text: $extractedText")
} }
} }
@ -75,7 +77,7 @@ class SaveSheetActivity : AppCompatActivity() {
setContent { setContent {
LaunchedEffect(extractedText) { LaunchedEffect(extractedText) {
extractedText?.let { url -> extractedText?.let { url ->
workManager.getWorkInfosByTagFlow(url).map { workManager.getWorkInfosForUniqueWorkFlow(url).map {
saveState = when (it.firstOrNull()?.state) { saveState = when (it.firstOrNull()?.state) {
WorkInfo.State.RUNNING -> SaveState.SAVING WorkInfo.State.RUNNING -> SaveState.SAVING
WorkInfo.State.SUCCEEDED -> SaveState.SAVED WorkInfo.State.SUCCEEDED -> SaveState.SAVED
@ -86,7 +88,6 @@ class SaveSheetActivity : AppCompatActivity() {
} }
} }
val scaffoldState: ScaffoldState = rememberScaffoldState()
val message = when (saveState) { val message = when (saveState) {
SaveState.DEFAULT -> "" SaveState.DEFAULT -> ""
SaveState.SAVING -> "Saved to Omnivore" SaveState.SAVING -> "Saved to Omnivore"
@ -94,35 +95,30 @@ class SaveSheetActivity : AppCompatActivity() {
SaveState.SAVED -> "Saved to Omnivore" SaveState.SAVED -> "Saved to Omnivore"
} }
Scaffold( Box(
modifier = Modifier.clickable { Modifier
Log.d("debug", "DISMISS SCAFFOLD") .background(Color.Transparent)
exit() .fillMaxSize()
}, .clickable {
scaffoldState = scaffoldState, Log.d("debug", "DISMISS BOX")
backgroundColor = Color.Transparent, exit()
}
// TODO: In future versions we can present Label, Note, Highlight options here
bottomBar = {
androidx.compose.material3.BottomAppBar(
modifier = Modifier
.height(55.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(topEnd = 5.dp, topStart = 5.dp)),
containerColor = MaterialTheme.colors.background,
actions = {
Spacer(modifier = Modifier.width(25.dp))
Text(
message,
style = androidx.compose.material3.MaterialTheme.typography.titleMedium
)
},
)
},
) { ) {
Row(
Modifier
.align(BottomCenter)
.height(55.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(topEnd = 5.dp, topStart = 5.dp))
.background(MaterialTheme.colors.background)
.padding(start = 25.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
message,
style = androidx.compose.material3.MaterialTheme.typography.titleMedium
)
}
} }
LaunchedEffect(saveState) { LaunchedEffect(saveState) {
@ -134,25 +130,30 @@ class SaveSheetActivity : AppCompatActivity() {
} }
} }
private fun WorkManager.enqueueSaveWorker(context: Context, url: String) { private fun WorkManager.enqueueSaveWorker(url: String) {
val saveData = workDataOf("url" to url) val saveData = workDataOf("url" to url)
val saveWork = OneTimeWorkRequestBuilder<SaveURLWorker>() val saveWork = OneTimeWorkRequestBuilder<SaveURLWorker>()
.setInputData(saveData) .setInputData(saveData)
.setConstraints(Constraints.Builder() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setRequiredNetworkType(NetworkType.CONNECTED) .setConstraints(
.build()) Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.build() .build()
val syncWork = OneTimeWorkRequestBuilder<LibrarySyncWorker>() val syncWork = OneTimeWorkRequestBuilder<LibrarySyncWorker>()
.setConstraints(Constraints.Builder() .setConstraints(
.setRequiredNetworkType(NetworkType.CONNECTED) Constraints.Builder()
.build()) .setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.setInitialDelay(5, TimeUnit.SECONDS) .setInitialDelay(5, TimeUnit.SECONDS)
.build() .build()
WorkManager.getInstance(context) // using url as name because requests with a different url might not be completed yet
.beginUniqueWork("saveAndSync", ExistingWorkPolicy.REPLACE, saveWork) beginUniqueWork(url, ExistingWorkPolicy.REPLACE, saveWork)
.then(syncWork) .then(syncWork)
.enqueue() .enqueue()
} }

View File

@ -101,4 +101,51 @@ class SaveURLWorker @AssistedInject constructor(
null null
} }
} }
companion object {
const val NOTIFICATION_CHANNEL_ID = "SAVE_URL_WORKER_CHANNEL"
const val NOTIFICATION_CHANNEL_NAME = "URL Saver"
const val NOTIFICATION_ID = 1
}
override suspend fun getForegroundInfo(): ForegroundInfo {
val notification = createNotification()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ForegroundInfo(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
} else {
ForegroundInfo(NOTIFICATION_ID, notification)
}
}
private fun createNotification(): Notification {
val channelId =
createNotificationChannel()
return NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle("Saving URL")
.setContentText("Your URL is being saved in the background.")
.setSmallIcon(R.drawable.ic_notification) // Ensure this icon is valid
.setPriority(NotificationCompat.PRIORITY_HIGH)
.build()
}
private fun createNotificationChannel(): String {
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH // Changed from LOW to HIGH
).apply {
description = "Notification channel for URL saving"
}
val notificationManager =
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
return NOTIFICATION_CHANNEL_ID
}
} }