Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd6d6344 authored by Philipp Heckel's avatar Philipp Heckel
Browse files

work manager

parent 573ab5db
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ android {
}

dependencies {
    def workManagerVersion = "2.5.0"

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion"
    implementation "androidx.core:core-ktx:$rootProject.coreKtxVersion"
@@ -55,6 +57,10 @@ dependencies {
    implementation "androidx.activity:activity-ktx:$rootProject.activityVersion"
    implementation 'com.google.code.gson:gson:2.8.8'

    // WorkManager
    implementation("androidx.work:work-runtime:$workManagerVersion")
    implementation("androidx.work:work-runtime-ktx:$workManagerVersion")

    // RecyclerView
    implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerViewVersion"

+107 −0
Original line number Diff line number Diff line
package io.heckel.ntfy.data

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import io.heckel.ntfy.R
import kotlinx.coroutines.*
import java.net.HttpURLConnection
import java.net.URL
import kotlin.random.Random

class ConnectionWorker(val ctx: Context, workerParams: WorkerParameters) : CoroutineWorker(ctx, workerParams) {
    private val gson = GsonBuilder().create()

    override suspend fun doWork(): Result {
        println("PHIL work started")

        while (isStopped) {
            openConnection(Random.nextLong(), "https://ntfy.sh/test/json")
        }

        println("PHIL work ended")
        // Indicate whether the work finished successfully with the Result
        return Result.success()
    }

    private fun openConnection(subscriptionId: Long, topicUrl: String) {
        println("Connecting to $topicUrl ...")
        val conn = (URL(topicUrl).openConnection() as HttpURLConnection).also {
            it.doInput = true
            it.readTimeout = READ_TIMEOUT
        }
        try {
            println("PHIL connected")
            val input = conn.inputStream.bufferedReader()
            while (isStopped) {
                val line = input.readLine() ?: break // Break if EOF is reached, i.e. readLine is null
                val json = gson.fromJson(line, JsonObject::class.java) ?: break // Break on unexpected line
                val validNotification = !json.isJsonNull
                        && !json.has("event") // No keepalive or open messages
                        && json.has("message")
                if (validNotification) {
                    val title = "ntfy.sh/test"
                    val message = json.get("message").asString
                    displayNotification(title, message)
                    println("notification received: ${json.get("message").asString}")
                }
            }
        } catch (e: Exception) {
            println("Connection error: " + e)
        } finally {
            conn.disconnect()
        }
        println("Connection terminated: $topicUrl")
    }

    private fun displayNotification(title: String, message: String) {
        val notificationManager =
            ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val channelId = ctx.getString(R.string.notification_channel_id)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = ctx.getString(R.string.notification_channel_name)
            val descriptionText = ctx.getString(R.string.notification_channel_name)
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(channelId, name, importance).apply {
                description = descriptionText
            }
            notificationManager.createNotificationChannel(channel)
        }
        val notification = NotificationCompat.Builder(ctx, channelId)
            .setSmallIcon(R.drawable.ntfy)
            .setContentTitle(title)
            .setContentText(message)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .build()
        notificationManager.notify(Random.nextInt(), notification)
    }

    /**
     * Create the NotificationChannel, but only on API 26+ because
     * the NotificationChannel class is new and not in the support library
     */
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channelId = ctx.getString(R.string.notification_channel_id)
            val name = ctx.getString(R.string.notification_channel_name)
            val descriptionText = ctx.getString(R.string.notification_channel_name)
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(channelId, name, importance).apply {
                description = descriptionText
            }
            // Register the channel with the system
            val notificationManager: NotificationManager =
                ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }

}
+20 −8
Original line number Diff line number Diff line
@@ -15,17 +15,18 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.work.*
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import io.heckel.ntfy.R
import io.heckel.ntfy.data.Notification
import io.heckel.ntfy.data.Status
import io.heckel.ntfy.data.Subscription
import io.heckel.ntfy.data.topicShortUrl
import io.heckel.ntfy.data.*
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.TimeUnit
import kotlin.random.Random


const val SUBSCRIPTION_ID = "topic_id"

class MainActivity : AppCompatActivity(), AddFragment.AddSubscriptionListener {
    private val uniqueWorkName = "connectionWorker"
    private val subscriptionsViewModel by viewModels<SubscriptionsViewModel> {
        SubscriptionsViewModelFactory()
    }
@@ -76,7 +77,8 @@ class MainActivity : AppCompatActivity(), AddFragment.AddSubscriptionListener {
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.menu_action_source -> {
                startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_source_url))))
                // startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.main_menu_source_url))))
                enqueueConnectionWorker()
                true
            }
            R.id.menu_action_website -> {
@@ -101,6 +103,15 @@ class MainActivity : AppCompatActivity(), AddFragment.AddSubscriptionListener {
        subscriptionsViewModel.add(subscription)
    }

    private fun enqueueConnectionWorker() {
        val workRequest =
            PeriodicWorkRequestBuilder<ConnectionWorker>(1, TimeUnit.MINUTES)
                .build()
        WorkManager
            .getInstance(this)
            .enqueueUniquePeriodicWork(uniqueWorkName, ExistingPeriodicWorkPolicy.KEEP, workRequest)
    }

    private fun displayNotification(n: Notification) {
        val channelId = getString(R.string.notification_channel_id)
        val notification = NotificationCompat.Builder(this, channelId)
@@ -132,3 +143,4 @@ class MainActivity : AppCompatActivity(), AddFragment.AddSubscriptionListener {
        }
    }
}