【问题标题】:Saving photos and videos using Android FileProvider to the gallery使用 Android FileProvider 将照片和视频保存到图库
【发布时间】:2017-04-06 06:46:12
【问题描述】:

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

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

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 及更高版本时发生异常:

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

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

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

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

制作乌里

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

【问题讨论】:

  • The implementation below can take a photo but the it does not appear in the gallery. 上面的旧实现可以拍照但它也不会出现在图库中。

标签: android security sdk


【解决方案1】:

该照片出现在 GT-I9300 Galaxy S3 的图库中,因此我知道该代码适用于该设备。在 Galaxy 7 上,只有在手机打开和关闭后,照片才会出现在图库中。

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

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

}

【讨论】:

    猜你喜欢
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多