From cce3223311134618446db6aec4cba5548a3d7dd6 Mon Sep 17 00:00:00 2001 From: Mygod Date: Mon, 20 Jan 2020 10:02:26 +0800 Subject: [PATCH] Allow monitoring current upstreams Fix #139. --- .../vpnhotspot/client/ClientsFragment.kt | 2 +- .../preference/UpstreamsPreference.kt | 65 +++++++++++++++++++ mobile/src/main/res/values-zh-rCN/strings.xml | 2 + mobile/src/main/res/values/strings.xml | 2 + mobile/src/main/res/xml/pref_settings.xml | 4 ++ 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt index 1ec06f90..cd6a51d9 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt @@ -81,7 +81,7 @@ class ClientsFragment : Fragment() { data class StatsArg(val title: CharSequence, val stats: ClientStats) : Parcelable class StatsDialogFragment : AlertDialogFragment() { override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) { - setTitle(SpanFormatter.format(getString(R.string.clients_stats_title), arg.title)) + setTitle(SpanFormatter.format(getText(R.string.clients_stats_title), arg.title)) val context = context val resources = resources val format = NumberFormat.getIntegerInstance(resources.configuration.locale) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt new file mode 100644 index 00000000..e87867ee --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt @@ -0,0 +1,65 @@ +package be.mygod.vpnhotspot.preference + +import android.content.Context +import android.graphics.Typeface +import android.net.LinkProperties +import android.text.SpannableStringBuilder +import android.text.style.StyleSpan +import android.util.AttributeSet +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.preference.Preference +import be.mygod.vpnhotspot.R +import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor +import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor +import be.mygod.vpnhotspot.util.SpanFormatter +import be.mygod.vpnhotspot.util.parseNumericAddress + +class UpstreamsPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs), + DefaultLifecycleObserver { + companion object { + private val internetAddress = parseNumericAddress("8.8.8.8") + } + + private data class Interface(val ifname: String, val internet: Boolean) + private inner class Monitor : UpstreamMonitor.Callback { + private var currentInterface: Interface? = null + val charSequence get() = currentInterface?.run { + if (internet) SpannableStringBuilder(ifname).apply { + setSpan(StyleSpan(Typeface.BOLD), 0, length, 0) + } else ifname + } ?: "∅" + + override fun onAvailable(ifname: String, properties: LinkProperties) { + currentInterface = Interface(ifname, properties.routes.any { it.matches(internetAddress) }) + onUpdate() + } + + override fun onLost() { + currentInterface = null + onUpdate() + } + } + + private val primary = Monitor() + private val fallback = Monitor() + + init { + (context as LifecycleOwner).lifecycle.addObserver(this) + } + + override fun onStart(owner: LifecycleOwner) { + UpstreamMonitor.registerCallback(primary) + FallbackUpstreamMonitor.registerCallback(fallback) + } + override fun onStop(owner: LifecycleOwner) { + UpstreamMonitor.unregisterCallback(primary) + FallbackUpstreamMonitor.unregisterCallback(fallback) + } + + private fun onUpdate() = (context as LifecycleOwner).lifecycleScope.launchWhenStarted { + summary = SpanFormatter.format(context.getText(R.string.settings_service_upstream_monitor_summary), + primary.charSequence, fallback.charSequence) + } +} diff --git a/mobile/src/main/res/values-zh-rCN/strings.xml b/mobile/src/main/res/values-zh-rCN/strings.xml index 1e1b4499..83abe2c3 100644 --- a/mobile/src/main/res/values-zh-rCN/strings.xml +++ b/mobile/src/main/res/values-zh-rCN/strings.xml @@ -98,6 +98,8 @@ Netlink 监听 (root) 轮询 轮询 (root) + 当前上游接口 + %1$s;备用:%2$s 上游网络接口 自动检测系统 VPN 备用上游接口 diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 54e3e2c5..9ae59eff 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -103,6 +103,8 @@ Netlink monitor with root Poll Poll with root + Current upstreams + %1$s; fallback: %2$s Upstream network interface Auto detect system VPN Fallback upstream interface diff --git a/mobile/src/main/res/xml/pref_settings.xml b/mobile/src/main/res/xml/pref_settings.xml index 51f707c9..d822138a 100644 --- a/mobile/src/main/res/xml/pref_settings.xml +++ b/mobile/src/main/res/xml/pref_settings.xml @@ -7,6 +7,10 @@ app:summary="@string/settings_service_clean_summary"/> +