Android 17 取色器 API:无需权限,一行 Intent 跨应用取色

在设计工具、图片编辑器、主题定制类应用中,跨应用取色一直是个刚需但又极其难搞的功能。

Android 17(API 37)带来了全新的 Eye Dropper API,用一行 Intent 就能调起系统取色器,无需任何权限申请。

以前有多麻烦?

想在 Android 上实现跨应用取色,传统方案需要借助 MediaProjection 截屏再取像素色值:

bash 复制代码
// 传统方案:复杂、侵入、吓人
val projectionManager = getSystemService(MediaProjectionManager::class.java)
val intent = projectionManager.createScreenCaptureIntent()
// → 弹出系统录屏警告对话框
// → 用户看到"将开始录制屏幕上显示的所有内容"
// → 大量用户直接拒绝退出

这个方案有三个致命问题:

1. 权限恐吓

需要 MEDIA_PROJECTION 权限,系统会弹出录屏警告对话框。用户看到"录制屏幕上显示的所有内容"这种措辞,转化率直接腰斩。

2. 实现复杂

拿到 MediaProjection 后,还要创建 VirtualDisplay、ImageReader,处理像素缓冲区,管理生命周期,代码量至少上百行。

3. 隐私过度

你只需要一个像素的颜色值,却要请求整个屏幕的录制权限,属于典型的"杀鸡用牛刀"。

Eye Dropper API:极简方案

Android 17 的 Eye Dropper API 把这一切简化到了极致。核心就两个常量:

Compose 完整实现

bash 复制代码
@Composable
fun EyeDropperScreen() {
    var pickedColor by remember { mutableStateOf(Color.Gray) }
    var colorHex by remember { mutableStateOf("#808080") }

    val launcher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val colorInt = result.data?.getIntExtra(
                "android.intent.extra.COLOR",
                android.graphics.Color.BLACK
            ) ?: android.graphics.Color.BLACK

            pickedColor = Color(colorInt)
            colorHex = String.format("#%06X", 0xFFFFFF and colorInt)
        }
    }

    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        // 颜色预览
        Box(
            modifier = Modifier
                .size(120.dp)
                .clip(CircleShape)
                .background(pickedColor)
                .border(2.dp, Color.White, CircleShape)
        )

        Spacer(modifier = Modifier.height(16.dp))

        Text(
            text = colorHex,
            style = MaterialTheme.typography.headlineMedium,
            fontFamily = FontFamily.Monospace
        )

        Spacer(modifier = Modifier.height(32.dp))

        // 取色按钮
        Button(
            onClick = {
                launcher.launch(
                    Intent("android.intent.action.OPEN_EYE_DROPPER")
                )
            },
            enabled = Build.VERSION.SDK_INT >= 37
        ) {
            Text("Pick a Color")
        }
    }
}

没看错,完整功能代码不到 50 行。

它是怎么工作的?

Eye Dropper API 的设计哲学是最小化数据暴露:

bash 复制代码
┌──────────────┐    Intent     ┌──────────────┐
│              │ ─────────────→│              │
│   你的 App   │               │  系统取色器   │
│              │←─────────────│              │
└──────────────┘  Color Int    └──────────────┘
                                     │
                                     │ 系统级
                                     │ 像素读取
                                     ↓
                              ┌──────────────┐
                              │   屏幕像素   │
                              └──────────────┘

关键点在于:

对比一下两种方案的差异:

版本兼容处理

由于该 API 要求 API 37,建议做好版本判断和降级处理:

bash 复制代码
fun isEyeDropperAvailable(): Boolean {
    return Build.VERSION.SDK_INT >= 37
}

// 在 UI 中
Button(
    onClick = { /* launch eye dropper */ },
    enabled = isEyeDropperAvailable()
) {
    Text(
        if (isEyeDropperAvailable()) "Pick a Color"
        else "Requires Android 17+"
    )
}

也可以用 Intent.resolveActivity() 做更精确的判断:

bash 复制代码
val intent = Intent("android.intent.action.OPEN_EYE_DROPPER")
val isAvailable = intent.resolveActivity(packageManager) != null

适合哪些场景?

  • • 设计工具:从任意 App 中采集品牌色、UI 配色

  • • 图片编辑器:从照片或其他应用中精准取色

  • • 主题生成器:根据壁纸或任意界面自动提取主题色

  • • 无障碍工具:帮助色觉异常用户识别屏幕颜色

  • • 开发调试:快速获取任意界面元素的颜色值

总结

Android 17 的 Eye Dropper API 是一个小而美的 API 设计典范:

  • • 零权限:不需要声明任何权限

  • • 零隐私风险:App 只拿到一个颜色值,无法窥探屏幕内容

  • • 零学习成本:一个 Intent 发出去,一个 Int 拿回来

如果你的应用有取色需求,这将是 Android 17 最值得适配的 API 之一。

相关推荐
三少爷的鞋11 小时前
Java 线程自上而下,Kotlin 协程自下而上
android
好的佩奇13 小时前
Dart 之增强枚举
android·flutter·dart
梦影_13 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
好的佩奇16 小时前
蓝牙之无线电与通信距离
android·flutter·蓝牙
vilya16 小时前
我把一套完整的 Python Agent 运行时塞进手机 APK:依赖闭包、Rust 轮子和三个真机坑
android
呆呆敲代码的小Y18 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
思想觉悟20 小时前
SEAndroid实战
android·linux·c++
思想觉悟20 小时前
Aosp开发磨刀石之ADB速查
android·c++
应用市场1 天前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理
企业数字化笔记1 天前
表单发布前怎么验收?版本引用、字段兼容和历史数据回归
android·数据挖掘·回归