owenclave / app/src/main/java/io/nekohasekai/sagernet/widget/QRCodeDialog.kt

github - dev - back to tree - upstream
/****************************************************************************** * * * Copyright (C) 2021 by nekohasekai * * Copyright (C) 2021 by Max Lv * * Copyright (C) 2021 by Mygod Studio * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************/ package io.nekohasekai.sagernet.widget import android.graphics.Bitmap import android.graphics.Color import android.os.Bundle import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import com.google.zxing.BarcodeFormat import com.google.zxing.EncodeHintType import com.google.zxing.WriterException import com.google.zxing.qrcode.QRCodeWriter import io.nekohasekai.sagernet.R import io.nekohasekai.sagernet.ktx.Logs import io.nekohasekai.sagernet.ktx.app import io.nekohasekai.sagernet.ktx.readableMessage import io.nekohasekai.sagernet.ui.MainActivity import java.nio.charset.StandardCharsets import kotlin.math.roundToInt class QRCodeDialog() : DialogFragment() { companion object { private const val KEY_URL = "io.nekohasekai.sagernet.QRCodeDialog.KEY_URL" private val iso88591 = StandardCharsets.ISO_8859_1.newEncoder() private val size by lazy { try { val displayMetrics: DisplayMetrics = app.resources.displayMetrics val height: Int = displayMetrics.heightPixels val width: Int = displayMetrics.widthPixels ((if (height > width) width else height) * 0.8).roundToInt() } catch (e: Exception) { Logs.w(e) app.resources.getDimensionPixelSize(R.dimen.qrcode_size) } } } constructor(url: String) : this() { arguments = bundleOf(Pair(KEY_URL, url)) } /** * Based on: * https://android.googlesource.com/platform/ packages/apps/Settings/+/0d706f0/src/com/android/settings/wifi/qrcode/QrCodeGenerator.java * https://android.googlesource.com/platform/ packages/apps/Settings/+/8a9ccfd/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java#153 */ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = try { val url = arguments?.getString(KEY_URL)!! val hints = mutableMapOf() if (!iso88591.canEncode(url)) hints[EncodeHintType.CHARACTER_SET] = StandardCharsets.UTF_8.name() val qrBits = QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, size, size, hints) ImageView(context).apply { layoutParams = ViewGroup.LayoutParams(size, size) setImageBitmap(Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565).apply { for (x in 0 until size) for (y in 0 until size) { setPixel(x, y, if (qrBits.get(x, y)) Color.BLACK else Color.WHITE) } }) } } catch (e: WriterException) { Logs.w(e) (activity as MainActivity).snackbar(e.readableMessage).show() dismiss() null } }