Android 7.0 以后禁止向外公开fille://URL,因此需要使用FileProvider 向外传递URL.
FileProvider
1. 简介
- 官方文档
https://developer.android.com/reference/android/support/v4/content/FileProvider - FileProvider实际上是ContentProvider的一个子类,它的作用也比较明显了,file:///Uri不给用,那么换个Uri为content://来替代
2. 使用步骤
- 在manifest 中声明provider
<provider
android:authorities="${packagename}.provider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider" />
</provider>
authorities:字段的值用来表明使用的使用者,在FileProvider的函数getUriForFile需要传入该参数。此值需要是唯一值,如果做sdk开发需要注意
name: 一般都固定为android.support.v4.content.FileProvider。如果开发者继承了FileProvider,则可以写上其绝对路径
exported:的值为false,表示该FileProvider只能本应用使用,不是public的
grantUriPermissions :值为true,表示允许赋予临时权限
meta-data:配置的是我们可以访问的文件的路径配置信息,需要使用xml文件进行配置,FileProvider会通过解析xml文件获取配置项,其中name名字不可改变为:{android.support.FILE_PROVIDER_PATHS},resource为配置路径信息的配置项目
- 编辑xml 文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<!--<root-path/> 代表设备的根目录new File("/");-->
<root-path
name = ""
path=""/>
<!-- Context.getFilesDir() + "/path/" -->
<files-path
name="my_files"
path="mazaiting/"/>
<!-- Context.getCacheDir() + "/path/" -->
<cache-path
name="my_cache"
path="mazaiting/"/>
<!-- Context.getExternalFilesDir(null) + "/path/" -->
<external-files-path
name="external-files-path"
path="mazaiting/"/>
<!-- Context.getExternalCacheDir() + "/path/" -->
<external-cache-path
name="name"
path="mazaiting/" />
<!-- Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="my_external_path"
path="mazaiting/"/>
<!-- Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="files_root"
path="Android/data/<包名>/"/>
<!-- path设置为'.'时代表整个存储卡 Environment.getExternalStorageDirectory() + "/path/" -->
<external-path
name="external_storage_root"
path="."/>
</paths>
</resources>
- 在java 文件中的使用
FileProvider.getUriForFile(context,"${authorities}",file);
完成了以上3步就可以在android 7.0 进行相机的拍照剪裁适配了
android 7.0 相机适配
1. 拍照适配
- 根据系统获取uri
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mOriPicUri = FileProvider.getUriForFile(context.getApplicationContext(),"com.letv.leeco.myapplication" +
".provider",mOriPicFile);
}else {
mOriPicUri = Uri.fromFile(mOriPicFile);
}
- 打开相机拍照(这个与我们平时的操作没有不同)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUtil.mOriPicUri);
startActivityForResult(intent, REQUEST_CODE_CAPTURE_CAMERA);
2. 照片剪裁适配
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");// mUri是已经选择的图片Uri
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);// 裁剪框比例
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 150);// 输出图片大小
intent.putExtra("outputY", 150);
intent.putExtra("return-data", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mFileUtil.mCropPicFile));
startActivityForResult(intent, REQUEST_CODE_CROP);
3.剪裁后处理适配
mBitmap = data.getParcelableExtra("data");
if (mBitmap!=null && mBitmap.getByteCount()>0){
// 有些机型需要从返回值中拿到数据进行保存,否则无法直接从申请剪裁的uri中读取到数据
mFileUtil.savePic(mBitmap,mFileUtil.mCropPicFile);
mPic.setImageBitmap(mBitmap);
}else {
try{
Uri uri = Uri.fromFile(mFileUtil.mCropPicFile);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),uri);
mPic.setImageBitmap(bitmap);
}catch (Exception e){
Log.i(TAG, "onActivityResult: e = "+e.getMessage());
}
}
网友评论