diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt index 5757cdfe..45168cb0 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterFragment.kt @@ -31,6 +31,7 @@ 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 be.mygod.vpnhotspot.util.ServiceForegroundConnector import be.mygod.vpnhotspot.util.broadcastReceiver import be.mygod.vpnhotspot.util.formatAddresses import java.net.NetworkInterface @@ -177,23 +178,20 @@ class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickL } binding.toolbar.inflateMenu(R.menu.repeater) binding.toolbar.setOnMenuItemClickListener(this) + ServiceForegroundConnector(this, RepeaterService::class) return binding.root } override fun onStart() { super.onStart() - val context = requireContext() - context.bindService(Intent(context, RepeaterService::class.java), this, Context.BIND_AUTO_CREATE) IpNeighbourMonitor.registerCallback(this) - context.registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) + requireContext().registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) } override fun onStop() { - val context = requireContext() - context.unregisterReceiver(receiver) + requireContext().unregisterReceiver(receiver) IpNeighbourMonitor.unregisterCallback(this) onServiceDisconnected(null) - context.unbindService(this) super.onStop() } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt index 9e4da3da..ee2d56cb 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/TetheringFragment.kt @@ -34,6 +34,7 @@ import be.mygod.vpnhotspot.databinding.ListitemManageTetherBinding import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.TetheringManager import be.mygod.vpnhotspot.net.wifi.WifiApManager +import be.mygod.vpnhotspot.util.ServiceForegroundConnector import be.mygod.vpnhotspot.util.broadcastReceiver import be.mygod.vpnhotspot.util.formatAddresses import java.lang.reflect.InvocationTargetException @@ -333,18 +334,11 @@ class TetheringFragment : Fragment(), ServiceConnection { binding.interfaces.itemAnimator = DefaultItemAnimator() binding.interfaces.adapter = adapter BluetoothAdapter.getDefaultAdapter()?.getProfileProxy(requireContext(), tetherListener, PAN) + ServiceForegroundConnector(this, if (Build.VERSION.SDK_INT >= 26) + listOf(TetheringService::class, LocalOnlyHotspotService::class) else listOf(TetheringService::class)) return binding.root } - override fun onStart() { - super.onStart() - val context = requireContext() - context.bindService(Intent(context, TetheringService::class.java), this, Context.BIND_AUTO_CREATE) - if (Build.VERSION.SDK_INT >= 26) { - context.bindService(Intent(context, LocalOnlyHotspotService::class.java), this, Context.BIND_AUTO_CREATE) - } - } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { if (requestCode == START_LOCAL_ONLY_HOTSPOT) @TargetApi(26) { if (grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED) { @@ -354,11 +348,6 @@ class TetheringFragment : Fragment(), ServiceConnection { } else super.onRequestPermissionsResult(requestCode, permissions, grantResults) } - override fun onStop() { - requireContext().unbindService(this) - super.onStop() - } - override fun onDestroy() { tetherListener.pan = null super.onDestroy() diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/util/ServiceForegroundConnector.kt b/mobile/src/main/java/be/mygod/vpnhotspot/util/ServiceForegroundConnector.kt new file mode 100644 index 00000000..ceef7daa --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/util/ServiceForegroundConnector.kt @@ -0,0 +1,34 @@ +package be.mygod.vpnhotspot.util + +import android.app.Service +import android.arch.lifecycle.Lifecycle +import android.arch.lifecycle.LifecycleObserver +import android.arch.lifecycle.LifecycleOwner +import android.arch.lifecycle.OnLifecycleEvent +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.support.v4.app.Fragment +import kotlin.reflect.KClass + +/** + * host also needs to be Context/Fragment and LifecycleOwner. + */ +class ServiceForegroundConnector(private val host: ServiceConnection, private val classes: List>) : + LifecycleObserver { + init { + (host as LifecycleOwner).lifecycle.addObserver(this) + } + constructor(host: ServiceConnection, vararg classes: KClass) : this(host, classes.toList()) + + private val context get() = if (host is Context) host else (host as Fragment).requireContext() + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + fun onStart() { + val context = context + for (clazz in classes) context.bindService(Intent(context, clazz.java), host, Context.BIND_AUTO_CREATE) + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + fun onStop() = context.unbindService(host) +}