简体   繁体   English

为什么在 API 29 上不再保存图像

[英]Why doesn't image saving work anymore on API 29

In my App the user is able to save images from a pciture gallery to the local device by clicking on a DL Button.在我的应用程序中,用户可以通过单击 DL 按钮将图片库中的图像保存到本地设备。

The Code does work on old devices but on API 29 it has the following behaviour: While saving I tried to open the Gallery to have a look what happens: the gallery gets updated and for 1 second an empty images appears and disappears immediately after.该代码确实适用于旧设备,但在 API 29 上它具有以下行为:在保存时,我尝试打开图库以查看会发生什么:图库更新,并且在 1 秒内出现空图像并立即消失。 I get noticed, that the image got saved but it doesn't appear, not even in the device explorer.我注意到,图像已保存但没有出现,甚至在设备资源管理器中也没有出现。

//DEXTER HERE  
Picasso.get().load(dummyimage.getLarge()).placeholder(R.drawable.ic_img_error).error(R.drawable.ic_red).into(saveImageToDirectory);


  final Target saveImageToDirectory = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            ProgressDialog mydialog = new ProgressDialog(getActivity());
            mydialog.setMessage("saving Image to phone");
            mydialog.show();

            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
            StrictMode.setVmPolicy(builder.build());

            try {
                String fileName = "myApp_" + timeStamp + ".JPG";
                String dirName= "/myApp";
                File file = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + dirName, fileName);

                //new File(path for the file to be saved, saving file name)
                if (!file.exists()) {
                    //check if the file already exist or if not create a new file
                    //if exist the file will be overwritten with the new image
                    File filedirectory = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath()  + dirName);
                    filedirectory.mkdirs();


                }
                if (file.exists()) {
                    file.delete();
                }
                FileOutputStream ostream = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
                Toast.makeText(getActivity(), "Picture saved to Gallery" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                ostream.close();
                mydialog.dismiss();

                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.TITLE, "My Images");
                values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
                values.put(MediaStore.MediaColumns.RELATIVE_PATH,"/myApp");
                // API LEVEL Q: values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
                values.put("_data", file.getAbsolutePath());
                ContentResolver cr = getActivity().getContentResolver();
                cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

            } catch (Exception e) {
                mydialog.dismiss();
                Log.e("file creation error", e.toString());
            }

        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {
        }
        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {
        }
    };

As you may see, instead of如您所见,而不是

File filedirectory = new File(Environment.getExternalStorageDirectory() + dirName);

I'm already using我已经在用

File filedirectory = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath()  + dirName);

I hope this shouldn't be the problem, but I'm a little stuck on this strange behaviour.我希望这不是问题,但我对这种奇怪的行为有点困惑。

This is the error I'm getting out of my Logcat:这是我从 Logcat 中得到的错误:

E/file creation error: java.lang.IllegalArgumentException: Primary directory (invalid) not allowed for content://media/external/images/media; E/文件创建错误:java.lang.IllegalArgumentException:主目录(无效)不允许用于 content://media/external/images/media; allowed directories are [DCIM, Pictures]允许的目录是 [DCIM, Pictures]

PS: I'm using Dexter to avoid problems with the permissions PS:我使用 Dexter 来避免权限问题

Try this尝试这个

private Uri saveImage(Context context, Bitmap bitmap, @NonNull String folderName, @NonNull String fileName) throws IOException
{
    OutputStream fos;
    File imageFile = null;
    Uri imageUri = null;


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        ContentResolver resolver = context.getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + File.separator + folderName);
        imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        fos = resolver.openOutputStream(imageUri);
    } else {
        String imagesDir = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DCIM).toString() + File.separator + folderName;
        imageFile = new File(imagesDir);
        if (!imageFile.exists()) {
            imageFile.mkdir();
        }
        imageFile = new File(imagesDir, fileName + ".png");
        fos = new FileOutputStream(imageFile);
    }

    boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
    fos.flush();
    fos.close();

    if (imageFile != null)  // pre Q
    {
        MediaScannerConnection.scanFile(context, new String[]{imageFile.toString()}, null, null);
        imageUri = Uri.fromFile(imageFile);
    }

    return imageUri;
}

And add requestLegacyExternalStorage in your Manifest file并在您的清单文件中添加 requestLegacyExternalStorage

<application
    android:allowBackup="true"
    android:icon="@drawable/icon"
    android:requestLegacyExternalStorage="true"
    android:label="@string/app_name"
    android:roundIcon="@drawable/icon"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    ...
    ...
    ...

</application>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM