Android 7.0中拍照和图片裁剪适配的问题详解

发布时间 - 2026-01-10 22:55:38    点击率:

前言

Android 7.0系统发布后,拿到能升级的nexus 6P,就开始了7.0的适配。发现在Android 7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错误:

Process: com.yuyh.imgsel, PID: 22995

// 错误1
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpg exposed beyond app through ClipData.Item.getUri()

// 错误2
android.os.FileUriExposedException: file:///storage/emulated/0/DCIM/RxGalleryFinal/IMG_20161018180127.jpg exposed beyond app through Intent.getData()

主要是由于在Android 7.0以后,用了Content Uri 替换了原本的File Uri,故在targetSdkVersion=24的时候,部分 “`Uri.fromFile() “` 方法就不适用了。 **File Uri 与 Content Uri 的区别** - File Uri 对应的是文件本身的存储路径 - Content Uri 对应的是文件在Content Provider的路径 所以在android 7.0 以上,我们就需要将File Uri转换为 Content Uri。

具体转换方法如下:

/**
 * 转换 content:// uri
 * 
 * @param imageFile
 * @return
 */
public Uri getImageContentUri(File imageFile) {
 String filePath = imageFile.getAbsolutePath();
 Cursor cursor = getContentResolver().query(
   MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
   new String[] { MediaStore.Images.Media._ID },
   MediaStore.Images.Media.DATA + "=? ",
   new String[] { filePath }, null);

 if (cursor != null && cursor.moveToFirst()) {
  int id = cursor.getInt(cursor
    .getColumnIndex(MediaStore.MediaColumns._ID));
  Uri baseUri = Uri.parse("content://media/external/images/media");
  return Uri.withAppendedPath(baseUri, "" + id);
 } else {
  if (imageFile.exists()) {
   ContentValues values = new ContentValues();
   values.put(MediaStore.Images.Media.DATA, filePath);
   return getContentResolver().insert(
     MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
  } else {
   return null;
  }
 }
}

那么,我们在裁剪的时候,应该如下调用:

private void crop(String imagePath) {
 File file = new File("xxx.jpg");
 cropImagePath = file.getAbsolutePath();

 Intent intent = new Intent("com.android.camera.action.CROP");
 intent.setDataAndType(getImageContentUri(new File(imagePath)), "image/*");
 intent.putExtra("crop", "true");
 intent.putExtra("aspectX", config.aspectX);
 intent.putExtra("aspectY", config.aspectY);
 intent.putExtra("outputX", config.outputX);
 intent.putExtra("outputY", config.outputY);
 intent.putExtra("scale", true);
 intent.putExtra("return-data", false);
 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
 intent.putExtra("noFaceDetection", true);
 startActivityForResult(intent, IMAGE_CROP_CODE);
}

这样就解决了裁剪的问题,但是!!拍照的时候就会出现以下错误:

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) {
 tempFile = new File(FileUtils.createRootPath(getActivity()) + "/" + System.currentTimeMillis() + ".jpg");
 LogUtils.e(tempFile.getAbsolutePath());
 FileUtils.createFile(tempFile);
 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
 startActivityForResult(cameraIntent, REQUEST_CAMERA);
}
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpg exposed beyond app through ClipData.Item.getUri()

这是因为拍照存储的文件,也需要以Content Uri的形式,故采用以下办法解决:

Step.1

修改AndroidManifest.xml

<application
 ...>

 <provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="{替换为你的包名}.provider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
   android:name="android.support.FILE_PROVIDER_PATHS"
   android:resource="@xml/provider_paths"/>
 </provider>
</application>

Step.2

在res/xml/下新建provider_paths.xml文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
 <external-path name="external_files" path="."/>
</paths>

Step.3

修改拍照时的参数

cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(getActivity(),BuildConfig.APPLICATION_ID + ".provider", tempFile)); //Uri.fromFile(tempFile)

总结

好了,以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们能带来一定的帮助,如果有疑问大家可以留言交流。


# android  # 7.0适配拍照  # 7拍照适配  # 7.0  # 图片裁剪  # Android实现拍照、选择图片并裁剪图片功能  # Android裁剪图片为圆形图片的实现原理与代码  # 解决Android从相册中获取图片出错图片却无法裁剪问题的方法  # Android实现从本地图库/相机拍照后裁剪图片并设置头像  # Android实现拍照及图片裁剪(6.0以上权限处理及7.0以上文件管理)  # Android编程实现调用系统图库与裁剪图片功能  # android文件上传示例分享(android图片上传)  # Android使用post方式上传图片到服务器的方法  # Android实现本地上传图片并设置为圆形头像  # Android实现图片裁剪和上传  # 的是  # 用了  # 就会  # 好了  # 这篇文章  # 要以  # 这是因为  # 转换为  # 也需  # 方法如下  # 开始了  # 解决了  # 是由于  # 有疑问  # getAbsolutePath  # return  # public  # String  # getImageContentUri  # filePath 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在搬瓦工VPS快速搭建网站?  C++时间戳转换成日期时间的步骤和示例代码  Python数据仓库与ETL构建实战_Airflow调度流程详解  JavaScript中的标签模板是什么_它如何扩展字符串功能  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  专业商城网站制作公司有哪些,pi商城官网是哪个?  Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤  如何在阿里云ECS服务器部署织梦CMS网站?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  Laravel模型事件有哪些_Laravel Model Event生命周期详解  大连 网站制作,大连天途有线官网?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  Laravel如何实现API版本控制_Laravel API版本化路由设计策略  动图在线制作网站有哪些,滑动动图图集怎么做?  如何快速查询网站的真实建站时间?  如何获取PHP WAP自助建站系统源码?  如何快速生成凡客建站的专业级图册?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  Laravel PHP版本要求一览_Laravel各版本环境要求对照  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  如何在IIS中配置站点IP、端口及主机头?  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  如何用JavaScript实现文本编辑器_光标和选区怎么处理  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  微信小程序 HTTPS报错整理常见问题及解决方案  javascript读取文本节点方法小结  Laravel如何使用Blade组件和插槽?(Component代码示例)  python中快速进行多个字符替换的方法小结  浅谈Javascript中的Label语句  UC浏览器如何设置启动页 UC浏览器启动页设置方法  bing浏览器学术搜索入口_bing学术文献检索地址  如何生成腾讯云建站专用兑换码?  Bootstrap整体框架之JavaScript插件架构  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  网站制作软件有哪些,制图软件有哪些?  音响网站制作视频教程,隆霸音响官方网站?  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  JS经典正则表达式笔试题汇总  javascript日期怎么处理_如何格式化输出  Laravel怎么连接多个数据库_Laravel多数据库连接配置  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  微信小程序 canvas开发实例及注意事项  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置