Android 7.0 之 FileProvider运用:拍照获取头像并设置

    FileProvider 是android 7.0 之后才有的一个东西,其目的也是加强管理碎片化严重的android文件夹,避免其内的应用随意使用手机的内存。

    使用一个例子来具体实操一下,拍照获取图片,并设置到ImageView中:

    把大象放到冰箱需要几个步骤?

    步骤一:打开相机:

// 相机
public static final int CAMERA_REQUEST_CODE = 1004;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_ss");
private File tempFile; // 中转的文件
private Uri mImgUri;


/**
     * 开启相机
     * @param activity
     */
    public void toCamera(Activity activity) {
        Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        String fileName = simpleDateFormat.format(new Date());
        tempFile = new File(Environment.getExternalStorageDirectory(), fileName + ".jpg");

        // 7.0 以下
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            mImgUri = Uri.fromFile(tempFile);
        } else {
            // 7.0 利用FileProvider
            String authority = activity.getPackageName() + ".fileprovider"; // 需要在配置文件中配置
            mImgUri = FileProvider.getUriForFile(activity, authority, tempFile);
            // 添加权限

            i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }

        LogUtils.i("toCamera mImgUri = " + mImgUri);

        i.putExtra(MediaStore.EXTRA_OUTPUT, mImgUri);

        activity.startActivityForResult(i, CAMERA_REQUEST_CODE);
    }

    步骤二:设置拍摄图片的回调:

    private File uploadFile = null;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        LogUtils.i("onActivityResult requestCode = " + requestCode);

        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == CAMERA_REQUEST_CODE) {
                uploadFile = FileHelper.getInstance().getTempFile();
            }
        }

        // 设置头像
        if (uploadFile != null) {
            Bitmap bitmap = BitmapFactory.decodeFile(uploadFile.getPath());
            iv_photo.setImageBitmap(bitmap);
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    步骤三:设置FileProvider

    小步骤1.设置xml/file_path.xml 文件

Android 7.0 之 FileProvider运用:拍照获取头像并设置

小步骤2.设置AndroidManifest文件

在Application节点中添加

        <!-- 兼容android7.0的Provider -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="{pkgName}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />

        </provider>

其中authorities 就是上面 步骤一 中设置的 authority,包名自己设置好即可。

解释一下其中几个标签:

android:exported="false" //不允许跨进程访问
android:grantUriPermissions="true" // 步骤一种添加的flag的权限

是不是跟把大象放进冰箱的步骤一样多?哈哈哈

过程中遇到的问题:

1. 如果系统拍照的图片过大,那么直接设置进去将发生OOM

解决办法:可以看我之前的博客,进行一下图片压缩

2. URI获取不到真实地址的问题,具体是:头像如果从相册中获取的话,获取到的图片路径并非真实路径,而是如下:

/external/images/media/134216

解决办法:

    1.首先通过 onActivityResult 中拿到系统返回的intent,通过intent.getData(),拿到返回的Uri

    2.处理Uri并返回真实路径:

/storage/emulated/0/MagazineUnlock/magazine-unlock-01-2.3.4332-_035B5B61EAFA5DB2B9982DCA612BA53C.jpg
    /**
     * 根据Uri获取真实的图片地址
     * @param context
     * @param uri
     * @return
     */
    public String getRealImgPathFromUri(Context context, Uri uri) {

        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null);
        Cursor cursor = cursorLoader.loadInBackground();
        int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(columnIndex);
        cursor.close();
        return path;
    }

下面把 跳转相册 的方法,也给大家贴一下:

    // 相册
    public static final int ALBUM_REQUEST_CODE = 1005;
    /**
     * 跳转到相册
     *
     * @param activity
     */
    public void toAlbum(Activity activity) {
        Intent i = new Intent(Intent.ACTION_PICK);
        i.setType("image/*");
        activity.startActivityForResult(i, ALBUM_REQUEST_CODE);
    }

   

遇到问题不要害怕,咱们见招拆招,没有解决不了的问题,如果有,那看看别人有啥好的解决办法没,skr~~

上一篇:面试重点一个不落:FileProvider你了解多少?透过FileProvider来看看四大组件之一ContentProvider!


下一篇:Android App检测新版本,自动下载、安装和升级,兼容Android7.0以上和以下版本