Support sharing via QR code
Another popular format is barcode but unfortunately I cannot seem to find documentations of that anywhere. Feel free to send me.
This commit is contained in:
@@ -20,6 +20,7 @@ import androidx.core.view.isGone
|
||||
import be.mygod.vpnhotspot.AlertDialogFragment
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.util.QRCodeDialog
|
||||
import be.mygod.vpnhotspot.util.toByteArray
|
||||
import be.mygod.vpnhotspot.util.toParcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
@@ -128,14 +129,7 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
||||
|
||||
private fun populateFromConfiguration(configuration: WifiConfiguration) {
|
||||
dialogView.ssid.setText(configuration.SSID)
|
||||
if (!arg.p2pMode) {
|
||||
val selected = configuration.allowedKeyManagement.nextSetBit(0)
|
||||
check(selected >= 0) { "No key management selected" }
|
||||
check(configuration.allowedKeyManagement.nextSetBit(selected + 1) < 0) {
|
||||
"More than 1 key managements supplied"
|
||||
}
|
||||
dialogView.security.setSelection(selected)
|
||||
}
|
||||
if (!arg.p2pMode) dialogView.security.setSelection(configuration.apKeyManagement)
|
||||
dialogView.password.setText(configuration.preSharedKey)
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
dialogView.band.setSelection(if (configuration.apChannel in 1..165) {
|
||||
@@ -171,18 +165,25 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { }
|
||||
override fun afterTextChanged(editable: Editable) = validate()
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?) = when (item?.itemId) {
|
||||
android.R.id.copy -> {
|
||||
app.clipboard.primaryClip =
|
||||
ClipData.newPlainText(null, Base64.encodeToString(ret.configuration.toByteArray(), BASE64_FLAGS))
|
||||
true
|
||||
}
|
||||
android.R.id.paste -> {
|
||||
app.clipboard.primaryClip?.getItemAt(0)?.text?.let {
|
||||
populateFromConfiguration(Base64.decode(it.toString(), BASE64_FLAGS).toParcelable())
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
return when (item?.itemId) {
|
||||
android.R.id.copy -> {
|
||||
app.clipboard.primaryClip =
|
||||
ClipData.newPlainText(null, Base64.encodeToString(ret.configuration.toByteArray(), BASE64_FLAGS))
|
||||
true
|
||||
}
|
||||
true
|
||||
android.R.id.paste -> {
|
||||
app.clipboard.primaryClip?.getItemAt(0)?.text?.let {
|
||||
populateFromConfiguration(Base64.decode(it.toString(), BASE64_FLAGS).toParcelable())
|
||||
}
|
||||
true
|
||||
}
|
||||
R.id.share_qr -> {
|
||||
QRCodeDialog().withArg(ret.configuration.toQRString())
|
||||
.show(fragmentManager ?: return false, "QRCodeDialog")
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,35 @@ fun channelToFrequency(channel: Int) = when (channel) {
|
||||
else -> throw IllegalArgumentException("Invalid channel $channel")
|
||||
}
|
||||
|
||||
val WifiConfiguration.apKeyManagement get() = allowedKeyManagement.nextSetBit(0).also { selected ->
|
||||
check(selected >= 0) { "No key management selected" }
|
||||
check(allowedKeyManagement.nextSetBit(selected + 1) < 0) { "More than 1 key managements supplied" }
|
||||
}
|
||||
|
||||
private val qrSanitizer = Regex("([\\\\\":;,])")
|
||||
/**
|
||||
* Documentation: https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
|
||||
*/
|
||||
fun WifiConfiguration.toQRString() = StringBuilder("WIFI:").apply {
|
||||
fun String.sanitize() = qrSanitizer.replace(this) { "\\${it.groupValues[1]}" }
|
||||
var password = true
|
||||
when (apKeyManagement) {
|
||||
WifiConfiguration.KeyMgmt.NONE -> password = false
|
||||
WifiConfiguration.KeyMgmt.WPA_PSK, WifiConfiguration.KeyMgmt.WPA_EAP, WPA2_PSK -> append("T:WPA;")
|
||||
else -> throw IllegalArgumentException("Unsupported authentication type")
|
||||
}
|
||||
append("S:")
|
||||
append(SSID.sanitize())
|
||||
append(';')
|
||||
if (password) {
|
||||
append("P:")
|
||||
append(preSharedKey.sanitize())
|
||||
append(';')
|
||||
}
|
||||
if (hiddenSSID) append("H:true;")
|
||||
append(';')
|
||||
}.toString()
|
||||
|
||||
/**
|
||||
* Based on:
|
||||
* https://android.googlesource.com/platform/packages/apps/Settings/+/android-5.0.0_r1/src/com/android/settings/wifi/WifiApDialog.java#88
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package be.mygod.vpnhotspot.util
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import be.mygod.vpnhotspot.R
|
||||
import net.glxn.qrgen.android.QRCode
|
||||
|
||||
class QRCodeDialog : DialogFragment() {
|
||||
companion object {
|
||||
private const val KEY_ARG = "arg"
|
||||
}
|
||||
|
||||
fun withArg(arg: String) = apply { arguments = bundleOf(KEY_ARG to arg) }
|
||||
private val arg get() = arguments?.getString(KEY_ARG)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) =
|
||||
ImageView(context).apply {
|
||||
val size = resources.getDimensionPixelSize(R.dimen.qr_code_size)
|
||||
layoutParams = ViewGroup.LayoutParams(size, size)
|
||||
setImageBitmap((QRCode.from(arg).withSize(size, size) as QRCode).bitmap())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user