目录

  • 一、问题背景
  • 二、定位原因
  • 三、解决办法
    • 1. 通过媒体库返回 Uri
    • 2. 通过照片墙读取 Uri
    • 3. 将图片缓存后生成 Uri
  • 附 Github 源码

一、问题背景

  • 在选择 Google Photos 的照片后,会返回 uri,然后再去调用照片裁剪功能会失败。系统提示 “Error, could not load media” 或 “发生错误,无法加载媒体”。

二、定位原因

  • 在选择 Google Photos 的照片后,返回的 uri 为:
content://com.google.android.apps.photos.contentprovider/-1/1/content://media/external/images/media/80/ORIGINAL/NONE/image/jpeg/122783088
  • 常规相册返回的照片 uri 为:
content://media/external/images/media/80

因为 Google Photos 返回的照片 Uri 不能被解析,所以导致无法加载图片进行裁剪。

三、解决办法

1. 通过媒体库返回 Uri

有其他小伙伴提出的办法比较简单,首先获取 Google Photos 照片 Uri 的输入流,然后将 输入流 转为 bitmap 插入到媒体库,插入完成后会返回一个 媒体库 新的 uri ,此时这个 uri 就是我们想要的能被正确解析的格式。

核心代码如下:

// java// 1. 获取 Google Photos 照片 Uri 的输入流,并转为 Bitmap
InputStream is = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);// 2. 将 bitmap 保存到手机本地相册中获取返回的 uri
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), bitmap, "temp", null);
// 能被正确解析的 uri
Uri result = Uri.parse(path);

2. 通过照片墙读取 Uri

在选择照片并裁剪的流程中,增加一个照片墙的页面。即先将手机相册中的图片 uri 读取出来,然后展示在照片墙页面,用户在照片墙页面选择想要的照片。照片的 uri 此时是我们从媒体库中读取的,是可以被正确解析的格式。

3. 将图片缓存后生成 Uri

  • 第一个方案的弊端是,需要向手机的相册中插入一张和所选照片完全一样的图片,这会让用户感到疑惑。当选择次数较多时,会产生多个重复的图片。
  • 可以将第一种方案 改为 将图片文件存入缓存,然后生成对应的 Uri,再给到系统去裁剪。这样就避免了生成另外一张完全一样的图片。
  • 具体做法是:先判断是谷歌相册返回的 uri,通过图片的输入流将图片文件存入到文件缓存目录,再根据系统版本生成对应的Uri。

核心代码如下:

// kotlin // 判断是谷歌相册返回的 uri。如果后续谷歌的规则发生并更,这里也需要更改
val googlePrefix = "content://com.google.android.apps.photos.contentprovider"
val newUri = if (uri.toString().startsWith(googlePrefix, true)) {// 处理谷歌相册返回的图片saveImageToCache(context, uri)
}/*** 将谷歌相册图片保存到外置存储目录,然后返回 uri*/
private suspend fun saveImageToCache(context: Context, uri: Uri): Uri {val imageName = "${System.currentTimeMillis()}.jpg"val parent = if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) {context.externalCacheDir?.absolutePath} else {context.cacheDir?.absolutePath}val path = parent + File.separator + imageNamewithContext(Dispatchers.IO) {copyInputStream(context, uri, path)}val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {FileProvider.getUriForFile(context, "${context.packageName}.fileprovider",File(parent, imageName))} else {Uri.fromFile(File(path))}"uri: $result".logV()return result
}/*** 字节流读写复制文件* @param context 上下文* @param uri 图片uri* @param outputPath 输出地址*/
private fun copyInputStream(context: Context, uri: Uri, outputPath: String) {"copy file begin...".logV()var inputStream: InputStream? = nullvar outputStream: FileOutputStream? = nulltry {inputStream = context.contentResolver.openInputStream(uri)outputStream = FileOutputStream(outputPath)val bytes = ByteArray(1024)var num: Intwhile (inputStream?.read(bytes).also { num = it ?: -1 } != -1) {outputStream.write(bytes, 0, num)outputStream.flush()}} catch (e: Exception) {"exception: $e".logE()} finally {try {outputStream?.close()inputStream?.close()"copy file end...".logV()} catch (e: IOException) {"exception: $e".logE()}}
}

附 Github 源码

RegisterForResultActivity

