Android FileProvider使用笔记

在Android 7.0以后使用相册或者需要存储oss上下载下来的apk之类需要将文件存储到App外部存储的时候可能会报android.os.FileUriExposedException的错误,原因是在Android7.0以后Google加强了StrictMode的审查,以往可以通过file://uri访问文件的方式现在也被禁用了。FileProvider的使用如下所示。
第一步在清单文件(AndroidManifest.xml)中注册FileProvider。

<application
	android:icon=""
	.......
	>
		<provider
			//name对应FileProvider类名
            android:name="android.support.v4.content.FileProvider"
            //authorities需要与FileProvider.getUriForFile()方法中的authority保持一致
            android:authorities="${applicationId}.provider"
            android:exported="false"
            //允许临时开启文件访问权限
            android:grantUriPermissions="true">
            <meta-data
            	//name对应属性是一个固定的常量,填写下面这个就行
                android:name="android.support.FILE_PROVIDER_PATHS"
                //资源文件指向xml文件夹中的file_provider.xml文件
                android:resource="@xml/file_provider" />
        </provider>
        .......
        </application>

在res文件夹内创建xml文件夹,xml文件夹内创建file_provider.xml,file_provider.xml的内容如下。

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="abcd" path="efgh" />
</paths>

Path标签内设置对应的文件夹目录标签

files-path 对应 /data/data/<包名>/files
cache-path 对应 /data/data/<包名>/cache
external-path 对应 /storage/emulate/0
external-files-path 对应 /storage/emulate/0/Android/data/<包名>/files
external-cache-path 对应 /storage/emulate/0/Android/data/<包名>/cache
例如 <external-files-path name=“abcd” path=“efgh” />

path属性代表文件需要存储的文件夹,上面这行代码就代表存在某个文件(A.jpg)将A.jpg存储到/storage/emulated/0/Android/data/<包名>/files/efgh文件夹下,前提是FileProvider.getUriForFile()中的authority与清单文件中的authority保持一致。

name代表FileProvider.getUriForFile()获取到的Uri,上面这行代码就代表A.jpg的Uri为content://<authority>/abcd/A.jpg。

使用之前的步骤完成后,接下来在项目中使用。

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = createFile();
Uri photoUri = FileProvider.getUriForFile(this, this.getPackageName() + ".provider", photoFile);
Log.e(TAG, photoUri.toString());
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(takePictureIntent, REQUEST_CODE);

private File createFile() {
	String timeStamp = new SimpleDateFormat("yyyy-MM-dd HHmm", Locale.CHINESE).format(new Date());
	File externalFilesDir = getExternalFilesDir("efgh");
	File image = null;
	try {
		image = File.createTempFile(timeStamp, ".jpg", externalFilesDir);
		mCurrentPhotoPath = image.getAbsolutePath();
		Log.e(TAG, mCurrentPhotoPath);
	} catch (IOException e) {
        e.printStackTrace();
    }
    return image;
    }

调用相机拍照将照片存入我们设置的efgh文件夹中
打印Log如下。

//图片绝对路径
E/MainActivity: /storage/emulated/0/Android/data/com.rick.flieproviderdemo/files/efgh/2019-08-07 17216833243804914530274.jpg
//图片uri
E/MainActivity: content://com.rick.flieproviderdemo.provider/abcd/2019-08-07%2017216833243804914530274.jpg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值