- Create a kill switch
- Fix some reconnection issues
This commit is contained in:
@@ -31,9 +31,13 @@
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
tools:targetApi="33">
|
||||
<receiver
|
||||
android:name=".service.ReconnectReceiver"
|
||||
android:name=".service.KillSwitchReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false"></receiver>
|
||||
<receiver
|
||||
android:name=".service.ReconnectReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<receiver
|
||||
android:name=".service.BootReceiver"
|
||||
android:enabled="true"
|
||||
|
||||
@@ -46,6 +46,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -183,28 +184,6 @@ class Amber : Application(), LifecycleObserver {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
Log.d("ProcessLifecycleOwner", "App in foreground")
|
||||
isAppInForeground = true
|
||||
|
||||
// activates the profile filter only when the app is in the foreground
|
||||
applicationIOScope.launch {
|
||||
profileSubscription.updateFilter()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
Log.d("ProcessLifecycleOwner", "App in background")
|
||||
isAppInForeground = false
|
||||
|
||||
// closes the filter when in the background
|
||||
applicationIOScope.launch {
|
||||
profileSubscription.closeSub()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
isStartingApp.value = true
|
||||
|
||||
Log.d(TAG, "onCreate Amber")
|
||||
@@ -248,7 +227,36 @@ class Amber : Application(), LifecycleObserver {
|
||||
settings = LocalPreferences.loadSettingsFromEncryptedStorage()
|
||||
LocalPreferences.reloadApp()
|
||||
isStartingApp.value = false
|
||||
|
||||
checkForNewRelaysAndUpdateAllFilters(true)
|
||||
if (settings.killSwitch) {
|
||||
client.disconnect()
|
||||
}
|
||||
launch(Dispatchers.Main) {
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
Log.d("ProcessLifecycleOwner", "App in foreground")
|
||||
isAppInForeground = true
|
||||
|
||||
// activates the profile filter only when the app is in the foreground
|
||||
if (!settings.killSwitch) {
|
||||
applicationIOScope.launch {
|
||||
profileSubscription.updateFilter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
Log.d("ProcessLifecycleOwner", "App in background")
|
||||
isAppInForeground = false
|
||||
|
||||
// closes the filter when in the background
|
||||
applicationIOScope.launch {
|
||||
profileSubscription.closeSub()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to run migrations", e)
|
||||
isStartingApp.value = false
|
||||
@@ -269,8 +277,15 @@ class Amber : Application(), LifecycleObserver {
|
||||
}
|
||||
|
||||
fun reconnect() {
|
||||
if (settings.killSwitch) {
|
||||
return
|
||||
}
|
||||
Log.d(TAG, "reconnecting relays")
|
||||
client.reconnect(true)
|
||||
val wasActive = client.isActive()
|
||||
if (!wasActive) {
|
||||
client.connect()
|
||||
}
|
||||
client.reconnect(wasActive)
|
||||
stats.updateNotification()
|
||||
}
|
||||
|
||||
@@ -297,9 +312,16 @@ class Amber : Application(), LifecycleObserver {
|
||||
return savedRelays
|
||||
}
|
||||
|
||||
fun checkForNewRelaysAndUpdateAllFilters(
|
||||
suspend fun checkForNewRelaysAndUpdateAllFilters(
|
||||
shouldReconnect: Boolean = false,
|
||||
) {
|
||||
if (settings.killSwitch) {
|
||||
client.disconnect()
|
||||
return
|
||||
}
|
||||
|
||||
val wasActive = client.isActive()
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
// TODO: You can filter inside each update filter for only
|
||||
// localhost relays and keep these alive even on the offline
|
||||
@@ -312,9 +334,14 @@ class Amber : Application(), LifecycleObserver {
|
||||
}
|
||||
notificationSubscription.updateFilter()
|
||||
}
|
||||
delay(3000)
|
||||
Log.d(TAG, "checkForNewRelaysAndUpdateAllFilters wasActive: $wasActive")
|
||||
if (!wasActive) {
|
||||
client.connect()
|
||||
}
|
||||
|
||||
if (shouldReconnect) {
|
||||
client.reconnect(true)
|
||||
client.reconnect(wasActive)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ private enum class SettingsKeys(val key: String) {
|
||||
USE_PROXY("use_proxy"),
|
||||
PROXY_PORT("proxy_port"),
|
||||
BATERRY_OPTIMIZATION("battery_optimization"),
|
||||
KILL_SWITCH("kill_switch"),
|
||||
}
|
||||
|
||||
@Immutable
|
||||
@@ -137,6 +138,7 @@ object LocalPreferences {
|
||||
putBoolean(SettingsKeys.USE_PIN.key, settings.usePin)
|
||||
putBoolean(SettingsKeys.USE_PROXY.key, settings.useProxy)
|
||||
putInt(SettingsKeys.PROXY_PORT.key, settings.proxyPort)
|
||||
putBoolean(SettingsKeys.KILL_SWITCH.key, settings.killSwitch)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,6 +248,7 @@ object LocalPreferences {
|
||||
usePin = getBoolean(SettingsKeys.USE_PIN.key, false),
|
||||
useProxy = getBoolean(SettingsKeys.USE_PROXY.key, false),
|
||||
proxyPort = getInt(SettingsKeys.PROXY_PORT.key, 9050),
|
||||
killSwitch = getBoolean(SettingsKeys.KILL_SWITCH.key, false),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,5 @@ data class AmberSettings(
|
||||
val usePin: Boolean = false,
|
||||
val useProxy: Boolean = false,
|
||||
val proxyPort: Int = 9050,
|
||||
val killSwitch: Boolean = false,
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.core.app.NotificationManagerCompat
|
||||
import com.greenart7c3.nostrsigner.Amber
|
||||
import com.greenart7c3.nostrsigner.MainActivity
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.service.KillSwitchReceiver
|
||||
import com.greenart7c3.nostrsigner.service.ReconnectReceiver
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
|
||||
@@ -119,6 +120,14 @@ class AmberRelayStats(
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE,
|
||||
)
|
||||
|
||||
val killSwitchIntent = Intent(appContext, KillSwitchReceiver::class.java)
|
||||
val killSwitchPendingIntent = PendingIntent.getBroadcast(
|
||||
appContext,
|
||||
0,
|
||||
killSwitchIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE,
|
||||
)
|
||||
|
||||
val notificationBuilder =
|
||||
NotificationCompat.Builder(appContext, channelId)
|
||||
.setGroup(group.id)
|
||||
@@ -128,6 +137,7 @@ class AmberRelayStats(
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentIntent(contentPendingIntent)
|
||||
.addAction(R.drawable.ic_notification, appContext.getString(R.string.reconnect), reconnectPendingIntent)
|
||||
.addAction(R.drawable.ic_notification, appContext.getString(if (Amber.instance.settings.killSwitch) R.string.disable_kill_switch else R.string.enable_kill_switch), killSwitchPendingIntent)
|
||||
|
||||
return notificationBuilder.build()
|
||||
}
|
||||
|
||||
@@ -353,7 +353,10 @@ object BunkerRequestUtils {
|
||||
),
|
||||
)
|
||||
if (didChangeRelays) {
|
||||
Amber.instance.notificationSubscription.updateFilter()
|
||||
Amber.instance.checkForNewRelaysAndUpdateAllFilters(true)
|
||||
}
|
||||
if (!Amber.instance.client.isActive()) {
|
||||
Amber.instance.client.connect()
|
||||
}
|
||||
|
||||
sendBunkerResponse(
|
||||
|
||||
@@ -30,9 +30,13 @@ class ConnectivityService : Service() {
|
||||
super.onAvailable(network)
|
||||
@Suppress("KotlinConstantConditions")
|
||||
if (BuildConfig.FLAVOR == "offline") return
|
||||
if (Amber.instance.settings.killSwitch) return
|
||||
|
||||
if (lastNetwork != null && lastNetwork != network) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
if (!Amber.instance.client.isActive()) {
|
||||
Amber.instance.client.connect()
|
||||
}
|
||||
Amber.instance.client.reconnect(true)
|
||||
}
|
||||
}
|
||||
@@ -48,13 +52,16 @@ class ConnectivityService : Service() {
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
if (BuildConfig.FLAVOR == "offline") return
|
||||
if (Amber.instance.settings.killSwitch) return
|
||||
|
||||
scope.launch(Dispatchers.IO) {
|
||||
Log.d(
|
||||
"ServiceManager NetworkCallback",
|
||||
"onCapabilitiesChanged: ${network.networkHandle} hasMobileData ${Amber.instance.isOnMobileDataState.value} hasWifi ${Amber.instance.isOnWifiDataState.value}",
|
||||
)
|
||||
|
||||
if (!Amber.instance.client.isActive()) {
|
||||
Amber.instance.client.connect()
|
||||
}
|
||||
Amber.instance.client.reconnect(true)
|
||||
}
|
||||
}
|
||||
@@ -90,7 +97,7 @@ class ConnectivityService : Service() {
|
||||
delay(1000)
|
||||
}
|
||||
@Suppress("KotlinConstantConditions")
|
||||
if (BuildConfig.FLAVOR != "offline") {
|
||||
if (BuildConfig.FLAVOR != "offline" && !Amber.instance.settings.killSwitch) {
|
||||
Amber.instance.client.connect()
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
Amber.instance.checkForNewRelaysAndUpdateAllFilters()
|
||||
@@ -114,8 +121,12 @@ class ConnectivityService : Service() {
|
||||
if (BuildConfig.FLAVOR == "offline") {
|
||||
return
|
||||
}
|
||||
if (Amber.instance.settings.killSwitch) return
|
||||
|
||||
scope.launch {
|
||||
if (!Amber.instance.client.isActive()) {
|
||||
Amber.instance.client.connect()
|
||||
}
|
||||
Amber.instance.client.reconnect(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.greenart7c3.nostrsigner.service
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.greenart7c3.nostrsigner.Amber
|
||||
import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class KillSwitchReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(killSwitch = !Amber.instance.settings.killSwitch)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
if (Amber.instance.settings.killSwitch) {
|
||||
Amber.instance.client.disconnect()
|
||||
} else {
|
||||
Amber.instance.checkForNewRelaysAndUpdateAllFilters(shouldReconnect = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
package com.greenart7c3.nostrsigner.service
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.greenart7c3.nostrsigner.Amber
|
||||
import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
@@ -53,6 +54,11 @@ class NotificationSubscription(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSend(relay: IRelayClient, msg: String, success: Boolean) {
|
||||
Log.d("NotificationSubscription", "onSend: ${relay.url}, $msg, $success")
|
||||
super.onSend(relay, msg, success)
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method every time the relay list or the user list changes
|
||||
*/
|
||||
|
||||
@@ -550,4 +550,6 @@
|
||||
<string name="of_connected_relays">%1$d of %2$d connected relays</string>
|
||||
<string name="proxy">Proxy</string>
|
||||
<string name="default_relay_text">Default</string>
|
||||
<string name="enable_kill_switch">Enable kill switch</string>
|
||||
<string name="disable_kill_switch">Disable kill switch</string>
|
||||
</resources>
|
||||
|
||||
@@ -13,7 +13,7 @@ lifecycle_version = "2.9.2"
|
||||
material3 = "1.3.2"
|
||||
mockk = "1.14.5"
|
||||
nav_version = "2.9.3"
|
||||
quartz = "v1.00.3"
|
||||
quartz = "v1.00.5"
|
||||
compose_ui = "1.9.0"
|
||||
richtextUi = "e1151c8"
|
||||
roomKtx = "2.7.2"
|
||||
|
||||
Reference in New Issue
Block a user