心里种花,人生才不会荒芜,如果你也想一起成长,请点个关注吧。
在 Android 开发中,监控应用的帧率(FPS)是评估应用性能和发现卡顿问题的一个重要指标。本次介绍一些常用的方法来监控 Android 应用的 FPS,包括如何实现这些方法的详细说明和代码示例。
从 Android 4.1(API 16)开始,Choreographer API 能够帮助开发者在每一帧进行操作,适合用于 FPS 的监控。
在使用 Choreographer API 中,可以通过以下方式判断掉帧或卡顿:
1、 计算帧间隔时间:
doFrame 方法中两次回调的时间差,如果明显高于目标帧时间间隔(例如大于16ms),则说明可能出现掉帧或卡顿。2、 设置阈值:
Choreographer.FrameCallback 接口来实现帧率监控。import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.view.Choreographer;
public class FPSMonitor implements Choreographer.FrameCallback {
private static final String TAG = "FrameMonitor";
private static final long FRAME_INTERVAL_NANOS = 16666666; // 16.6ms in nanoseconds (roughly 60 FPS)
private long lastFrameTimeNanos = 0;
public void start() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
Choreographer.getInstance().postFrameCallback(this);
} else {
// 对于低于 API 16 的设备需要实现兼容方案
Log.e(TAG, "Device does not support Choreographer API");
}
}
@Override
public void doFrame(long frameTimeNanos) {
if (lastFrameTimeNanos == 0) {
lastFrameTimeNanos = frameTimeNanos;
} else {
long elapsedNanos = frameTimeNanos - lastFrameTimeNanos;
if (elapsedNanos > FRAME_INTERVAL_NANOS) {
long droppedFrames = elapsedNanos / FRAME_INTERVAL_NANOS;
Log.w(TAG, "Dropped frames: " + droppedFrames);
// 检测到掉帧,打印当前线程的堆栈信息
Thread currentThread = Thread.currentThread();
StackTraceElement[] stackTraceElements = currentThread.getStackTrace();
StringBuilder stackTrace = new StringBuilder("Stack trace:\n");
for (StackTraceElement element : stackTraceElements) {
stackTrace.append("\tat ").append(element.toString()).append("\n");
}
Log.i(TAG, stackTrace.toString());
}
lastFrameTimeNanos = frameTimeNanos;
}
// Schedule the next frame callback
Choreographer.getInstance().postFrameCallback(this);
}
}
public class MainActivity extends AppCompatActivity {
private FPSMonitor fpsMonitor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fpsMonitor = new FPSMonitor();
fpsMonitor.start();
}
}
在 Android 7.0(API 24)及更高版本中,你可以使用 FrameMetrics API 来监控应用的帧率和掉帧情况。FrameMetrics 提供了一种强大的方法来衡量和分析视图的绘制性能。
以下是使用 FrameMetrics API 进行掉帧检测的详细介绍和代码示例:
1、 确保设备支持:仅在 API 24 及更高版本上可用,因此需要进行版本检查。
2、 注册 FrameMetrics Listener:
我们需要使用 Window 对象来注册一个 OnFrameMetricsAvailableListener,这个监听器会在每一帧结束时提供 FrameMetrics 数据。
以下是一个简单的示例,展示如何使用 FrameMetrics API 进行掉帧检测并打印相关信息:
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.FrameMetrics;
import android.view.Window;
import android.view.Window.OnFrameMetricsAvailableListener;
public class FrameMetricsActivity extends Activity {
private static final String TAG = "FrameMetricsActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getWindow().addOnFrameMetricsAvailableListener(new OnFrameMetricsAvailableListener() {
@Override
public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, int dropCountSinceLastInvocation) {
long totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION);
long intendedDuration = frameMetrics.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)
- frameMetrics.getMetric(FrameMetrics.FRAME_PRESENT_TIMESTAMP);
// 拿到掉的帧数量
Log.d(TAG, "Dropped frames since last: " + dropCountSinceLastInvocation);
if (totalDuration > intendedDuration) {
Log.w(TAG, "Frame duration exceeded: " + totalDuration);
// 当检测到掉帧时打印堆栈信息
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StringBuilder stackTrace = new StringBuilder("Stack trace:\n");
for (StackTraceElement element : stackTraceElements) {
stackTrace.append("\tat ").append(element.toString()).append("\n");
}
Log.i(TAG, stackTrace.toString());
}
}
}, null);
} else {
Log.e(TAG, "FrameMetrics API not available on this device");
}
}
}
TOTAL_DURATION:表示完整帧的时间,包括应用、合成和发布时间。INTENDED_VSYNC_TIMESTAMP 和 FRAME_PRESENT_TIMESTAMP 之间的差值被认为是理想的帧时间。TOTAL_DURATION 大于理想持续时间,则可能存在掉帧。SurfaceView 的 FPS 监控:
SurfaceView,可以在绘制回调中统计帧率。OpenGL 的 FPS 监控:
SwapBuffers 时统计帧率。第三方工具:
TraceView 和 systrace:
TraceView 和 systrace 工具可以帮助深度分析性能瓶颈,尽管不是实时监控,但有助于定位问题。
END
点赞转发,让精彩不停歇!关注我们,评论区见,一起期待下期的深度好文!