You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android实现SeekBar亮度调节与系统亮度变化检测同步问题

问题描述

在Android应用中实现了SeekBar调节系统亮度,同时监听系统亮度变化同步到SeekBar,但部分小米设备(如Redmi Note7)的亮度范围为0-4000,与官方文档定义的0-255不符,且无公开API可获取亮度最大值,导致双向同步功能失效。

原调节亮度代码:

binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
    @RequiresApi(api = Build.VERSION_CODES.M)
    override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
        val permission = Settings.System.canWrite(applicationContext)
        if (permission) {
            var brightnessValue = p1 * 255 / 100
            Settings.System.putInt(
                applicationContext.contentResolver,
                Settings.System.SCREEN_BRIGHTNESS_MODE,
                Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
            Settings.System.putInt(contentResolver, SCREEN_BRIGHTNESS, brightnessValue)
            binding.seekBar.progress = brightnessValue
        } else {
            val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
            intent.data = Uri.parse("package:" + applicationContext.packageName)
            startActivityForResult(intent, 0)
        }
    }

    override fun onStartTrackingTouch(p0: SeekBar?) {
    }

    override fun onStopTrackingTouch(p0: SeekBar?) {
    }
})

原监听亮度变化代码:

val contentObserver: ContentObserver = object : ContentObserver(Handler()) {
    override fun onChange(selfChange: Boolean) {
        val a = Settings.System.getInt(contentResolver, SCREEN_BRIGHTNESS, 0)
        Log.d("MainActivity", "Brightness value: $a")
        binding.seekBar.progress = a* 255 / 100
    }
}
contentResolver.registerContentObserver(
    Settings.System.getUriFor(SCREEN_BRIGHTNESS),
    false, contentObserver
)
解决方案

核心思路是通过比例映射适配设备实际亮度范围,避免依赖硬编码的最大值,同时加入状态标记避免循环同步。

1. 获取设备实际亮度最大值

由于无公开API,通过写入大值再读取的方式获取设备支持的亮度上限:

private fun getMaxBrightness(): Int {
    val resolver = contentResolver
    // 尝试写入一个足够大的值
    Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, 4000)
    // 读取实际生效的最大值
    return Settings.System.getInt(resolver, Settings.System.SCREEN_BRIGHTNESS, 255)
}

2. 修正SeekBar调节逻辑

将SeekBar固定为0-100的用户友好范围,通过比例转换为设备实际亮度值,同时关闭自动亮度避免冲突:

private var isUpdatingFromApp = false // 标记是否为应用内部修改亮度
val maxBrightness = getMaxBrightness()

binding.seekBar.max = 100 // 设置SeekBar进度范围为0-100

binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
    @RequiresApi(api = Build.VERSION_CODES.M)
    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        if (!fromUser) return // 非用户操作直接返回,避免循环同步
        val permission = Settings.System.canWrite(applicationContext)
        if (permission) {
            // 关闭自动亮度模式,确保手动调节生效
            Settings.System.putInt(
                contentResolver,
                Settings.System.SCREEN_BRIGHTNESS_MODE,
                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
            )
            isUpdatingFromApp = true
            // 将SeekBar进度转换为设备实际亮度值
            val brightnessValue = (progress * maxBrightness / 100).coerceIn(0, maxBrightness)
            Settings.System.putInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS, brightnessValue)
            isUpdatingFromApp = false
        } else {
            val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
            intent.data = Uri.parse("package:" + applicationContext.packageName)
            startActivityForResult(intent, 0)
        }
    }

    override fun onStartTrackingTouch(p0: SeekBar?) {}
    override fun onStopTrackingTouch(p0: SeekBar?) {}
})

3. 修正亮度监听同步逻辑

监听系统亮度变化时,将实际亮度值转换为SeekBar的0-100进度,同时跳过应用内部修改的触发:

val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
    override fun onChange(selfChange: Boolean) {
        if (isUpdatingFromApp) return // 跳过应用内部修改的同步
        val currentBrightness = Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS, 0)
        // 将实际亮度值转换为SeekBar进度
        val progress = (currentBrightness * 100 / maxBrightness).coerceIn(0, 100)
        binding.seekBar.progress = progress
    }
}

contentResolver.registerContentObserver(
    Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
    false,
    contentObserver
)

4. 销毁时清理资源

在Activity销毁时注销ContentObserver,避免内存泄漏:

override fun onDestroy() {
    super.onDestroy()
    contentResolver.unregisterContentObserver(contentObserver)
}

内容的提问来源于stack exchange,提问作者Halil Ozel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:27:17