yggdrasil-android/app/src/main/java/eu/neilalexander/yggdrasil/YggTileService.kt

113 lines
No EOL
3.7 KiB
Kotlin

package eu.neilalexander.yggdrasil
import android.content.Intent
import android.graphics.drawable.Icon
import android.os.Build
import android.os.IBinder
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.content.edit
import androidx.preference.PreferenceManager
private const val TAG = "TileService"
@RequiresApi(Build.VERSION_CODES.N)
class YggTileService: TileService(), YggStateReceiver.StateReceiver {
private lateinit var receiver: YggStateReceiver
override fun onCreate() {
super.onCreate()
receiver = YggStateReceiver(this)
}
/**
* We need to override the method onBind to avoid crashes that were detected on Android 8
*
* The possible reason of crashes is described here:
* https://github.com/aosp-mirror/platform_frameworks_base/commit/ee68fd889c2dfcd895b8e73fc39d7b97826dc3d8
*/
override fun onBind(intent: Intent?): IBinder? {
return try {
super.onBind(intent)
} catch (th: Throwable) {
null
}
}
override fun onTileAdded() {
super.onTileAdded()
updateTileState((application as GlobalApplication).getCurrentState())
}
override fun onTileRemoved() {
super.onTileRemoved()
updateTileState((application as GlobalApplication).getCurrentState())
}
override fun onStartListening() {
super.onStartListening()
receiver.register(this)
updateTileState((application as GlobalApplication).getCurrentState())
}
override fun onStopListening() {
super.onStopListening()
receiver.unregister(this)
}
override fun onDestroy() {
super.onDestroy()
receiver.unregister(this)
}
override fun onClick() {
super.onClick()
// Saving new state
val preferences = PreferenceManager.getDefaultSharedPreferences(this.baseContext)
val enabled = preferences.getBoolean(PREF_KEY_ENABLED, false)
preferences.edit(commit = true) { putBoolean(PREF_KEY_ENABLED, !enabled) }
// Starting or stopping VPN service
val intent = Intent(this, PacketTunnelProvider::class.java)
intent.action = PacketTunnelProvider.ACTION_TOGGLE
startService(intent)
}
private fun updateTileState(state: State) {
val tile = qsTile ?: return
val oldState = tile.state
val preferences = PreferenceManager.getDefaultSharedPreferences(this.baseContext)
val enabled = preferences.getBoolean(PREF_KEY_ENABLED, false)
tile.state = when (enabled) {
false -> Tile.STATE_INACTIVE
true -> Tile.STATE_ACTIVE
}
var changed = oldState != tile.state
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val oldText = tile.subtitle
tile.subtitle = when (state) {
State.Enabled -> getText(R.string.tile_enabled)
State.Connected -> getText(R.string.tile_connected)
else -> getText(R.string.tile_disabled)
}
changed = changed || (oldText != tile.subtitle)
}
// Update tile if changed state
if (changed) {
Log.i(TAG, "Updating tile, old state: $oldState, new state: ${tile.state}")
/*
Force set the icon in the tile, because there is a problem on icon tint in the Android Oreo.
Issue: https://github.com/AdguardTeam/AdguardForAndroid/issues/1996
*/
tile.icon = Icon.createWithResource(applicationContext, R.drawable.ic_tile_icon)
tile.updateTile()
}
}
override fun onStateChange(state: State) {
updateTileState(state)
}
}