I write an app in Android Studio and want to save a bitmap which contains a self-made qr-code. If the code contains a text with less than 20 characters it works but not if the code contains more than 20 chars. The creation works but not the saving. Here’s my code:
https://github.com/GrossadmiralThrawn/MyBarCode.git
import android.graphics.Bitmap
import android.os.Environment
import android.os.StatFs
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class ExportLocal(private var data: Bitmap) : IExport {
override fun setData(newData: Bitmap) {
data = newData
}
private fun getDataSize(): Long {
return data.byteCount.toLong()
}
private fun getAvailableInternalMemorySizeSpace(): Long {
val path = Environment.getDataDirectory()
val stat = StatFs(path.path)
val blockSize = stat.blockSizeLong
val availableBlocks = stat.availableBlocksLong
return availableBlocks * blockSize
}
/**
* @return a boolean which says if the source is available. In this case it checks if the phone has enough capacities to store the image.
*/
override fun checkAvailability(): Boolean {
return getDataSize() < getAvailableInternalMemorySizeSpace()
}
override fun export(information: String?): Boolean {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val folderName = "MyBarcodeData"
val fileName = if (!information.isNullOrEmpty()) {
"${sanitizeFileName(information)}_$timeStamp.jpg"
} else {
"barcode_$timeStamp.jpg"
}
val folder = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), folderName)
if (!folder.exists()) {
folder.mkdirs()
}
val file = File(folder, truncatedFileName(fileName))
return try {
FileOutputStream(file).use { out ->
data.compress(Bitmap.CompressFormat.JPEG, 100, out)
}
true
} catch (e: IOException) {
e.printStackTrace()
false
}
}
private fun truncatedFileName(fileName: String): String {
return if (fileName.length > 90) {
fileName.subSequence(0, 89).toString()
} else {
fileName
}
}
private fun sanitizeFileName(fileName: String): String {
// Replace invalid characters in file name with underscores
return fileName.replace("[^a-zA-Z0-9.-]".toRegex(), "_")
}
private fun getExternalFilesDir(type: String): File? {
return Environment.getExternalStoragePublicDirectory(type)
}
}
class ShowCodeActivity : AppCompatActivity() {
private lateinit var returnButton: Button
private lateinit var saveButton: Button
private lateinit var shareButton: Button
private lateinit var receivedIntent: Intent
private lateinit var showCodeImageView: ImageView
private lateinit var saveCode: IExport
private var creationSucceed: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_show_code)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
receivedIntent = intent
returnButton = findViewById(R.id.returnToPreviousButton)
saveButton = findViewById(R.id.saveButton)
shareButton = findViewById(R.id.shareButton)
showCodeImageView = findViewById(R.id.showCodeImageView)
val codeText = receivedIntent.getStringExtra("codeText")
when (receivedIntent.getStringExtra("codeType")) {
"QR" -> generateQRCode(codeText!!)
"Bar" -> generateBarcode(codeText!!)
}
saveButton.setOnClickListener {
val options = arrayOf(getString(R.string.save_location_local))
AlertDialog.Builder(this)
.setTitle(getString(R.string.select_save_option))
.setItems(options) { _, which ->
when (which) {
0 -> saveLocally(showCodeImageView.drawable?.toBitmap(), codeText)
}
}
.setNegativeButton(getString(R.string.quit)) { dialog, _ ->
dialog.dismiss()
}
.show()
}
shareButton.setOnClickListener {
shareImage()
}
returnButton.setOnClickListener {
finish()
}
}
private fun saveLocally(data: Bitmap?, information: String?) {
data?.let {
saveCode = ExportLocal(it)
val success = saveCode(data, saveCode, information)
if (success) {
Toast.makeText(this, getString(R.string.save_successfully), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, getString(R.string.save_unsuccessfully), Toast.LENGTH_SHORT).show()
}
} ?: Toast.makeText(this, getString(R.string.save_unsuccessfully), Toast.LENGTH_SHORT).show()
}
private fun saveCode(data: Bitmap, storeObject: IExport, information: String?): Boolean {
val options = arrayOf("Automatic Naming", "Custom Naming")
var selectedOption = 0
storeObject.setData(data)
if (storeObject.checkAvailability()) {
if (storeObject.export(information)) {
return true
}
}
return false
}
private fun generateQRCode(data: String) {
val barcodeEncoder = BarcodeEncoder()
try {
val bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.QR_CODE, 600, 400)
showCodeImageView.setImageBitmap(bitmap)
creationSucceed = true
} catch (e: WriterException) {
e.printStackTrace()
}
}
private fun generateBarcode(data: String) {
val barcodeEncoder = BarcodeEncoder()
try {
val bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.MAXICODE, 800, 400)
showCodeImageView.setImageBitmap(bitmap)
creationSucceed = true
} catch (e: WriterException) {
e.printStackTrace()
}
}
private fun shareImage() {
val bitmap = showCodeImageView.drawable?.toBitmap()
if (bitmap != null) {
try {
// Save bitmap to cache directory
val cachePath = File(cacheDir, "images")
cachePath.mkdirs() // Create directory if not exists
val file = File(cachePath, "shared_image.png")
val fileOutputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)
fileOutputStream.close()
// Get file URI
val fileUri: Uri = FileProvider.getUriForFile(
this,
"$packageName.fileprovider",
file
)
// Create share intent
val shareIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, fileUri)
type = "image/*"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // Grant permission to read the URI
}
// Start share activity
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_via)))
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
It tried to improve the qualitiy ofe the code and to cut of to long names and also to play a little bit with the library setting. Also I tried to add some permissions but it didn’t help.
It would be nice if someone could look over the code.
user26613137 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.