Untitled

mail@pastecode.io avatar
unknown
plain_text
8 months ago
5.8 kB
2
Indexable
Never
package com.secuso.privacyfriendlycodescanner.qrscanner.generator

import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Point
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import com.google.zxing.BarcodeFormat
import com.google.zxing.WriterException
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.*

object QRGeneratorUtils {

    private const val IMAGE_FOLDER = "Generated QR Codes"
    private const val TAG = "QRGeneratorUtils"
    private var cache: Uri? = null

    fun shareImage(context: AppCompatActivity, imageUri: Uri) {
        val intent = Intent(Intent.ACTION_SEND)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.type = "image/png"
        intent.putExtra(Intent.EXTRA_STREAM, imageUri)
        context.startActivity(Intent.createChooser(intent, "Share via"))
    }

    fun purgeCacheFolder(context: Context) {
        try {
            val imageFilePath = File(context.cacheDir, "images/")
            val files = imageFilePath.listFiles()
            files?.forEach { file -> file.delete() }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun cacheImage(context: Context, image: Bitmap): Uri? {
        val imageFilePath = File(context.cacheDir, "images/").apply { mkdir() }
        val file = writeToFile(File(imageFilePath, buildFileString()), image)
        cache = file?.let { FileProvider.getUriForFile(context, "org.secuso.qrscanner.fileprovider", it) }
        return cache
    }

    fun getCachedUri(): Uri? {
        return cache
    }

    fun createImage(context: Context, qrInputText: String, qrType: Contents.Type,
                    barcodeFormat: BarcodeFormat, errorCorrectionLevel: String): Uri? {

        val manager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = manager.defaultDisplay
        val point = Point()
        display.getSize(point)
        val width = point.x
        val height = point.y
        var smallerDimension = if (width < height) width else height
        smallerDimension = smallerDimension * 3 / 4

        val qrCodeEncoder = QRCodeEncoder(qrInputText, null, qrType, barcodeFormat.toString(), smallerDimension)
        var bitmap: Bitmap? = null
        try {
            bitmap = qrCodeEncoder.encodeAsBitmap(errorCorrectionLevel)
        } catch (e: WriterException) {
            e.printStackTrace()
        }

        return bitmap?.let { cacheImage(context, it) }
    }

    fun saveCachedImageToExternalStorage(context: Context) {
        val bitmap = MediaStore.Images.Media.getBitmap(context.contentResolver, cache)
        bitmap?.let { saveImageToExternalStorage(context, it) }
    }

    @Throws(IOException::class)
    fun saveImageToExternalStorage(context: Context, finalBitmap: Bitmap) {
        val fileName = buildFileString()
        val oStream: OutputStream

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val resolver: ContentResolver = context.contentResolver
            val imageCollection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
            val relativePath = Environment.DIRECTORY_PICTURES + File.separator + IMAGE_FOLDER

            val newImage = ContentValues().apply {
                put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
                put(MediaStore.Images.Media.MIME_TYPE, "image/png")
                put(MediaStore.Images.ImageColumns.RELATIVE_PATH, relativePath)
            }

            val imageUri = resolver.insert(imageCollection, newImage)
            oStream = resolver.openOutputStream(imageUri)!!
            finalBitmap.compress(Bitmap.CompressFormat.PNG, 100, oStream)
        } else {
            val externalPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
            val myDir = File(externalPath, IMAGE_FOLDER).apply { mkdirs() }
            val file = writeToFile(File(myDir, fileName), finalBitmap)

            MediaScannerConnection.scanFile(context, arrayOf(file.toString()), null) { path, uri ->
                Log.i("ExternalStorage", "Scanned $path:")
                Log.i("ExternalStorage", "-> uri=$uri")
            }
        }
    }

    private fun buildFileString(): String {
        val sb = StringBuffer().apply {
            append("QrCode_")
            append(SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.getDefault()).format(Date()))
            append(".png")
        }
        return sb.toString()
    }

    private fun writeToFile(file: File, image: Bitmap): File? {
        var outFile = file
        val sb = StringBuilder(file.toString())

        var i = 2
        while (outFile.exists()) {
            sb.delete(sb.length - 4, sb.length)
            sb.append("_($i).png")
            outFile = File(sb.toString())
            i++
        }

        return try {
            FileOutputStream(outFile).use { fOut ->
                image.compress(Bitmap.CompressFormat.PNG, 100, fOut)
            }
            outFile
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }

    fun escapeQRPropertyValue(value: String): String {
        return value.replace("\\", "\\\\")
                .replace(",", "\\,")
                .replace(":", "\\:")
                .replace(";", "\\;")
    }
}
Leave a Comment