作者:夏至,欢迎转载,但请保留这段申明,谢谢。
http://blog.csdn.net/u011418943/article/details/77712662

首先,好规则,看看自己的实现效果:

当然,这个github 各种开源库,这里只讲 Android 自带的功能。

其实这个也不难,关键点无非就2个:

  • 7.0 之后相机的 uri 获取
  • 裁剪时的 uri 获取

这里可以放一下底部 popupwindow 的布局,另外可以看我的 popupwindow封装:
拒绝无用功,封装一个通用的 PopupWindow

<?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"android:id="@+id/pop_root_ly"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:orientation="vertical"><android.support.v7.widget.CardView
        android:layout_width="match_parent"android:layout_height="wrap_content"app:cardCornerRadius="5dp"><LinearLayout
            android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextView
                android:id="@+id/pop_pic"android:layout_width="match_parent"android:layout_height="40dp"android:gravity="center"android:text="@string/pic"android:textColor="@color/black"android:textSize="18sp" /><View
                android:layout_width="match_parent"android:layout_height="1dp"android:background="?android:attr/listDivider"android:padding="2dp" /><TextView
                android:id="@+id/pop_camera"android:layout_width="match_parent"android:layout_height="40dp"android:gravity="center"android:text="@string/camera"android:textColor="@color/black"android:textSize="18sp" /></LinearLayout></android.support.v7.widget.CardView><android.support.v7.widget.CardView
        android:layout_width="match_parent"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:layout_height="wrap_content"><TextView
            android:id="@+id/pop_cancel"android:layout_width="match_parent"android:layout_height="40dp"android:gravity="center"android:text="取消"android:textColor="@color/black"android:textSize="18sp" /></android.support.v7.widget.CardView>
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

而头像,我用的时开源框架,circleiamgeview,这个用来处理圆形头像就可以了,这里就不贴出来了,链接如下:

compile 'de.hdodenhof:circleimageview:2.1.0'
  • 1
  • 1

其中点击事件如下:
图片:

/*Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image*//**//*");
startActivityForResult(intent,ToolUtils.SCAN_OPEN_PHONE);*///由于模拟器图库的刷新问题,采用如下打开方式,实际开发请采用上面这种Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intent, ToolUtils.SCAN_OPEN_PHONE);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

