FileProvider进阶知识点,你所不知道的
FileProvider是什么?为什么要用FileProvider?怎么用?网上已经有很多文章了,文章末尾也会推荐给大家比较好的文章。我们说一些网上没有或者很少提到的。
1、流行的FileProvider的写法
例子一:调用相机拍照并进行保存
/**
*
* @param context
* @param saveFile 照片保存路径
* @param authorities 身份认证字符串,用FileProvider生成分享URI的时候使用
*/
private void takeAndSavePhoto(Context context, File saveFile, String authorities) {
if (saveFile != null) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri imageUri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = FileProvider.getUriForFile(context, authorities, saveFile);
} else {
imageUri = Uri.fromFile(saveFile);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
context.startActivity(intent);
}
}
上面的写法是标准的写法,在代码中做了版本判断,如果当前运行的系统版本大于7.0,采用FileProvider的方式分享URI,否则采用之前的方式。简单说明一下为什么要区分版本,虽然说分享文件使用FileProvider方式,在7.0系统上是强制要求的(否则会报错),但是在7.0以下使用FileProvider也是没有问题的,只是在4.4及一下会有问题,这是由于不同系统实现不同导致的。所以为了解决这个问题,就直接以7.0为界限进行了版本区分。那么问题来了,上面这段代码就百分之百没有问题吗?答案是否定的。
请看saveFile参数,这个参数是用来表示照片要保存的地方。我们都知道,对于一个app来说,有三个目录的概念,简单来说:
私有目录 data/data/<包名>/files [及cache] context.getFilesDir() [及context.getCacheDir()]
SD卡公有目录 storage/emulated/0 Enviroment.getExternalStorageDirectory() 这个是SD卡的根目录
SD卡私有目录 storage/emulated/0/Android/data/<包名>/files[及cache] context.getExternalFilesDir()[及context.getExternalCacheDir()]
对于这三个目录都可以用来保存照片吗?不是的。
采用FileProvider的方式,这三个目录都可以,Uri.fromFile的方式,只有SD卡的这两个目录可以,所以大家在使用的时候一定要注意。
例子二:调用系统安装器安装apk包
/**
* @param context
* @param installFile apk包所在路径
* @param authorities
*/
private void installApk(Context context, File installFile, String authorities) {
if (installFile != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri apkUri = FileProvider.getUriForFile(context, authorities, installFile);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
}
}
上面这段代码是安装apk的标准写法,不过这里面有个坑,还是出在路径上,如果apk所在的目录位于SD卡的公共目录里,调起安装器时就会包“解析安装包失败”的错误,不过需要说的一点是如果采用Uri.fromFile的方式,是可以正常安装的。
不过需要注意在android 8.0系统上安装apk时候的权限问题,否则在8.0系统上拉不起安装界面,具体看参考文章
2、上面说的FileProvider用法,都是调用系统相机和安装器。那么,我们自己写两个app,怎么共享数据呢?
比如,我们怎么把上面相机保存的图片(App A),怎么共享给另一个app(B)。
App A
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.lzy.fileproviderclient", "com.lzy.fileproviderclient.MainActivity"));
File imageFile = new File(mContext.getExternalFilesDir(null) + "/image/" + "photo.jpg");
Uri uri = FileProvider.getUriForFile(mContext, "com.lzy.myapplication.fileProvider", imageFile);
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
App B
mImageView = (ImageView) findViewById(R.id.photo_image_view);
if (getIntent() != null) {
Uri uri = getIntent().getData();
if (uri != null) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
mImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
参考:
Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
上一篇: Hibernate的查询方法(2动态参数绑定查询)
下一篇: 多对一关联映射