Add stop button in background service notification

This commit is contained in:
Matéo Duparc 2021-08-06 21:29:19 +02:00
parent 3562362916
commit fc46326deb
Signed by: hardcoresushi
GPG Key ID: 007F84120107191E
4 changed files with 105 additions and 76 deletions

View File

@ -17,6 +17,7 @@ import sushi.hardcore.aira.adapters.Session
import sushi.hardcore.aira.adapters.SessionAdapter
import sushi.hardcore.aira.background_service.AIRAService
import sushi.hardcore.aira.background_service.FilesReceiver
import sushi.hardcore.aira.background_service.NotificationBroadcastReceiver
import sushi.hardcore.aira.databinding.ActivityMainBinding
import sushi.hardcore.aira.databinding.DialogIpAddressesBinding
import sushi.hardcore.aira.utils.FileUtils
@ -145,6 +146,9 @@ class MainActivity : ServiceBoundActivity() {
}
setOnScrollListener(onSessionsScrollListener)
}
if (intent.action == NotificationBroadcastReceiver.ACTION_LOGOUT) {
askLogOut()
}
}
serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder) {
@ -209,18 +213,7 @@ class MainActivity : ServiceBoundActivity() {
}
R.id.close -> {
if (isServiceInitialized()) {
AlertDialog.Builder(this, R.style.CustomAlertDialog)
.setTitle(R.string.warning)
.setMessage(R.string.ask_log_out)
.setPositiveButton(R.string.yes) { _, _ ->
airaService.logOut()
if (AIRADatabase.isIdentityProtected(Constants.getDatabaseFolder(this))) {
startActivity(Intent(this, LoginActivity::class.java))
}
finish()
}
.setNegativeButton(R.string.cancel, null)
.show()
askLogOut()
}
true
}
@ -334,6 +327,21 @@ class MainActivity : ServiceBoundActivity() {
})
}
private fun askLogOut() {
AlertDialog.Builder(this, R.style.CustomAlertDialog)
.setTitle(R.string.warning)
.setMessage(R.string.ask_log_out)
.setPositiveButton(R.string.yes) { _, _ ->
airaService.logOut()
if (AIRADatabase.isIdentityProtected(Constants.getDatabaseFolder(this))) {
startActivity(Intent(this, LoginActivity::class.java))
}
finish()
}
.setNegativeButton(R.string.cancel, null)
.show()
}
private fun askShareFileTo(session: Session) {
var uris: ArrayList<Uri>? = null
when (intent.action) {

View File

@ -1,5 +1,6 @@
package sushi.hardcore.aira.background_service
import android.annotation.SuppressLint
import android.app.*
import android.content.Context
import android.content.Intent
@ -22,6 +23,7 @@ import java.io.IOException
import java.net.*
import java.nio.channels.*
@SuppressLint("UnspecifiedImmutableFlag")
class AIRAService : Service() {
private external fun releaseIdentity()
@ -36,6 +38,7 @@ class AIRAService : Service() {
const val MESSAGE_SEND_NAME = 3
const val MESSAGE_SEND_AVATAR = 4
const val MESSAGE_CANCEL_FILE_TRANSFER = 5
const val FLAG_PENDING_INTENT = PendingIntent.FLAG_UPDATE_CURRENT
var isServiceRunning = false
}
@ -360,7 +363,7 @@ class AIRAService : Service() {
}
private fun sendNotification(sessionId: Int, msgContent: ByteArray) {
val notificationBuilder = NotificationCompat.Builder(this, MESSAGES_NOTIFICATION_CHANNEL_ID)
val notification = NotificationCompat.Builder(this, MESSAGES_NOTIFICATION_CHANNEL_ID)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getNameOf(sessionId))
@ -374,49 +377,35 @@ class AIRAService : Service() {
.setContentIntent(
PendingIntent.getActivity(this, 0, Intent(this, ChatActivity::class.java).apply {
putExtra("sessionId", sessionId)
}, 0)
}, FLAG_PENDING_INTENT)
)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.apply {
priority = NotificationCompat.PRIORITY_HIGH
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
val markReadIntent = PendingIntent.getBroadcast(this, 0,
Intent(this, NotificationBroadcastReceiver::class.java).apply {
val bundle = Bundle()
bundle.putBinder("binder", AIRABinder())
bundle.putInt("sessionId", sessionId)
putExtra("bundle", bundle)
action = NotificationBroadcastReceiver.ACTION_MARK_READ
}, PendingIntent.FLAG_UPDATE_CURRENT)
notificationBuilder.addAction(
NotificationCompat.Action(
R.drawable.ic_launcher,
getString(R.string.mark_read),
markReadIntent
.addAction(NotificationCompat.Action(
R.drawable.ic_launcher,
getString(R.string.mark_read),
newActionPendingIntent {
it.putBinder(sessionId)
it.action = NotificationBroadcastReceiver.ACTION_MARK_READ
}
))
.addAction(
NotificationCompat.Action.Builder(R.drawable.ic_launcher, getString(R.string.reply), newActionPendingIntent {
it.putBinder(sessionId)
it.action = NotificationBroadcastReceiver.ACTION_REPLY
})
.addRemoteInput(
RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY)
.setLabel(getString(R.string.reply))
.build()
)
)
val replyPendingIntent: PendingIntent =
PendingIntent.getBroadcast(this, 0,
Intent(this, NotificationBroadcastReceiver::class.java).apply {
val bundle = Bundle()
bundle.putBinder("binder", AIRABinder())
bundle.putInt("sessionId", sessionId)
putExtra("bundle", bundle)
action = NotificationBroadcastReceiver.ACTION_REPLY
}, PendingIntent.FLAG_UPDATE_CURRENT)
notificationBuilder.addAction(
NotificationCompat.Action.Builder(R.drawable.ic_launcher, getString(R.string.reply), replyPendingIntent)
.addRemoteInput(
RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY)
.setLabel(getString(R.string.reply))
.build()
)
.build()
)
}
notificationManager.notify(notificationIdManager.getMessageNotificationId(sessionId), notificationBuilder.build())
.build()
)
.build()
notificationManager.notify(notificationIdManager.getMessageNotificationId(sessionId), notification)
}
private fun initFileTransferNotification(sessionId: Int, fileTransferNotification: FileTransferNotification, file: PendingFile) {
@ -425,15 +414,19 @@ class AIRAService : Service() {
file.fileName,
file.fileSize.toInt(),
Intent(this, NotificationBroadcastReceiver::class.java).apply {
val bundle = Bundle()
bundle.putBinder("binder", AIRABinder())
bundle.putInt("sessionId", sessionId)
putExtra("bundle", bundle)
putBinder(sessionId)
action = NotificationBroadcastReceiver.ACTION_CANCEL_FILE_TRANSFER
}
)
}
private fun Intent.putBinder(sessionId: Int) {
val bundle = Bundle()
bundle.putBinder("binder", AIRABinder())
bundle.putInt("sessionId", sessionId)
putExtra("bundle", bundle)
}
private fun saveMsg(sessionId: Int, timestamp: Long, msg: ByteArray) {
var msgSaved = false
contacts[sessionId]?.uuid?.let { uuid ->
@ -768,7 +761,7 @@ class AIRAService : Service() {
.setContentIntent(
PendingIntent.getActivity(this, 0, Intent(this, ChatActivity::class.java).apply {
putExtra("sessionId", sessionId)
}, 0)
}, FLAG_PENDING_INTENT)
)
.setDefaults(Notification.DEFAULT_ALL)
.apply {
@ -875,6 +868,7 @@ class AIRAService : Service() {
}
}
}
keys.clear()
}
for (session in sessions.values) {
session.close()
@ -928,21 +922,37 @@ class AIRAService : Service() {
)
}
private fun newActionPendingIntent(intentBuilder: (Intent) -> Unit): PendingIntent {
return PendingIntent.getBroadcast(this, 0,
Intent(this, NotificationBroadcastReceiver::class.java).apply {
intentBuilder(this)
}, FLAG_PENDING_INTENT
)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
notificationManager = NotificationManagerCompat.from(this)
val notificationBuilder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannels()
Notification.Builder(this, SERVICE_NOTIFICATION_CHANNEL_ID)
} else {
@Suppress("Deprecation")
Notification.Builder(this)
}
val notificationBuilder = NotificationCompat.Builder(this, SERVICE_NOTIFICATION_CHANNEL_ID)
val notification: Notification = notificationBuilder
.setContentTitle(getString(R.string.background_service))
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(
PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java), 0)
PendingIntent.getActivity(this, 0,
Intent(this, MainActivity::class.java).apply {
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
},
FLAG_PENDING_INTENT)
)
.addAction(NotificationCompat.Action(
R.drawable.ic_launcher,
getString(R.string.stop),
newActionPendingIntent {
it.action = NotificationBroadcastReceiver.ACTION_LOGOUT
}
))
.build()
startForeground(1, notification)

