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:
@@ -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))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user