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

Android代码-使用注解自动生成 Content provider 。 Autoprovider Content provider generator for android that uses annotation processing. All helper classes are generated based on a Java Object. Documentation is WIP. A sample app is provided. Download Gradle: buildscript { dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } apply plugin: 'com.neenbedankt.android-apt' dependencies { compile 'in.workarounds.autoprovider:autoprovider:0.0.1' apt 'in.workarounds.autoprovider:autoprovider-compiler:0.0.1' } Licens 立即下载

一、问题背景

  • 在选择 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 + imageName

    withContext(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? = null
    var outputStream: FileOutputStream? = null
    try {
        inputStream = context.contentResolver.openInputStream(uri)
        outputStream = FileOutputStream(outputPath)
        val bytes = ByteArray(1024)
        var num: Int
        while (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

OpenClaw 在 Windows 环境下的完整安装、配置和部署指南 介绍Windows环境下OpenClaw的完整安装,配置和部署的全流程 阅读详情

相关推荐

10分钟训练你的AI歌手:RVC WebUI声音克隆保姆级教程

本文提供了一份详细的RVC WebUI声音克隆保姆级教程,指导用户如何在10分钟内利用Retrieval-based-Voice-Conversion技术训练专属AI歌手。教程涵盖从环境配置、数据准备、模型训练到最终推理应用的全流程,即使是新手也能快速上手,实现高质量的声音克隆与歌曲生成。

weixin_29073241的博客 818

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.con

问题描述Samsung-G9287手机(android7.0系统),已经安装了google play store,已经给了权限。从相册读取图片时报错。报错日志2-22 12:03:37.106 22068-22068/? E/UriImage: createFromUri: content://com.google.android.apps.photos.contentprovider/-1/1/c

codehxy的专栏 6133

从零开始:STM32C011开发板的硬件生态与快速验证

本文全面解析STM32C011开发板的硬件生态与快速验证方法,帮助开发者从零开始掌握这款基于ARM Cortex-M0+内核的微控制器。内容涵盖硬件架构解析、开发环境搭建、基础功能验证及性能优化技巧,为嵌入式开发提供实用指导。

swift5iosmith的博客 480

GooglePhoto设置壁纸----壁纸裁剪界面配置

背景描述Googlephoto打开一张图片,点击设为、弹出提示框里选择photo,提示“发生错误,无法加载媒体”。 photo---Use as---complete action using---photo wallpaper

纵容的博客 1634

TOPCon vs PERC:2024年光伏电站投资,哪种技术更划算?

本文深入分析了2024年光伏电站投资中TOPCon与PERC技术的财务表现。通过对比初始系统成本、全生命周期发电量及环境适应性,指出当前TOPCon组件与PERC价差已显著缩小,其更高的转换效率和更低的衰减率能有效降低度电成本并提升项目内部收益率,为投资者提供更具长期价值的方案。

p5l2m9n4o6q的博客 266

HFSS实战(二)——精准仿真高速PCB差分线的信号完整性

本文深入探讨了使用HFSS进行高速PCB差分线信号完整性仿真的关键技术与实战经验。从设计文件导入、模型裁剪到差分端口设置,详细解析了精准仿真的全流程,特别强调了材料特性和3D电磁场仿真在解决微带线损耗等问题中的重要性。文章还提供了常见问题排查指南和效率优化技巧,帮助工程师提升高速PCB设计的仿真精度与效率。

weixin_38170829的博客 572

Android 11剪裁照片 以及google相册处理

2.android11 之后剪裁照片就不能使用file://了,建议使用 MediaStore.Images.Media 来处理,但是问题是,在相册会对应生成bitmap照片,我的处理方式是,在逻辑完成之后删除生成的照片,避免影响用户体验。在android 11之后,android系统存储权限被强制分区,所以照片存储也变得越来越麻烦,加大了开发出现的问题,以下是本人写的demo,沉余代码比较多,我就不删除了,大家也可以通过这些,看到我的调试过程。不,太天真了,还有我们的google手机呢。

chenluming210的博客 815

AI智能体项目管理框架agent-pm:从原理到实战的多智能体协作指南

在人工智能和自动化技术快速发展的今天,多智能体系统已成为实现复杂任务自动化的重要技术路径。其核心原理在于通过任务分解、角色分配和状态管理,让多个AI智能体像人类团队一样协同工作,从而突破单个模型的性能边界。这种架构的技术价值在于将软件工程中成熟的项目管理方法论引入AI领域,显著提升了自动化流程的可预测性、可观测性和可复用性。在实际应用场景中,多智能体协作框架能够高效处理从代码开发、文档撰写到数据分析等一系列任务,尤其适合需要多步骤、多专业协同的复杂项目。本文聚焦的agent-pm框架,正是这一领域的典型实践

weixin_42533910的博客 714

Android4.4之后以及7.0访问相册和裁剪相关问题

Android4.4之后我们知道,android4.4以后,如果以下代码直接访问系统图库Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*");得到的Uri不再是content://media/类型的Uri,而是conten://…provider/类型的Uri。Android4.4之前返回的格

HB-pencil 1250

syslog RFC5424协议详解

RFC5424协议解读与报文分析。

chenwr2018的博客 6690

HFSS仿真PCB射频通路间的隔离度

本文介绍HFSS方式仿真带有器件的射频通路间的隔离度,可视为CST方式的补充,二者的结果相互参照。在前期靠仿真确认风险点时,可以作为一种较为直观和可信的手段。

sinat_15150363的博客 1524

android选择系统图库、拍照裁剪,适配Android6.0、7.0、8.0

1.选择系统图库 a.第一种 Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); activity.startActivityForResult(intent, CHOOSE_P...

947

【软件系统架构】系列四:嵌入式技术

嵌入式系统是以应用为中心、以计算机技术为基础,并将可配置与可裁剪的软硬件集成于一体的专用计算机系统。它需要满足功能、可靠性、成本、体积、功耗等方面的严格要求。 嵌入式系统一般由以下组成部分构成:

moton2017的博客 999

Android学习笔记(兼容篇)

好记性不如烂笔头,仅以记之一:摩托罗拉Android 7.0系统剪切图片后崩溃。日志如下:FATAL EXCEPTION: main Process: com.google.android.apps.photos, PID: 8332 java.lang.RuntimeException: Unable to resume activity {com.google.android.apps.

kongge的专栏 3470

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

android客户端学习-拍照或从相册选择图片并裁剪

1.在activity中定义变量 private final int RESULT_PHOTO_KITKAT = 0;//图库返回  private final int RESULT_PHOTO = 1;//相册返回  private final int RESULT_CAMERA = 2;//相机返回  private final int RESULT_CROP = 3;//裁剪  p

蚂蚁搬家 592

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

安卓从googlephoto上选择云端图片导致程序崩溃的解决方案

当软件选择照片时,如果选择的是使用googlephoto或google云备份过,并在本地删除过的图片时,程序就会崩溃或图片是空白 ,报错原因:IllegalArgumentException:InvalidURI:content://com.google.android.apps.photos.contentprovider/0/1‌​/mediaKey%3A...6mkQk‌​-P4tzU/ACT

lc352778616的博客 1310

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Android根据图片Uri获取图片path绝对路径

在Android 编程中经常会用到Uri转化为文件路径,如我们从相册选择图片上传至服务器,一般上传前需要对图片进行压缩,这时候就要用到图片的绝对路径。 下面对我开发中uri转path路径遇到的问题进行总结,其中涉及到Android不同api下对于uri的处理,还有对于Google相册图片该如何获取其图片路径。 1. 从相册获取图片 我们从相册获取的图片的代码如下: // 激活系统图...

smileiam的专栏 3万+

从DocumentUI获取图片正确姿势

1 请求打开DocumentUI Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType(“/“); startActivityForResult(intent, REQUEST); 2 获取DocumentUI返回的uri @Override prot

killer991684069的博客 3025

Android7.0系统应用包名信息

    Chrome    com.android.chrome/com.google.android.apps.chrome.Main         通讯录    com.android.contacts/com.android.contacts.activities.PeopleActivity         时钟    com.android.deskclock/com.android....

white_wt的博客 4109

兼容Android11的手机拍照上传图片和相册选择图片功能(可直接用)

//需要的权限数组 读/写/相机 private static String[] PERMISSIONS_STORAGE = {android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; // 头像 private ImageView imageView; private String imgUrl; .

僅此的博客 4270

Pixelify Google Photos 使用指南

**Pixelify Google Photos** 是一个由开发者[BaltiApps](https://github.com/BaltiApps)基于MIT许可协议创建的开源项目。该工具旨在非Pixel设备上模拟谷歌Pixel手机专享的Google Photos特性。通过Xposed或LSPosed框架,它能够“欺骗”Google Photos应用,使其认为运行环境是Pixel设备,从而启用一...

gitblog_00797的博客 1281

解决Android从相册中获取图片却无法裁剪的问题

1.原因: 主要是4.4,如果使用pick的原生方法 ntent.ACTION_PICK,null来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完全不一样的,4.3返回的是带文件路径的,而4.4返回的却是content://com.android.providers.media.documents/document/image:3951

xvzhengyang的博客 1883

Content Provider

Content providers存储和检索数据并使其可以让所有apps访问,公开自己数据的两种方法:创建自己的provider或者把数据加到现有的provider里面。 基础 所有的content provider都现一个为provider查询和返回结果的公共接口,这是一个

812

android contentprovider及其查看

它通过 URI(如 content://com.example.app.provider/data) 被其他应用访问,由系统自动管理其生命周期。查看某包的 Provider adb shell dumpsys activity providers com.your.package。authority Provider 的唯一标识(如 com.example.app.provider)🔄 五、dumpsys activity providers vs dumpsys package。

aaajj的专栏 434

Android存储之MediaStore的使用

上文中提到了Android提供内容的叫ContentProvider,那么在Android中怎么区分各个Provider?有的是提供联系人的,有的是提供图片的,有的是提供视频的等等。所以就需要有一个唯一的标识来标识这个Provider,Uri(通用资源标识符 Universal Resource Identifier)就是起到了这个标识的作用。每一个ContentProvider都会有一个唯一的Uri地址,通过这个Uri标识可以获取到ContentProvider和其中的数据,然后进行数据操作。

XBlithe的博客 2万+

Android 获取选择文件的绝对路径

Android程序开发中会经常涉及到选择本地文件(如图片和视频)的问题,文件可能位于相册、媒体库或者SD中,而且选择的文件信息统一以Uri的形式返回,有时可能会根据此Uri获取到文件的本地绝对路径(如上传文件等),这里提供一个解析类来实现此功能(要求开发SDK版本为4.4.2或以上,对于运行2.2及以上系统版本的设备都适用)。 package com.utils.common;

sdsx_pioneer的专栏 6179
上一篇: Android 11 适配 软件包可见性
下一篇: 【iOS 开发】基础控件:UILabel
Lucky_William
博客等级 码龄11年 161粉丝 57原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值