Refactor WifiP2pDialog as DialogFragment

This commit is contained in:
Mygod
2018-07-21 18:26:14 +08:00
parent f92210c1a6
commit b526de681e
6 changed files with 133 additions and 102 deletions

View File

@@ -11,7 +11,7 @@ android {
minSdkVersion 21
targetSdkVersion 28
resConfigs "zh-rCN"
versionCode 29
versionCode 30
versionName "1.3.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -1,8 +1,6 @@
package be.mygod.vpnhotspot.manage
import android.annotation.TargetApi
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
import android.content.ServiceConnection
import android.net.wifi.WifiConfiguration
@@ -13,6 +11,7 @@ import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDialog
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.recyclerview.widget.RecyclerView
@@ -20,7 +19,7 @@ import be.mygod.vpnhotspot.*
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.databinding.ListitemRepeaterBinding
import be.mygod.vpnhotspot.net.wifi.P2pSupplicantConfiguration
import be.mygod.vpnhotspot.net.wifi.WifiP2pDialog
import be.mygod.vpnhotspot.net.wifi.WifiP2pDialogFragment
import be.mygod.vpnhotspot.util.ServiceForegroundConnector
import be.mygod.vpnhotspot.util.formatAddresses
import com.crashlytics.android.Crashlytics
@@ -111,18 +110,11 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
wifi.preSharedKey = conf.readPsk { mainActivity.snackbar(it.message.toString()).show() }
}
if (wifi.preSharedKey != null) {
var dialog: WifiP2pDialog? = null
dialog = WifiP2pDialog(mainActivity, DialogInterface.OnClickListener { _, which ->
when (which) {
DialogInterface.BUTTON_POSITIVE -> @TargetApi(23) when (conf.update(dialog!!.config!!)) {
true -> app.handler.postDelayed(binder::requestGroupUpdate, 1000)
false -> mainActivity.snackbar().setText(R.string.noisy_su_failure).show()
null -> mainActivity.snackbar().setText(R.string.root_unavailable).show()
}
DialogInterface.BUTTON_NEUTRAL -> binder.resetCredentials()
}
}, wifi)
dialog.show()
WifiP2pDialogFragment().apply {
arguments = bundleOf(Pair(WifiP2pDialogFragment.KEY_CONFIGURATION, wifi),
Pair(WifiP2pDialogFragment.KEY_CONFIGURER, conf))
setTargetFragment(parent, 0)
}.show(parent.fragmentManager, WifiP2pDialogFragment.TAG)
return
}
}
@@ -136,7 +128,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
override val type get() = VIEW_TYPE_REPEATER
private val data = Data()
private var binder: RepeaterService.Binder? = null
internal var binder: RepeaterService.Binder? = null
private var p2pInterface: String? = null
override fun bindTo(viewHolder: RecyclerView.ViewHolder) {

View File

@@ -36,7 +36,7 @@ class TetheringFragment : Fragment(), ServiceConnection {
}
inner class ManagerAdapter : ListAdapter<Manager, RecyclerView.ViewHolder>(Manager) {
private val repeaterManager by lazy { RepeaterManager(this@TetheringFragment) }
internal val repeaterManager by lazy { RepeaterManager(this@TetheringFragment) }
private val localOnlyHotspotManager by lazy @TargetApi(26) { LocalOnlyHotspotManager(this@TetheringFragment) }
private val tetherManagers by lazy @TargetApi(24) {
listOf(TetherManager.Wifi(this@TetheringFragment),

View File

@@ -1,6 +1,8 @@
package be.mygod.vpnhotspot.net.wifi
import android.net.wifi.WifiConfiguration
import android.os.Parcel
import android.os.Parcelable
import android.util.Log
import androidx.annotation.RequiresApi
import be.mygod.vpnhotspot.App.Companion.app
@@ -9,8 +11,11 @@ import be.mygod.vpnhotspot.util.noisySu
import com.crashlytics.android.Crashlytics
import java.io.File
class P2pSupplicantConfiguration {
companion object {
class P2pSupplicantConfiguration(private val initContent: String? = null) : Parcelable {
companion object CREATOR : Parcelable.Creator<P2pSupplicantConfiguration> {
override fun createFromParcel(parcel: Parcel) = P2pSupplicantConfiguration(parcel.readString())
override fun newArray(size: Int): Array<P2pSupplicantConfiguration?> = arrayOfNulls(size)
private const val TAG = "P2pSupplicationConf"
/**
* Format for ssid is much more complicated, therefore we are only trying to find the line and rely on
@@ -25,7 +30,13 @@ class P2pSupplicantConfiguration {
private val pskParser = "^[\\r\\t ]*psk=(ext:|\"(.*)\"|\"(.*)|[0-9a-fA-F]{64}\$)".toRegex(RegexOption.MULTILINE)
}
private val content by lazy { loggerSu("cat /data/misc/wifi/p2p_supplicant.conf") }
override fun writeToParcel(out: Parcel, flags: Int) {
out.writeString(if (contentDelegate.isInitialized()) content else null)
}
override fun describeContents() = 0
private val contentDelegate = lazy { initContent ?: loggerSu("cat /data/misc/wifi/p2p_supplicant.conf") }
private val content by contentDelegate
fun readPsk(handler: ((RuntimeException) -> Unit)? = null): String? {
return try {

View File

@@ -1,81 +0,0 @@
package be.mygod.vpnhotspot.net.wifi
import android.content.Context
import android.content.DialogInterface
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiConfiguration.AuthAlgorithm
import android.os.Build
import android.os.Bundle
import com.google.android.material.textfield.TextInputLayout
import androidx.appcompat.app.AlertDialog
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.EditText
import android.widget.TextView
import be.mygod.vpnhotspot.R
import java.nio.charset.Charset
/**
* https://android.googlesource.com/platform/packages/apps/Settings/+/39b4674/src/com/android/settings/wifi/WifiApDialog.java
*/
class WifiP2pDialog(mContext: Context, private val mListener: DialogInterface.OnClickListener,
private val mWifiConfig: WifiConfiguration?) : AlertDialog(mContext), TextWatcher {
companion object {
private const val BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE
}
private lateinit var mView: View
private lateinit var mSsid: TextView
private lateinit var mPassword: EditText
val config: WifiConfiguration?
get() {
val config = WifiConfiguration()
config.SSID = mSsid.text.toString()
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN)
if (mPassword.length() != 0) {
val password = mPassword.text.toString()
config.preSharedKey = password
}
return config
}
override fun onCreate(savedInstanceState: Bundle?) {
mView = layoutInflater.inflate(R.layout.dialog_wifi_ap, null)
setView(mView)
val context = context
setTitle(R.string.repeater_configure)
mSsid = mView.findViewById(R.id.ssid)
mPassword = mView.findViewById(R.id.password)
// Note: Reading persistent group information in p2p_supplicant.conf wasn't available until this commit:
// https://android.googlesource.com/platform/external/wpa_supplicant_8/+/216983bceec7c450951e2fbcd076b5c75d432e57%5E%21/
// which isn't merged until Android 6.0.
if (Build.VERSION.SDK_INT >= 23) setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener)
setButton(DialogInterface.BUTTON_NEGATIVE,
context.getString(R.string.wifi_cancel), mListener)
setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(R.string.repeater_reset_credentials), mListener)
if (mWifiConfig != null) {
mSsid.text = mWifiConfig.SSID
mPassword.setText(mWifiConfig.preSharedKey)
}
mSsid.addTextChangedListener(this)
mPassword.addTextChangedListener(this)
super.onCreate(savedInstanceState)
validate()
}
private fun validate() {
val mSsidString = mSsid.text.toString()
val ssidValid = mSsid.length() != 0 && Charset.forName("UTF-8").encode(mSsidString).limit() <= 32
val passwordValid = mPassword.length() >= 8
mView.findViewById<TextInputLayout>(R.id.password_wrapper).error =
if (passwordValid) null else context.getString(R.string.credentials_password_too_short)
getButton(BUTTON_SUBMIT).isEnabled = ssidValid && passwordValid
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { }
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { }
override fun afterTextChanged(editable: Editable) {
validate()
}
}

View File

@@ -0,0 +1,109 @@
package be.mygod.vpnhotspot.net.wifi
import android.annotation.TargetApi
import android.content.DialogInterface
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiConfiguration.AuthAlgorithm
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.MainActivity
import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.manage.TetheringFragment
import com.google.android.material.textfield.TextInputLayout
import java.nio.charset.Charset
/**
* https://android.googlesource.com/platform/packages/apps/Settings/+/39b4674/src/com/android/settings/wifi/WifiApDialog.java
*/
class WifiP2pDialogFragment : DialogFragment(), TextWatcher, DialogInterface.OnClickListener {
companion object {
const val TAG = "WifiP2pDialogFragment"
const val KEY_CONFIGURATION = "configuration"
const val KEY_CONFIGURER = "configurer"
}
private lateinit var mView: View
private lateinit var mSsid: TextView
private lateinit var mPassword: EditText
private lateinit var configurer: P2pSupplicantConfiguration
private val config: WifiConfiguration?
get() {
val config = WifiConfiguration()
config.SSID = mSsid.text.toString()
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN)
if (mPassword.length() != 0) {
val password = mPassword.text.toString()
config.preSharedKey = password
}
return config
}
override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog {
return AlertDialog.Builder(requireContext()).apply {
mView = requireActivity().layoutInflater.inflate(R.layout.dialog_wifi_ap, null)
setView(mView)
setTitle(R.string.repeater_configure)
mSsid = mView.findViewById(R.id.ssid)
mPassword = mView.findViewById(R.id.password)
// Note: Reading persistent group information in p2p_supplicant.conf wasn't available until this commit:
// https://android.googlesource.com/platform/external/wpa_supplicant_8/+/216983bceec7c450951e2fbcd076b5c75d432e57%5E%21/
// which isn't merged until Android 6.0.
if (Build.VERSION.SDK_INT >= 23) {
setPositiveButton(context.getString(R.string.wifi_save), this@WifiP2pDialogFragment)
}
setNegativeButton(context.getString(R.string.wifi_cancel), this@WifiP2pDialogFragment)
setNeutralButton(context.getString(R.string.repeater_reset_credentials), this@WifiP2pDialogFragment)
val arguments = arguments!!
configurer = arguments.getParcelable(KEY_CONFIGURER)
val mWifiConfig = arguments.getParcelable<WifiConfiguration>(KEY_CONFIGURATION)
if (mWifiConfig != null) {
mSsid.text = mWifiConfig.SSID
mPassword.setText(mWifiConfig.preSharedKey)
}
mSsid.addTextChangedListener(this@WifiP2pDialogFragment)
mPassword.addTextChangedListener(this@WifiP2pDialogFragment)
}.create()
}
override fun onStart() {
super.onStart()
validate()
}
private fun validate() {
val mSsidString = mSsid.text.toString()
val ssidValid = mSsid.length() != 0 && Charset.forName("UTF-8").encode(mSsidString).limit() <= 32
val passwordValid = mPassword.length() >= 8
mView.findViewById<TextInputLayout>(R.id.password_wrapper).error =
if (passwordValid) null else requireContext().getString(R.string.credentials_password_too_short)
(dialog as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE).isEnabled = ssidValid && passwordValid
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { }
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { }
override fun afterTextChanged(editable: Editable) = validate()
override fun onClick(dialog: DialogInterface?, which: Int) {
when (which) {
DialogInterface.BUTTON_POSITIVE -> @TargetApi(23) when (configurer.update(config!!)) {
true -> {
app.handler.postDelayed((targetFragment as TetheringFragment).adapter.repeaterManager
.binder!!::requestGroupUpdate, 1000)
}
false -> (activity as MainActivity).snackbar().setText(R.string.noisy_su_failure).show()
null -> (activity as MainActivity).snackbar().setText(R.string.root_unavailable).show()
}
DialogInterface.BUTTON_NEUTRAL -> {
(targetFragment as TetheringFragment).adapter.repeaterManager.binder!!.resetCredentials()
}
}
}
}