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 后,还要创建 VirtualDisplayImageReader,处理像素缓冲区,管理生命周期,代码量至少上百行。

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 之一。

相关推荐
SHoM SSER2 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
程序员陆业聪4 小时前
别再说 Flutter 是唯一选择了——KMP 正在悄悄抢走它的地盘
android
三少爷的鞋4 小时前
2026 已过 1/3:事豫则立,不预则废——关于架构、协程与边界的思考
android
冬奇Lab4 小时前
Android 15 音频子系统(八):Audio HAL 与硬件接口——音频数据的最后一公里
android·音视频开发·源码阅读
黄林晴7 小时前
Compose Multiplatform 1.10 发布:里程碑式更新!
android
流星白龙7 小时前
【MySQL】19.MySQL用户管理
android·mysql·adb
匆忙拥挤repeat8 小时前
Android Compose 可组合项的生命周期、副作用API
android
hnlgzb9 小时前
目前编写安卓app的话有哪几种设计模式?
android·设计模式·kotlin·android jetpack·compose
studyForMokey9 小时前
【Android面试】Fragment生命周期专题
android·microsoft·面试