Fix bitmap recycle race condition and startActivity crash

- Null the Compose state reference before recycling bitmaps to prevent
  the renderer from drawing a recycled bitmap between recycle() and
  the state update
- Wrap ACTION_VIEW startActivity in try-catch for devices without
  an image viewer installed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-05 11:56:29 +01:00
commit 5e08fb9c13

View file

@ -6,6 +6,7 @@ import android.graphics.SurfaceTexture
import android.location.Location
import android.net.Uri
import android.opengl.GLSurfaceView
import android.util.Log
import android.view.Surface
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
@ -359,9 +360,10 @@ fun CameraScreen(
// Cancel button
IconButton(
onClick = {
galleryBitmap?.recycle()
val oldBitmap = galleryBitmap
galleryBitmap = null
galleryImageUri = null
oldBitmap?.recycle()
},
modifier = Modifier
.size(56.dp)
@ -392,9 +394,10 @@ fun CameraScreen(
when (result) {
is SaveResult.Success -> {
haptics.success()
lastThumbnailBitmap?.recycle()
val oldThumb = lastThumbnailBitmap
lastThumbnailBitmap = result.thumbnail
lastSavedUri = result.uri
oldThumb?.recycle()
showSaveSuccess = true
delay(1500)
showSaveSuccess = false
@ -406,9 +409,10 @@ fun CameraScreen(
showSaveError = null
}
}
galleryBitmap?.recycle()
val oldGalleryBitmap = galleryBitmap
galleryBitmap = null
galleryImageUri = null
oldGalleryBitmap?.recycle()
isCapturing = false
}
}
@ -492,9 +496,10 @@ fun CameraScreen(
when (result) {
is SaveResult.Success -> {
haptics.success()
lastThumbnailBitmap?.recycle()
val oldThumb = lastThumbnailBitmap
lastThumbnailBitmap = result.thumbnail
lastSavedUri = result.uri
oldThumb?.recycle()
showSaveSuccess = true
delay(1500)
showSaveSuccess = false
@ -524,11 +529,15 @@ fun CameraScreen(
thumbnail = lastThumbnailBitmap,
onTap = {
lastSavedUri?.let { uri ->
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "image/jpeg")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
try {
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "image/jpeg")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(intent)
} catch (e: android.content.ActivityNotFoundException) {
Log.w("CameraScreen", "No activity found to view image", e)
}
context.startActivity(intent)
}
},
modifier = Modifier