课程答疑和新课信息:QQ交流群:422901085进行课程讨论
专题博客系列:
Android 8.1代码分析FallbackHome结束启动Launcher篇:
上一讲已经分析到了FallbackHome Activity的启动,但其实FallbackHome只是系统由未解密到解密过程的一个过度界面,只要用户把系统解锁过一次后,那么就一直会把系统的Home变成Launcher,这个时候FallbackHome的使命就已经完成,不会再出现了。所以经常用户会发现现在手机普遍存在一个问题就是第一次解锁手机会发现有1-2s的一个空白界面,接下来才是显示Launcher的一个图标界面。
那接下就详细分析FallbackHome源码看看是怎么结束的
这时候就需要去FallbackHome的Activity代码中看,源码路径:packages/apps/Settings/src/com/android/settings/FallbackHome.java
//省略
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//省略
//注册监听系统的解锁广播
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
maybeFinish();
}
@Override
protected void onResume() {
super.onResume();
if (mProvisioned) {
mHandler.postDelayed(mProgressTimeoutRunnable, PROGRESS_TIMEOUT);
}
}
@Override
protected void onPause() {
super.onPause();
mHandler.removeCallbacks(mProgressTimeoutRunnable);
}
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
//监听系统的解锁广播,触发检测是不是该结束自己
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
maybeFinish();
}
};
//判断是否该结束自己的方法
private void maybeFinish() {
if (getSystemService(UserManager.class).isUserUnlocked()) {
final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME);
final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
//简单判断PMS中获取到的Home类型的Activity还是不是自己,如果不是了,说明已解锁,可以启动真正Launcher了
if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
if (UserManager.isSplitSystemUser()
&& UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
// This avoids the situation where the system user has no home activity after
// SUW and this activity continues to throw out warnings. See b/28870689.
return;
}
Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");
mHandler.sendEmptyMessageDelayed(0, 500);
} else {
Log.d(TAG, "User unlocked and real home found; let's go!");
getSystemService(PowerManager.class).userActivity(
SystemClock.uptimeMillis(), false);
//这里检测到获取的Home类型Activity已经不是自己,说明系统中真正Launcher已经可以获取到了,则finish自己
finish();
}
}
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
maybeFinish();
}
};
}
注册监听系统的解锁ACTION_USER_UNLOCKED广播,根据这个条件来触发检测,本质上这里其实FallbackHome就是一直在不断的检测系统中的获取的Home 类型的Activtiy还是不是自己,如果不是了,比如是Launcher,那说明系统已经可以启动真正Launcher了。
但细心同学会发现,这个只看到了FallbackHome finish自己,并没有看到有启动Launcher的操作?那Launcher到底是怎么启动的呢?
这里如果正面分析可能会较为困难,即使我把对应的调用流程又重新给大家写一遍对大家作用也不是很大,这里给大家用我们的老方法打日志堆栈的方式来辅助分析定位真正的Launcher是怎么启动的:
上节课已经分析了FallbackHome启动是ActivityManagerService的startHomeActivityLocked,那么有理由相信Launcher的启动一样会调用这个方法,所以在这个方法加入堆栈日志打印,看到了系统启动要进入Launcher时,有如下打印:
在
boolean startHomeActivityLocked(int userId, String reason) {
android.util.Log.i("test2","startHomeActivityLocked reason = " + reason,new Exception());
//省略。。。。
}
1521 1575 I test2 : startHomeActivityLocked reason = noMoreActivities resumeHomeStackTask
1521 1575 I test2 : java.lang.Exception
1521 1575 I test2 : at com.android.server.am.ActivityManagerService.startHomeActivityLocked(ActivityManagerService.java:4059)
1521 1575 I test2 : at com.android.server.am.ActivityStackSupervisor.resumeHomeStackTask(ActivityStackSupervisor.java:772)
1521 1575 I test2 : at com.android.server.am.ActivityStack.resumeTopActivityInNextFocusableStack(ActivityStack.java:2750)
1521 1575 I test2 : at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2313)
1521 1575 I test2 : at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2255)
1521 1575 I test2 : at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2103)
1521 1575 I test2 : at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:2084)
1521 1575 I test2 : at com.android.server.am.ActivityStack.finishCurrentActivityLocked(ActivityStack.java:3901)
1521 1575 I test2 : at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1445)
1521 1575 I test2 : at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1413)
1521 1575 I test2 : at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:7443)
1521 1575 I test2 : at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:317)
1521 1575 I test2 : at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2919)
1521 1575 I test2 : at android.os.Binder.execTransact(Binder.java:697)
明显看到了这里有调用startHomeActivityLocked,而且这次的reason是noMoreActivities resumeHomeStackTask,那么到底是哪里调用到这个地方呢?
这时候看堆栈就可以详细准确定位出如下流程:
FallbackHome请求finish自己,当然会请求执行onPasue方法: ActivityManagerService.activityPaused --》触发调用到ActivityStack.activityPausedLocked --》 调用到 ActivityStack.completePauseLocked —》 调用到 ActivityStack.finishCurrentActivityLocked --》调用到 ActivityStackSupervisor.resumeFocusedStackTopActivityLocked --》。。。。。。。-》最后调用到了ActivityManagerService.startHomeActivityLocked
如上堆栈一打印里面把代码行数和方法都打印了,非常详细,相比自己去一步步分析效率高出太多,也准确许多,不用去挨个每个条件进行分析。
到了startHomeActivityLocked之后相信有前几节视频带领就不需要这里再进行分析了。
好了那整个系列的实战课程1就给大家分析完了,相信大家跟着视频和博客学习完成,自己去动手操作后一定会有不一样的收获,最后谢谢大家,后面如果想要关注课程信息及作者答疑,请购买课程或者加入qq技术讨论群(422901085)进行了解
最后祝大家android水平可以站在我的肩膀上飞起来飞得很高很高。。。。