访问和共享 Internal/External 存储 Android 中图片文件夹下的文件 Q

Access and share file under Picture folder in Internal/External Storage Android Q

在存储管理方面,Android Q 发生了许多重大变化,我在应用程序中的一项功能是允许用户在 View 中拍摄照片,例如 CardView 项目,为它创建一个 Bitmap 并将其保存到设备的大容量存储器中。保存完成后,它将触发 Intent.ACTION_SEND,这样用户就可以将最近保存的图片与一些描述分享到社交应用程序,并使用 GMail 撰写电子邮件。

此代码片段工作正常。

        try {
        //Get primary storage status
        String state = Environment.getExternalStorageState();
        File filePath = new File(view.getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/" + "Shared");

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            try {
                if (filePath.mkdirs())
                    Log.d("Share Intent", "New folder is created.");
            } catch (Exception e) {
                e.printStackTrace();
                Crashlytics.logException(e);
            }
        }

        //Create a new file
        File imageFile = new File(filePath, UUID.randomUUID().toString() + ".png");

        //Create bitmap screen capture
        Bitmap bitmap = Bitmap.createBitmap(loadBitmapFromView(view));

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);

        outputStream.flush();
        outputStream.close();

        Toast.makeText(view.getContext(), "Successfully save!", Toast.LENGTH_SHORT).show();

        shareToInstant(description, imageFile, view);


    } catch (IOException e) {
        e.printStackTrace();
        Crashlytics.logException(e);
    }

但这会将图像文件保存到 /storage/emulated/0/Android/data/YOUR_APP_PACKAGE_NAME/files/Pictures

我想要的是像大多数应用程序一样将它们保存在根目录下的默认图片文件夹中 /storage/emulated/0/Pictures 这样图像就更加暴露并且可以很容易地被 [=39= 查看和扫描]图库.

为了做到这一点,我将上面的代码片段更改为此。

 //Create bitmap screen capture
    Bitmap bitmap = Bitmap.createBitmap(loadBitmapFromView(view));

    final String relativeLocation = Environment.DIRECTORY_PICTURES + "/" + view.getContext().getString(R.string.app_name);

    final ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, UUID.randomUUID().toString() + ".png");
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
    contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);

    final ContentResolver resolver = view.getContext().getContentResolver();

    OutputStream stream = null;
    Uri uri = null;

    try {

        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        uri = resolver.insert(contentUri, contentValues);

        if (uri == null || uri.getPath() == null) {
            throw new IOException("Failed to create new MediaStore record.");
        }

        stream = resolver.openOutputStream(uri);

        if (stream == null) {
            throw new IOException("Failed to get output stream.");
        }

        if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)) {
            throw new IOException("Failed to save bitmap.");
        }

        //If we reach this part we're good to go
        Intent mediaScannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File imageFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), contentValues.getAsString(MediaStore.MediaColumns.DISPLAY_NAME));
        Uri fileContentUri = Uri.fromFile(imageFile);
        mediaScannerIntent.setData(fileContentUri);
        view.getContext().sendBroadcast(mediaScannerIntent);

        shareToInstant(description, imageFile, view);

    } catch (IOException e) {
        if (uri != null) {
            // Don't leave an orphan entry in the MediaStore
            resolver.delete(uri, null, null);
        }
        e.printStackTrace();
        Crashlytics.logException(e);
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
                Crashlytics.logException(e);
            }
        }
    }

也可以,但无法 attached/share 将图像发送到 GMail 等其他应用程序,而且据说 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 已弃用,所以我想知道现在应该怎么做,因为我已经尝试了很多对此进行了研究,但没有运气在这件事上找到类似的情况。

这是我的 FileProvider 的样子。

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external"
        path="." />
    <external-files-path
        name="external_files"
        path="." />
    <cache-path
        name="cache"
        path="." />
    <external-cache-path
        name="external_cache"
        path="." />
    <files-path
        name="files"
        path="." />
</paths>

这是我的 Intent 分享片段。

private static void shareToInstant(String content, File imageFile, View view) {

    Intent sharingIntent = new Intent(Intent.ACTION_SEND);
    sharingIntent.setType("image/png");
    sharingIntent.setType("text/plain");
    sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    sharingIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    sharingIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(view.getContext(), BuildConfig.APPLICATION_ID + ".provider", imageFile));
    sharingIntent.putExtra(Intent.EXTRA_TEXT, content);

    try {
        view.getContext().startActivity(Intent.createChooser(sharingIntent, "Share it Via"));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(view.getContext(), R.string.unknown_error, Toast.LENGTH_SHORT).show();
    }
}

看来您仍然可以在 Android Q 中访问该文件而无需 FileProvider.getUriForFile(context, authority, file);,只需传递来自 resolver.insert(contentUri, contentValues);

的 uri