前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[029]如何获取屏幕帧率

[029]如何获取屏幕帧率

作者头像
王小二
发布2020-06-08 10:53:11
2.1K0
发布2020-06-08 10:53:11
举报

前言

王小二图解Android【006】高帧率屏幕这期的视频中,我给大家揭秘今年所有安卓旗舰都会吹的高帧率屏幕,其实高帧率屏幕不需要应用开发人员去主动适配,只要应用能在当前的硬件配置下,规定时间(1s/屏幕帧率)中完成一帧的绘制就可以了。

那肯定有人就要问了,能否当前获得屏幕帧率,然后对高帧率屏幕做针对性优化,在有限的时间内完成一帧的绘制。

一、标准SDK接口

很简单,只要能够拿到WindowManager就可以获取。

代码语言:javascript
复制
//this是Activity
Log.v("Kobe", "Screen Hz is " + this.getWindowManager().getDefaultDisplay().getRefreshRate());
代码语言:javascript
复制
02-26 23:31:50.526 18982 18982 V Kobe    : Screen Hz is 60.000004

二、帧率约等于 1s/两次Vsync时间差

代码语言:javascript
复制
public class MainActivity extends AppCompatActivity {

    private long firstVsync;
    private long secondVsync;

    private Choreographer.FrameCallback firstCallBack = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            firstVsync = frameTimeNanos;
            Choreographer.getInstance().postFrameCallback(secondCallBack);
        }
    };

    private Choreographer.FrameCallback secondCallBack = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            secondVsync = frameTimeNanos;
            //1s = 1000000000ns
            long hz = 1000000000 / (secondVsync - firstVsync);
            Log.v("Kobe", "Screen Hz is " + hz);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        HandlerThread vSyncThread = new HandlerThread("Vsync");
        vSyncThread.start();
        Handler handler = new Handler(vSyncThread.getLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Choreographer.getInstance().postFrameCallback(firstCallBack);
            }
        });
    }
}

原理就是利用Choreographer这个类的postFrameCallback的方法。调用postFrameCallback之后将会在下一个Vsync信号来的时候触发运行FrameCallback的doFrame,Vsync的上报时间就是形参frameTimeNanos(单位:纳秒)。

代码语言:javascript
复制
long hz = 1000000000 / (secondVsync - firstVsync);

简单的计算就可以算出来了。

代码语言:javascript
复制
02-26 23:38:01.633 19234 19261 V Kobe    : Screen Hz is 59//大概的推测出是60hz的屏幕

有没有发现上述代码中的两个细节

1.Choreographer.getInstance()必须运行在有Looper的线程中。

因为Vsync信号的监听是通过Looper中的epoll机制监听的。

2.我没有使用主线程的Looper,而是另外新建HandlerThread。

因为主线程的Looper比较忙,容易导致Vsync信号监听推迟,导致两次Vsync时间差不对。 我之前没有另外新建HandlerThread,得到的结果是不固定的,而且是错的。

代码语言:javascript
复制
02-26 23:22:29.374 18442 18442 V Kobe    : Screen Hz is 14
02-26 23:31:21.079 18753 18753 V Kobe    : Screen Hz is 19
如果听不懂,可以看我的视频

王小二图解Android【001】Looper上篇 王小二图解Android【002】Looper下篇

三、总结

一般来说用标准SDK接口就够了,为什么我要大费周章的讲方法2,其实是想让大家了解Choreographer的作用,因为在我们调用View的渲染中就是用到了这个类,在下一个Vsync信号到来的时候触发渲染的代码。

思考

如果你们有其他想法可以获得屏幕的帧率,也可以回复留言。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、标准SDK接口
  • 二、帧率约等于 1s/两次Vsync时间差
    • 有没有发现上述代码中的两个细节
    • 三、总结
    • 思考
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档