Refactor WifiP2pDialog as DialogFragment
This commit is contained in:
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user