相机:

 /*** 打开相册*/private void cameraPic() {//创建一个file,用来存储拍照后的照片File outputfile = new File(mActivity.getExternalCacheDir(),"output.png");try {if (outputfile.exists()){outputfile.delete();//删除}outputfile.createNewFile();} catch (Exception e) {e.printStackTrace();}Uri imageuri ;if (Build.VERSION.SDK_INT >= 24){imageuri = FileProvider.getUriForFile(mActivity,"com.rachel.studyapp.fileprovider", //可以是任意字符串outputfile);}else{imageuri = Uri.fromFile(outputfile);}//启动相机程序Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");intent.putExtra(MediaStore.EXTRA_OUTPUT,imageuri);startActivityForResult(intent,ToolUtils.PHONE_CAMERA);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在拍照这里,7.0 是需要做处理的,google 在7.0 之后,考虑到安全性的问题,用 fileProvider 来封装 uri了,所以,这里我们也处理一下,mCameraUri 是用来保存拍照后,照片的 uri,可以简单理解成该图片的索引。

注意!!!如果是6.0的手机,请添加权限申请,我这里已经封装好,就不贴出来干扰大家了。

既然上面填写了 fileprovider 了,那么用过content provider的都知道,我们得配置 provider 属性了,如下,在你的 Androidmanifest.xml 下添加:

<provider
            android:name="android.support.v4.content.FileProvider"android:authorities="com.rachel.studyapp.fileprovider"android:exported="false"android:grantUriPermissions="true"><!--提供共享路径--><meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths"/></provider>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上面得 authorities 必须跟你刚才在 getUriForFile 得authorities 一致,exported 这里填写 false,不然又得来权限问题了,grantUriPermissions 表示授予临时访问,然后再在下面添加一个 mete-data 标签,用来提供 fileprovider 的共享路径。
file_paths 名字随便取,然后在新建一个 xml 文件夹,席间 file_paths 文件填写如下代码:

<?xml version="1.0" encoding="utf-8"?>
<resources><paths><external-path path="" name="camera_photos" /></paths>
</resources>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

解释如下:

  • external-path 表示用来指定共享路径的
  • name 随便取,只是一个标签,买个关子,下面会解释
  • path 这个比较重要,如果不设置,则表示将整个 SD 卡进行共享,然后制定了,比如 path=”Pictrues”那么,就只共享 sd卡下的 Pictures 文件夹

既然都配置好了,我们把上面的 mCameraUri 打印一下,如下所示:

cameraPic: content://com.rachel.studyapp.fileprovider/camera_photos/Android/data/com.rachel.studyapp/cache/output.png
  • 1
  • 1

看到这个 camera_photos 了吧,其实它就是一个 虚拟目录,可以不管的。这个就是 7.0 之后 uri 经过封装后的样子。

拍照之后,就是要处理获取的图片了,在 onActivityReslut 中的处理也非常简单,既然不管是从相册,还是从相册,我们都获取到了正确的 uri,那么,在获取到 这个 uri 之后,启动裁剪的 activity 就可以了,如下:

@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK){switch (requestCode){case ToolUtils.SCAN_OPEN_PHONE: //从相册图片后返回的uri//启动裁剪startActivityForResult(CutForPhoto(data.getData()),ToolUtils.PHONE_CROP);break;case ToolUtils.PHONE_CAMERA: //相机返回的 uri//启动裁剪String path = mActivity.getExternalCacheDir().getPath();String name = "output.png";startActivityForResult(CutForCamera(path,name),ToolUtils.PHONE_CROP);break;case ToolUtils.PHONE_CROP:try {//获取裁剪后的图片,并显示出来Bitmap bitmap = BitmapFactory.decodeStream(mActivity.getContentResolver().openInputStream(mCutUri));mUserLogoIcon.setImageBitmap(bitmap);} catch (FileNotFoundException e) {e.printStackTrace();}break;}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

可以看到,裁剪分为两个,一个是从相册中获取,另一个则是拍照之后,再来裁剪的。不一样的地方,往下看:
相册裁剪:

/*** 图片裁剪* @param uri* @return*/@NonNullprivate 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();//初始化 uriUri imageUri = uri; //返回来的 uriUri outputUri = null; //真实的 uriLog.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)); //200dpintent.putExtra("outputY",ToolUtils.dip2px(mActivity,200));intent.putExtra("scale",true);//如果图片过大,会导致oom,这里设置为falseintent.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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

相机裁剪:

 /*** 拍照之后,启动裁剪* @param camerapath 路径* @param imgname img 的名字* @return*/@NonNullprivate Intent CutForCamera(String camerapath,String imgname) {try {//设置裁剪之后的图片路径文件File cutfile = new File(Environment.getExternalStorageDirectory().getPath(),"cutcamera.png"); //随便命名一个if (cutfile.exists()){ //如果已经存在,则先删除,这里应该是上传到服务器,然后再删除本地的,没服务器,只能这样了cutfile.delete();}cutfile.createNewFile();//初始化 uriUri imageUri = null; //返回来的 uriUri outputUri = null; //真实的 uriIntent 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,这里设置为falseintent.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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

上面两个,相似度极高,不同的是,相册是直接获取 uri,而相机,则是通过拍照之后,获取的 uri,你这里可以合并一下,只是参数不一样而已,这里我为了让大家有个对比的效果,就分开出来了。

上面一个,注意到用了 intent.putExtra(“return-data”,false);如果这里设置为 true,那么,返回是就是一个 btimap,但这样做在内存不足的情况下,会报 OOM 的,所以,像这种大图片的,我们一般是在本地生成一个裁剪之后的图片,然后获取到这个裁剪之后的 uri,再解析出来,才是正确的做法,所以这里设置为false,并用 mcuturi 来作为这个本地存储的 uri。

这样就讲完了。
这里推荐一下,github,我觉得还不错的两个裁剪开源库,SmartCropper,链接如下:

https://github.com/pqpo/SmartCropper
  • 1
  • 1

TakePhoto :

https://github.com/crazycodeboy/TakePhoto/
  • 1
  • 1

Android7.0 头像 拍照、照片裁剪相关推荐

  1. Android 7.0下拍照和裁剪图片

    Android 7.0下拍照和裁剪图片 最近,公司的APP集中爆发了头像上传中拍照或照片裁剪的bug,让我才意识到及时学习Android新特性是多么重要,一个过去式的APP是无法一直满足日益变化的新需 ...

  2. Android7.0上拍照与选择照片Crash问题

    在Android7.0系统上,Android 框架强制执行了 StrictMode API 政策禁止向你的应用外公开 file:// URI. 如果一项包含文件 file:// URI类型 的 Int ...

  3. Android - 更换头像及图片裁剪(适配Android7.0)

    我的CSDN: ListerCi 我的简书: 东方未曦 一.概述 相信大家都用过 Android 应用中更换头像的功能,在这个功能中,用户可以拍照或者选择相册图片,然后裁剪出头像所需要的图案. 那么你 ...

  4. Android7.0以上如何获取头像(拍照或者从相册中选择)

    大概的流程 动态权限管理 创建布局文件,这里不多说了 拍照的实现 2.1创建存放图片的文件夹 2.2将文件夹路径转换为uri 2.3隐式启动相机的Activity,uri作为intent的一个参数. ...

  5. Android7.0 拍照 选择照片 权限 实现

    参考链接: http://blog.csdn.net/hu5080126/article/details/53738625 http://www.jianshu.com/p/ba57444a7e69 ...

  6. 安卓开发——拍照、裁剪并保存为头像报错:裁剪图片无法保存的

    在做学校大创项目的安卓开发时,需要从相册获取图片或者拍照,然后裁剪保存为头像.由于我是第一次弄安卓开发,也对Android现在越来越多的权限限制不了解,debug过程真的是异常心塞啊. 闲话不说(文末 ...

  7. android 7.0 手机拍照裁剪问题

    在android7.0 之前 ,如果需要用到拍照的时候 我们一般都这样去写 //先新建一个File类型的对象 File file=new File(Environment.getExternalSto ...

  8. Android7.0调用系统相机和裁剪

    最近将项目的targetSdkVersion升级到了26,发现调用系统相机的时候报了下面这个错误: android.os.FileUriExposedException: file:///storag ...

  9. Android7.0,剪裁后提示“无法保存经过裁剪的图片”

    今天在适配一下 7.0的拍照和选择照片,裁剪,发现拍照可以,选择图片也可以, 但是就是裁剪的时候不行,会弹出提示:无法保存经过裁剪的图片 后来才发现,在设置裁剪要保存的 intent.putExtra ...

  10. android 适配7.0,Android7.0适配心得(一)_拍照兼容

    1.在Android7.0上调用系统相机拍照,裁切照片的适配 在Android7.0以前,若是你想调用系统相机拍照能够经过如下代码来进行:java File file = new File(Envir ...

最新文章

  1. QPS和并发数,这次给你说清楚
  2. 生成朋友圈转发点赞截图的小工具
  3. python【蓝桥杯vip练习题库】ALGO-1区间k大数查询
  4. SQLServer中数据库的创建
  5. 公共方法-利用for else搜索字典列表-for else
  6. IOS基础之愤怒的小方块
  7. 使用静态代理模式实现公用的报表导出功能
  8. docker 部署Python项目 以及dockerfile文件的编写
  9. SpringBoot-视图解析与模板引擎
  10. 每日算法系列【LeetCode 115】不同的子序列
  11. Sass的安装(windows 10)
  12. 从应用层修改系统日期和时间
  13. visio用例图箭头怎么画_visio2010绘制用例图-带图例
  14. 信息录入率百分百上海强化施工现场建筑工人实名制管理
  15. 解决Source Not Found问题
  16. Android——超简单悬浮窗使用教程
  17. chrome浏览器替换code.jquery.com CDN的加速URL
  18. 物联网网关神器 Kong ( 四 )- 利用 Konga 来配置生产环境安全连接 Kong
  19. Qt编写物联网管理平台32-表格数据
  20. 房间脉冲响应测量与模拟方法

热门文章

  1. 大学及毕业总共9年时间追求过一个女孩却最终没有成功,期间的心酸,痛苦,怨恨以及最后消散写成了这篇2万字的散文诗小说。每一个字都是自己的心血,试问人生有几个9年?更何况是在你最美好的年华。喜欢的交流下。
  2. Ubuntu桌面版以太网无法设置IP
  3. 数值分析-数值分析下的误差分析
  4. 基于机智云平台的厨房智能监控系统
  5. 使用 Microsoft Symbol Server 获取调试符号文件
  6. 开源一个简单的android手机音乐app
  7. [ICCV2021] TransReID: Transformer-based Object Re-Identification 行人重识别
  8. Linu系统 rpm软件包 管理
  9. 微信小程相对图片路径_微信小程序中图片绝对定位(背景图片)的方法
  10. 鸿蒙OS开发蜂鸣器播放《两只老虎》