Gopal Awasthi
Gopal Awasthi

Reputation: 433

App Crashes on Storing the Bitmap on Android 10 even if Target Sdk is set to 28?

I am attaching the Bitmap to the Imageview by storing in the MediaStore. It works fine in all the device below android 10, but when crash occured in pixel. My android id targeted to sdk 28

try {
                Bitmap thePic = MediaStore.Images.Media.GetBitmap(ContentResolver, croppedPicUri);
                if(thePic != null){
                    imgProfileIcon.SetImageBitmap(thePic);

                //mediaStorageDir = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDcim);
                mediaStorageDir = GetExternalFilesDir(Environment.DirectoryPictures);
                if (!mediaStorageDir.Exists())
                {
                    mediaStorageDir.Mkdirs();
                }


                // Create a media file name
                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").Format(new Java.Util.Date());
                sendFile = new File(mediaStorageDir.Path + File.Separator + "IMG_" + timeStamp + ".png");

                String path_ = MediaStore.Images.Media.InsertImage(this.ContentResolver, thePic, "Title", null);
                if (path_ != null){
                    Uri tempUri = Uri.Parse(path_);
                    path = GetPathToImage(tempUri);
                }
                }
            } catch (Exception ex) {
                Toast.MakeText(this, "Bundle extras : " + ex.Message, ToastLength.Short).Show();
            }

{Java.Lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures Title image/jpeg at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in <205bc242eb64455b94479843fca3eeb7>:0 at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) [0x00018] in <205bc242eb64455b94479843fca3eeb7>:0 at Android.Provider.MediaStore+Images+Media.InsertImage (Android.Content.ContentResolver cr, Android.Graphics.Bitmap source, System.String title, System.String description) [0x0008d] in <072ebd6d3ae947ac8b3980f8fd1aeee1>:0 at EventApp.ProfileListActivity.OnActivityResult (System.Int32 requestCode, Android.App.Result resultCode, Android.Content.Intent data) [0x00200] in D:\EventApp\EventApp\Activity\ProfileListActivity.cs:1310 --- End of managed Java.Lang.IllegalStateException stack trace --- java.lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures Title image/jpeg at android.os.Parcel.createException(Parcel.java:2079) at android.os.Parcel.readException(Parcel.java:2039) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140) at android.content.ContentProviderProxy.insert(ContentProviderNative.java:481) at android.content.ContentResolver.insert(ContentResolver.java:1828) at android.provider.MediaStore.createPending(MediaStore.java:616) at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:1771)

Upvotes: 5

Views: 4288

Answers (5)

gcantoni
gcantoni

Reputation: 787

Let's consider:

MediaStore.Images.Media.insertImage(ContentResolver cr, Bitmap source, String title, String description)

Let's apply it to a real example:

MediaStore.Images.Media.insertImage(context.getContentResolver(), imageToSave, "ThisIsImageTitleString", null);

You will notice that this safely saves any type of bitmap in memory. But how is the output bitmap name?

First time:

ThisIsImageTitleString

Second time:

ThisIsImageTitleString(2)

...

32th time:

ThisIsImageTitleString(32)

33th time:

java.lang.IllegalStateException: Failed to build unique file: /storage/emulated/0/Pictures ThisIsImageTitleString image/jpeg

Simple solution: add a timestamp.

Declare this as constant ( static or non static according to what you need )

static Date currentTime;

and then change MediaStore way to save bitmaps to:

MediaStore.Images.Media.insertImage(context.getContentResolver(), imageToSave, "ThisIsImageTitleString" + " - " + (currentTime = Calendar.getInstance().getTime()), null);

Please note: (currentTime = Calendar.getInstance().getTime())

Upvotes: 8

Pooran Kharol
Pooran Kharol

Reputation: 58

replace "Title" to File.separator + "IMG_" + timeStamp + ".png

eg.String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, File.separator + "IMG_" + timeStamp + ".png", null);

Upvotes: 1

Aliaksandr Kotau
Aliaksandr Kotau

Reputation: 21

I figured out that while saving image via MediaStore.Images.Media.insertImage(ContentResolver cr, Bitmap source, String title, String description) method, title param must be specified explicitly on Android 10. In other way file name will look like this: Image. Every next image will be saved as Image (n). App throws an error after n reaches value of 32.

Upvotes: 2

Coldfish
Coldfish

Reputation: 378

As far as I know, this method is deprecated in API 29.

https://developer.android.com/reference/android/provider/MediaStore.Images.Media

insertImage(ContentResolver cr, String imagePath, String name, String description)

This method was deprecated in API level 29. inserting of images should be performed using MediaColumns#IS_PENDING, which offers richer control over lifecycle. 

You should use MediaColumns#IS_PENDING for the devices using API 29+.

More info: https://developer.android.com/training/data-storage/files/media#pending-media-files

Upvotes: -1

Jill Joshi
Jill Joshi

Reputation: 31

Change/Create file with the use of math's random function rather then time stamp and make sure it FileOutputStream object is going to flush. for the reference,

 private void SaveImage(Bitmap finalBitmap) {

        String root = Environment.getExternalStorageDirectory().toString();
        File myDir = new File(root + "/saved_images");    
         if (!myDir.exists()) {
                        myDir.mkdirs();
                    }
        Random generator = new Random();
        int n = 10000;
        n = generator.nextInt(n);
        String fname = "Image-"+ n +".jpg";
        File file = new File (myDir, fname);
        if (file.exists ())
          file.delete (); 
        try {
            FileOutputStream out = new FileOutputStream(file);
            finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();

        } catch (Exception e) {
             e.printStackTrace();
        }
    }

Upvotes: 3

Related Questions