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包

扫描二维码关注公众号,回复: 6030654 查看本文章
    /**
     * @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 FileProvider的使用

Android 7.0 行为变更 通过FileProvider在应用间共享文件吧

记 Android 7.0 8.0版本更新安装遇到的坑

猜你喜欢

转载自blog.csdn.net/lizhongyisailang/article/details/81257703