streaming: implemented streaming for notifications
This commit is contained in:
parent
828198dab7
commit
55d3e9ed08
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 25,
|
||||
"identityHash": "7ab8482b8d5dcb97c4c8932f578879f2",
|
||||
"identityHash": "ce7a96213f9e12e00a6ec21f3efaf547",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "TootEntity",
|
||||
|
@ -92,7 +92,7 @@
|
|||
},
|
||||
{
|
||||
"tableName": "AccountEntity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsEmojiReactions` INTEGER NOT NULL, `notificationsChatMessages` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `activeNotifications` TEXT NOT NULL, `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `defaultFormattingSyntax` TEXT NOT NULL)",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsStreamingEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsEmojiReactions` INTEGER NOT NULL, `notificationsChatMessages` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `activeNotifications` TEXT NOT NULL, `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `defaultFormattingSyntax` TEXT NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
|
@ -148,6 +148,12 @@
|
|||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "notificationsStreamingEnabled",
|
||||
"columnName": "notificationsStreamingEnabled",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "notificationsMentioned",
|
||||
"columnName": "notificationsMentioned",
|
||||
|
@ -879,7 +885,7 @@
|
|||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7ab8482b8d5dcb97c4c8932f578879f2')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ce7a96213f9e12e00a6ec21f3efaf547')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -43,6 +43,9 @@
|
|||
<string name="attachment_type_unknown">Attachment</string>
|
||||
|
||||
<string name="link">Link</string> <!-- Web Link -->
|
||||
|
||||
<string name="streaming_notification_name">Live notifications</string>
|
||||
<string name="streaming_notification_description">Running live notifications for: </string>
|
||||
|
||||
<!-- REPLACEMENT FOR TUSKY STRINGS -->
|
||||
<string name="action_toggle_visibility">Post visibility</string>
|
||||
|
|
|
@ -168,6 +168,8 @@
|
|||
|
||||
<service android:name=".service.SendTootService" />
|
||||
|
||||
<service android:name=".service.StreamingService" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.keylesspalace.tusky.interfaces.AccountSelectionListener
|
|||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment
|
||||
import com.keylesspalace.tusky.pager.MainPagerAdapter
|
||||
import com.keylesspalace.tusky.service.StreamingService
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
|
@ -191,53 +192,15 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
|
||||
// Setup push notifications
|
||||
if (NotificationHelper.areNotificationsEnabled(this, accountManager)) {
|
||||
NotificationHelper.enablePullNotifications(this)
|
||||
|
||||
// Use when WorkManager doesn't want to work
|
||||
/*
|
||||
val accountList = accountManager.getAllAccountsOrderedByActive()
|
||||
for (account in accountList) {
|
||||
if (account.notificationsEnabled) {
|
||||
try {
|
||||
Log.d(TAG, "getting Notifications for " + account.fullName)
|
||||
// don't care about withMuted because they are always silently ignored
|
||||
val notificationsResponse = mastodonApi.notificationsWithAuth(
|
||||
String.format("Bearer %s", account.accessToken),
|
||||
account.domain, true,
|
||||
setOf(Notification.Type.CHAT_MESSAGE.presentation)
|
||||
).enqueue(object: Callback<List<Notification>> {
|
||||
override fun onFailure(call: Call<List<Notification>>, t: Throwable) {
|
||||
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call<List<Notification>>, response: Response<List<Notification>>) {
|
||||
val notifications = response.body()
|
||||
val newId = account.lastNotificationId
|
||||
var newestId = ""
|
||||
var isFirstOfBatch = true
|
||||
notifications?.reversed()?.forEach { notification ->
|
||||
val currentId = notification.id
|
||||
if (newestId.isLessThan(currentId)) {
|
||||
newestId = currentId
|
||||
}
|
||||
if (newId.isLessThan(currentId)) {
|
||||
NotificationHelper.make(this@MainActivity, notification, account, isFirstOfBatch)
|
||||
isFirstOfBatch = false
|
||||
}
|
||||
}
|
||||
account.lastNotificationId = newestId
|
||||
accountManager.saveAccount(account)
|
||||
}
|
||||
})
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "error receiving notifications", e)
|
||||
}
|
||||
if(accountManager.areNotificationsStreamingEnabled()) {
|
||||
NotificationHelper.disablePullNotifications(this)
|
||||
StreamingService.startStreaming(this)
|
||||
} else {
|
||||
StreamingService.stopStreaming(this)
|
||||
NotificationHelper.enablePullNotifications(this)
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
} else {
|
||||
StreamingService.stopStreaming(this)
|
||||
NotificationHelper.disablePullNotifications(this)
|
||||
}
|
||||
eventHub.events
|
||||
|
|
|
@ -138,7 +138,7 @@ public class NotificationHelper {
|
|||
/**
|
||||
* by setting this as false, it's possible to test legacy notification channels on newer devices
|
||||
*/
|
||||
//public static final boolean NOTIFICATION_USE_CHANNELS = false;
|
||||
// public static final boolean NOTIFICATION_USE_CHANNELS = false;
|
||||
public static final boolean NOTIFICATION_USE_CHANNELS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
|
||||
/**
|
||||
|
@ -518,7 +518,7 @@ public class NotificationHelper {
|
|||
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS, TimeUnit.MILLISECONDS
|
||||
)
|
||||
.addTag(NOTIFICATION_PULL_TAG)
|
||||
//.setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
||||
.setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
||||
.build();
|
||||
|
||||
workManager.enqueue(workRequest);
|
||||
|
|
|
@ -46,8 +46,7 @@ class NotificationWorker(
|
|||
val notificationsResponse = mastodonApi.notificationsWithAuth(
|
||||
String.format("Bearer %s", account.accessToken),
|
||||
account.domain, true,
|
||||
setOf(Notification.Type.CHAT_MESSAGE.presentation)
|
||||
).execute()
|
||||
Notification.Type.asStringList).execute()
|
||||
val notifications = notificationsResponse.body()
|
||||
if (notificationsResponse.isSuccessful && notifications != null) {
|
||||
onNotificationsReceived(account, notifications)
|
||||
|
|
|
@ -37,6 +37,7 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
|
|||
var displayName: String = "",
|
||||
var profilePictureUrl: String = "",
|
||||
var notificationsEnabled: Boolean = true,
|
||||
var notificationsStreamingEnabled: Boolean = true,
|
||||
var notificationsMentioned: Boolean = true,
|
||||
var notificationsFollowed: Boolean = true,
|
||||
var notificationsFollowRequested: Boolean = false,
|
||||
|
|
|
@ -184,6 +184,10 @@ class AccountManager @Inject constructor(db: AppDatabase) {
|
|||
return accounts.any { it.notificationsEnabled }
|
||||
}
|
||||
|
||||
fun areNotificationsStreamingEnabled() : Boolean {
|
||||
return accounts.any { it.notificationsStreamingEnabled }
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an account by its database id
|
||||
* @param accountId the id of the account
|
||||
|
|
|
@ -372,6 +372,7 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
"PRIMARY KEY (`localId`, `messageId`))");
|
||||
database.execSQL("ALTER TABLE `InstanceEntity` ADD COLUMN `chatLimit` INTEGER");
|
||||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsChatMessages` INTEGER NOT NULL DEFAULT 1");
|
||||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsStreamingEnabled` INTEGER NOT NULL DEFAULT 1");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -60,9 +60,9 @@ class NetworkModule {
|
|||
addInterceptor(InstanceSwitchAuthInterceptor(accountManager))
|
||||
if (BuildConfig.DEBUG) {
|
||||
addInterceptor(HttpLoggingInterceptor().apply {
|
||||
//level = HttpLoggingInterceptor.Level.BASIC
|
||||
level = HttpLoggingInterceptor.Level.BASIC
|
||||
//level = HttpLoggingInterceptor.Level.HEADERS
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
//level = HttpLoggingInterceptor.Level.BODY
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.content.Context
|
|||
import com.keylesspalace.tusky.service.SendTootService
|
||||
import com.keylesspalace.tusky.service.ServiceClient
|
||||
import com.keylesspalace.tusky.service.ServiceClientImpl
|
||||
import com.keylesspalace.tusky.service.StreamingService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
|
@ -28,6 +29,9 @@ abstract class ServicesModule {
|
|||
@ContributesAndroidInjector
|
||||
abstract fun contributesSendTootService(): SendTootService
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesStreamingService(): StreamingService
|
||||
|
||||
@Module
|
||||
companion object {
|
||||
@Provides
|
||||
|
|
|
@ -57,6 +57,8 @@ data class Notification(
|
|||
return UNKNOWN
|
||||
}
|
||||
val asList = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, POLL, EMOJI_REACTION, FOLLOW_REQUEST, CHAT_MESSAGE)
|
||||
|
||||
val asStringList = asList.map { it.presentation }
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package com.keylesspalace.tusky.entity
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class StreamEvent (
|
||||
val event: EventType,
|
||||
val payload: String
|
||||
) {
|
||||
enum class EventType {
|
||||
UNKNOWN,
|
||||
@SerializedName("update")
|
||||
UPDATE,
|
||||
@SerializedName("notification")
|
||||
NOTIFICATION,
|
||||
@SerializedName("delete")
|
||||
DELETE,
|
||||
@SerializedName("filters_changed")
|
||||
FILTERS_CHANGED;
|
||||
}
|
||||
}
|
|
@ -110,7 +110,7 @@ interface MastodonApi {
|
|||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("with_muted") withMuted: Boolean?,
|
||||
@Query("include_types[]") includeTypes: Set<String>?
|
||||
@Query("include_types[]") includeTypes: List<String>?
|
||||
): Call<List<Notification>>
|
||||
|
||||
@POST("api/v1/notifications/clear")
|
||||
|
|
|
@ -52,7 +52,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
val senderIdentifier = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_IDENTIFIER)
|
||||
val senderFullName = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_FULL_NAME)
|
||||
val citedStatusId = intent.getStringExtra(NotificationHelper.KEY_CITED_STATUS_ID)
|
||||
val visibility = intent.getSerializableExtra(NotificationHelper.KEY_VISIBILITY) as Status.Visibility
|
||||
val visibility = intent.getSerializableExtra(NotificationHelper.KEY_VISIBILITY)
|
||||
val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER)
|
||||
val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS)
|
||||
val citedText = intent.getStringExtra(NotificationHelper.KEY_CITED_TEXT)
|
||||
|
@ -93,7 +93,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
|
||||
val composeIntent = ComposeActivity.startIntent(context, ComposeOptions(
|
||||
inReplyToId = citedStatusId,
|
||||
replyVisibility = visibility,
|
||||
replyVisibility = visibility as Status.Visibility,
|
||||
contentWarning = spoiler,
|
||||
mentionedUsernames = mentions.toSet(),
|
||||
replyingStatusAuthor = localAuthorId,
|
||||
|
@ -114,7 +114,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
TootToSend(
|
||||
text,
|
||||
spoiler,
|
||||
visibility.serverString(),
|
||||
(visibility as Status.Visibility).serverString(),
|
||||
false,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
|
|
|
@ -8,9 +8,7 @@ import android.content.ClipData
|
|||
import android.content.ClipDescription
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.os.Parcelable
|
||||
import android.os.*
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
package com.keylesspalace.tusky.service
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.IBinder
|
||||
import android.os.Message
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.gson.Gson
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.db.AccountManager
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.entity.Notification
|
||||
import com.keylesspalace.tusky.entity.StreamEvent
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import dagger.android.AndroidInjection
|
||||
import okhttp3.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class StreamingService: Service(), Injectable {
|
||||
@Inject
|
||||
lateinit var api: MastodonApi
|
||||
|
||||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
@Inject
|
||||
lateinit var accountManager: AccountManager
|
||||
|
||||
@Inject
|
||||
lateinit var gson: Gson
|
||||
|
||||
private val sockets: MutableMap<Long, WebSocket> = mutableMapOf()
|
||||
|
||||
private val notificationManager by lazy { getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
AndroidInjection.inject(this)
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
private fun stopStreamingForId(id: Long) {
|
||||
if(id in sockets) {
|
||||
sockets[id]!!.close(1000, null)
|
||||
sockets.remove(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopStreaming() : Int {
|
||||
for(sock in sockets) {
|
||||
sock.value.close(1000, null)
|
||||
}
|
||||
sockets.clear()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||
}
|
||||
|
||||
notificationManager.cancel(1337)
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
if(intent.hasExtra(KEY_STOP_STREAMING)) {
|
||||
Log.d(TAG, "Stopping stream")
|
||||
return stopStreaming()
|
||||
}
|
||||
|
||||
var description = getString(R.string.streaming_notification_description)
|
||||
val accounts = accountManager.getAllAccountsOrderedByActive()
|
||||
var count = 0
|
||||
for(account in accounts) {
|
||||
stopStreamingForId(account.id)
|
||||
|
||||
if(!account.notificationsStreamingEnabled)
|
||||
continue
|
||||
|
||||
val endpoint = "wss://${account.domain}/api/v1/streaming/?access_token=${account.accessToken}&stream=user:notification"
|
||||
|
||||
val request = Request.Builder().url(endpoint).build()
|
||||
val client = OkHttpClient.Builder().build()
|
||||
|
||||
Log.d(TAG, "Running stream for ${account.fullName}")
|
||||
|
||||
sockets[account.id] = client.newWebSocket(request, StreamingListener(this, gson, account))
|
||||
description += "\n" + account.fullName
|
||||
count++
|
||||
}
|
||||
|
||||
if(count <= 0) {
|
||||
Log.d(TAG, "No accounts. Stopping stream")
|
||||
return stopStreaming()
|
||||
}
|
||||
|
||||
if (NotificationHelper.NOTIFICATION_USE_CHANNELS) {
|
||||
val channel = NotificationChannel(CHANNEL_ID, getString(R.string.streaming_notification_name), NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setContentTitle(getString(R.string.streaming_notification_name))
|
||||
.setContentText(description)
|
||||
.setOngoing(true)
|
||||
.setColor(ContextCompat.getColor(this, R.color.tusky_blue))
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||
startForeground(1337, builder.build())
|
||||
} else {
|
||||
notificationManager.notify(1337, builder.build())
|
||||
}
|
||||
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CHANNEL_ID = "streaming"
|
||||
val KEY_STOP_STREAMING = "stop_streaming"
|
||||
val TAG = "StreamingService"
|
||||
|
||||
@JvmStatic
|
||||
private fun startForegroundService(ctx: Context, intent: Intent) {
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ctx.startForegroundService(intent)
|
||||
} else {
|
||||
ctx.startService(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startStreaming(context: Context) {
|
||||
val intent = Intent(context, StreamingService::class.java)
|
||||
|
||||
Log.d(TAG, "Starting notifications streaming service...")
|
||||
|
||||
startForegroundService(context, intent)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun stopStreaming(context: Context) {
|
||||
val intent = Intent(context, StreamingService::class.java)
|
||||
intent.putExtra(KEY_STOP_STREAMING, 123)
|
||||
|
||||
Log.d(TAG, "Stopping notifications streaming service...")
|
||||
|
||||
startForegroundService(context, intent)
|
||||
}
|
||||
}
|
||||
|
||||
class StreamingListener(val context: Context, val gson: Gson, val account: AccountEntity) : WebSocketListener() {
|
||||
|
||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||
Log.d(TAG, "Stream connected to: ${account.fullName}/user:notification")
|
||||
}
|
||||
|
||||
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
||||
Log.d(TAG, "Stream closed for: ${account.fullName}/user:notification")
|
||||
}
|
||||
|
||||
override fun onMessage(webSocket: WebSocket, text: String) {
|
||||
val event = gson.fromJson(text, StreamEvent::class.java)
|
||||
when(event.event) {
|
||||
StreamEvent.EventType.NOTIFICATION -> {
|
||||
val notification = gson.fromJson(event.payload, Notification::class.java)
|
||||
NotificationHelper.make(context, notification, account, true)
|
||||
}
|
||||
else -> {
|
||||
Log.d(TAG, "Unknown event type: ${event.event.toString()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
super.onMessage(webSocket, text)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue