Android进阶之路 - 拍照与相册选图

老夫逛遍数10篇blog,写了百行code,解了数千问题,万望一篇足以解决所有问题 !~ !

基于6.0动态权限的图片选取方式,包含拍照与相册,根据此文快速实现相关功能!

如果你的项目要适用于6.0,7.0版本的系统的话,就需要兼容6.0的动态权限,7.0的数据保护!

最终效果图:
这里写图片描述

操作步骤

步骤1 :AndroidMainfest

   <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.yongliu.takephoto.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
    </provider>
  • android:name
    建议统一设置为”android.support.v4.content.FileProvider”
  • android:authorities
    表示授权列表,当有多个授权时,用分号隔开。名字填写你的应用包名
  • android:exported
    表示该内容提供器(ContentProvider)是否能被第三方程序组件使用。一般填false,为 true则会报安全异常
  • android:grantUriPermissions
    这个是为是否对ContentProvider中的内容无访问权限的用户提供临时权限。true,表示授予URI 临时访问权限,false表示不授予

  • < meta-data > 指定私有文件的路径
    name:可统一设置为”android.support.FILE_PROVIDER_PATHS”
    android:resource:资源文件的路径名称可自行取名创建

步骤2 :res - 创建xml文件夹 - 创建file_paths(需要和之前清单文件中的名称一致)
这里写图片描述

file_paths:

  • 万能方式
//可统一设置path为null,默认放在sd卡最外层空间内
<external-path name="files_root" path=""/>
  • 正确方式
<?xml version="1.0" encoding="utf-8"?>
<paths>
<-- PS: path的地址需要与拍照时候存储照片的地址一致,不然会报出参数异常!!!-->
    <external-path
        name="files_root"
        path="pictures"/>
</paths>

拍照存储地址
这里写图片描述

  • 万能方式再走一波 - 。-
<?xml version="1.0" encoding="utf-8"?>
<paths>
<-- PS: name随便起,能识别就好;path表示要共享文件的路径"."表示所有路径 -->
    <external-path path="." name="external_storage_root" />
