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.mzph.cn/news/893532.shtml

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

相关文章

基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【Arduino】语言参考功能

前言 翻译Arduino 参考处列出的常用函数。文中为了减少篇幅&#xff0c;达到能快速翻到查询的目标&#xff0c;在介绍函数中&#xff0c;对部分内容进行了省略&#xff0c;不会列出函数输入参数类型&#xff0c;以及使用注意事项等等&#xff0c;所以若是首次使用或者是调试时出…

Alibaba Spring Cloud 二 Seata 的详细介绍、使用场景以及集成方法

Seata 是一个开源的分布式事务解决方案&#xff0c;它由阿里巴巴开源&#xff0c;专注于解决微服务架构中的分布式事务问题。它支持高性能的分布式事务处理&#xff0c;提供了多种事务模型&#xff08;AT、TCC、SAGA 和 XA&#xff09;&#xff0c;并与 Spring Boot 和 Spring …

ChatGPT结合Excel辅助学术数据分析详细步骤分享!

目录 一.Excel在学术论文中的作用✔ 二.Excel的提示词✔ 三. 编写 Excel 命令 四. 编写宏 五. 执行复杂的任务 六. 将 ChatGPT 变成有用的 Excel 助手 一.Excel在学术论文中的作用✔ Excel作为一种广泛使用的电子表格软件&#xff0c;在学术论文中可以发挥多种重要作用&a…

flume和kafka整合 flume和kafka为什么一起用?

‌Flume和Kafka一起使用的主要原因是为了实现高效、可靠的数据采集和实时处理。‌‌12 实时流式日志处理的需求 Flume和Kafka结合使用的主要目的是为了完成实时流式的日志处理。Flume负责数据的采集和传输,而Kafka则作为消息缓存队列,能够有效地缓冲数据,防止数据堆积或丢…

国内有哪些著名的CRM系统提供商?

嘿&#xff0c;你有没有想过&#xff0c;在这个信息爆炸的时代里&#xff0c;企业怎么才能更好地管理客户关系呢&#xff1f;答案就是使用高效的CRM系统。今天我就来给大家聊聊那些在国际上非常有名的CRM系统提供商吧。 悟空CRM 首先不得不提的就是悟空CRM了&#xff01;这可…

Linux中的几个基本指令(二)

文章目录 1、cp指令例一&#xff1a;例二&#xff1a;例三&#xff1a;例四&#xff1a;例五&#xff1a; 2、mv 指令例一&#xff1a;例二&#xff1a; 3、cat指令例一&#xff1a; 4、tac指令5、which指令6、date指令时间戳&#xff1a;7、zip指令 今天我们继续学习Linux下的…

mock可视化生成前端代码

介绍&#xff1a;mock是我们前后端分离的必要一环、ts、axios编写起来也很麻烦。我们就可以使用以下插件&#xff0c;来解决我们的问题。目前支持vite和webpack。&#xff08;配置超级简单&#xff01;&#xff09; 欢迎小伙伴们提issues、我们共建。提升我们的开发体验。 vi…

【Linux】APT 密钥管理迁移指南:有效解决 apt-key 弃用警告

引言 随着 Debian 11 和 Ubuntu 22.04 版本的推出&#xff0c;APT 的密钥管理方式发生了重大的变化。apt-key 命令被正式弃用&#xff0c;新的密钥管理机制要求使用 /etc/apt/keyrings/ 或 /etc/apt/trusted.gpg.d/ 来存储和管理密钥。这一变化对管理员和普通用户来说至关重要…

9. 神经网络(一.神经元模型)

首先&#xff0c;先看一个简化的生物神经元结构&#xff1a; 生物神经元有多种类型&#xff0c;内部也有复杂的结构&#xff0c;但是可以把单个神经元简化为3部分组成&#xff1a; 树突&#xff1a;一个神经元往往有多个树突&#xff0c;用于接收传入的信息。轴突&#xff1a;…

Web 音视频(二)在浏览器中解析视频

前言 浏览器中已经能直接播放视频&#xff0c;为什么还需要手动写代码解析&#xff1f; 因为&#xff0c;某些场景需要对视频进行更细致的处理&#xff0c;比如截取关键帧、提取视频中的文字、人物打码、极低延时播放视频等等。 总之&#xff0c;除了最单纯的视频播放外&…

代码随想录刷题day14(2)|(链表篇)02.07. 链表相交(疑点)

目录 一、链表理论基础 二、链表相交求解思路 三、相关算法题目 四、疑点 一、链表理论基础 代码随想录 二、链表相交求解思路 链表相交时&#xff0c;是结点的位置&#xff0c;也就是指针相同&#xff0c;不是结点的数值相同&#xff1b; 思路&#xff1a;定义两个指针…

ETLCloud在iPaas中的是关键角色?

在当今的数字化时代&#xff0c;企业越来越依赖于其处理和分析数据的能力。为了实现这一目标&#xff0c;企业需要将各种异构的应用和数据源集成在一起&#xff0c;形成一个统一的数据视图。在这一过程中&#xff0c;ETL&#xff08;Extract, Transform, Load&#xff09;和iPa…

以太网实战AD采集上传上位机——FPGA学习笔记27

一、设计目标 使用FPGA实现AD模块驱动采集模拟电压&#xff0c;通过以太网上传到电脑上位机。 二、框架设计 数据位宽转换模块&#xff08;ad_10bit_to_16bit&#xff09;&#xff1a;为了方便数据传输&#xff0c;数据位宽转换模块实现了将十位的 AD 数据转换成十六位&#…

YOLOv1、YOLOv2、YOLOv3目标检测算法原理与实战第十三天|YOLOv3实战、安装Typora

1.学习哔哩哔哩《YOLOv1、YOLOv2、YOLOv3目标检测算法原理与实战》 炮哥带你学视频链接 第5章 YOLOv3实战 5.1 YOLOv3实战先导 5.2 pycharm与anaconda的安装 之前已经安装过了&#xff0c;见Pytorch框架与经典卷积神经网络与实战第一天|安装PyCharm&Anaconda&#xff0…

C语言常用知识结构深入学习

面试大保健-C语言-变量day01 1. C语言的重要性 大家好&#xff01;今天我们来聊一聊 C 语言。作为嵌入式开发的基础&#xff0c;C语言在面试中必定是一个重点&#xff0c;虽然具体会问到哪些问题不好预测&#xff0c;但可以肯定的是&#xff0c;基础知识绝对不会少问。所以&a…

Java算法——排序

目录 引言1. 插入排序1.1 基本思想1.2 直接插入排序1.3 希尔排序 2. 选择排序2.1 基本思想2.2 直接选择排序2.3 直接选择排序变种2.4 堆排序 3. 交换排序3.1 基本思想3.2 冒泡排序3.3 快速排序3.3.1 快速排序的基本结构3.3.2 Hoare法3.3.3 挖坑法3.3.4 双指针法 3.4 快速排序非…

java字典注入与关联注入

一、注解类 import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Documented Target(ElementType.METHOD) Retent…

数据库SQLite和SCADA DIAView应用教程

课程简介 此系列课程大纲主要包含七个课时。主要使用到的开发工具有&#xff1a;SQLite studio 和 SCADA DIAView。详细的可成内容大概如下&#xff1a; 1、SQLite 可视化管理工具SQLite Studio &#xff1a;打开数据库和查询数据&#xff1b;查看视频 2、创建6个变量&#x…

docker 部署.netcore应用优势在什么地方?

目录 1. 环境一致性 2. 简化依赖管理 3. 快速部署与扩展 4. 资源利用率高 5. 版本控制与回滚 6. 安全性 7. 生态系统支持 8. 微服务架构支持 9. 降低成本 10. 开发体验提升 总结 使用 Docker 部署 .NET Core 应用有许多优势&#xff0c;特别是在开发、测试和生产环境…