使用 Android FileProvider 将照片和视频保存到图库 [英] Saving photos and videos using Android FileProvider to the gallery

查看:102
本文介绍了使用 Android FileProvider 将照片和视频保存到图库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序(使用 SDK 小于 24)可以使用相机拍摄照片和视频.照片和视频可以在应用程序外的图库中查看.SDK 24 及更高版本需要 FileProvider 创建用于将照片或视频保存到图库的 uri.

My application (using SDK less than 24) can take photos and video using the camera. The photos and videos can be viewed in the gallery outside the app. SDK 24 and above requires FileProvider to create the uri for saving the photo or video to the gallery.

在 SDK 24 之前,我会使用 uri 和意图来拍照:

Prior to SDK 24 I would use a uri and an intent to take a photo:

private void openCameraForResult(int requestCode){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    picturesDirectoryPhotoFileName = nextFileName();
    File photoFile = makePicturesPhotoFile();
    Uri uri = Uri.fromFile(photoFile);
    intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(intent, requestCode);
}

private File makePicturesPhotoFile() {
    File photoGallery = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    File media = new File(photoGallery, picturesDirectoryPhotoFileName);

    return media;
}

使用 SDK 24 及更高版本时发生异常:

Using SDK 24 and higher an exception occurs:

Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/126cfd69-59c6-4534-9b2e-4af9753d3643.jpg exposed beyond app through ClipData.Item.getUri()

我想使用 FileProvider 实现相同的(无一例外).下面的实现可以拍照,但它不会出现在图库中.我想知道我做错了什么.

I want to achieve the same (without the exception) using FileProvider. The implementation below can take a photo but the it does not appear in the gallery. I want to know what I am doing wrong.

AndroidManifest.xml:

AndroidManifest.xml:

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>

provider_paths.xml

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="Pictures" path="Pictures"/>
    <external-path name="Movies" path="Movies"/>
</paths>

拍照:

private void openCameraForResult(int requestCode){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    picturesDirectoryPhotoFileName = nextFileName();
    File photoFile = makePicturesPhotoFile();
    getDependencyService().getLogger().debug(photoFile.getAbsolutePath());
    Uri uri = fileProviderUri.makeUriUsingSdkVersion(photoFile);
    intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(intent, requestCode);
}

制作 Uri

private static final String AUTHORITY_FORMAT = "%s.fileprovider";

public  Uri makeUriUsingSdkVersion(File file) {
    Uri uri;

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
        uri = Uri.fromFile(file);
    } else {
        String packageName = getApplicationContext().getPackageName();
        String authority = String.format(Locale.getDefault(), AUTHORITY_FORMAT, packageName);
        uri = getUriForFile(getApplicationContext(), authority, file);
    }

    return uri;
}

推荐答案

这张照片出现在 GT-I9300 Galaxy S3 的图库中,所以我知道代码在该设备上有效.在 Galaxy 7 上,照片只有在手机开机和关机后才会出现在图库中.

The photo appears in the gallery on a GT-I9300 Galaxy S3 so I know the code works on that device. On a Galaxy 7 the photo does not appear in the gallery until the phone is switched on and off.

经过多天的研究,答案是使用对文件的媒体扫描来更新图库.在 PICTURES 目录中创建照片是不够的.这是一个扫描单个文件的类:

After many days of research, the answer is to update the gallery using a media scan on the file. Creating a photo in the PICTURES directory is not enough. Here is a class that scans a single file:

import android.app.Activity;
import android.media.MediaScannerConnection;
import android.net.Uri;

import java.io.File;

class Gallery implements IGallery {

    private Activity activity;

    public Gallery(Activity activity) {
        this.activity = activity;
    }

    @Override
    public void scanFile(File file) {
        if(activity == null || file == null) {
            return;
        }

        MediaScannerConnection.scanFile(activity,
                new String[] { file.getAbsolutePath() }, null,
                new MediaScannerConnection.OnScanCompletedListener() {
                    public void onScanCompleted(String path, Uri uri) {
                    }
                });
    }

}

这篇关于使用 Android FileProvider 将照片和视频保存到图库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