View File

@ -4,28 +4,38 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.RemoteInput
import sushi.hardcore.aira.MainActivity
class NotificationBroadcastReceiver: BroadcastReceiver() {
companion object {
const val ACTION_LOGOUT = "logout"
const val ACTION_MARK_READ = "mark_read"
const val ACTION_CANCEL_FILE_TRANSFER = "cancel"
const val ACTION_REPLY = "reply"
const val KEY_TEXT_REPLY = "key_text_reply"
}
override fun onReceive(context: Context?, intent: Intent) {
intent.getBundleExtra("bundle")?.let { bundle ->
(bundle.getBinder("binder") as AIRAService.AIRABinder?)?.let { binder ->
val sessionId = bundle.getInt("sessionId")
val airaService = binder.getService()
when (intent.action) {
ACTION_MARK_READ -> airaService.setSeen(sessionId, true)
ACTION_CANCEL_FILE_TRANSFER -> airaService.cancelFileTransfer(sessionId)
ACTION_REPLY -> RemoteInput.getResultsFromIntent(intent)?.getString(KEY_TEXT_REPLY)?.let { reply ->
airaService.sendOrAddToPending(sessionId, Protocol.newMessage(reply))
airaService.setSeen(sessionId, true)
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == ACTION_LOGOUT) {
context.startActivity(Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
action = ACTION_LOGOUT
})
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
} else {
intent.getBundleExtra("bundle")?.let { bundle ->
(bundle.getBinder("binder") as AIRAService.AIRABinder?)?.let { binder ->
val sessionId = bundle.getInt("sessionId")
val airaService = binder.getService()
when (intent.action) {
ACTION_MARK_READ -> airaService.setSeen(sessionId, true)
ACTION_CANCEL_FILE_TRANSFER -> airaService.cancelFileTransfer(sessionId)
ACTION_REPLY -> RemoteInput.getResultsFromIntent(intent)?.getString(KEY_TEXT_REPLY)?.let { reply ->
airaService.sendOrAddToPending(sessionId, Protocol.newMessage(reply))
airaService.setSeen(sessionId, true)
}
else -> {}
}
else -> {}
}
}
}

View File

@ -99,6 +99,11 @@
<string name="github_summary">AIRA-android repository on GitHub.</string>
<string name="gitea">Gitea</string>
<string name="gitea_summary">AIRA-android repository on the Gitea instance of the Chapril project. Unlike GitHub, Gitea is fully free software and self-hosted.</string>
<string name="offline_warning_title">Your contact seems to be offline.</string>
<string name="offline_warning_msg">Sent messages will be stored until a connection is established.</string>
<string name="pending_messages">Pending messages:</string>
<string name="sending_pending_messages">Sending pending messages…</string>
<string name="stop">Stop</string>
<!--accessibility strings-->
<string name="send_file">Send file</string>
@ -108,9 +113,5 @@
<string name="clickable_indicator">Clickable indicator</string>
<string name="avatar">Avatar</string>
<string name="name">Name</string>
<string name="offline_warning_title">Your contact seems to be offline.</string>
<string name="offline_warning_msg">Sent messages will be stored until a connection is established.</string>
<string name="warning_desc">Warning icon</string>
<string name="pending_messages">Pending messages:</string>
<string name="sending_pending_messages">Sending pending messages…</string>
</resources>