Android系统开发(十五):从 60Hz 到 120Hz,多刷新率进化简史

引言

欢迎来到“帧率探索实验室”!今天,我们要聊聊 Android 11 中对多种刷新率设备的支持。你可能会问:“这和我写代码有什么关系?”别急,高刷新率不仅仅让屏幕更顺滑,还会直接影响用户体验。想象一下,当你的 app 在 120Hz 上流畅飞舞,而别人的 app 却“卡”在 60Hz,是不是就已经赢了?本文将带你深挖多刷新率支持背后的硬核技术,帮助你的 app 成为用户的心头好。不多说了,先刷个屏,再来深入了解 Hz 的奥秘!
在这里插入图片描述


一、背景

自从手机厂商开始推出高刷新率设备,用户对“流畅体验”的期待不断提升。然而,高刷新率不仅仅是硬件层面的事,系统与应用也需要配合优化。Android 11 正是在这一背景下增加了对多种刷新率的支持。这项技术的核心,是通过 HAL(Hardware Abstraction Layer)、平台代码和全新的 SDK/NDK API,将设备能力和应用需求完美结合。想象一下,从 60Hz 到 90Hz,再到 120Hz,你的 app 瞬间“飞”起来,而用户的惊叹声便是对你努力的最好回报!
在这里插入图片描述


二、原理

多刷新率支持的核心,是如何让设备和应用协同工作,以实现动态调整帧率。

  1. HAL API:定义了设备硬件的能力接口。Android 11 中新增的 android.hardware.graphics.composer@2.4,负责管理设备支持的刷新率范围。
  2. 平台代码:系统解析设备配置文件,读取支持的刷新率选项,并为开发者提供设置接口。
  3. SDK 和 NDK API:通过 Java 或 C++ 调用,开发者可以指定应用的目标帧率。例如,游戏可以设置 120Hz,而视频播放可能限制在 60Hz。

这些组件协作,实现了设备硬件能力与应用实际需求的无缝对接。


三、实现

工具和环境
  • Android Studio 4.0 或更高版本
  • 支持多刷新率的 Android 11 设备
  • 必备工具:ADB 调试工具
步骤详解
  1. 读取设备支持的刷新率

    Display display = getDisplay();
    Display.Mode[] modes = display.getSupportedModes();
    for (Display.Mode mode : modes) {Log.d("RefreshRate", "Mode: " + mode.getRefreshRate() + " Hz");
    }
    
  2. 设置目标帧率
    使用 Surface.setFrameRate() API 设置帧率:

    Surface surface = getSurface();
    surface.setFrameRate(120.0f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
    
  3. 配置设备支持刷新率
    res/xml/device_config.xml 中定义设备支持的刷新率范围:

    <device><refresh-rate><min>60</min><max>120</max></refresh-rate>
    </device>
    

四、项目实战:高刷新率

在多刷新率支持的开发中,我们将通过三个实际案例展示如何实现动态刷新率设置。每个案例不仅包含详细实现步骤,还会提供代码示例,让你可以直接在项目中运行。


案例 1:高刷新率游戏开发
需求描述

为一款 FPS 游戏设置目标帧率为 120Hz,以提高用户的游戏体验,减少画面延迟感,确保高流畅度。

实现步骤
  1. 检查设备支持的刷新率
    在游戏初始化时,读取设备支持的刷新率范围,确保目标帧率可以被支持。

    Display display = getWindowManager().getDefaultDisplay();
    Display.Mode[] modes = display.getSupportedModes();
    for (Display.Mode mode : modes) {Log.d("GameRefreshRate", "Supported Refresh Rate: " + mode.getRefreshRate() + " Hz");
    }
    
  2. 设置高刷新率
    在游戏的主要渲染窗口(SurfaceViewSurfaceHolder)中,调用 Surface.setFrameRate(),指定目标刷新率为 120Hz。

    Surface surface = surfaceView.getHolder().getSurface();
    surface.setFrameRate(120.0f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
    
  3. 优化渲染逻辑
    使用 Choreographer 实现高帧率下的精准帧同步。

    Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {renderFrame(); // 渲染游戏帧Choreographer.getInstance().postFrameCallback(this);}
    });
    
最终效果

运行在支持 120Hz 刷新率设备上的游戏画面更流畅,用户操作响应更加快速,显著提升了用户体验。


案例 2:高效视频播放器开发
需求描述

在一个视频播放器中,根据视频帧率动态调整设备的刷新率,以确保流畅播放,并避免额外的功耗。例如,为 30fps 视频设置 60Hz 刷新率,为 60fps 视频设置 120Hz 刷新率。

实现步骤
  1. 获取视频帧率
    在播放器初始化时,解析视频文件,获取其原始帧率。

    MediaExtractor extractor = new MediaExtractor();
    extractor.setDataSource(videoPath);
    MediaFormat format = extractor.getTrackFormat(0);
    int frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
    Log.d("VideoPlayer", "Video Frame Rate: " + frameRate);
    
  2. 动态调整刷新率
    根据帧率,调用 Surface.setFrameRate() 设置设备刷新率。

    float targetRefreshRate = frameRate > 60 ? 120.0f : 60.0f;
    surface.setFrameRate(targetRefreshRate, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
    
  3. 同步播放帧率
    使用 ExoPlayer 的帧回调功能,与设备刷新率同步。

    player.setVideoFrameMetadataListener((presentationTimeUs, releaseTimeNs, format) -> {surface.setFrameRate(format.frameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
    });
    
最终效果

视频播放始终匹配设备刷新率,避免因刷新率差异导致的卡顿或撕裂现象,同时节省电量。


案例 3:动态刷新率切换应用
需求描述

开发一个动态切换刷新率的工具应用,用户可以通过界面选择不同的目标刷新率,并实时应用到设备屏幕。

实现步骤
  1. 设计 UI 界面
    提供一个下拉菜单,显示设备支持的所有刷新率选项。

    <Spinnerandroid:id="@+id/spinner_refresh_rate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:entries="@array/refresh_rates" />
    
  2. 获取支持的刷新率
    Activity 初始化时,读取设备支持的刷新率,并填充到下拉菜单中。

    Display display = getWindowManager().getDefaultDisplay();
    Display.Mode[] modes = display.getSupportedModes();
    ArrayList<String> refreshRates = new ArrayList<>();
    for (Display.Mode mode : modes) {refreshRates.add(mode.getRefreshRate() + " Hz");
    }
    ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, refreshRates);
    spinner.setAdapter(adapter);
    
  3. 实现动态切换逻辑
    根据用户选择,动态应用刷新率。

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {Display.Mode mode = modes[position];Window window = getWindow();window.setPreferredRefreshRate(mode.getRefreshRate());}@Overridepublic void onNothingSelected(AdapterView<?> parent) {}
    });
    
  4. 适配不同设备
    检查设备是否支持动态刷新率切换,确保应用在低版本设备上可以正常运行。

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {// 支持 Android 11 以上的设备动态刷新率切换
    } else {Log.w("RefreshRateApp", "Dynamic refresh rate not supported on this device.");
    }
    
最终效果

用户可以通过界面实时切换刷新率,应用直接调整屏幕刷新率,感受到流畅与动态切换的便利。


归纳

这些项目展示了多刷新率支持的不同应用场景,包括高帧率游戏、流畅视频播放器和动态刷新率工具。每个案例都提供了详细的代码与实现步骤,可以直接用于实践或改进开发效率。

五、避坑

  1. 设备支持问题:并非所有设备都支持高刷新率,需检查兼容性。
  2. 耗电问题:高刷新率耗电量增加,需平衡性能与功耗。
  3. API 调用失败:确保使用了 Android 11 或更高版本的 API。

六、快稳省

优点
  • 极大提升用户体验。
  • 提供灵活的帧率设置接口,满足不同场景需求。
缺点
  • 增加开发复杂度。
  • 不支持低版本设备。

七、性能

使用 GPU Profiler 监测高刷新率下的应用性能,评估帧率与资源消耗的平衡点。


八、未来

未来,Android 系统或将支持更智能的动态帧率调整,结合 AI 技术预测用户操作,进一步优化资源分配。

本文从技术背景、实现原理到项目实战,为你详细解析了 Android 11 多刷新率支持。希望通过这些技术,让你的应用体验更上一层楼!


九、开发者选项

设置菜单中新增了一个开发者选项,它可以使用当前刷新率在屏幕上切换叠加层。新选项位于设置 > 系统 > 开发者选项 > 显示刷新频率下。
在这里插入图片描述

十、参考资料

以下是撰写本文时参考的技术资源,涵盖书籍、论文、官方网站和博客,帮助读者进一步深入理解多刷新率支持的实现与优化。


官方文档
  1. Android Developers Documentation

    • 官方多刷新率支持文档
      Android 官方提供的多刷新率支持指南,详细介绍了功能组成、API 使用方法和平台支持。
  2. Surface API Reference

    • Surface.setFrameRate
      提供 Surface 类的完整 API 说明,包含帧率设置和兼容性选项。
  3. NDK Documentation

    • NDK API for Refresh Rate
      介绍了通过 NDK 实现刷新率动态调整的相关工具和方法。

书籍
  1. 《Android 高级编程》
    作者:[Joseph Annuzzi Jr., Lauren Darcey, Shane Conder]
    讲解 Android 开发高级特性,包括硬件抽象层和系统架构,适合了解多刷新率支持的底层实现。

  2. 《Android 深入理解与实战》
    作者:邓凡平
    提供 Android 系统机制与应用开发的深入剖析,是学习 Android 系统级开发的好工具书。

  3. 《Graphics Programming Black Book》
    作者:Michael Abrash
    虽然主要针对图形编程基础,但对优化刷新率和性能调优有很大的启发。


论文
  1. “Variable Refresh Rate Displays and Their Impact on Visual Performance”
    描述多刷新率技术在视觉效果和用户体验中的重要性,涵盖了刷新率动态调整的研究数据。

  2. “Adaptive Refresh Rate Mechanisms in Modern Display Technologies”
    探讨了现代显示技术中自适应刷新率机制的设计与实现。


技术博客
  1. Android Developers Blog: New Features in Android 11
    Android 官方博客详细介绍了 Android 11 的新特性,包括多刷新率支持。

  2. Medium: Implementing High Refresh Rates in Android Apps
    技术博主在实际项目中如何实现动态刷新率设置的案例分享。

  3. CSDN: 动态刷新率实现的坑与优化
    提供在实际开发过程中遇到的问题及解决方案。


社区资源
  1. Stack Overflow

    • Handling Variable Refresh Rates
      解答开发者在多刷新率开发中常见的问题,拥有丰富的社区实践经验。
  2. GitHub

    • 示例代码仓库:Dynamic Refresh Rate Demo
      提供完整的多刷新率实现样例代码,可直接下载学习。

工具与环境
  1. Android Studio Arctic Fox 或更高版本
    支持 Android 11 开发的 IDE。

  2. 设备

    • 测试设备需支持多刷新率,如 Pixel 5、Samsung Galaxy S 系列等。
  3. 工具

    • adb shell:用于调试和检查设备支持的刷新率。
    • Choreographer:实现帧同步的重要工具。

这些参考资料涵盖了理论知识、实践经验和代码示例,帮助开发者全面掌握多刷新率技术的实现与优化。如果你有更多推荐或想法,欢迎在评论区留言交流! 😊

文章结尾

欢迎关注我们的 GongZhongHao:码农的乌托邦,程序员的精神家园!获取更多技术干货,我们一起提升代码水平!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/6002.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Genetic Prompt Search via Exploiting Language Model Probabilities

题目 利用语言模型概率的遗传提示搜索 论文地址&#xff1a;https://www.ijcai.org/proceedings/2023/0588.pdf 项目地址&#xff1a;https://github.com/zjjhit/gap3 摘要 针对大规模预训练语言模型(PLMs)的即时调优已经显示出显著的潜力&#xff0c;尤其是在诸如fewshot学习…

css动画水球图

由于echarts水球图动画会导致ios卡顿&#xff0c;所以纯css模拟 展示效果 组件 <template><div class"water-box"><div class"water"><div class"progress" :style"{ --newProgress: newProgress % }"><…

接口 V2 完善:基于责任链模式、Canal 监听 Binlog 实现数据库、缓存的库存最终一致性

&#x1f3af; 本文介绍了一种使用Canal监听MySQL Binlog实现数据库与缓存最终一致性的方案。文章首先讲解了如何修改Canal配置以适应订单表和时间段表的变化&#xff0c;然后详细描述了通过责任链模式优化消息处理逻辑的方法&#xff0c;确保能够灵活应对不同数据表的更新需求…

postgresql15的停止

PostgreSQL是一个功能非常强大的、源代码开放的客户/服务器关系型数据库管理系统&#xff0c;且因为许可证的灵活&#xff0c;任何人都可以以任何目的免费使用、修改和分发PostgreSQL。介绍过postgresql的启动方法&#xff0c;就很有必要介绍下postgresql的停止方法。 一、停止…

IP协议格式

在传输层中有两个重要的协议&#xff0c;分别为UDP和TCP。UDP追求高效的效率&#xff0c;TCP追求更可靠的传输。但是这两个协议都太极端了&#xff0c;有没有一个协议可以在保证可靠性的同时又不失较高的效率。 针对上面的问题&#xff0c;网络层的IP协议是更好的解决方案。 …

Qt Creator 15.0.0如何更换主题和字体

1.打开Qt Creator 15.0.0 (Community)&#xff0c; 2.点击编辑栏3.点击Preferences... 4.修改主题&#xff0c;点击环境&#xff0c;修改Theme:栏 5.修改字体大小&#xff0c;点击文本编辑器&#xff0c;修改字号栏。&#xff0c;修改Theme:栏

靶机复现-pikachu靶机文件包含漏洞

本篇文章旨在为网络安全渗透测试靶机复现学习。通过阅读本文&#xff0c;读者将能够对渗透pikachu靶场文件包含漏洞复现有一定的了解 原文学习链接 CSDN博主&#xff1a;One_Blanks主页地址 靶机资源下载 PHPStudy pikachu 一、前言 文件包含漏洞是编程中的一种安全隐患&a…

