讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

updream

一键生成高质量推广成片

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Seko
Seko

AI短剧一键生成成片

如何在 Android 11+(API 30+)中安全、合规地从图库选取图片

落涛酱_3272

落涛酱_3272

发布时间:2026-02-08 15:27:55

|

868人浏览过

|

来源于php中文网

原创

如何在 Android 11+(API 30+)中安全、合规地从图库选取图片

android 11 及以上版本因分区存储(scoped storage)限制,使用 `action_pick` + `extra_output` 方式会导致“access denied”错误;应改用 `action_get_content` 获取只读 uri,并通过 `contentresolver` 安全读取图像数据。

在 Android 11(API 30)及更高版本中,Google 强制推行 分区存储(Scoped Storage),大幅收紧对共享存储(如 DCIM、Pictures)的直接文件路径访问权限。你当前代码中使用 Intent.ACTION_PICK 并传入 EXTRA_OUTPUT 的方式,在 Android 11+ 上已被系统拒绝写入权限——即使你声明了 READ_MEDIA_IMAGES,MediaStore 也不再允许第三方 App 向外部 URI 写入临时结果,因此会触发 “Access denied” 错误。

✅ 正确做法:放弃 ACTION_PICK + EXTRA_OUTPUT,改用 ACTION_GET_CONTENT
该方式不尝试写入外部 URI,而是由系统返回一个具有临时读取权限的 content:// URI(如 content://media/...),App 可通过 ContentResolver 安全读取图像数据,完全符合 Android 11+ 的隐私与存储规范。

✅ 推荐实现(现代 AndroidX Activity Result API)

// Kotlin 示例(推荐)
private val pickerActivityResultLauncher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == RESULT_OK && result.data?.data != null) {
        val photoUri: Uri = result.data!!.data!!

        // ✅ 安全获取 Bitmap(无需文件路径!)
        val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, photoUri)
        imageView.setImageBitmap(bitmap)

        // ✅ 或转换为 File(如需保存/上传)
        val inputStream = contentResolver.openInputStream(photoUri)
        val tempFile = File(cacheDir, "picked_${System.currentTimeMillis()}.jpg")
        inputStream?.use { input ->
            FileOutputStream(tempFile).use { output ->
                input.copyTo(output)
            }
        }
        Log.d("Picker", "Saved to: ${tempFile.absolutePath}")
    }
}
// Java 示例(兼容写法)
private final ActivityResultLauncher<Intent> pickerActivityResultLauncher =
    registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                Uri photoUri = result.getData().getData();
                try {
                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(
                        getContentResolver(), photoUri);
                    imageView.setImageBitmap(bitmap);

                    // 如需保存为本地文件(推荐缓存目录)
                    InputStream is = getContentResolver().openInputStream(photoUri);
                    File tempFile = new File(getCacheDir(), "picked_" + System.currentTimeMillis() + ".jpg");
                    try (FileOutputStream os = new FileOutputStream(tempFile)) {
                        is.transferTo(os);
                    }
                    Log.d("Picker", "Saved: " + tempFile.getAbsolutePath());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

调用选取器:

Productivity Google Workspace
Productivity Google Workspace

Access Gmail, Calendar, Drive, Docs, and Sheets via the gws CLI or Python.

下载
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
    type = "image/*"
    // 可选:限定格式(如仅 JPEG)
    // type = "image/jpeg"
}
pickerActivityResultLauncher.launch(Intent.createChooser(intent, "选择照片"))

⚠️ 关键注意事项

  • ❌ 不要使用 ACTION_PICK + EXTRA_OUTPUT:Android 11+ 已废弃此组合,强制返回 null 或抛出安全异常;
  • ✅ 无需 WRITE_EXTERNAL_STORAGE 或 READ_EXTERNAL_STORAGE(API 33+ 已弃用),只需声明:
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  • ✅ ACTION_GET_CONTENT 返回的 content:// URI 自动附带 临时读取权限(grantUriPermission),无需手动 takePersistableUriPermission(除非需长期访问);
  • ? 若需裁剪,避免使用过时的 com.android.camera.action.CROP(厂商兼容性差、无权限保障)。推荐使用 AndroidX Crop Library 或 Bitmap 内存裁剪;
  • ? 不要尝试用 Cursor 查询 MediaStore.Images.Media.DATA 字段(Android 10+ 已返回 null)——这是你原代码中 picturePath 为空的根本原因。

✅ 总结

方案 Android 11+ 兼容性 安全性 推荐度
ACTION_PICK + EXTRA_OUTPUT ❌ 失败(Access Denied) 低 ⛔ 不可用
ACTION_GET_CONTENT(现代 API) ✅ 完全支持 高(URI 权限沙箱) ✅ 强烈推荐
ActivityResultLauncher + getBitmap() ✅ 简洁可靠 ✅ ✅ 最佳实践

遵循上述方案,即可彻底解决 Android 11+ 图库选图“Access Denied”问题,同时满足 Google Play 政策与用户隐私要求。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

讯飞智文

一款面向学习和办公场景的AI文档创作工具,可辅助生成PPT与Word文档,提高资料整理和内容制作效率。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

922

2023.08.14

android是什么系统
android是什么系统

Android是一种功能强大、灵活可定制、应用丰富、多任务处理能力强、兼容性好、网络连接能力强的操作系统。本专题为大家提供android相关的文章、下载、课程内容,供大家免费下载体验。

2787

2023.08.22

android权限限制怎么解开
android权限限制怎么解开

android权限限制可以使用Root权限、第三方权限管理应用程序、ADB命令和Xposed框架解开。详细介绍:1、Root权限,通过获取Root权限,用户可以解锁所有权限,并对系统进行自定义和修改;2、第三方权限管理应用程序,用户可以轻松地控制和管理应用程序的权限;3、ADB命令,用户可以在设备上执行各种操作,包括解锁权限;4、Xposed框架,用户可以在不修改系统文件的情况下修改应用程序的行为和权限。

5617

2023.09.19

android重启应用的方法有哪些
android重启应用的方法有哪些

android重启应用有通过Intent、PendingIntent、系统服务、Runtime等方法。本专题为大家提供Android相关的文章、下载、课程内容,供大家免费下载体验。

745

2023.10.18

Android语音播放功能实现方法
Android语音播放功能实现方法

实现方法有使用MediaPlayer实现、使用SoundPool实现两种。可以根据具体的需求选择适合的方法进行实现。想了解更多语音播放的相关内容,可以阅读本专题下面的文章。

984

2024.03.01

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

922

2023.08.14

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

40

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn