Notifications: deep linking
This commit is contained in:
@@ -27,10 +27,14 @@
|
|||||||
android:theme="@style/Theme.KordophoneDroid">
|
android:theme="@style/Theme.KordophoneDroid">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<!-- Message List Deep Link -->
|
||||||
|
<data android:scheme="kordophone" android:host="messages" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="" />
|
android:value="" />
|
||||||
|
|||||||
@@ -17,14 +17,19 @@ import android.util.Log
|
|||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.navigation.NavDeepLinkBuilder
|
||||||
|
import androidx.navigation.NavDeepLinkRequest
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.buzzert.kordophone.backend.model.Message
|
import net.buzzert.kordophone.backend.model.Message
|
||||||
import net.buzzert.kordophone.backend.server.ChatRepository
|
import net.buzzert.kordophone.backend.server.ChatRepository
|
||||||
|
import net.buzzert.kordophonedroid.ui.Destination
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
const val PUSH_CHANNEL_ID = "net.buzzert.kordophone.persistentNotification"
|
const val PUSH_CHANNEL_ID = "net.buzzert.kordophone.persistentNotification"
|
||||||
@@ -38,6 +43,7 @@ class UpdateMonitorService: Service()
|
|||||||
@Inject lateinit var chatRepository: ChatRepository
|
@Inject lateinit var chatRepository: ChatRepository
|
||||||
|
|
||||||
private var newMessageID: Int = 0
|
private var newMessageID: Int = 0
|
||||||
|
private var watchJob: Job? = null
|
||||||
private val job = SupervisorJob()
|
private val job = SupervisorJob()
|
||||||
private val scope = CoroutineScope(Dispatchers.IO + job)
|
private val scope = CoroutineScope(Dispatchers.IO + job)
|
||||||
|
|
||||||
@@ -53,7 +59,18 @@ class UpdateMonitorService: Service()
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
Log.v(UPDATER_LOG, "UpdateMonitor onCreate: Begin watching for updates.")
|
||||||
|
|
||||||
createNotificationChannel(NEW_MESSAGE_CHANNEL_ID, "New Messages")
|
createNotificationChannel(NEW_MESSAGE_CHANNEL_ID, "New Messages")
|
||||||
|
|
||||||
|
// Connect to monitor
|
||||||
|
chatRepository.beginWatchingForUpdates(scope)
|
||||||
|
|
||||||
|
// Connect to new message flow for notifications
|
||||||
|
watchJob?.cancel()
|
||||||
|
watchJob = scope.launch {
|
||||||
|
chatRepository.newMessages.collectLatest(::onReceiveNewMessage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
@@ -77,14 +94,6 @@ class UpdateMonitorService: Service()
|
|||||||
|
|
||||||
startForeground(5738, notification)
|
startForeground(5738, notification)
|
||||||
|
|
||||||
// Connect to monitor
|
|
||||||
chatRepository.beginWatchingForUpdates(scope)
|
|
||||||
|
|
||||||
// Connect to new message flow for notifications
|
|
||||||
scope.launch {
|
|
||||||
chatRepository.newMessages.collectLatest(::onReceiveNewMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart if we get killed
|
// Restart if we get killed
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
@@ -98,25 +107,39 @@ class UpdateMonitorService: Service()
|
|||||||
|
|
||||||
if (message.conversation.unreadCount == 0) {
|
if (message.conversation.unreadCount == 0) {
|
||||||
// Not unread.
|
// Not unread.
|
||||||
|
Log.v(UPDATER_LOG, "Ignoring read message.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.sender == null) {
|
if (message.sender == null) {
|
||||||
// From me.
|
// From me.
|
||||||
|
Log.v(UPDATER_LOG, "Ignoring message from me.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.conversation.isGroupChat) {
|
if (message.conversation.isGroupChat) {
|
||||||
// For now, since these can be noisy and there's no UI for changing it, ignore group chats.
|
// For now, since these can be noisy and there's no UI for changing it, ignore group chats.
|
||||||
|
Log.v(UPDATER_LOG, "Ignoring group chat message.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val guid = message.conversation.guid
|
||||||
|
val deepLinkIntent = Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
"kordophone://messages/$guid".toUri(),
|
||||||
|
this,
|
||||||
|
MainActivity::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
val pendingIntent = PendingIntent.getActivity(this, 0, deepLinkIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
val groupId = message.conversation.guid
|
val groupId = message.conversation.guid
|
||||||
val notification = NotificationCompat.Builder(this, NEW_MESSAGE_CHANNEL_ID)
|
val notification = NotificationCompat.Builder(this, NEW_MESSAGE_CHANNEL_ID)
|
||||||
.setContentTitle(message.sender)
|
.setContentTitle(message.sender)
|
||||||
.setContentText(message.text)
|
.setContentText(message.text)
|
||||||
.setSmallIcon(R.drawable.stat_notify_chat)
|
.setSmallIcon(R.drawable.stat_notify_chat)
|
||||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
.setGroup(groupId)
|
.setGroup(groupId)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import androidx.navigation.NavHostController
|
|||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.navigation.navDeepLink
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import net.buzzert.kordophone.backend.server.ChatRepository
|
import net.buzzert.kordophone.backend.server.ChatRepository
|
||||||
|
|
||||||
@@ -77,11 +78,14 @@ fun KordophoneApp(
|
|||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = Destination.ConversationList.route,
|
startDestination = Destination.ConversationList.route,
|
||||||
) {
|
) {
|
||||||
composable(route = Destination.ConversationList.route) {
|
composable(Destination.ConversationList.route) {
|
||||||
ConversationListScreen()
|
ConversationListScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
composable(Destination.MessageList.route) {
|
composable(
|
||||||
|
route = Destination.MessageList.route,
|
||||||
|
deepLinks = listOf(navDeepLink { uriPattern = "kordophone://messages/{id}" })
|
||||||
|
) {
|
||||||
val conversationID = it.arguments?.getString("id")!!
|
val conversationID = it.arguments?.getString("id")!!
|
||||||
MessageListScreen(conversationGUID = conversationID)
|
MessageListScreen(conversationGUID = conversationID)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user