机器学习-线性回归(简单回归、多元回归)

这一篇文章&#xff0c;我们主要来理解一下&#xff0c;什么是线性回归中的简单回归和多元回归&#xff0c;顺便掌握一下特征向量的概念。 一、简单回归 简单回归是线性回归的一种最基本形式&#xff0c;它用于研究**一个自变量&#xff08;输入&#xff09;与一个因变量&…

5.SQLAlchemy对两张有关联关系表查询

问题 例如&#xff0c;一个用户可以有多个收获地址。 定义表如下&#xff1a; 用户表 地址表 一般情况&#xff0c;我们会先查询用户表&#xff0c;拿到用户id后&#xff0c;再到地址表中查询关联的地址数据。这样就要执行两次查询。 仅仅为了方便查询&#xff0c;需要一些属…

【Unity】ScrollViewContent适配问题(Contentsizefilter不刷新、ContentSizeFilter失效问题)

最近做了一个项目&#xff0c;菜单栏读取数据后自动生成&#xff0c;结果用到了双重布局 父物体 尝试了很多方式&#xff0c;也看过很多大佬的文章&#xff0c;后来自己琢磨了一下&#xff0c;当子物体组件自动生成之后&#xff0c;使用以下以下代码效果会好一些&#xff1a; …

springboot基于微信小程序的商城系统

基于Spring Boot的微信小程序商城系统是一种现代化的电商解决方案&#xff0c;它将Spring Boot框架的强大后端能力与微信小程序的便捷前端体验相结合&#xff0c;为商家和用户提供了高效、稳定的在线购物平台。 一、后端框架 &#xff1a;Spring Boot 1. 简介&#xff1a; 2.…

63,【3】buuctf web Upload-Labs-Linux 1

进入靶场 点击pass1 查看提示 既然是上传文件&#xff0c;先构造一句话木马&#xff0c;便于用蚁剑连接 <?php eval($_POST[123])?> 上传木马 文件后缀写为.php.jpg 右键复制图片地址 打开蚁剑连接 先点击测试连接&#xff0c;显示成功后&#xff0c;再点击添加即可 …

【玩转全栈】----基于ModelForm完成用户管理页面

目录 大致效果 添加用户代码 引入ModelForm ModelForm 与一般表单的区别&#xff1a; ModelForm 与传统 Form 的区别&#xff1a; 使用ModelForm制作用户管理 新建用户 编辑用户&#xff1a; 删除数据 完整代码 在学完前面的部门管理案例后&#xff0c;自己独立写出个用户管理应…

AIGC视频生成模型:ByteDance的PixelDance模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍ByteDance的视频生成模型PixelDance&#xff0c;论文于2023年11月发布&#xff0c;模型上线于2024年9月&#xff0c;同时期上线的模型还有Seaweed&…

深入探究 YOLOv5:从优势到模型导出全方位解析

一、引言 在计算机视觉领域&#xff0c;目标检测是一项至关重要的任务&#xff0c;它在自动驾驶、安防监控、工业检测等众多领域都有着广泛的应用。而 YOLO&#xff08;You Only Look Once&#xff09;系列作为目标检测算法中的佼佼者&#xff0c;一直备受关注。其中&#xff…

Qt —— 控件属性

一、概述 控件有很多属性&#xff0c;我们学习和整理常见和常用的几个属性&#xff0c;由于所有的控件基本都是继承Widget类的&#xff0c;所以前面会先拿Widget类和常见的控件进行示范。 Qt Designer左侧一长条就是Qt给我们内置好的控件&#xff1a; 二、enabled 状态属性 …

会议签到系统的架构和实现

会议签到系统的架构和实现 摘要:通过定制安卓会议机开机APP呈现签到界面&#xff0c;并且通过W/B结构采集管理签到信息&#xff0c;实现会议签到的功能。为达到此目标本文将探讨使用Redis提供后台数据支持&#xff1b;使用SocketIo处理适时消息&#xff1b;使用Flask进行原型开…

WPF实战案例 | C# WPF实现大学选课系统

WPF实战案例 | C# WPF实现大学选课系统 一、设计来源1.1 主界面1.2 登录界面1.3 新增课程界面1.4 修改密码界面 二、效果和源码2.1 界面设计&#xff08;XAML&#xff09;2.2 代码逻辑&#xff08;C#&#xff09; 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&a…

JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南

1、简述 在复杂的业务系统中&#xff0c;订单流程往往需要一系列的操作&#xff0c;比如验证订单、检查库存、处理支付、更新订单状态等。责任链模式&#xff08;Chain of Responsibility&#xff09;可以帮助我们将这些处理步骤分开&#xff0c;并且以链式方式处理每一个操作…

stm32单片机个人学习笔记14(USART串口数据包)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…