Add support for WPS in repeater

This commit is contained in:
Mygod
2018-01-13 16:08:44 +08:00
parent aeab1059b4
commit 5e97e3d9ae
5 changed files with 81 additions and 8 deletions

View File

@@ -13,16 +13,18 @@ import android.os.IBinder
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat import android.support.v4.content.ContextCompat
import android.support.v4.content.LocalBroadcastManager import android.support.v4.content.LocalBroadcastManager
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatDialog
import android.support.v7.widget.DefaultItemAnimator import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater import android.support.v7.widget.Toolbar
import android.view.View import android.view.*
import android.view.ViewGroup import android.widget.EditText
import be.mygod.vpnhotspot.databinding.FragmentRepeaterBinding import be.mygod.vpnhotspot.databinding.FragmentRepeaterBinding
import be.mygod.vpnhotspot.databinding.ListitemClientBinding import be.mygod.vpnhotspot.databinding.ListitemClientBinding
class RepeaterFragment : Fragment(), ServiceConnection { class RepeaterFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickListener {
inner class Data : BaseObservable() { inner class Data : BaseObservable() {
val switchEnabled: Boolean val switchEnabled: Boolean
@Bindable get() = when (binder?.service?.status) { @Bindable get() = when (binder?.service?.status) {
@@ -71,7 +73,7 @@ class RepeaterFragment : Fragment(), ServiceConnection {
fun fetchClients() { fun fetchClients() {
val binder = binder val binder = binder
if (binder?.service?.status == RepeaterService.Status.ACTIVE) { if (binder?.active == true) {
owner = binder.service.group.owner owner = binder.service.group.owner
clients = binder.service.group.clientList clients = binder.service.group.clientList
arpCache = NetUtils.arp(binder.service.routing?.downstream) arpCache = NetUtils.arp(binder.service.routing?.downstream)
@@ -113,6 +115,8 @@ class RepeaterFragment : Fragment(), ServiceConnection {
binding.clients.itemAnimator = animator binding.clients.itemAnimator = animator
binding.clients.adapter = adapter binding.clients.adapter = adapter
binding.swipeRefresher.setOnRefreshListener { adapter.fetchClients() } binding.swipeRefresher.setOnRefreshListener { adapter.fetchClients() }
binding.toolbar.inflateMenu(R.menu.repeater)
binding.toolbar.setOnMenuItemClickListener(this)
return binding.root return binding.root
} }
@@ -143,4 +147,21 @@ class RepeaterFragment : Fragment(), ServiceConnection {
LocalBroadcastManager.getInstance(context!!).unregisterReceiver(data.statusListener) LocalBroadcastManager.getInstance(context!!).unregisterReceiver(data.statusListener)
data.onStatusChanged() data.onStatusChanged()
} }
override fun onMenuItemClick(item: MenuItem) = when (item.itemId) {
R.id.wps -> if (binder?.active == true) {
val dialog = AlertDialog.Builder(context!!)
.setTitle("Enter PIN")
.setView(R.layout.dialog_wps)
.setPositiveButton(android.R.string.ok, { dialog, _ -> binder?.startWps((dialog as AppCompatDialog)
.findViewById<EditText>(android.R.id.edit)!!.text.toString()) })
.setNegativeButton(android.R.string.cancel, null)
.setNeutralButton("Push Button", { _, _ -> binder?.startWps(null) })
.create()
dialog.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
dialog.show()
true
} else false
else -> false
}
} }

View File

@@ -5,6 +5,7 @@ import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.NetworkInfo import android.net.NetworkInfo
import android.net.wifi.WpsInfo
import android.net.wifi.p2p.WifiP2pGroup import android.net.wifi.p2p.WifiP2pGroup
import android.net.wifi.p2p.WifiP2pInfo import android.net.wifi.p2p.WifiP2pInfo
import android.net.wifi.p2p.WifiP2pManager import android.net.wifi.p2p.WifiP2pManager
@@ -37,6 +38,18 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnListener.C
* https://android.googlesource.com/platform/frameworks/base.git/+/220871a/core/java/android/net/NetworkInfo.java#415 * https://android.googlesource.com/platform/frameworks/base.git/+/220871a/core/java/android/net/NetworkInfo.java#415
*/ */
private val patternNetworkInfo = "^mNetworkInfo .* (isA|a)vailable: (true|false)".toPattern(Pattern.MULTILINE) private val patternNetworkInfo = "^mNetworkInfo .* (isA|a)vailable: (true|false)".toPattern(Pattern.MULTILINE)
/**
* Available since Android 4.3.
*
* Source: https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r0.9/wifi/java/android/net/wifi/p2p/WifiP2pManager.java#958
*/
private val startWpsMethod = WifiP2pManager::class.java.getDeclaredMethod("startWps",
WifiP2pManager.Channel::class.java, WpsInfo::class.java, WifiP2pManager.ActionListener::class.java)
private fun WifiP2pManager.startWps(c: WifiP2pManager.Channel, wps: WpsInfo,
listener: WifiP2pManager.ActionListener) {
startWpsMethod.invoke(this, c, wps, listener)
}
} }
enum class Status { enum class Status {
@@ -46,6 +59,23 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, VpnListener.C
inner class HotspotBinder : Binder() { inner class HotspotBinder : Binder() {
val service get() = this@RepeaterService val service get() = this@RepeaterService
var data: RepeaterFragment.Data? = null var data: RepeaterFragment.Data? = null
val active get() = status == Status.ACTIVE
fun startWps(pin: String? = null) {
if (status != Status.ACTIVE) return
val wps = WpsInfo()
if (pin == null) wps.setup = WpsInfo.PBC else {
wps.setup = WpsInfo.KEYPAD
wps.pin = pin
}
p2pManager.startWps(channel, wps, object : WifiP2pManager.ActionListener {
override fun onSuccess() = Toast.makeText(this@RepeaterService,
if (pin == null) "Please use WPS push button within the next 2 minutes to connect your device."
else "PIN registered.", Toast.LENGTH_SHORT).show()
override fun onFailure(reason: Int) = Toast.makeText(this@RepeaterService,
"Failed to start WPS (reason: ${formatReason(reason)})", Toast.LENGTH_SHORT).show()
})
}
fun shutdown() { fun shutdown() {
if (status == Status.ACTIVE) removeGroup() if (status == Status.ACTIVE) removeGroup()

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@android:id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:inputType="number"
tools:text="12345678">
<requestFocus/>
</EditText>
</FrameLayout>

View File

@@ -27,10 +27,8 @@
android:enabled="@{data.switchEnabled}" android:enabled="@{data.switchEnabled}"
android:checked="@{data.serviceStarted}" android:checked="@{data.serviceStarted}"
android:onCheckedChanged="@{(_, checked) -> data.setServiceStarted(checked)}" android:onCheckedChanged="@{(_, checked) -> data.setServiceStarted(checked)}"
android:paddingEnd="8dp"
android:text="@string/app_name" android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"/>
tools:ignore="RtlSymmetry"/>
</android.support.v7.widget.Toolbar> </android.support.v7.widget.Toolbar>
<GridLayout <GridLayout

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/wps"
android:title="WPS"/>
</menu>