Fix crash in SendTootService
This commit is contained in:
parent
a3791a16f7
commit
751cf89b0c
1 changed files with 155 additions and 113 deletions
|
@ -8,44 +8,59 @@ import android.content.ClipData
|
||||||
import android.content.ClipDescription
|
import android.content.ClipDescription
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.*
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.os.Parcelable
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
|
import com.keylesspalace.tusky.appstore.ChatMessageDeliveredEvent
|
||||||
import com.keylesspalace.tusky.appstore.EventHub
|
import com.keylesspalace.tusky.appstore.EventHub
|
||||||
import com.keylesspalace.tusky.appstore.*
|
import com.keylesspalace.tusky.appstore.StatusComposedEvent
|
||||||
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
import com.keylesspalace.tusky.appstore.StatusPreviewEvent
|
||||||
|
import com.keylesspalace.tusky.appstore.StatusScheduledEvent
|
||||||
import com.keylesspalace.tusky.components.drafts.DraftHelper
|
import com.keylesspalace.tusky.components.drafts.DraftHelper
|
||||||
|
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
||||||
import com.keylesspalace.tusky.db.AccountManager
|
import com.keylesspalace.tusky.db.AccountManager
|
||||||
import com.keylesspalace.tusky.db.AppDatabase
|
import com.keylesspalace.tusky.db.AppDatabase
|
||||||
import com.keylesspalace.tusky.di.Injectable
|
import com.keylesspalace.tusky.di.Injectable
|
||||||
import com.keylesspalace.tusky.entity.*
|
import com.keylesspalace.tusky.entity.ChatMessage
|
||||||
|
import com.keylesspalace.tusky.entity.NewChatMessage
|
||||||
|
import com.keylesspalace.tusky.entity.NewPoll
|
||||||
|
import com.keylesspalace.tusky.entity.NewStatus
|
||||||
|
import com.keylesspalace.tusky.entity.Status
|
||||||
import com.keylesspalace.tusky.network.MastodonApi
|
import com.keylesspalace.tusky.network.MastodonApi
|
||||||
import com.keylesspalace.tusky.util.Either
|
import com.keylesspalace.tusky.util.Either
|
||||||
import com.keylesspalace.tusky.util.SaveTootHelper
|
import com.keylesspalace.tusky.util.SaveTootHelper
|
||||||
import dagger.android.AndroidInjection
|
import dagger.android.AndroidInjection
|
||||||
|
import java.util.Timer
|
||||||
|
import java.util.TimerTask
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SendTootService : Service(), Injectable {
|
class SendTootService : Service(), Injectable {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var mastodonApi: MastodonApi
|
lateinit var mastodonApi: MastodonApi
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var accountManager: AccountManager
|
lateinit var accountManager: AccountManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var eventHub: EventHub
|
lateinit var eventHub: EventHub
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var database: AppDatabase
|
lateinit var database: AppDatabase
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var draftHelper: DraftHelper
|
lateinit var draftHelper: DraftHelper
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var saveTootHelper: SaveTootHelper
|
lateinit var saveTootHelper: SaveTootHelper
|
||||||
|
|
||||||
|
@ -76,7 +91,11 @@ class SendTootService : Service(), Injectable {
|
||||||
?: throw IllegalStateException("SendTootService started without $KEY_CHATMSG or $KEY_TOOT extra")
|
?: throw IllegalStateException("SendTootService started without $KEY_CHATMSG or $KEY_TOOT extra")
|
||||||
|
|
||||||
if(NotificationHelper.NOTIFICATION_USE_CHANNELS) {
|
if(NotificationHelper.NOTIFICATION_USE_CHANNELS) {
|
||||||
val channel = NotificationChannel(CHANNEL_ID, getString(R.string.send_toot_notification_channel_name), NotificationManager.IMPORTANCE_LOW)
|
val channel = NotificationChannel(
|
||||||
|
CHANNEL_ID,
|
||||||
|
getString(R.string.send_toot_notification_channel_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
)
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +106,11 @@ class SendTootService : Service(), Injectable {
|
||||||
.setProgress(1, 0, true)
|
.setProgress(1, 0, true)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setColor(ContextCompat.getColor(this, R.color.tusky_blue))
|
.setColor(ContextCompat.getColor(this, R.color.tusky_blue))
|
||||||
.addAction(0, getString(android.R.string.cancel), cancelSendingIntent(sendingNotificationId))
|
.addAction(
|
||||||
|
0,
|
||||||
|
getString(android.R.string.cancel),
|
||||||
|
cancelSendingIntent(sendingNotificationId)
|
||||||
|
)
|
||||||
|
|
||||||
if(tootsToSend.size == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if(tootsToSend.size == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||||
|
@ -103,7 +126,6 @@ class SendTootService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendToot(tootId: Int) {
|
private fun sendToot(tootId: Int) {
|
||||||
|
|
||||||
// when tootToSend == null, sending has been canceled
|
// when tootToSend == null, sending has been canceled
|
||||||
val postToSend = tootsToSend[tootId] ?: return
|
val postToSend = tootsToSend[tootId] ?: return
|
||||||
|
|
||||||
|
@ -120,7 +142,8 @@ class SendTootService : Service(), Injectable {
|
||||||
postToSend.incrementRetries()
|
postToSend.incrementRetries()
|
||||||
|
|
||||||
if(postToSend is TootToSend) {
|
if(postToSend is TootToSend) {
|
||||||
val contentType : String? = if(postToSend.formattingSyntax.isNotEmpty()) postToSend.formattingSyntax else null
|
val contentType: String? =
|
||||||
|
if(postToSend.formattingSyntax.isNotEmpty()) postToSend.formattingSyntax else null
|
||||||
val preview: Boolean? = if(postToSend.preview) true else null
|
val preview: Boolean? = if(postToSend.preview) true else null
|
||||||
|
|
||||||
val newStatus = NewStatus(
|
val newStatus = NewStatus(
|
||||||
|
@ -160,9 +183,12 @@ class SendTootService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
postToSend.preview -> response.body()?.let(::StatusPreviewEvent)?.let(eventHub::dispatch)
|
postToSend.preview -> response.body()?.let(::StatusPreviewEvent)
|
||||||
scheduled -> response.body()?.let(::StatusScheduledEvent)?.let(eventHub::dispatch)
|
?.let(eventHub::dispatch)
|
||||||
else -> response.body()?.let(::StatusComposedEvent)?.let(eventHub::dispatch)
|
scheduled -> response.body()?.let(::StatusScheduledEvent)
|
||||||
|
?.let(eventHub::dispatch)
|
||||||
|
else -> response.body()?.let(::StatusComposedEvent)
|
||||||
|
?.let(eventHub::dispatch)
|
||||||
}
|
}
|
||||||
notificationManager.cancel(tootId)
|
notificationManager.cancel(tootId)
|
||||||
|
|
||||||
|
@ -174,7 +200,12 @@ class SendTootService : Service(), Injectable {
|
||||||
.setSmallIcon(R.drawable.ic_notify)
|
.setSmallIcon(R.drawable.ic_notify)
|
||||||
.setContentTitle(getString(R.string.send_toot_notification_error_title))
|
.setContentTitle(getString(R.string.send_toot_notification_error_title))
|
||||||
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
||||||
.setColor(ContextCompat.getColor(this@SendTootService, R.color.tusky_blue))
|
.setColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
this@SendTootService,
|
||||||
|
R.color.tusky_blue
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
notificationManager.cancel(tootId)
|
notificationManager.cancel(tootId)
|
||||||
notificationManager.notify(errorNotificationId--, builder.build())
|
notificationManager.notify(errorNotificationId--, builder.build())
|
||||||
|
@ -224,7 +255,12 @@ class SendTootService : Service(), Injectable {
|
||||||
.setSmallIcon(R.drawable.ic_notify)
|
.setSmallIcon(R.drawable.ic_notify)
|
||||||
.setContentTitle(getString(R.string.send_toot_notification_error_title))
|
.setContentTitle(getString(R.string.send_toot_notification_error_title))
|
||||||
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
||||||
.setColor(ContextCompat.getColor(this@SendTootService, R.color.tusky_blue))
|
.setColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
this@SendTootService,
|
||||||
|
R.color.tusky_blue
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
notificationManager.cancel(tootId)
|
notificationManager.cancel(tootId)
|
||||||
notificationManager.notify(errorNotificationId--, builder.build())
|
notificationManager.notify(errorNotificationId--, builder.build())
|
||||||
|
@ -253,7 +289,6 @@ class SendTootService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopSelfWhenDone() {
|
private fun stopSelfWhenDone() {
|
||||||
|
|
||||||
if(tootsToSend.isEmpty()) {
|
if(tootsToSend.isEmpty()) {
|
||||||
ServiceCompat.stopForeground(this@SendTootService, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
ServiceCompat.stopForeground(this@SendTootService, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||||
stopSelf()
|
stopSelf()
|
||||||
|
@ -296,7 +331,6 @@ class SendTootService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveTootToDrafts(toot: TootToSend) {
|
private fun saveTootToDrafts(toot: TootToSend) {
|
||||||
|
|
||||||
draftHelper.saveDraft(
|
draftHelper.saveDraft(
|
||||||
draftId = toot.draftId,
|
draftId = toot.draftId,
|
||||||
accountId = toot.getAccountId(),
|
accountId = toot.getAccountId(),
|
||||||
|
@ -314,14 +348,21 @@ class SendTootService : Service(), Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelSendingIntent(tootId: Int): PendingIntent {
|
private fun cancelSendingIntent(tootId: Int): PendingIntent {
|
||||||
|
|
||||||
val intent = Intent(this, SendTootService::class.java)
|
val intent = Intent(this, SendTootService::class.java)
|
||||||
|
|
||||||
intent.putExtra(KEY_CANCEL, tootId)
|
intent.putExtra(KEY_CANCEL, tootId)
|
||||||
|
val flags =
|
||||||
return PendingIntent.getService(this, tootId, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||||
|
} else {
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
}
|
||||||
|
return PendingIntent.getService(
|
||||||
|
this,
|
||||||
|
tootId,
|
||||||
|
intent,
|
||||||
|
flags
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@ -333,7 +374,8 @@ class SendTootService : Service(), Injectable {
|
||||||
private val MAX_RETRY_INTERVAL = TimeUnit.MINUTES.toMillis(1)
|
private val MAX_RETRY_INTERVAL = TimeUnit.MINUTES.toMillis(1)
|
||||||
|
|
||||||
private var sendingNotificationId = -1 // use negative ids to not clash with other notis
|
private var sendingNotificationId = -1 // use negative ids to not clash with other notis
|
||||||
private var errorNotificationId = Int.MIN_VALUE // use even more negative ids to not clash with other notis
|
private var errorNotificationId =
|
||||||
|
Int.MIN_VALUE // use even more negative ids to not clash with other notis
|
||||||
|
|
||||||
private fun Intent.forwardUriPermissions(mediaUris: List<String>) {
|
private fun Intent.forwardUriPermissions(mediaUris: List<String>) {
|
||||||
if(mediaUris.isEmpty())
|
if(mediaUris.isEmpty())
|
||||||
|
|
Loading…
Reference in a new issue