diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt index 14c7be60..451f0737 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt @@ -28,6 +28,7 @@ import be.mygod.vpnhotspot.net.IpNeighbour import be.mygod.vpnhotspot.net.IpNeighbourMonitor import be.mygod.vpnhotspot.net.ConnectivityManagerHelper import be.mygod.vpnhotspot.net.TetherType +import java.net.NetworkInterface class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickListener, IpNeighbourMonitor.Callback { inner class Data : BaseObservable() { @@ -56,6 +57,9 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL val ssid @Bindable get() = binder?.service?.ssid ?: getText(R.string.repeater_inactive) val password @Bindable get() = binder?.service?.password ?: "" + val addresses @Bindable get(): String { + return NetworkInterface.getByName(p2pInterface ?: return "")?.formatAddresses() ?: "" + } fun onStatusChanged() { notifyPropertyChanged(BR.switchEnabled) @@ -67,6 +71,7 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL notifyPropertyChanged(BR.ssid) notifyPropertyChanged(BR.password) p2pInterface = group?.`interface` + notifyPropertyChanged(BR.addresses) adapter.p2p = group?.clientList ?: emptyList() adapter.recreate() } @@ -80,7 +85,7 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL val ip = neighbour?.ip val icon get() = TetherType.ofInterface(iface, p2pInterface).icon - val title get() = listOf(ip, mac).filter { !it.isNullOrEmpty() }.joinToString() + val title get() = listOf(ip, mac).filter { !it.isNullOrEmpty() }.joinToString("\t\t") val description get() = getString(when (neighbour?.state) { IpNeighbour.State.INCOMPLETE, null -> R.string.connected_state_incomplete IpNeighbour.State.VALID -> R.string.connected_state_valid diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt index 5c436653..70d2cfd1 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt @@ -21,6 +21,8 @@ import be.mygod.vpnhotspot.databinding.FragmentTetheringBinding import be.mygod.vpnhotspot.databinding.ListitemInterfaceBinding import be.mygod.vpnhotspot.net.ConnectivityManagerHelper import be.mygod.vpnhotspot.net.TetherType +import java.net.Inet4Address +import java.net.NetworkInterface class TetheringFragment : Fragment(), ServiceConnection { companion object { @@ -42,11 +44,11 @@ class TetheringFragment : Fragment(), ServiceConnection { private open class DefaultSorter> : BaseSorter() { override fun compareNonNull(o1: T, o2: T): Int = o1.compareTo(o2) } - private object StringSorter : DefaultSorter() + private object TetheredInterfaceSorter : DefaultSorter() - inner class Data(val iface: String) : BaseObservable() { - val icon: Int get() = TetherType.ofInterface(iface).icon - var active = binder?.active?.contains(iface) == true + inner class Data(val iface: TetheredInterface) : BaseObservable() { + val icon: Int get() = TetherType.ofInterface(iface.name).icon + val active = binder?.active?.contains(iface.name) == true } private class InterfaceViewHolder(val binding: ListitemInterfaceBinding) : RecyclerView.ViewHolder(binding.root), @@ -59,10 +61,9 @@ class TetheringFragment : Fragment(), ServiceConnection { val context = itemView.context val data = binding.data!! if (data.active) context.startService(Intent(context, TetheringService::class.java) - .putExtra(TetheringService.EXTRA_REMOVE_INTERFACE, data.iface)) + .putExtra(TetheringService.EXTRA_REMOVE_INTERFACE, data.iface.name)) else ContextCompat.startForegroundService(context, Intent(context, TetheringService::class.java) - .putExtra(TetheringService.EXTRA_ADD_INTERFACE, data.iface)) - data.active = !data.active + .putExtra(TetheringService.EXTRA_ADD_INTERFACE, data.iface.name)) } } private class ManageViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener { @@ -73,12 +74,18 @@ class TetheringFragment : Fragment(), ServiceConnection { override fun onClick(v: View?) = itemView.context.startActivity(Intent() .setClassName("com.android.settings", "com.android.settings.Settings\$TetherSettingsActivity")) } + class TetheredInterface(val name: String, lookup: Map) : Comparable { + val addresses = lookup[name]!!.formatAddresses() + + override fun compareTo(other: TetheredInterface) = name.compareTo(other.name) + } inner class TetheringAdapter : RecyclerView.Adapter() { - private val tethered = SortedList(String::class.java, StringSorter) + private val tethered = SortedList(TetheredInterface::class.java, TetheredInterfaceSorter) fun update(data: Set) { + val lookup = NetworkInterface.getNetworkInterfaces().asSequence().associateBy { it.name } tethered.clear() - tethered.addAll(data) + tethered.addAll(data.map { TetheredInterface(it, lookup) }) notifyDataSetChanged() } @@ -104,7 +111,7 @@ class TetheringFragment : Fragment(), ServiceConnection { private var binder: TetheringService.TetheringBinder? = null val adapter = TetheringAdapter() private val receiver = broadcastReceiver { _, intent -> - adapter.update(ConnectivityManagerHelper.getTetheredIfaces(intent.extras).toSet()) + adapter.update(ConnectivityManagerHelper.getTetheredIfaces(intent.extras)) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt index 4dc8821c..4f50313e 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt @@ -9,6 +9,8 @@ import android.support.annotation.DrawableRes import android.util.Log import android.widget.ImageView import java.io.IOException +import java.net.Inet4Address +import java.net.NetworkInterface fun debugLog(tag: String?, message: String?) { if (BuildConfig.DEBUG) Log.d(tag, message) @@ -27,6 +29,14 @@ fun intentFilter(vararg actions: String): IntentFilter { @BindingAdapter("android:src") fun setImageResource(imageView: ImageView, @DrawableRes resource: Int) = imageView.setImageResource(resource) +fun NetworkInterface.formatAddresses() = + (this.interfaceAddresses.asSequence() + .filter { !it.address.isLinkLocalAddress } + .map { "${it.address.hostAddress}/${it.networkPrefixLength}" } + .toList() + + listOfNotNull(this.hardwareAddress?.joinToString(":") { "%02x".format(it) })) + .joinToString("\n") + private const val NOISYSU_TAG = "NoisySU" private const val NOISYSU_SUFFIX = "SUCCESS\n" fun loggerSu(command: String): String? { diff --git a/mobile/src/main/res/layout/fragment_repeater.xml b/mobile/src/main/res/layout/fragment_repeater.xml index 8c110f24..63964926 100644 --- a/mobile/src/main/res/layout/fragment_repeater.xml +++ b/mobile/src/main/res/layout/fragment_repeater.xml @@ -76,6 +76,24 @@ android:text="@{data.password}" android:textIsSelectable="true" tools:text="p4ssW0rd"/> + + + + + tools:text="192.168.49.123\t\t01:23:45:ab:cd:ef"/> - + + + + + + + + android:gravity="center_vertical"/> diff --git a/mobile/src/main/res/layout/listitem_manage.xml b/mobile/src/main/res/layout/listitem_manage.xml index d197ac44..2e69cd8b 100644 --- a/mobile/src/main/res/layout/listitem_manage.xml +++ b/mobile/src/main/res/layout/listitem_manage.xml @@ -23,7 +23,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:textAppearance="@style/TextAppearance.AppCompat.Body1" + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" android:text="@string/tethering_manage"/> diff --git a/mobile/src/main/res/values-zh-rCN/strings.xml b/mobile/src/main/res/values-zh-rCN/strings.xml index b37a80e9..5a4402b6 100644 --- a/mobile/src/main/res/values-zh-rCN/strings.xml +++ b/mobile/src/main/res/values-zh-rCN/strings.xml @@ -7,6 +7,7 @@ 中继名称 中继密码 + 中继地址 输入 PIN 一键加密 请在 2 分钟内在需要连接的设备上使用一键加密以连接到此中继。 diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index f6de6b26..209dfb51 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ Network name Password + Addresses WPS Enter PIN Push Button