</paths>
  • external-path 表示用来指定共享路径的
  • name 随便取,只是一个标签,买个关子,下面会解释
  • path 这个比较重要,如果不设置,则表示将整个 SD 卡进行共享,然后制定了,比如 path=”Pictrues”那么,就只共享 sd卡- 下的 Pictures 文件夹
  • file-path 物理路径为Context.getFilesDir() + /files/*
  • cache-path 物理路径为Context.getCacheDir() + /files/*
  • external-path 物理路径为Environment.getExternalStorageDirectory() + /files/*
  • external-files-path 物理路径为Context.getExternalFilesDir(String) + /files/*
  • external-cache-path 物理路径为Context.getExternalCacheDir() + /files/*

步骤3 :AndroidMainfest 添加权限

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

步骤4:使用BottomSheetDialog弹出相机,相册选取框(先把布局copy到layout下,待会儿用)

  • Effect
    这里写图片描述

  • bsd_new_order:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:id="@+id/tv_take_photo"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="拍照"
        android:textColor="#2981DD"
        android:textSize="14sp"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#E4E4E4"/>

    <TextView
        android:id="@+id/tv_select_gallery"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="相册"
        android:textColor="#2981DD"
        android:textSize="14sp"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#E4E4E4"/>


    <TextView
        android:id="@+id/tv_cancel"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="取消"
        android:textColor="#363636"
        android:textSize="14sp"/>

</LinearLayout>

步骤5:因为demo是我从当前项目中找出来的,我们的请求都写在base中,调用比较方便,不过当前为了方便理解,我全部写在了一个类中~(如不想看此步骤,这直接跳到步骤6看全文)

  • 创建接口

    /**
     * 读写SD卡权限申请后回调
     **/
    public interface OnCheckStoragePermission {
        /**
         * @param haspermission true 允许  false 拒绝
         **/
        void onCheckStoragePression(boolean haspermission);
    }

    /**
     * 拍照权限申请后回调
     **/
    public interface OnCheckCameraPermission {
        /**
         * @param haspermission true 允许  false 拒绝
         **/
        void onCheckCameraPression(boolean haspermission);
    }
  • 权限判断
    /**
     * android6.0动态权限申请:SD卡读写权限
     **/
    public void checkStoragePression(OnCheckStoragePermission callback) {
        mOnCheckStoragePermission = callback;
        if (Build.VERSION.SDK_INT >= 23) {
            int checkCamerapression = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (checkCamerapression != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS}, PERMISSIONS_WRITE_STORAGE);
                return;
            }
            mOnCheckStoragePermission.onCheckStoragePression(true);
            return;
        }
        mOnCheckStoragePermission.onCheckStoragePression(true);
    }

    /**
     * android6.0动态权限申请:相机使用权限
     **/
    public void checkCameraPression(OnCheckCameraPermission callback) {
        mOnCheckCameraPermission = callback;
        if (Build.VERSION.SDK_INT >= 23) {
            int checkCamerapression = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
            if (checkCamerapression != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSIONS_CAMERA);
                return;
            }
            mOnCheckCameraPermission.onCheckCameraPression(true);
            return;
        }
        mOnCheckCameraPermission.onCheckCameraPression(true);
    }
  • 权限申请
    /**
     * 权限申请
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean permit = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        switch (requestCode) {
            case PERMISSIONS_CAMERA:
                if (mOnCheckCameraPermission != null) {
                    mOnCheckCameraPermission.onCheckCameraPression(permit);
                }
                break;
            case PERMISSIONS_WRITE_STORAGE:
                if (mOnCheckStoragePermission != null) {
                    mOnCheckStoragePermission.onCheckStoragePression(permit);
                }
                break;
            default:
                break;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
  • 调用方式
        //随意的一个点击事件既可
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkCameraPression(new OnCheckCameraPermission() {
                    @Override
                    public void onCheckCameraPression(boolean haspermission) {
                        if (haspermission) {
                            checkStoragePression(new OnCheckStoragePermission() {
                                @Override
                                public void onCheckStoragePression(boolean hasStorePermission) {
                                    if (hasStorePermission) {
                                        //相机、相册弹框
                                        showBottomDialog();
                                    }
                                }
                            });
                        }
                    }
                });
            }
        });
    }

步骤6 :全文预览 > <(差不多可以copy搞定,附带demo地址

Mainactivity :

package com.example.yongliu.takephoto;

import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetDialog;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {
    protected OnCheckCameraPermission mOnCheckCameraPermission;
    private OnCheckStoragePermission mOnCheckStoragePermission;
    private File sdcardTempFile;
    private TextView mBtn;
    private ImageView mImg;
    protected final int PERMISSIONS_WRITE_STORAGE = 1;
    public final int PERMISSIONS_CAMERA = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBtn = findViewById(R.id.btn);
        mImg = findViewById(R.id.img);

        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkCameraPression(new OnCheckCameraPermission() {
                    @Override
                    public void onCheckCameraPression(boolean haspermission) {
                        if (haspermission) {
                            checkStoragePression(new OnCheckStoragePermission() {
                                @Override
                                public void onCheckStoragePression(boolean hasStorePermission) {
                                    if (hasStorePermission) {
                                        showBottomDialog();
                                    }
                                }
                            });
                        }
                    }
                });
            }
        });
    }

    /**
     * 显示拍照/从相册选取的底部对话框
     */
    public void showBottomDialog() {
        final BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
        View dialogView = LayoutInflater.from(this).inflate(R.layout.bsd_new_order, null);
        dialogView.findViewById(R.id.tv_take_photo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bottomSheetDialog != null) {
                    bottomSheetDialog.dismiss();
                }
                takePhoto();
            }
        });
        dialogView.findViewById(R.id.tv_select_gallery).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bottomSheetDialog != null) {
                    bottomSheetDialog.dismiss();
                }
                selectFromGallery();
            }
        });
        dialogView.findViewById(R.id.tv_cancel).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (bottomSheetDialog != null) {
                    bottomSheetDialog.dismiss();
                }
            }
        });
        bottomSheetDialog.setContentView(dialogView);
        bottomSheetDialog.show();
    }

    /**
     * 拍照
     */
    private void takePhoto() {
        String path = Environment.getExternalStorageDirectory().getPath() + "/myPhoto" + SystemClock.currentThreadTimeMillis() + ".jpg";
        //         String path1 = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + DeviceUtils.getPackageName(GarageApp.getAppContext()) + "/img_dow_"+SystemClock.currentThreadTimeMillis() + ".jpg";
        sdcardTempFile = new File(path);
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(MainActivity.this, "com.example.yongliu.takephoto.fileprovider", sdcardTempFile));
        } else {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(sdcardTempFile));
        }
        startActivityForResult(intent, 101);

    }

    /**
     * 从相册选取照片
     */
    private void selectFromGallery() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, 102);
    }

    /**
     * android6.0动态权限申请:SD卡读写权限
     **/
    public void checkStoragePression(OnCheckStoragePermission callback) {
        mOnCheckStoragePermission = callback;
        if (Build.VERSION.SDK_INT >= 23) {
            int checkCamerapression = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (checkCamerapression != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS}, PERMISSIONS_WRITE_STORAGE);
                return;
            }
            mOnCheckStoragePermission.onCheckStoragePression(true);
            return;
        }
        mOnCheckStoragePermission.onCheckStoragePression(true);
    }

    /**
     * android6.0动态权限申请:相机使用权限
     **/
    public void checkCameraPression(OnCheckCameraPermission callback) {
        mOnCheckCameraPermission = callback;
        if (Build.VERSION.SDK_INT >= 23) {
            int checkCamerapression = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
            if (checkCamerapression != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSIONS_CAMERA);
                return;
            }
            mOnCheckCameraPermission.onCheckCameraPression(true);
            return;
        }
        mOnCheckCameraPermission.onCheckCameraPression(true);
    }

    /**
     * 权限申请
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean permit = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        switch (requestCode) {
            case PERMISSIONS_CAMERA:
                if (mOnCheckCameraPermission != null) {
                    mOnCheckCameraPermission.onCheckCameraPression(permit);
                }
                break;
            case PERMISSIONS_WRITE_STORAGE:
                if (mOnCheckStoragePermission != null) {
                    mOnCheckStoragePermission.onCheckStoragePression(permit);
                }
                break;
            default:
                break;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    /**
     * Uri 转 绝对路径
     */
    public static String getFilePathFromContentUri(Uri selectedVideoUri, ContentResolver contentResolver) {
        String filePath;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA};
        Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
        //也可用下面的方法拿到cursor
        //Cursor  cursor  =  this.context.managedQuery(selectedVideoUri,  filePathColumn,  null,  null,  null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }

    /**
     * 读写SD卡权限申请后回调
     **/
    public interface OnCheckStoragePermission {
        /**
         * @param haspermission true 允许  false 拒绝
         **/
        void onCheckStoragePression(boolean haspermission);
    }

    /**
     * 拍照权限申请后回调
     **/
    public interface OnCheckCameraPermission {
        /**
         * @param haspermission true 允许  false 拒绝
         **/
        void onCheckCameraPression(boolean haspermission);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            /**
             * 根据路径获取数据
             * */
            case 101:
                if (resultCode == RESULT_OK && sdcardTempFile.exists()) {
                    try {
                        //如果需要上传照片到服务器,上传方法写这里既可
                        FileInputStream inputStream = new FileInputStream(sdcardTempFile);
                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        mImg.setImageBitmap(bitmap);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            case 102:
                ContentResolver contentResolver = getContentResolver();
                if (data != null) {
                    //如果需要把选取的图片进行上传服务器,请把下面代码注释解开,因为这样 才能获取到文件URI转的文件路径~方便上传的时候使用
                    //Uri uri = data.getData();
                    //使用工具类获取绝对路径
                    //String path = getFilePathFromContentUri(uri, contentResolver);
                    //File sdcardTempFile = new File(path);
                    //if (resultCode == RESULT_OK && sdcardTempFile.exists()) {
                    if (resultCode == RESULT_OK) {
                        //显示在我们UI上
                        Bitmap bitmap = null;
                        try {
                            //如果需要上传照片到服务器,上传方法写这里既可
                            bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(data.getData()));
                            mImg.setImageBitmap(bitmap);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
                break;
            default:
                break;
        }
    }
}

MainActivity Xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.yongliu.takephoto.MainActivity">

    <TextView
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="获取照片"
        />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#363636"
        />

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        />
</LinearLayout>

问题解决:

  • 出现只要有关 permisssion字段的错误,很可能就是权限问题了

    根据上面的步骤3 加入对应的权限吧,宁多勿少!宁可杀错不可放过 = = !

  • 出现 FileUriExposedException 异常

    用FileProvider来解决这一问题,配置方式在文章上方

  • 回传图片用于ImageView展示时,无法充满屏幕

 //为用于展示的ImageView添加scaleType属性
 android:scaleType="centerCrop"

scaleType属性:

center  按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
centerCrop  按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
centerInside  将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
fitCenter  把图片按比例扩大/缩小到View的宽度,居中显示
fitEnd   把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
fitStart  把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
fitXY  把图片不按比例扩大/缩小到View的大小显示
matrix 用矩阵来绘制,动态缩小放大图片来显示
  • 每次点击只调用一次权限申请,如第一次点击申请相机权限,第二次点击申请文件存储权限,第三次点击触发相机,相册选取框

    好好看看是不是有忘记重写 onRequestPermissionsResult 方法啦!

  • 图片裁剪

方式一

public void cropRawPhoto(Uri uri) {

    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/*");
    intent.putExtra("crop", "true");
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);

    intent.putExtra("outputX", output_X);
    intent.putExtra("outputY", output_Y);
    intent.putExtra("return-data", true);

    startActivityForResult(intent, CODE_RESULT_REQUEST);
}

在拍照完成后调用裁剪时

cropRawPhoto(FileProvider.getUriForFile(mActivity, BuildConfig.APPLICATION_ID +
        ".provider", mCurrentFile));

相册选图调用裁剪

cropRawPhoto(data.getData());

方式二:

相机裁剪

 /**
     * 拍照之后,启动裁剪
     * @param camerapath 路径
     * @param imgname img 的名字
     * @return
     */
    @NonNull
    private Intent CutForCamera(String camerapath,String imgname) {
        try {

            //设置裁剪之后的图片路径文件
            File cutfile = new File(Environment.getExternalStorageDirectory().getPath(),
                    "cutcamera.png"); //随便命名一个
            if (cutfile.exists()){ //如果已经存在,则先删除,这里应该是上传到服务器,然后再删除本地的,没服务器,只能这样了
                cutfile.delete();
            }
            cutfile.createNewFile();
            //初始化 uri
            Uri imageUri = null; //返回来的 uri
            Uri outputUri = null; //真实的 uri
            Intent intent = new Intent("com.android.camera.action.CROP");
            //拍照留下的图片
            File camerafile = new File(camerapath,imgname);
            if (Build.VERSION.SDK_INT >= 24) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                imageUri = FileProvider.getUriForFile(mActivity,
                        "com.rachel.studyapp.fileprovider",
                        camerafile);
            } else {
                imageUri = Uri.fromFile(camerafile);
            }
            outputUri = Uri.fromFile(cutfile);
            //把这个 uri 提供出去,就可以解析成 bitmap了
            mCutUri = outputUri;
            // crop为true是设置在开启的intent中设置显示的view可以剪裁
            intent.putExtra("crop",true);
            // aspectX,aspectY 是宽高的比例,这里设置正方形
            intent.putExtra("aspectX",1);
            intent.putExtra("aspectY",1);
            //设置要裁剪的宽高
            intent.putExtra("outputX", ToolUtils.dip2px(mActivity,200));
            intent.putExtra("outputY",ToolUtils.dip2px(mActivity,200));
            intent.putExtra("scale",true);
            //如果图片过大,会导致oom,这里设置为false
            intent.putExtra("return-data",false);
            if (imageUri != null) {
                intent.setDataAndType(imageUri, "image/*");
            }
            if (outputUri != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
            }
            intent.putExtra("noFaceDetection", true);
            //压缩图片
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            return intent;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

相册裁剪

/**
     * 图片裁剪
     * @param uri
     * @return
     */
    @NonNull
    private Intent CutForPhoto(Uri uri) {
        try {
            //直接裁剪
            Intent intent = new Intent("com.android.camera.action.CROP");
            //设置裁剪之后的图片路径文件
            File cutfile = new File(Environment.getExternalStorageDirectory().getPath(),
                    "cutcamera.png"); //随便命名一个
            if (cutfile.exists()){ //如果已经存在,则先删除,这里应该是上传到服务器,然后再删除本地的,没服务器,只能这样了
                cutfile.delete();
            }
            cutfile.createNewFile();
            //初始化 uri
            Uri imageUri = uri; //返回来的 uri
            Uri outputUri = null; //真实的 uri
            Log.d(TAG, "CutForPhoto: "+cutfile);
            outputUri = Uri.fromFile(cutfile);
            mCutUri = outputUri;
            Log.d(TAG, "mCameraUri: "+mCutUri);
            // crop为true是设置在开启的intent中设置显示的view可以剪裁
            intent.putExtra("crop",true);
            // aspectX,aspectY 是宽高的比例,这里设置正方形
            intent.putExtra("aspectX",1);
            intent.putExtra("aspectY",1);
            //设置要裁剪的宽高
            intent.putExtra("outputX", ToolUtils.dip2px(mActivity,200)); //200dp
            intent.putExtra("outputY",ToolUtils.dip2px(mActivity,200));
            intent.putExtra("scale",true);
            //如果图片过大,会导致oom,这里设置为false
            intent.putExtra("return-data",false);
            if (imageUri != null) {
                intent.setDataAndType(imageUri, "image/*");
            }
            if (outputUri != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
            }
            intent.putExtra("noFaceDetection", true);
            //压缩图片
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            return intent;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

说了这么多,还有一个大家比较关心的问题就是:哪些已经上线的旧版本应用没有做 7.0 适配工作怎么办?关于这个问题,Google 已经提前帮我们想好解决方案啦。

还记得 6.0 运行时权限问题吗?如果你不想处理运行时权限事宜的话,只需要在 build.gradle 文件中将 targetSdkVersion 的值设为 23 以下即可。

同样的,只要 targetSdkVersion 值小于 24,File URI 的使用依旧可以出现在 7.0 及以上版本的设备中。不过需要注意的是,如前面所述,调用系统裁剪功能比较特殊,可能会出现一些问题。

虽然 Google 在每次发布新版 Android 系统时,都提供这种设置 targetSdkVersion 的方式兼容旧版本,但只是一种临时解决方案,并不推荐大家使用这种技巧绕开新版本的适配问题。要知道,新出现的 API 改变一定是在解决过去存在的系统问题,是一种进步的表现。遵循规范,是我们每个开发人员开发时都应铭记于心的格言。

扩展文章:

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/80687916