即使将目标SDK设置为28,应用程序也会在Android 10上存储位图时崩溃?

问题描述 投票:3回答:5

我通过存储在MediaStore中将位图附加到Imageview。它在android 10以下的所有设备上都可以正常工作,但是当崩溃发生在像素上时。我针对sdk 28的android id

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:无法构建唯一文件:/ storage / emulated / 0 / Pictures Title image / jpeg在<205bc242eb64455b94479843fca3eeb7> :: 0中的Java.Interop.JniEnvironment + StaticMethods.CallStaticObjectMethod(Java.Interop.JniObjectReference类型,Java.Interop.JniMethodInfo方法,Java.Interop.JniArgumentValue * args)中[0x00069]在<205bc242eb64455b94479843fca3eeb7>:0中的Java.Interop.JniPeerMembers + JniStaticMethods.InvokeObjectMethod(System.String编码的成员,Java.Interop.JniArgumentValue *参数)[0x00018]中在<072ebd6d3ae947ac8b3980f8fd1aeee1>:0中的Android.Provider.MediaStore + Images + Media.InsertImage(Android.Content.ContentResolver cr,Android.Graphics.Bitmap源,System.String标题,System.String描述)[0x0008d]在D:\ EventApp \ EventApp \ Activity \ ProfileListActivity.cs:1310中的EventApp.ProfileListActivity.OnActivityResult(System.Int32 requestCode,Android.App.Result resultCode,Android.Content.Intent数据)[0x00200]处---托管Java.Lang.IllegalStateException堆栈跟踪的结尾-java.lang.IllegalStateException:无法构建唯一文件:/ storage / emulated / 0 / Pictures Title image / jpeg在android.os.Parcel.createException(Parcel.java:2079)在android.os.Parcel.readException(Parcel.java:2039)在android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)在android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)在android.content.ContentProviderProxy.insert(ContentProviderNative.java:481)在android.content.ContentResolver.insert(ContentResolver.java:1828)在android.provider.MediaStore.createPending(MediaStore.java:616)在android.provider.MediaStore $ Images $ Media.insertImage(MediaStore.java:1771)

android xamarin xamarin.android mediastore
5个回答
2
投票

使用数学的随机函数而不是时间戳来更改/创建文件,并确保FileOutputStream对象将被刷新。供参考,

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

1
投票

我发现通过MediaStore.Images.Media.insertImage(ContentResolver cr, Bitmap source, String title, String description)方法保存图像时,必须在Android 10上显式指定title参数。否则,文件名将如下所示:Image。下一张图像将另存为Image (n)n达到值32后,App引发错误。


1
投票

让我们考虑:

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

让我们将其应用于一个真实的示例:

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

您会注意到,这可以安全地将任何类型的位图保存在内存中。但是输出位图名称如何?

第一次:

ThisIsImageTitleString

第二时间:

ThisIsImageTitleString(2)

...

第32次:

ThisIsImageTitleString(32)

第33次:

java.lang.IllegalStateException:无法构建唯一文件:/ storage / emulated / 0 / Pictures ThisIsImageTitleString image / jpeg

简单的解决方案:添加timestamp

将其声明为常量(根据需要声明为静态或非静态)

static Date currentTime;

然后更改MediaStore的方式将位图保存到:

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

请注意: (currentTime = Calendar.getInstance().getTime())


0
投票

将“标题”替换为File.separator +“ IMG_” +时间戳+“ .png

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


-1
投票

据我所知,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. 

您应该对使用API​​ 29+的设备使用MediaColumns#IS_PENDING。

更多信息:https://developer.android.com/training/data-storage/files/media#pending-media-files

© www.soinside.com 2019 - 2024. All rights reserved.