0

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

srisindhu saride
  • 391
  • 6
  • 25
  • `getExternalFilesDir(DIRECTORY_PICTURES)` Does that directory exist? I thinkk it will not just be created by that call. – blackapps Jan 03 '20 at 11:21
  • `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 Jan 03 '20 at 11:24
  • @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 Jan 03 '20 at 11:27
  • 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 Jan 03 '20 at 11:29
  • @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 Jan 03 '20 at 11:37
  • `BitmapFactory.decodeFile(newPicturePath` What is the value of newPicturePath now? It is very well possible that it is null or the default value when starting your activity. Your activity can be killed when you start the Camera app. Put a log statement or Toast before decodeFile(). – blackapps Jan 03 '20 at 11:38
  • @blackapps Actually you are right, only the empty file has been created , there is no image in it – srisindhu saride Jan 03 '20 at 11:40
  • @blackapps I added this like takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri) before startActivityForResult and it worked. – srisindhu saride Jan 03 '20 at 11:46
  • @blackapps Thank you so much for helping me see through the right way – srisindhu saride Jan 03 '20 at 11:48
  • ???? You had that already wasnt it? It is in above code!! Did you use other code then posted? – blackapps Jan 03 '20 at 11:48
  • Ah ya the code here has it, but my code had it commented. Its my mistake – srisindhu saride Jan 03 '20 at 11:49
  • And now... do not create the file yourself. You will be left with empty files if the user cancels the operation. – blackapps Jan 03 '20 at 11:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205292/discussion-between-srisindhu-saride-and-blackapps). – srisindhu saride Jan 03 '20 at 11:51
  • @blackapps ok. No problem. Do u have any samples of how we can just send path to camera intent ? – srisindhu saride Jan 03 '20 at 11:57
  • Look at the bottom of following page. The file is not created. Only the path is build up: https://stackoverflow.com/questions/18501439/android-camera-capture-activity-returns-null-uri – blackapps Jan 03 '20 at 12:02

3 Answers3

0

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".

Dharmik Ghori
  • 182
  • 1
  • 8
0

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)
                }
srisindhu saride
  • 391
  • 6
  • 25
0

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