源码标准:API : 29「Android 10.0」
补充知识点:
上一篇讲了Android开机流程,就是Zygote开始fork出SystemServer进程。
在SystemServer中会创建一个socket接口来监听请求以及初始化AMS。
根据请求,Zygote会基于自身,预先加载的虚拟机来创建一个新的虚拟机,创建一个新的进程,来管理新的App进程。
为什么点击手机屏幕上的图标就能打开app?
屏幕本质上就是一个程序app,当我们安装好app后就会出现一个图标。
/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
/** * Default launcher application. * 也就是桌面 */ public class Launcher extends BaseDraggingActivity implements LauncherExterns, LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate, InvariantDeviceProfile.OnIDPChangeListener { public static final String TAG = "Launcher"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null); setContentView(mLauncherView); } }
Launcher「桌面」 进程通过 Binder ICP 机制,通知ActivityManagerService「AMS」来创建新的进程。
也就是ActivityThread「UI线程」(Activity运行在ActivityThread实例中)。
ActivityThread通过 Binder ICP 机制将Binder对象传递给AMS,彼此进行通信。
当点击app图标。
/** * Creates a view representing a shortcut inflated from the specified resource. * * @param parent The group the shortcut belongs to. * @param info The data structure describing the shortcut. * @return A View inflated from layoutResId. */ public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) { BubbleTextView favorite = (BubbleTextView) LayoutInflater.from(parent.getContext()) .inflate(R.layout.app_icon, parent, false); favorite.applyFromWorkspaceItem(info); favorite.setOnClickListener(ItemClickHandler.INSTANCE); favorite.setOnFocusChangeListener(mFocusHandler); return favorite; }
这里定位到具体的点击holder类。
/packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java
/** * Class for handling clicks on workspace and all-apps items */ public class ItemClickHandler { private static void onClick(View v, String sourceContainer) { Launcher launcher = Launcher.getLauncher(v.getContext()); Object tag = v.getTag(); if (tag instanceof WorkspaceItemInfo) { onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher, sourceContainer); } else if (tag instanceof FolderInfo) { if (v instanceof FolderIcon) { onClickFolderIcon(v); } } else if (tag instanceof AppInfo) { //app类型点击 startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher, sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer); } else if (tag instanceof LauncherAppWidgetInfo) { if (v instanceof PendingAppWidgetHostView) { onClickPendingWidget((PendingAppWidgetHostView) v, launcher); } } } /** * Event handler for an app shortcut click. * @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}. */ public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher, @Nullable String sourceContainer) { // Check for abandoned promise if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) { String packageName = shortcut.intent.getComponent() != null ? shortcut.intent.getComponent().getPackageName() : shortcut.intent.getPackage(); if (!TextUtils.isEmpty(packageName)) { onClickPendingAppItem(v, launcher, packageName, shortcut.hasStatusFlag(WorkspaceItemInfo.FLAG_INSTALL_SESSION_ACTIVE)); return; } } // Start activities startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer); } private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher, @Nullable String sourceContainer) { Intent intent; if (item instanceof PromiseAppInfo) { PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item; intent = promiseAppInfo.getMarketIntent(launcher); } else { intent = item.getIntent(); } if (item instanceof WorkspaceItemInfo) { WorkspaceItemInfo si = (WorkspaceItemInfo) item; if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) && Intent.ACTION_VIEW.equals(intent.getAction())) { intent = new Intent(intent); intent.setPackage(null); } } if (v != null && launcher.getAppTransitionManager().supportsAdaptiveIconAnimation()) { // Preload the icon to reduce latency b/w swapping the floating view with the original. FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */); } launcher.startActivitySafely(v, intent, item, sourceContainer); } }
真是从里寻他千百度,我快进入死循环里出不来了,多少有点费劲。
最后通过startActivitySafely方法,在新的Task中启动MainActivity。