如何最精确地测量Android应用程序的启动时间?
在这里,启动时间是指从以下两个时间点之间所经过的时间:
- 应用程序进程未运行
- 用户在启动器中单击应用程序图标
- 主要活动已完全初始化
因此,您需要以某种方式获取自JVM启动以来经过的时间并记录它。
如何最精确地测量Android应用程序的启动时间?
在这里,启动时间是指从以下两个时间点之间所经过的时间:
因此,您需要以某种方式获取自JVM启动以来经过的时间并记录它。
我知道我回答晚了,不过这确切地回答了这个问题。
从Android 4.4(API级别19)开始,默认情况下,此信息将在Logcat中记录。Logcat包含一个输出行,其中包含一个名为Displayed的值。这个值代表启动进程和完成在屏幕上绘制相应activity之间经过的时间。
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
关键是要在正确的位置查找它-
如果您正在跟踪命令行或终端中的logcat输出,则寻找经过的时间就很简单。要在Android Studio中查找经过的时间,必须在logcat视图中禁用筛选器。禁用筛选器是必要的,因为此日志由系统服务器而不是应用程序本身提供。
这些摘录来自文档。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing("startup");
}
}
停止跟踪:
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Debug.stopMethodTracing();
}
一旦收集到跟踪数据,您应该能够看到任何对启动时间产生重大影响的内容。在我的情况下,如下所示,UI线程上有一个大的间隙,导致其被阻塞。
事实证明,Crashlytics和Coremetrics都需要调用randomUUID()
,然后在各个线程之间进行同步并阻塞主线程。解决方案只是启动一个新线程来初始化Coremetrics代码。
这是我仅通过测量启动时间不会发现的问题,但实际上它使应用程序的“启动时间”加快了几百毫秒。
在为Coremetrics初始化启动单独的线程后,这是另一个快照:
请在adb shell中按照以下方式进行检查。
adb shell
adb logcat -b events | grep am_activity_launch_time
[Output]
01-01 12:32:53.469 1236 1262 I am_activity_launch_time:
[0,205360373,com.sec.android.app.clockpackage/.ClockPackage,378,**378**,0]
Remarks:
Launch time for Clock is 378ms.
将整个onCreate()
方法用TimingLogger
包装起来。只需将以下代码放在开头:
TimingLogger timings = new TimingLogger(TAG, "methodA");
and this at the end:
timings.dumpToLog();
timings.addSplit("name");
获取到达该步骤所需的时间。一种在安卓中展示启动时间的简单方法。
有时候logcat输出中的Displayed
行会包含一个额外的总时间字段。例如:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
可以使用以下代码实现时间跟踪:
覆盖你的 Application
:
public class CustomApplication extends Application {
public final static long APP_START_TIME = System.currentTimeMillis();
/**
* Do all other application stuff
*/
}
Activity
中添加几行代码:public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View contentView = findViewById(android.R.id.content);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
contentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
contentView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
long launchTime = System.currentTimeMillis() - CustomApplication.APP_START_TIME;
Log.e("TEST", "App launch time = " + launchTime);
}
});
}
}
别忘了在Manifest
中定义你的自定义应用程序:
<application
android:label="@string/app_name"
android:name=".CustomApplication" >
</application>
重要提示:在启动应用程序之前,您必须将其关闭,因为应用程序存储了跟踪初始时间的静态变量。
onGlobalLayout
实际上是正确的措施。感谢分享。 - YashonCreate()
方法的开始和结束时保存时间,然后将这些时间相减以获取初始化应用程序所需的时间。