Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)

like image 344
Gopal Awasthi Avatar asked Oct 21 '19 13:10

Gopal Awasthi


2 Answers

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())

like image 144
gcantoni Avatar answered Sep 28 '22 02:09

gcantoni


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();
        }
    }
like image 32
Jill Joshi Avatar answered Sep 28 '22 04:09

Jill Joshi