其中点击事件如下: 

图片:

Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intent, ToolUtils.SCAN_OPEN_PHONE);

相机:

 /**
     * 打开相册
     */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);}

在拍照这里,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>

上面得 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>

解释如下:

  • 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

看到这个 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;}}}

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

/**
     * 图片裁剪
     * @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;}

相机裁剪:

 /**
     * 拍照之后,启动裁剪
     * @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;}

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

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

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

Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intent, ToolUtils.SCAN_OPEN_PHONE);

相机:

 /**
     * 打开相册
     */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);}

在拍照这里,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>

上面得 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>

解释如下:

  • 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

看到这个 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;}}

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

/**
     * 图片裁剪
     * @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;}

相机裁剪:

 /**
     * 拍照之后,启动裁剪
     * @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;}

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

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

Andorid 拍照、从相册中选择图片兼容7.0uri相关推荐

  1. 微信小程序 拍照/从相册中选择图片

    微信小程序提供的众多API中,wx.chooseImage函数就是用来访问手机相册或摄像头的.调用该函数后,界面下方会呼出一个菜单,可以分别选择进入相册挑选已有照片或是打开摄像头进行拍照: 我们往WX ...

  2. 兼容Android 11 相机拍照,从相册中选择,裁剪图片

    由于android 11对存储空间进行了更新,导致无法进入裁剪或者裁剪后无法保存,返回路径等问题. android 10以下可以参考:android 相机拍照,从相册中选择,裁剪图片 前面部分和之前的 ...

  3. Android 拍照以及相册中选择(适配高版本)————上传多张照片之压缩处理、在线预览可伸缩放大(二)

    ______ Introduction ______ 前言 上一篇文章刚给大家总结完,关于上传头像的功能.此文章所述 主要是关于上传头像的具体流程以及如何对照片做裁剪处理,回调给控件显示:当然重中之重 ...

  4. uni-app用uni.chooseImage API调用相机或从相册中选择图片

    uni-app用uni.chooseImage API调用相机或从相册中选择图片 chooseImage: function() {var _this = this;uni.chooseImage({ ...

  5. Android --- 从相册中选择图片或者拍着选择图片遇到的问题

    1.从相册选择的图片会存储到 data 里面,而相机拍照的图片不会存储到 data 里面 2.由于从相册选择的图片会存储到 data 里面,而相机拍照的图片不会存储到 data 里面,所以在获取图片资 ...

  6. 【Flutter】Flutter 拍照示例 ( 浮动按钮及点击事件 | 底部显示按钮组件 | 手势检测器组件 | 拍照并获取当前拍摄照片 | 从相册中选择图片 )

    文章目录 一.浮动按钮及点击事件 二.底部显示按钮组件 三.手势检测器组件 四.image_picker 完整代码示例 五.相关资源 一.浮动按钮及点击事件 一般使用 Scaffold 组件作为界面的 ...

  7. iOS 自带二维码识别(识别二维码,条形码以及从相册中选择图片进行识别)

    一:初始化 //扫描区域 UIImage *hbImage=[UIImage imageNamed:@"pick_bg"]; UIImageView * scanZomeBack= ...

  8. 坑:Android从相册中选择图片加载到ImageView中显示不出

  9. php拍照从手机相册中选择,微信js-sdk预览图片接口及从拍照或手机相册中选图接口用法示例...

    本文实例讲述了微信js-sdk预览图片接口及从拍照或手机相册中选图接口用法.分享给大家供大家参考,具体如下: 目前中js-sdk 1.0版本中,预览图片提供了2个接口,接口的定义参考官方文档 1.预览 ...

最新文章

  1. 最大似然估计MLE和最大后验估计MAP理解
  2. LaTex 插入数学公式
  3. INTERSPEECH 2021 AutoSpeech挑战赛开启报名
  4. C++前缀++/–比后缀++/–的效率高
  5. 使用Custom.pll修改标准Form的LOV
  6. Android init.rc 服务启动不成功
  7. zookeeper学习入门
  8. echarts迁徙图 vue_vue中echarts引入中国地图的案例
  9. 利用react native创建一个天气APP
  10. final关键字多态
  11. 缺陷管理工具(jira,禅道)
  12. 2008服务器系统初始密码,2008服务器地址和密码
  13. 电视盒是计算机网络连接设备,电视盒子怎么连接电脑
  14. 在Mac下载安装win10虚拟机教程及分辨率等问题。
  15. C++高斯分布随机数的产生
  16. 远程连接云服务器中的mysql数据库_云服务器远程连接mysql数据库
  17. Cg插画需要学习什么,难不难?
  18. 需求工程之原型法获取需求
  19. 美指为何坚挺100关口?黄金大涨必须拿下1700
  20. Tkinter GUI界面添加图标及窗口图标

热门文章

  1. 鬼知道我昨晚经历了什么......
  2. 2022出海欧美:英国电商市场现状及发展前景
  3. 用C语言编写5个学生,每个学生有3门课程成绩,从键盘输入学生数据(学号,姓名,3门成绩)计算平均成绩,将成绩放入磁盘文件stud中
  4. DML和DDL的区别
  5. Qt6教程之三(2) QT使用qss
  6. 微观平台_不再受到微观管理
  7. 程序员的开发工具:Java语言开发人员常用软件
  8. 来自春天的仪式感:英伦花艺佳作,用鲜花点缀生活丨好书优选
  9. 网站引用字体兼容IE
  10. AC自动机+状压dp hdu2825 Wireless Password