android: make disconnected notification non-foreground (#391)

android: make disconnected notification a non-foreground notification

Follow-up to https://github.com/tailscale/tailscale-android/pull/389
Only use foreground notifications when VPN was started as a foreground service.

Updates #cleanup

Signed-off-by: kari-ts <kari@tailscale.com>
pull/413/head
kari-ts 6 months ago committed by GitHub
parent a6fd8a8093
commit cbc47791ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -99,6 +99,7 @@ class App : UninitializedApp(), libtailscale.AppContext {
override fun onTerminate() { override fun onTerminate() {
super.onTerminate() super.onTerminate()
Notifier.stop() Notifier.stop()
notificationManager.cancelAll()
applicationScope.cancel() applicationScope.cancel()
} }
@ -127,8 +128,12 @@ class App : UninitializedApp(), libtailscale.AppContext {
applicationScope.launch { applicationScope.launch {
Notifier.state.collect { state -> Notifier.state.collect { state ->
val ableToStartVPN = state > Ipn.State.NeedsMachineAuth val ableToStartVPN = state > Ipn.State.NeedsMachineAuth
// If VPN is stopped, show a disconnected notification. If it is running as a foregrround service, IPNService will show a connected notification.
if (state == Ipn.State.Stopped){
notifyStatus(false)
}
val vpnRunning = state == Ipn.State.Starting || state == Ipn.State.Running val vpnRunning = state == Ipn.State.Starting || state == Ipn.State.Running
updateConnStatus(ableToStartVPN, vpnRunning) updateConnStatus(ableToStartVPN)
QuickToggleService.setVPNRunning(vpnRunning) QuickToggleService.setVPNRunning(vpnRunning)
} }
} }
@ -212,11 +217,10 @@ class App : UninitializedApp(), libtailscale.AppContext {
* by storing this in a shared preference. This allows us to check this * by storing this in a shared preference. This allows us to check this
* value without needing a fully initialized instance of the application. * value without needing a fully initialized instance of the application.
*/ */
private fun updateConnStatus(ableToStartVPN: Boolean, vpnRunning: Boolean) { private fun updateConnStatus(ableToStartVPN: Boolean) {
setAbleToStartVPN(ableToStartVPN) setAbleToStartVPN(ableToStartVPN)
QuickToggleService.updateTile() QuickToggleService.updateTile()
Log.d("App", "Set Tile Ready: $ableToStartVPN") Log.d("App", "Set Tile Ready: $ableToStartVPN")
notifyStatus(vpnRunning)
} }
override fun getModelName(): String { override fun getModelName(): String {
@ -341,6 +345,7 @@ open class UninitializedApp : Application() {
private const val UNENCRYPTED_PREFERENCES = "unencrypted" private const val UNENCRYPTED_PREFERENCES = "unencrypted"
private lateinit var appInstance: UninitializedApp private lateinit var appInstance: UninitializedApp
lateinit var notificationManager: NotificationManagerCompat
@JvmStatic @JvmStatic
fun get(): UninitializedApp { fun get(): UninitializedApp {
@ -378,11 +383,11 @@ open class UninitializedApp : Application() {
fun createNotificationChannel(id: String, name: String, description: String, importance: Int) { fun createNotificationChannel(id: String, name: String, description: String, importance: Int) {
val channel = NotificationChannel(id, name, importance) val channel = NotificationChannel(id, name, importance)
channel.description = description channel.description = description
val nm: NotificationManagerCompat = NotificationManagerCompat.from(this) notificationManager = NotificationManagerCompat.from(this)
nm.createNotificationChannel(channel) notificationManager.createNotificationChannel(channel)
} }
protected fun notifyStatus(vpnRunning: Boolean) { fun notifyStatus(vpnRunning: Boolean) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
PackageManager.PERMISSION_GRANTED) { PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling // TODO: Consider calling
@ -394,8 +399,7 @@ open class UninitializedApp : Application() {
// for ActivityCompat#requestPermissions for more details. // for ActivityCompat#requestPermissions for more details.
return return
} }
val nm: NotificationManagerCompat = NotificationManagerCompat.from(this) notificationManager.notify(STATUS_NOTIFICATION_ID, buildStatusNotification(vpnRunning))
nm.notify(STATUS_NOTIFICATION_ID, buildStatusNotification(vpnRunning))
} }
fun buildStatusNotification(vpnRunning: Boolean): Notification { fun buildStatusNotification(vpnRunning: Boolean): Notification {

@ -39,8 +39,9 @@ open class IPNService : VpnService(), libtailscale.IPNService {
} }
"android.net.VpnService" -> { "android.net.VpnService" -> {
// This means we were started by Android due to Always On VPN. // This means we were started by Android due to Always On VPN.
// We don't show a foreground notification because we weren't // We show a non-foreground notification because we weren't
// started as a foreground service. // started as a foreground service.
App.get().notifyStatus(true)
App.get().setWantRunning(true) App.get().setWantRunning(true)
Libtailscale.requestVPN(this) Libtailscale.requestVPN(this)
START_STICKY START_STICKY
@ -49,6 +50,7 @@ open class IPNService : VpnService(), libtailscale.IPNService {
// This means that we were restarted after the service was killed // This means that we were restarted after the service was killed
// (potentially due to OOM). // (potentially due to OOM).
if (UninitializedApp.get().isAbleToStartVPN()) { if (UninitializedApp.get().isAbleToStartVPN()) {
showForegroundNotification()
App.get() App.get()
Libtailscale.requestVPN(this) Libtailscale.requestVPN(this)
START_STICKY START_STICKY
@ -59,7 +61,7 @@ open class IPNService : VpnService(), libtailscale.IPNService {
} }
override fun close() { override fun close() {
stopForeground(true) stopForeground(STOP_FOREGROUND_REMOVE)
Libtailscale.serviceDisconnect(this) Libtailscale.serviceDisconnect(this)
} }

Loading…
Cancel
Save