I am trying to capture images in my Android App using camera and show it in a list using RecyclerView
But because the images are quite heavy in size (6-7 MB each) and my list is can contains approx 8-9 images, I can see this in my logs:-
06-08 17:22:44.318 14283 14283 I Choreographer: Skipped 40 frames! The application may be doing too much work on its main thread.
And it's not just about the logs. I can even see that when I am trying to capture the image with camera in the foreground, sometimes(frequency : 30%) my application is getting killed and automatically recreated. Because of this, I am losing my images that were earlier captured.
This is my code to capture the image written in my SampleFragment.kt
:-
fun onBtnTakePicture() {
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
outputFileName = "${System.currentTimeMillis()}.jpg"
val photo = File(context!!.filesDir, outputFileName)
val outputFileUri = FileProvider.getUriForFile(context!!, AUTHORITY_APP_FILES,photo)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri)
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode == AppCompatActivity.RESULT_OK){
if(requestCode == CAMERA_REQUEST_CODE){
//To add to db, we need to add this in view model
transactionViewModel.addImagePathInList(outputFileName)
//to show in the UI, we need to add it into this list
myCardsList.add(FeatureCarouselCardData(outputFileName))
featureCardsView.notifyAdapaterAboutDataSetChange()
}
}
}
private lateinit var featureCardsView: FeatureCarouselView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
..........
..........
featureCardsView = binding.featureCardsView
featureCardsView.showFeatureCarouselCards(myCardsList)
..........
..........
}
Adapter object is created in my class extending the RecyclerView : FeatureCarouselView.kt
fun showFeatureCarouselCards(featureCarouselCards: List<FeatureCarouselCardData>){
this.featureCarouselCards = featureCarouselCards
featureCarouselAdapter = FeatureCarouselAdapter(context, featureCarouselCards)
adapter = featureCarouselAdapter
}
This is the onBindViewHolder
function in my FeatureCarouselAdapter.kt
class
override fun onBindViewHolder(holder: FeatureCarouselViewHolder, position: Int) {
val currentItem = featureCarouselCards[position]
var bitmap = mContext.resources.getDrawable(R.drawable.ic_file_not_found).toBitmap()
Log.d(LOG_TAG, "currentItem in onBindViewHolder : "+currentItem)
try {
Log.d(LOG_TAG, "try")
val photo = File(mContext.filesDir, currentItem.fileName)
val outputFileUri = FileProvider.getUriForFile(mContext, AUTHORITY_APP_FILES,photo)
bitmap = MediaStore.Images.Media.getBitmap(mContext.contentResolver, outputFileUri)
}catch (e: FileNotFoundException) {
Log.d(LOG_TAG, "catch filenotfound")
e.printStackTrace()
} catch (e: IOException) {
Log.d(LOG_TAG, "catch ioexception")
e.printStackTrace()
}
holder.imageView.setImageBitmap(bitmap)
}
While I know that there are some tools that can be used to load images alternatively and efficiently like Picasso or Glide. But these needs INTERNET permissions to be added in the Manifest file.
I want to keep my app offline only. So want to avoid this.
How can I achieve this?
Update
I even tried using loading images using Glide:-
Glide.with(mContext)
.load(outputFileUri)
.into(holder.imageView)
But still, I am facing the same problem. So, what could be the possible root cause for my issue?