0
votes

I am trying to take a photo using camera and then trying to save to gallery and decode the stream using BitmapFactory but it returns null and also photo taken is not saved to gallery.

So two things here i noticed is photo taken is not getting saved to GALLERY and decodeFile retuning false.

I have tried using BitmapFactory.decodeStream and also tried getting from Uri but nothing worked.

Here is my code:

Take Photo:

 if (ActivityCompat.checkSelfPermission(context!!, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context!!, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
     ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE), photoWithCamera)
 else
     displayCamera()

Camera Display:

private fun displayCamera() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
     // Ensure that there's a camera activity to handle the intent
     takePictureIntent.resolveActivity(context!!.packageManager)?.also {
     // Create the File where the photo should go
        createImageFile()?.also {
           uri = FileProvider.getUriForFile(context!!,"com.app.android.sample.fileprovider",it)
           startActivityForResult(takePictureIntent, photoWithCamera)
        }
      }
   }
}
private fun createImageFile(): File? = try {
        File.createTempFile("test", ".png",context?.getExternalFilesDir(DIRECTORY_PICTURES)).apply {
            newPicturePath = absolutePath
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == Activity.RESULT_OK && data != null && (requestCode == photoWithCamera){
            when (requestCode) {
                photoWithCamera -> {
                    galleryAddPic()
                    setPic()
                }
            }
        }
    }

Decode Stream and Set pic (Not Working):

private fun setPic() {
      // Get the dimensions of the View
      val targetW: Int = headingImg.width
      val targetH: Int = headingImg.height

      val bmOptions = BitmapFactory.Options().apply {
         // Get the dimensions of the bitmap
         inJustDecodeBounds = true

         val photoW: Int = outWidth
         val photoH: Int = outHeight

         // Determine how much to scale down the image
         val scaleFactor: Int = min(photoW / targetW, photoH / targetH)

         // Decode the image file into a Bitmap sized to fill the View
         inJustDecodeBounds = false
         inSampleSize = scaleFactor
         inPurgeable = true
     }
    //decodeFile returns null here
     BitmapFactory.decodeFile(newPicturePath, bmOptions)?.also { bitmap ->
         headingImg.setImageBitmap(bitmap)
     }
 }

Adding photo taken to gallery(Not working):

private fun galleryAddPic() {
     Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
         val f = File(newPicturePath)
         mediaScanIntent.data = Uri.fromFile(f)
         context!!.sendBroadcast(mediaScanIntent)
     }
 }

Android Manifest:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:permissionGroup="android.permission-group.STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

<provider
   android:name="androidx.core.content.FileProvider"
   android:authorities="${applicationId}.fileprovider"
   android:exported="false"
   android:grantUriPermissions="true">
   <meta-data
         android:name="android.support.FILE_PROVIDER_PATHS"
         android:resource="@xml/provider_paths"/>
 </provider>

Provider Paths:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <external-path name="external_files" path="."/>
</paths>

The file created using createImageFile() is returning file as below: /storage/emulated/0/Android/data/com.app.android.sample/files/Pictures/test4153865961621152704.png and I could see the file in the same location

Thanks, Sindhu

3
getExternalFilesDir(DIRECTORY_PICTURES) Does that directory exist? I thinkk it will not just be created by that call. - blackapps
and also photo taken is not saved to gallery That should not be your first concern whatrever you mean with saving to gallery. The camera app will use your FileProvider to save the image to the file you temporarily created. So you should first look there if there is a nice file. Please tell. - blackapps
@blackapps This file is created as so: /storage/emulated/0/Android/data/com.app.android.example/files/Pictures/test4153865961621152704.png. And this file is existing in the device - srisindhu saride
Have you checked the file size? Sure it is not 0? You are creating an empty file yourself before you start the camera. Better not create the file yourself first. You only need a path. So just determine a path. If the user cancels the image taken you will be left with an empty file too which is not nice. - blackapps
@blackapps I have tried getting the length of file and it returned 0. So does that mean it is an empty file yet and image is being created later as I could see the image in the given absolute path on the device? - srisindhu saride

3 Answers

0
votes

You should use same package name

'com.app.android.sample.fileprovider'

which you are using while opening camera in manifest file - 'com.app.android.sample.fileprovider' instead

android:authorities="${applicationId}.fileprovider".

0
votes

I forgot to add the file uri before starting the Camera intent. So i changed my code from

createImageFile()?.also {
                    uri = FileProvider.getUriForFile(
                        context!!,
                        "com.app.android.traderpro.etx.fileprovider",
                        it
                    )
                    startActivityForResult(takePictureIntent, photoWithCamera)
                }

to this:

createImageFile()?.also {
                    uri = FileProvider.getUriForFile(
                        context!!,
                        "com.app.android.traderpro.etx.fileprovider",
                        it
                    )
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
                    startActivityForResult(takePictureIntent, photoWithCamera)
                }
0
votes

I faced the same issue and I fixed it by adding android:requestLegacyExternalStorage="true" under the application tag in the AndroidMaifest.xml file.