【Fix Bug】针对 Google Photos 返回的图片Uri,裁剪照片失败相关推荐

  1. 设计与算法 | Google Photos Web UI

    作者 / Antin Harasymiv, UX Engineer, Google * 很多时候,体验设计和算法的联系会比想象中要紧密得多.本文将从代码和体验两个层面和大家深度分享. 几年前,我有幸成 ...

  2. html怎么显示返回的图片,想要预览文件或是图片,将后端返回的信息转换为前端可以正常显示的格式...

    文件.图片在后端主要以两种方式存储: 1.保存在服务器上,数据库中存储的是该文件.图片的地址: 2.将文件.图片转为二进制流,数据库中存储的是对应的二进制流. 针对第一种情况的话,直接请求接口获取到对 ...

  3. layer.photos 查看本地图片,并实现缩放和旋转功能

    公司用了layui这个框架,需要用到展示图片这个功能,千辛万苦终于实现啦!!!记录一下 后端: 1.controller(我这边是直接从前端传递来图片地址) @Log(title = "查看 ...

  4. 【Google photos 谷歌相册 在图片信息更改后需要刷新】

    项目场景: receiver App图片信息缺失,sender App再次发送完整的图片信息(两次传输的图片名相同)给receiver,receiver接收到信息后,Google photos不能够完 ...

  5. Google Photos上线一年 照片存储达13.7PB

    Google Photos GooglePhotos是一款Google推出的帮助用户整理照片的一款工具,而最近Google为了纪念GooglePhotos服务正式上线一周年,特意对这项功能做了一个详细 ...

  6. 分享一个针对触摸设备优化的图片幻灯jQuery插件 - touchtouch

    为什么80%的码农都做不了架构师?>>>    日期:2012-5-6  来源:GBin1.com 在线演示  本地下载 触摸设备越来越流行了,很多互联网用户都使用ipad等平板电脑 ...

  7. Android之给图片去色,返回灰度图片以及ColorMatrix中setSaturation方法的用法

    原图: 效果图: 实现以上效果其实很简单,直接上代码: public class MainActivity extends Activity {private Button btn_start;pri ...

  8. Android之解决toolbar里面显示返回按钮图片太大和没有水平居中的问题

    1.问题 1.toolbar里面显示返回按钮图片太大 2.返回按钮图片没有水平居中 2.解决办法 1.把drawable里面的图片移动到mipmap-xhdpi里面去,还大了就移动到mipmap-xx ...

  9. 谷歌聊天机器人api_如何编写针对Google地图等网络应用量身定制的聊天机器人

    谷歌聊天机器人api by Paul Pinard 保罗·皮纳德(Paul Pinard) 如何编写针对Google地图等网络应用量身定制的聊天机器人 (How to code a chatbot t ...

最新文章

  1. QQ“远程协助”文字输入技巧
  2. 【工具】WPS安卓电脑无广告版
  3. ubuntu 打开ssh登陆_Ubuntu 开启远程登录 SSH 的安装和配置
  4. logstash日志用于匹配多行日志
  5. JS里的时间有关的标签
  6. php程序里如何实现图片翻页,php图片上传代码一例-php 生成翻页链接(页码)列表的...-带多种分页方式的php分页类_169IT.COM...
  7. vue项目:this.function()中关于:this指针失效的问题
  8. Cisco IP Phone 功能亮相(4)
  9. 2021年系统集成项目管理工程师(软考中级)连夜整理考前重点
  10. MFC导入图标文件的方法
  11. springboot kafka集成
  12. 密码学的安全性浅析-3
  13. <笔记本电脑设备管理器检测不到触控板,电脑触控板失灵>
  14. 防疫与复工同行,长沙望城进入“双统筹”的关键时刻
  15. 进程概念(PCB、进程创建、进程状态等)
  16. android sqlite 打包 xe,C++ Builder XE10快速开发关于sqlite数据库APP应用发布小结
  17. 【2018慢性病与信息大会】闫树:区块链与医疗技术共享
  18. 华为拿数百亿资金给员工分红,2021年每股可分1.58元
  19. 前端React教程第二课 React生命周期设计思想
  20. web前端期末大作业 html+css+javascript+jquery+bootstarp响应式鲜花售卖网站16页

热门文章

  1. 移动硬盘数据恢复,90%的人都是这么做的…
  2. 如何通过7个步骤编写出色的在线用户手册,让天下没有难用的产品
  3. LXD介绍+配置使用
  4. linux性能(一):cpu性能指标及工具
  5. Delphi XE2 下载地址(记录)
  6. 开源的文章又被培训机构“BP”了,这次不忍了
  7. 巨控GRMOPC模块实现很多企业的组态软件(上位机),wincc,组态王,力控等互联,工业APP远程监控
  8. java游戏开发毕业论文_基于JAVA的五子游戏的开发设计毕业论文
  9. 银行票据业务如何实现BI赋能
  10. php面试题-MySQL篇