一、引入
Android在7.0中修改了文件权限,所以从Android7.0开始要使用FileProvider来处理uri,从网上找了好多文章,解决了在7.0下拍照及相册选图的问题,但是参照网上的解决方案前切图片一直搞不定,最终使用了UCrop进行剪切图片并返回文件地址,便于与服务器交互。
本文主要介绍在Android7.0上进行拍照,相册选图以及相应的图片剪切,当然也会向下兼容,同时我也在Android4.3的手机上进行了测试,在文章最后我会附上源码,会有我自认为详细的注释哈哈。
二、拍照及相册
- FileProvider
想必FileProvider大家都很熟悉了,但是想了一下感觉还是写一下比较好。
- 在manifest中配置
<application... ...<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.sdwfqin.sample.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths_public"/></provider></application>
- 在 res 目录下新建文件夹 xml 然后创建资源文件 file_paths_public(名字随意,但是要和manifest中的名字匹配)
<?xml version="1.0" encoding="utf-8"?><paths><!--照片--><external-pathname="my_images"path="Pictures"/><!--下载--><paths><external-pathname="download"path=""/></paths></paths>
- 调用相机拍照
// 全局变量public static final int RESULT_CODE_1 = 201;// 7.0 以上的uriprivate Uri mProviderUri;// 7.0 以下的uriprivate Uri mUri;// 图片路径private String mFilepath = SDCardUtils.getSDCardPath() + "AndroidSamples";-----------/*** 拍照*/private void camera() {File file = new File(mFilepath, System.currentTimeMillis() + ".jpg");if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// Android7.0以上URIif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//通过FileProvider创建一个content类型的UrimProviderUri = FileProvider.getUriForFile(this, "com.sdwfqin.sample.fileprovider", file);intent.putExtra(MediaStore.EXTRA_OUTPUT, mProviderUri);//添加这一句表示对目标应用临时授权该Uri所代表的文件intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);} else {mUri = Uri.fromFile(file);intent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);}try {startActivityForResult(intent, RESULT_CODE_1);} catch (ActivityNotFoundException anf) {ToastUtils.showShort("摄像头未准备好!");}}
- 相册选图
// 全局变量public static final int RESULT_CODE_2 = 202;----------private void selectImg() {Intent pickIntent = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");startActivityForResult(pickIntent, RESULT_CODE_2);}
- onActivityResult
需要注意的是拍照没有返回数据,用之前的uri就可以,从相册查找图片会返回uri
case RESULT_CODE_1:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// 调用裁剪方法cropRawPhoto(mProviderUri);} else {cropRawPhoto(mUri);}break;case RESULT_CODE_2:Log.i(TAG, "onActivityResult: " + data.getData());cropRawPhoto(data.getData());break;
三、图片剪裁(重点)
因为用原生的一直是各种报错,所以我这里用的是UCrop,大家可能都见过官方的展示图,界面可能在有些需求下显得过于复杂,但是真正使用起来感觉有很多都是可以修改的哈哈哈!推荐大家看一下官方的例子。项目地址:https://github.com/Yalantis/uCrop
简单说一下引入方法但是并不能保证是最新的
- 依赖
compile 'com.github.yalantis:ucrop:2.2.1'
- 在AndroidManifest中添加Activity
<activityandroid:name="com.yalantis.ucrop.UCropActivity"android:screenOrientation="portrait"android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
- 剪切图片
public void cropRawPhoto(Uri uri) {// 修改配置参数(我这里只是列出了部分配置,并不是全部)UCrop.Options options = new UCrop.Options();// 修改标题栏颜色options.setToolbarColor(getResources().getColor(R.color.colorPrimary));// 修改状态栏颜色options.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));// 隐藏底部工具options.setHideBottomControls(true);// 图片格式options.setCompressionFormat(Bitmap.CompressFormat.JPEG);// 设置图片压缩质量options.setCompressionQuality(100);// 是否让用户调整范围(默认false),如果开启,可能会造成剪切的图片的长宽比不是设定的// 如果不开启,用户不能拖动选框,只能缩放图片options.setFreeStyleCropEnabled(true);// 设置源uri及目标uriUCrop.of(uri, Uri.fromFile(new File(mFilepath, System.currentTimeMillis() + ".jpg")))// 长宽比.withAspectRatio(1, 1)// 图片大小.withMaxResultSize(200, 200)// 配置参数.withOptions(options).start(this);}
- 剪切完图片的回掉
if (resultCode == UCrop.RESULT_ERROR){mCameraTv.setText(UCrop.getError(data) + "");showMsg("图片剪裁失败");return;}if (resultCode == RESULT_OK) {switch (requestCode) {case UCrop.REQUEST_CROP:// 成功(返回的是文件地址)Log.i(TAG, "onActivityResult: " + UCrop.getOutput(data));mCameraTv.setText(UCrop.getOutput(data) + "");// 使用Glide显示图片Glide.with(this).load(UCrop.getOutput(data)).crossFade().into(mCameraImg);break;}}
- 完整的onActivityResult,包含拍照的回掉
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == UCrop.RESULT_ERROR){mCameraTv.setText(UCrop.getError(data) + "");showMsg("图片剪裁失败");return;}if (resultCode == RESULT_OK) {switch (requestCode) {case RESULT_CODE_1:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {cropRawPhoto(mProviderUri);} else {cropRawPhoto(mUri);}break;case RESULT_CODE_2:Log.i(TAG, "onActivityResult: " + data.getData());cropRawPhoto(data.getData());break;case UCrop.REQUEST_CROP:Log.i(TAG, "onActivityResult: " + UCrop.getOutput(data));mCameraTv.setText(UCrop.getOutput(data) + "");Glide.with(this).load(UCrop.getOutput(data)).crossFade().into(mCameraImg);break;}}}
