源码标准: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。
网友评论