Support monitoring tethered interface

This would be useful to be used in together with Instant Tethering + Turn off hotspot automatically.

Refine #26, #53.
This commit is contained in:
Mygod
2019-02-06 01:26:06 +08:00
parent 6d6418b8e0
commit cbc65f989c
14 changed files with 174 additions and 61 deletions

View File

@@ -9,29 +9,26 @@ import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import be.mygod.vpnhotspot.LocalOnlyHotspotService
import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.RepeaterService
import be.mygod.vpnhotspot.TetheringService
import be.mygod.vpnhotspot.*
import be.mygod.vpnhotspot.databinding.FragmentTetheringBinding
import be.mygod.vpnhotspot.net.TetherType
import be.mygod.vpnhotspot.net.TetheringManager
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
import be.mygod.vpnhotspot.util.broadcastReceiver
import kotlinx.android.synthetic.main.activity_main.*
import timber.log.Timber
import java.net.NetworkInterface
import java.net.SocketException
class TetheringFragment : Fragment(), ServiceConnection {
class TetheringFragment : Fragment(), ServiceConnection, MenuItem.OnMenuItemClickListener {
companion object {
const val START_LOCAL_ONLY_HOTSPOT = 1
const val REPEATER_EDIT_CONFIGURATION = 2
@@ -63,7 +60,10 @@ class TetheringFragment : Fragment(), ServiceConnection {
val list = ArrayList<Manager>()
if (RepeaterService.supported) list.add(repeaterManager)
if (Build.VERSION.SDK_INT >= 26) list.add(localOnlyHotspotManager)
list.addAll(activeIfaces.map { InterfaceManager(this@TetheringFragment, it) }.sortedBy { it.iface })
val monitoredIfaces = binder?.monitoredIfaces ?: emptyList()
updateMonitorList(activeIfaces - monitoredIfaces)
list.addAll((activeIfaces + monitoredIfaces).toSortedSet()
.map { InterfaceManager(this@TetheringFragment, it) })
list.add(ManageBar)
if (Build.VERSION.SDK_INT >= 24) {
list.addAll(tetherManagers)
@@ -94,6 +94,27 @@ class TetheringFragment : Fragment(), ServiceConnection {
extras.getStringArrayList(TetheringManager.EXTRA_ERRORED_TETHER)!!)
}
private fun updateMonitorList(canMonitor: List<String> = emptyList()) {
val toolbar = requireActivity().toolbar
val menu = toolbar.menu
if (canMonitor.isEmpty()) menu.removeItem(R.id.monitor) else {
var item = menu.findItem(R.id.monitor)
if (item == null) {
toolbar.inflateMenu(R.menu.toolbar_monitor)
item = menu.findItem(R.id.monitor)!!
}
item.subMenu.apply {
clear()
canMonitor.sorted().forEach { add(it).setOnMenuItemClickListener(this@TetheringFragment) }
}
}
}
override fun onMenuItemClick(item: MenuItem?): Boolean {
ContextCompat.startForegroundService(requireContext(), Intent(context, TetheringService::class.java)
.putExtra(TetheringService.EXTRA_ADD_INTERFACE_MONITOR, item?.title ?: return false))
return true
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_tethering, container, false)
binding.setLifecycleOwner(this)
@@ -127,7 +148,13 @@ class TetheringFragment : Fragment(), ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
binder = service as TetheringService.Binder
service.routingsChanged[this] = { adapter.notifyDataSetChanged() }
service.routingsChanged[this] = {
requireContext().apply {
// flush tethered interfaces
unregisterReceiver(receiver)
registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
}
}
requireContext().registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED))
}
@@ -136,4 +163,9 @@ class TetheringFragment : Fragment(), ServiceConnection {
binder = null
requireContext().unregisterReceiver(receiver)
}
override fun onDestroy() {
updateMonitorList()
super.onDestroy()
}
}