Доступ к файлу и общий доступ к нему в папке «Изображение» во внутренней / внешней памяти Android Q - PullRequest
0 голосов
/ 02 апреля 2020

Многие критические изменения происходят в 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.

. Я хочу сохранить их, как большинство приложений, в папке «Изображения» по умолчанию в root /storage/emulated/0/Pictures, чтобы изображение было Gallery .

. Для этого я изменяю приведенный выше фрагмент кода на этот.

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

Также работал, но не смог прикрепить / поделиться изображением с другим приложением, таким как 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>

Это мой фрагмент для намеренного обмена.

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

1 Ответ

0 голосов
/ 02 апреля 2020

Кажется, что вы все еще можете получить доступ к файлу без необходимости FileProvider.getUriForFile(context, authority, file); в Android Q, просто передав URI из resolver.insert(contentUri, contentValues);

...