首先简单介绍下检测流畅度的原理:
大家在看logcat的时候是不是有时候会看到这样的log
Skipped 30 frames! The application may be doing too much work on its main thread.
输出这段log的是android.view.Choreographer
private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt("debug.choreographer.skipwarning", 30); |
也就是当跳帧数大于设置的SKIPPED_FRAME_WARNING_LIMIT
值时会在当前进程输出这个log.
这也是google在android 4.1中加入的vsync垂直同步特性,防止界面过于卡顿。
那么我们只要捕获这个log提取出skippedFrames
不就可以知道界面是否卡顿了吗?
而且如果可以把SKIPPED_FRAME_WARNING_LIMIT
设置为1的话更是可以非常精准的知道跳过了多少帧!
首先非常感谢腾讯开源了 TencentOpen/GT,现在我们来看看GT是怎么做到的:
1.在com.tencent.wstt.gt.plugin.smtools.SMActivity
中我们看到几条读写prop的命令
>getprop debug.choreographer.skipwarning //读取
setprop debug.choreographer.skipwarning 1 //修改
setprop debug.choreographer.skipwarning 30
setprop ctl.restart surfaceflinger; setprop ctl.restart zygote //重启
显然,当设置为1后重启,SKIPPED_FRAME_WARNING_LIMIT
值就修改了,可能会有很多log输出。
注意:getprop不需要权限但是setprop需要root权限,而且
SKIPPED_FRAME_WARNING_LIMIT
是
静态常量所以会在重启后生效。
2.然后在com.tencent.wstt.gt.plugin.smtools.SMLogService
protected void onHandleIntent(Intent intent) { |
我们可以看到内部其实执行的是logcat -v time Choreographer:I *:S
这条命令只输出Log.i("Choreographer","")
的log
3.最后在com.tencent.wstt.gt.plugin.smtools.SMDataService
中计算出处理的流畅度的。
整个过程也不是非常复杂但是需要root权限有点坑,其实核心的2个步骤是修改SKIPPED_FRAME_WARNING_LIMIT
和 读取logcat,其中读取自己logcat是不需要root权限的,但是怎么修改SKIPPED_FRAME_WARNING_LIMIT
呢,反射吗?这可是static final
的啊,在jvm里面确实不可修改,但是在android里面呢?试试吧
|
你没看错,其实是可以修改的!当然只是修改自己进程的,但这就够了。
还有一个问题的怎么在A应用中读取B应用的logcat呢?不错,设置相同的android:sharedUserId
就可以了。
说了这么多,来试试!
TencentOpen/GT 原项目没有提供依赖jar,这里我添加好了,并添加了build.gradle方便编译
项目地址https://github.com/8enet/GT/tree/master/android
没有修改任何代码,可以自行根据说明添加jar包,那么现在只需要通过以下步骤即可免root检测应用流畅度了
- 在自己开发的应用中通过反射修改
SKIPPED_FRAME_WARNING_LIMIT
并且设置android:sharedUserId
- 手动编译GT项目,设置和自己应用一样的
android:sharedUserId
ok,安装后即可检测流畅度了。