Stop using LocalBroadcastManager
This commit is contained in:
@@ -12,10 +12,10 @@ import android.os.Handler
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.annotation.StringRes
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.util.Event0
|
||||
|
||||
class App : Application() {
|
||||
companion object {
|
||||
const val ACTION_CLEAN_ROUTINGS = "be.mygod.vpnhotspot.CLEAN_ROUTINGS"
|
||||
const val KEY_OPERATING_CHANNEL = "service.repeater.oc"
|
||||
private const val KEY_DNS = "service.dns"
|
||||
|
||||
@@ -54,5 +54,7 @@ class App : Application() {
|
||||
get() = pref.getString(KEY_DNS, "8.8.8.8")
|
||||
set(value) = pref.edit().putString(KEY_DNS, value).apply()
|
||||
|
||||
val cleanRoutings = Event0()
|
||||
|
||||
fun toast(@StringRes resId: Int) = handler.post { Toast.makeText(this, resId, Toast.LENGTH_SHORT).show() }
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package be.mygod.vpnhotspot
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.net.Routing
|
||||
@@ -11,13 +7,12 @@ import be.mygod.vpnhotspot.net.VpnMonitor
|
||||
import java.net.InetAddress
|
||||
import java.net.SocketException
|
||||
|
||||
class LocalOnlyInterfaceManager(val downstream: String, private val owner: InetAddress? = null) :
|
||||
BroadcastReceiver(), VpnMonitor.Callback {
|
||||
class LocalOnlyInterfaceManager(val downstream: String, private val owner: InetAddress? = null) : VpnMonitor.Callback {
|
||||
private var routing: Routing? = null
|
||||
private var dns = emptyList<InetAddress>()
|
||||
|
||||
init {
|
||||
LocalBroadcastManager.getInstance(app).registerReceiver(this, intentFilter(App.ACTION_CLEAN_ROUTINGS))
|
||||
app.cleanRoutings[this] = this::clean
|
||||
VpnMonitor.registerCallback(this) { initRouting() }
|
||||
}
|
||||
|
||||
@@ -34,7 +29,8 @@ class LocalOnlyInterfaceManager(val downstream: String, private val owner: InetA
|
||||
if (!routing.stop()) app.toast(R.string.noisy_su_failure)
|
||||
initRouting(null, routing.hostAddress, emptyList())
|
||||
}
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
|
||||
private fun clean() {
|
||||
val routing = routing ?: return
|
||||
routing.started = false
|
||||
initRouting(routing.upstream, routing.hostAddress, dns)
|
||||
@@ -59,7 +55,7 @@ class LocalOnlyInterfaceManager(val downstream: String, private val owner: InetA
|
||||
|
||||
fun stop() {
|
||||
VpnMonitor.unregisterCallback(this)
|
||||
LocalBroadcastManager.getInstance(app).unregisterReceiver(this)
|
||||
app.cleanRoutings -= this
|
||||
if (routing?.stop() == false) app.toast(R.string.noisy_su_failure)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.app.AppCompatDialog
|
||||
import android.support.v7.recyclerview.extensions.ListAdapter
|
||||
@@ -28,8 +27,8 @@ import be.mygod.vpnhotspot.databinding.FragmentRepeaterBinding
|
||||
import be.mygod.vpnhotspot.databinding.ListitemClientBinding
|
||||
import be.mygod.vpnhotspot.net.IpNeighbour
|
||||
import be.mygod.vpnhotspot.net.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.net.TetheringManager
|
||||
import be.mygod.vpnhotspot.net.TetherType
|
||||
import be.mygod.vpnhotspot.net.TetheringManager
|
||||
import be.mygod.vpnhotspot.net.wifi.P2pSupplicantConfiguration
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pDialog
|
||||
import java.net.NetworkInterface
|
||||
@@ -61,7 +60,7 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL
|
||||
}
|
||||
}
|
||||
|
||||
val ssid @Bindable get() = binder?.ssid ?: getText(R.string.service_inactive)
|
||||
val ssid @Bindable get() = binder?.service?.group?.networkName ?: getText(R.string.service_inactive)
|
||||
val addresses @Bindable get(): String {
|
||||
return try {
|
||||
NetworkInterface.getByName(p2pInterface ?: return "")?.formatAddresses() ?: ""
|
||||
@@ -74,18 +73,14 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL
|
||||
fun onStatusChanged() {
|
||||
notifyPropertyChanged(BR.switchEnabled)
|
||||
notifyPropertyChanged(BR.serviceStarted)
|
||||
val binder = binder
|
||||
onGroupChanged(if (binder?.active == true) binder.service.group else null)
|
||||
}
|
||||
fun onGroupChanged(group: WifiP2pGroup?) {
|
||||
fun onGroupChanged(group: WifiP2pGroup? = binder?.service?.group) {
|
||||
notifyPropertyChanged(BR.ssid)
|
||||
p2pInterface = group?.`interface`
|
||||
notifyPropertyChanged(BR.addresses)
|
||||
adapter.p2p = group?.clientList ?: emptyList()
|
||||
adapter.recreate()
|
||||
}
|
||||
|
||||
val statusListener = broadcastReceiver { _, _ -> onStatusChanged() }
|
||||
}
|
||||
|
||||
inner class Client(p2p: WifiP2pDevice? = null, neighbour: IpNeighbour? = null) {
|
||||
@@ -202,18 +197,18 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
val binder = service as RepeaterService.RepeaterBinder
|
||||
binder.data = data
|
||||
this.binder = binder
|
||||
data.onStatusChanged()
|
||||
LocalBroadcastManager.getInstance(requireContext())
|
||||
.registerReceiver(data.statusListener, intentFilter(RepeaterService.ACTION_STATUS_CHANGED))
|
||||
binder.statusChanged[this] = data::onStatusChanged
|
||||
binder.groupChanged[this] = data::onGroupChanged
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
binder?.data = null
|
||||
binder = null
|
||||
LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(data.statusListener)
|
||||
val binder = binder ?: return
|
||||
binder.statusChanged -= this
|
||||
binder.groupChanged -= this
|
||||
this.binder = null
|
||||
data.onStatusChanged()
|
||||
data.onGroupChanged()
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem) = when (item.itemId) {
|
||||
@@ -239,13 +234,14 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL
|
||||
|
||||
private fun editConfigurations() {
|
||||
val binder = binder
|
||||
val ssid = binder?.ssid
|
||||
val group = binder?.service?.group
|
||||
val ssid = group?.networkName
|
||||
val context = requireContext()
|
||||
if (ssid != null) {
|
||||
val wifi = WifiConfiguration()
|
||||
val conf = P2pSupplicantConfiguration()
|
||||
wifi.SSID = ssid
|
||||
wifi.preSharedKey = binder.password
|
||||
wifi.preSharedKey = group.passphrase
|
||||
if (wifi.preSharedKey == null) wifi.preSharedKey = conf.readPsk()
|
||||
if (wifi.preSharedKey != null) {
|
||||
var dialog: WifiP2pDialog? = null
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.net.wifi.p2p.WifiP2pManager
|
||||
import android.os.Binder
|
||||
import android.os.Looper
|
||||
import android.support.annotation.StringRes
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
@@ -22,12 +21,13 @@ import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.netId
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.requestPersistentGroupInfo
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.setWifiP2pChannels
|
||||
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.startWps
|
||||
import be.mygod.vpnhotspot.util.StickyEvent0
|
||||
import be.mygod.vpnhotspot.util.StickyEvent1
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.net.InetAddress
|
||||
|
||||
class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
companion object {
|
||||
const val ACTION_STATUS_CHANGED = "be.mygod.vpnhotspot.RepeaterService.STATUS_CHANGED"
|
||||
private const val TAG = "RepeaterService"
|
||||
}
|
||||
|
||||
@@ -37,11 +37,9 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
||||
|
||||
inner class RepeaterBinder : Binder() {
|
||||
val service get() = this@RepeaterService
|
||||
var data: RepeaterFragment.Data? = null
|
||||
val active get() = status == Status.ACTIVE
|
||||
|
||||
val ssid get() = group?.networkName
|
||||
val password get() = group?.passphrase
|
||||
val statusChanged = StickyEvent0()
|
||||
val groupChanged = StickyEvent1 { group }
|
||||
|
||||
private var groups: Collection<WifiP2pGroup> = emptyList()
|
||||
|
||||
@@ -93,7 +91,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
||||
var group: WifiP2pGroup? = null
|
||||
private set(value) {
|
||||
field = value
|
||||
binder.data?.onGroupChanged(value)
|
||||
binder.groupChanged(value)
|
||||
}
|
||||
private val binder = RepeaterBinder()
|
||||
private var receiverRegistered = false
|
||||
@@ -114,7 +112,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
||||
private set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(ACTION_STATUS_CHANGED))
|
||||
binder.statusChanged()
|
||||
}
|
||||
|
||||
private fun formatReason(@StringRes resId: Int, reason: Int) = getString(resId, when (reason) {
|
||||
@@ -245,7 +243,6 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
||||
Toast.makeText(this@RepeaterService,
|
||||
formatReason(R.string.repeater_remove_group_failure, reason), Toast.LENGTH_SHORT).show()
|
||||
status = Status.ACTIVE
|
||||
LocalBroadcastManager.getInstance(this@RepeaterService).sendBroadcast(Intent(ACTION_STATUS_CHANGED))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -5,16 +5,15 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.graphics.drawable.Icon
|
||||
import android.net.wifi.p2p.WifiP2pGroup
|
||||
import android.os.IBinder
|
||||
import android.service.quicksettings.Tile
|
||||
import android.service.quicksettings.TileService
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
|
||||
@RequiresApi(24)
|
||||
class RepeaterTileService : TileService(), ServiceConnection {
|
||||
private val statusListener = broadcastReceiver { _, _ -> updateTile() }
|
||||
private val tileOff by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_off) }
|
||||
private val tileOn by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_on) }
|
||||
|
||||
@@ -41,18 +40,20 @@ class RepeaterTileService : TileService(), ServiceConnection {
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder) {
|
||||
binder = service as RepeaterService.RepeaterBinder
|
||||
updateTile()
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(statusListener,
|
||||
intentFilter(RepeaterService.ACTION_STATUS_CHANGED))
|
||||
val binder = service as RepeaterService.RepeaterBinder
|
||||
this.binder = binder
|
||||
binder.statusChanged[this] = { updateTile() }
|
||||
binder.groupChanged[this] = this::updateTile
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
binder = null
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(statusListener)
|
||||
val binder = binder ?: return
|
||||
this.binder = null
|
||||
binder.statusChanged -= this
|
||||
binder.groupChanged -= this
|
||||
}
|
||||
|
||||
private fun updateTile() {
|
||||
private fun updateTile(group: WifiP2pGroup? = binder?.service?.group) {
|
||||
val qsTile = qsTile ?: return
|
||||
when (binder?.service?.status) {
|
||||
RepeaterService.Status.IDLE -> {
|
||||
@@ -68,7 +69,7 @@ class RepeaterTileService : TileService(), ServiceConnection {
|
||||
RepeaterService.Status.ACTIVE -> {
|
||||
qsTile.state = Tile.STATE_ACTIVE
|
||||
qsTile.icon = tileOn
|
||||
qsTile.label = binder?.ssid
|
||||
qsTile.label = group?.networkName
|
||||
}
|
||||
null -> {
|
||||
qsTile.state = Tile.STATE_UNAVAILABLE
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.os.Bundle
|
||||
import android.support.customtabs.CustomTabsIntent
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.FileProvider
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.net.Routing
|
||||
@@ -30,9 +29,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompatDividers() {
|
||||
findPreference("service.clean").setOnPreferenceClickListener {
|
||||
if (Routing.clean() == null) {
|
||||
Toast.makeText(requireContext(), R.string.root_unavailable, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
LocalBroadcastManager.getInstance(requireContext()).sendBroadcastSync(Intent(App.ACTION_CLEAN_ROUTINGS))
|
||||
}
|
||||
} else app.cleanRoutings()
|
||||
true
|
||||
}
|
||||
findPreference("misc.logcat").setOnPreferenceClickListener {
|
||||
|
||||
@@ -2,7 +2,6 @@ package be.mygod.vpnhotspot
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.widget.Toast
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.net.IpNeighbourMonitor
|
||||
@@ -31,14 +30,9 @@ class TetheringService : IpNeighbourMonitoringService(), VpnMonitor.Callback {
|
||||
private var receiverRegistered = false
|
||||
private val receiver = broadcastReceiver { _, intent ->
|
||||
synchronized(routings) {
|
||||
when (intent.action) {
|
||||
TetheringManager.ACTION_TETHER_STATE_CHANGED -> {
|
||||
val failed = (routings.keys - TetheringManager.getTetheredIfaces(intent.extras))
|
||||
.any { routings.remove(it)?.stop() == false }
|
||||
if (failed) Toast.makeText(this, getText(R.string.noisy_su_failure), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
App.ACTION_CLEAN_ROUTINGS -> for (iface in routings.keys) routings[iface] = null
|
||||
}
|
||||
val failed = (routings.keys - TetheringManager.getTetheredIfaces(intent.extras))
|
||||
.any { routings.remove(it)?.stop() == false }
|
||||
if (failed) Toast.makeText(this, getText(R.string.noisy_su_failure), Toast.LENGTH_SHORT).show()
|
||||
updateRoutingsLocked()
|
||||
}
|
||||
}
|
||||
@@ -63,8 +57,12 @@ class TetheringService : IpNeighbourMonitoringService(), VpnMonitor.Callback {
|
||||
if (failed) Toast.makeText(this, getText(R.string.noisy_su_failure), Toast.LENGTH_SHORT).show()
|
||||
} else if (!receiverRegistered) {
|
||||
registerReceiver(receiver, intentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
|
||||
LocalBroadcastManager.getInstance(this)
|
||||
.registerReceiver(receiver, intentFilter(App.ACTION_CLEAN_ROUTINGS))
|
||||
app.cleanRoutings[this] = {
|
||||
synchronized(routings) {
|
||||
for (iface in routings.keys) routings[iface] = null
|
||||
updateRoutingsLocked()
|
||||
}
|
||||
}
|
||||
IpNeighbourMonitor.registerCallback(this)
|
||||
VpnMonitor.registerCallback(this)
|
||||
receiverRegistered = true
|
||||
@@ -121,7 +119,7 @@ class TetheringService : IpNeighbourMonitoringService(), VpnMonitor.Callback {
|
||||
private fun unregisterReceiver() {
|
||||
if (receiverRegistered) {
|
||||
unregisterReceiver(receiver)
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
|
||||
app.cleanRoutings -= this
|
||||
IpNeighbourMonitor.unregisterCallback(this)
|
||||
VpnMonitor.unregisterCallback(this)
|
||||
upstream = null
|
||||
|
||||
34
mobile/src/main/java/be/mygod/vpnhotspot/util/Events.kt
Normal file
34
mobile/src/main/java/be/mygod/vpnhotspot/util/Events.kt
Normal file
@@ -0,0 +1,34 @@
|
||||
package be.mygod.vpnhotspot.util
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* These class are based off https://github.com/1blustone/kotlin-events.
|
||||
*/
|
||||
open class Event0 : ConcurrentHashMap<Any, () -> Unit>() {
|
||||
operator fun invoke() {
|
||||
for ((_, handler) in this) handler()
|
||||
}
|
||||
}
|
||||
|
||||
class StickyEvent0 : Event0() {
|
||||
override fun put(key: Any, value: () -> Unit): (() -> Unit)? {
|
||||
val result = super.put(key, value)
|
||||
if (result == null) value()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
open class Event1<T> : ConcurrentHashMap<Any, (T) -> Unit>() {
|
||||
operator fun invoke(arg: T) {
|
||||
for ((_, handler) in this) handler(arg)
|
||||
}
|
||||
}
|
||||
|
||||
class StickyEvent1<T>(private val fire: () -> T) : Event1<T>() {
|
||||
override fun put(key: Any, value: (T) -> Unit): ((T) -> Unit)? {
|
||||
val result = super.put(key, value)
|
||||
if (result == null) value(fire())
|
||||
return result
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user