Remove repeater from UI if it's not supported

This could happen on devices like Chrome OS and Android emulators.
This commit is contained in:
Mygod
2018-12-13 15:04:19 +08:00
parent 6002794905
commit ca1fc946ca
6 changed files with 43 additions and 21 deletions

View File

@@ -27,6 +27,8 @@ class BootReceiver : BroadcastReceiver() {
Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_LOCKED_BOOT_COMPLETED -> started = true Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_LOCKED_BOOT_COMPLETED -> started = true
else -> return else -> return
} }
if (RepeaterService.supported) {
ContextCompat.startForegroundService(context, Intent(context, RepeaterService::class.java)) ContextCompat.startForegroundService(context, Intent(context, RepeaterService::class.java))
} }
} }
}

View File

@@ -27,13 +27,28 @@ import be.mygod.vpnhotspot.widget.SmartSnackbar
import timber.log.Timber import timber.log.Timber
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
/**
* Service for handling Wi-Fi P2P. `supported` must be checked before this service is started otherwise it would crash.
*/
class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPreferences.OnSharedPreferenceChangeListener { class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPreferences.OnSharedPreferenceChangeListener {
companion object { companion object {
private const val TAG = "RepeaterService" private const val TAG = "RepeaterService"
/**
* This is only a "ServiceConnection" to system service and its impact on system is minimal.
*/
private val p2pManager: WifiP2pManager? by lazy {
try {
app.getSystemService<WifiP2pManager>()
} catch (e: RuntimeException) {
Timber.w(e)
null
}
}
val supported get() = p2pManager != null
} }
enum class Status { enum class Status {
IDLE, STARTING, ACTIVE IDLE, STARTING, ACTIVE, DESTROYED
} }
inner class Binder : android.os.Binder() { inner class Binder : android.os.Binder() {
@@ -92,7 +107,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
} }
} }
private lateinit var p2pManager: WifiP2pManager private val p2pManager get() = RepeaterService.p2pManager!!
private var channel: WifiP2pManager.Channel? = null private var channel: WifiP2pManager.Channel? = null
var group: WifiP2pGroup? = null var group: WifiP2pGroup? = null
private set(value) { private set(value) {
@@ -138,12 +153,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
try {
p2pManager = getSystemService()!!
onChannelDisconnected() onChannelDisconnected()
} catch (e: RuntimeException) {
Timber.w(e)
}
app.pref.registerOnSharedPreferenceChangeListener(this) app.pref.registerOnSharedPreferenceChangeListener(this)
} }
@@ -169,7 +179,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
override fun onChannelDisconnected() { override fun onChannelDisconnected() {
channel = null channel = null
try { if (status != Status.DESTROYED) try {
channel = p2pManager.initialize(this, Looper.getMainLooper(), this) channel = p2pManager.initialize(this, Looper.getMainLooper(), this)
setOperatingChannel() setOperatingChannel()
binder.requestGroupUpdate() binder.requestGroupUpdate()
@@ -282,6 +292,8 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
if (status != Status.IDLE) binder.shutdown() if (status != Status.IDLE) binder.shutdown()
clean() // force clean to prevent leakage clean() // force clean to prevent leakage
app.pref.unregisterOnSharedPreferenceChangeListener(this) app.pref.unregisterOnSharedPreferenceChangeListener(this)
status = Status.DESTROYED
channel?.close()
super.onDestroy() super.onDestroy()
} }
} }

View File

@@ -22,12 +22,14 @@ class RepeaterTileService : TileService(), ServiceConnection {
override fun onStartListening() { override fun onStartListening() {
super.onStartListening() super.onStartListening()
if (RepeaterService.supported) {
bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE) bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE)
} }
}
override fun onStopListening() { override fun onStopListening() {
super.onStopListening() super.onStopListening()
stopAndUnbind(this) if (RepeaterService.supported) stopAndUnbind(this)
} }
override fun onClick() { override fun onClick() {
@@ -72,7 +74,7 @@ class RepeaterTileService : TileService(), ServiceConnection {
qsTile.icon = tileOn qsTile.icon = tileOn
qsTile.label = group?.networkName qsTile.label = group?.networkName
} }
null -> { else -> { // null or DESTROYED, which should never occur
qsTile.state = Tile.STATE_UNAVAILABLE qsTile.state = Tile.STATE_UNAVAILABLE
qsTile.icon = tileOff qsTile.icon = tileOff
qsTile.label = getString(R.string.title_repeater) qsTile.label = getString(R.string.title_repeater)

View File

@@ -32,11 +32,13 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref) preferenceManager.preferenceDataStore = SharedPreferenceDataStore(app.pref)
addPreferencesFromResource(R.xml.pref_settings) addPreferencesFromResource(R.xml.pref_settings)
val boot = findPreference("service.repeater.startOnBoot") as SwitchPreference val boot = findPreference("service.repeater.startOnBoot") as SwitchPreference
if (RepeaterService.supported) {
boot.setOnPreferenceChangeListener { _, value -> boot.setOnPreferenceChangeListener { _, value ->
BootReceiver.enabled = value as Boolean BootReceiver.enabled = value as Boolean
true true
} }
boot.isChecked = BootReceiver.enabled boot.isChecked = BootReceiver.enabled
} else boot.parent!!.removePreference(boot)
findPreference("service.clean").setOnPreferenceClickListener { findPreference("service.clean").setOnPreferenceClickListener {
val cleaned = try { val cleaned = try {
Routing.clean() Routing.clean()

View File

@@ -64,7 +64,9 @@ class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Ca
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
if (RepeaterService.supported) {
bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE) bindService(Intent(this, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE)
}
IpNeighbourMonitor.registerCallback(this) IpNeighbourMonitor.registerCallback(this)
registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
} }
@@ -72,7 +74,7 @@ class ClientMonitorService : Service(), ServiceConnection, IpNeighbourMonitor.Ca
override fun onDestroy() { override fun onDestroy() {
unregisterReceiver(receiver) unregisterReceiver(receiver)
IpNeighbourMonitor.unregisterCallback(this) IpNeighbourMonitor.unregisterCallback(this)
stopAndUnbind(this) if (RepeaterService.supported) stopAndUnbind(this)
super.onDestroy() super.onDestroy()
} }

View File

@@ -20,6 +20,7 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import be.mygod.vpnhotspot.LocalOnlyHotspotService import be.mygod.vpnhotspot.LocalOnlyHotspotService
import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.RepeaterService
import be.mygod.vpnhotspot.TetheringService import be.mygod.vpnhotspot.TetheringService
import be.mygod.vpnhotspot.databinding.FragmentTetheringBinding import be.mygod.vpnhotspot.databinding.FragmentTetheringBinding
import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.TetherType
@@ -59,7 +60,8 @@ class TetheringFragment : Fragment(), ServiceConnection {
this@TetheringFragment.enabledTypes = this@TetheringFragment.enabledTypes =
(activeIfaces + localOnlyIfaces).map { TetherType.ofInterface(it) }.toSet() (activeIfaces + localOnlyIfaces).map { TetherType.ofInterface(it) }.toSet()
val list = arrayListOf<Manager>(repeaterManager) val list = ArrayList<Manager>()
if (RepeaterService.supported) list.add(repeaterManager)
if (Build.VERSION.SDK_INT >= 26) { if (Build.VERSION.SDK_INT >= 26) {
list.add(localOnlyHotspotManager) list.add(localOnlyHotspotManager)
localOnlyHotspotManager.update() localOnlyHotspotManager.update()