Comments
This commit is contained in:
parent
bec263d1c8
commit
496bdcd285
7 changed files with 42 additions and 4 deletions
|
@ -23,8 +23,8 @@ class NotificationDispatcher(val context: Context, val repository: Repository) {
|
||||||
fun dispatch(subscription: Subscription, notification: Notification) {
|
fun dispatch(subscription: Subscription, notification: Notification) {
|
||||||
val muted = checkMuted(subscription)
|
val muted = checkMuted(subscription)
|
||||||
val notify = checkNotify(subscription, notification, muted)
|
val notify = checkNotify(subscription, notification, muted)
|
||||||
val broadcast = subscription.upAppId == null
|
val broadcast = subscription.upAppId == null // Never broadcast for UnifiedPush
|
||||||
val distribute = subscription.upAppId != null
|
val distribute = subscription.upAppId != null // Only distribute for UnifiedPush subscriptions
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifier.send(subscription, notification)
|
notifier.send(subscription, notification)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@ import io.heckel.ntfy.up.BroadcastReceiver
|
||||||
/**
|
/**
|
||||||
* This class only manages the SubscriberService, i.e. it starts or stops it.
|
* This class only manages the SubscriberService, i.e. it starts or stops it.
|
||||||
* It's used in multiple activities.
|
* It's used in multiple activities.
|
||||||
|
*
|
||||||
|
* We are starting the service via a worker and not directly because since Android 7
|
||||||
|
* (but officially since Lollipop!), any process called by a BroadcastReceiver
|
||||||
|
* (only manifest-declared receiver) is run at low priority and hence eventually
|
||||||
|
* killed by Android.
|
||||||
*/
|
*/
|
||||||
class SubscriberServiceManager(private val context: Context) {
|
class SubscriberServiceManager(private val context: Context) {
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
|
@ -20,6 +25,10 @@ class SubscriberServiceManager(private val context: Context) {
|
||||||
workManager.enqueue(startServiceRequest)
|
workManager.enqueue(startServiceRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts or stops the foreground service by figuring out how many instant delivery subscriptions
|
||||||
|
* exist. If there's > 0, then we need a foreground service.
|
||||||
|
*/
|
||||||
class RefreshWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) {
|
class RefreshWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
if (context.applicationContext !is Application) {
|
if (context.applicationContext !is Application) {
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
package io.heckel.ntfy.ui
|
package io.heckel.ntfy.ui
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.preference.*
|
import androidx.preference.*
|
||||||
|
import androidx.preference.Preference.OnPreferenceClickListener
|
||||||
import io.heckel.ntfy.BuildConfig
|
import io.heckel.ntfy.BuildConfig
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.app.Application
|
import io.heckel.ntfy.app.Application
|
||||||
|
@ -37,6 +42,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.main_preferences, rootKey)
|
setPreferencesFromResource(R.xml.main_preferences, rootKey)
|
||||||
|
|
||||||
|
// Important note: We do not use the default shared prefs to store settings. Every
|
||||||
|
// preferenceDataStore is overridden to use the repository. This is convenient, because
|
||||||
|
// everybody has access to the repository.
|
||||||
|
|
||||||
// UnifiedPush Enabled
|
// UnifiedPush Enabled
|
||||||
val upEnabledPrefId = context?.getString(R.string.pref_unified_push_enabled) ?: return
|
val upEnabledPrefId = context?.getString(R.string.pref_unified_push_enabled) ?: return
|
||||||
val upEnabled: SwitchPreference? = findPreference(upEnabledPrefId)
|
val upEnabled: SwitchPreference? = findPreference(upEnabledPrefId)
|
||||||
|
@ -82,7 +91,18 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
// Version
|
// Version
|
||||||
val versionPrefId = context?.getString(R.string.pref_version) ?: return
|
val versionPrefId = context?.getString(R.string.pref_version) ?: return
|
||||||
val versionPref: Preference? = findPreference(versionPrefId)
|
val versionPref: Preference? = findPreference(versionPrefId)
|
||||||
versionPref?.summary = getString(R.string.settings_about_version_format, BuildConfig.VERSION_NAME, BuildConfig.FLAVOR)
|
val version = getString(R.string.settings_about_version_format, BuildConfig.VERSION_NAME, BuildConfig.FLAVOR)
|
||||||
|
versionPref?.summary = version
|
||||||
|
versionPref?.onPreferenceClickListener = OnPreferenceClickListener {
|
||||||
|
val context = context ?: return@OnPreferenceClickListener false
|
||||||
|
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = ClipData.newPlainText("app version", version)
|
||||||
|
clipboard.setPrimaryClip(clip)
|
||||||
|
Toast
|
||||||
|
.makeText(context, getString(R.string.settings_about_version_copied_to_clipboard_message), Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,10 @@ import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the UnifiedPush broadcast receiver to handle the distributor actions REGISTER and UNREGISTER.
|
||||||
|
* See https://unifiedpush.org/spec/android/ for details.
|
||||||
|
*/
|
||||||
class BroadcastReceiver : android.content.BroadcastReceiver() {
|
class BroadcastReceiver : android.content.BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (context == null || intent == null) {
|
if (context == null || intent == null) {
|
||||||
|
@ -69,7 +73,6 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
|
||||||
newCount = 0,
|
newCount = 0,
|
||||||
lastActive = Date().time/1000
|
lastActive = Date().time/1000
|
||||||
)
|
)
|
||||||
|
|
||||||
Log.d(TAG, "Adding subscription with for app $appId (connectorToken $connectorToken): $subscription")
|
Log.d(TAG, "Adding subscription with for app $appId (connectorToken $connectorToken): $subscription")
|
||||||
repository.addSubscription(subscription)
|
repository.addSubscription(subscription)
|
||||||
distributor.sendEndpoint(appId, connectorToken, endpoint)
|
distributor.sendEndpoint(appId, connectorToken, endpoint)
|
||||||
|
|
|
@ -4,6 +4,10 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the UnifiedPush distributor, an amalgamation of messages to be sent as part of the spec.
|
||||||
|
* See https://unifiedpush.org/spec/android/ for details.
|
||||||
|
*/
|
||||||
class Distributor(val context: Context) {
|
class Distributor(val context: Context) {
|
||||||
fun sendMessage(app: String, connectorToken: String, message: String) {
|
fun sendMessage(app: String, connectorToken: String, message: String) {
|
||||||
Log.d(TAG, "Sending MESSAGE to $app (token=$connectorToken): $message")
|
Log.d(TAG, "Sending MESSAGE to $app (token=$connectorToken): $message")
|
||||||
|
|
|
@ -104,6 +104,7 @@ fun fadeStatusBarColor(window: Window, fromColor: Int, toColor: Int) {
|
||||||
statusBarColorAnimation.start()
|
statusBarColorAnimation.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates a (cryptographically secure) random string of a certain length
|
||||||
fun randomString(len: Int): String {
|
fun randomString(len: Int): String {
|
||||||
val random = SecureRandom()
|
val random = SecureRandom()
|
||||||
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
|
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
|
||||||
|
|
|
@ -157,6 +157,7 @@
|
||||||
<string name="settings_about_header">About</string>
|
<string name="settings_about_header">About</string>
|
||||||
<string name="settings_about_version">Version</string>
|
<string name="settings_about_version">Version</string>
|
||||||
<string name="settings_about_version_format">ntfy %1$s (%2$s)</string>
|
<string name="settings_about_version_format">ntfy %1$s (%2$s)</string>
|
||||||
|
<string name="settings_about_version_copied_to_clipboard_message">Copied to clipboard</string>
|
||||||
|
|
||||||
<!-- Preferences IDs -->
|
<!-- Preferences IDs -->
|
||||||
<string name="pref_unified_push_enabled">UnifiedPushEnabled</string>
|
<string name="pref_unified_push_enabled">UnifiedPushEnabled</string>
|
||||||
|
|
Loading…
Reference in a new issue