在Launcher (桌面)上,长按应用图标然后点击 右上角的 应用详情 按钮,
将会进入 该 应用的详情 界面。
这个过程将会涉及 Client (Launcher App) -> App API(LauncherApps ) -> Framework API(LauncherAppsService)
下面将以 LauncherApps -> LauncherAppsService 深入Framework 分析,然后再看在 客服端的调用
1. 客户端接口 LauncherApps.startAppDetailsActivity
frameworks/base/core/java/android/content/pm/LauncherApps.java
@SystemService(Context.LAUNCHER_APPS_SERVICE)
public class LauncherApps {/** @hide */public LauncherApps(Context context, ILauncherApps service) {mContext = context;mService = service;mPm = context.getPackageManager();mUserManager = context.getSystemService(UserManager.class);}/*** Starts the settings activity to show the application details for a* package in the specified profile.** @param component The ComponentName of the package to launch settings for.* @param user The UserHandle of the profile* @param sourceBounds The Rect containing the source bounds of the clicked icon* @param opts Options to pass to startActivity*/public void startAppDetailsActivity(ComponentName component, UserHandle user,Rect sourceBounds, Bundle opts) {logErrorForInvalidProfileAccess(user);try {mService.showAppDetailsAsUser(mContext.getIApplicationThread(),mContext.getPackageName(), mContext.getAttributionTag(),component, sourceBounds, opts, user);} catch (RemoteException re) {throw re.rethrowFromSystemServer();}}
客户端 可以通过 context.getSystemService(Context.LAUNCHER_APPS_SERVICE)
或者 context.getSystemService(LauncherApps.class)
获取到LauncherApps 实例对象.
2. AIDL 接口 ILauncherApps.showAppDetailsAsUser
上面的代码可以看出,实际上是通过 AIDL 接口进行调用方法 showAppDetailsAsUser,即:
frameworks/base/core/java/android/content/pm/ILauncherApps.aidl
interface ILauncherApps {....void showAppDetailsAsUser(in IApplicationThread caller, String callingPackage,String callingFeatureId, in ComponentName component, in Rect sourceBounds,in Bundle opts, in UserHandle user);
}
3. system_server 实现 LauncherAppsService.showAppDetailsAsUser
showAppDetailsAsUser 最终的实现是在 system_server 进程里的
frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java
@Overridepublic void showAppDetailsAsUser(IApplicationThread caller,String callingPackage, String callingFeatureId, ComponentName component,Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {return;}final Intent intent;final long ident = Binder.clearCallingIdentity();try {String packageName = component.getPackageName();int uId = -1;try {uId = mContext.getPackageManager().getApplicationInfo(packageName, PackageManager.MATCH_ANY_USER).uid;} catch (PackageManager.NameNotFoundException e) {Log.d(TAG, "package not found: " + e);}intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,Uri.fromParts("package", packageName, null));intent.putExtra("uId", uId);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);intent.setSourceBounds(sourceBounds);} finally {Binder.restoreCallingIdentity(ident);}mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,callingFeatureId, intent, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK,opts, user.getIdentifier());}
可以看出,最后调用的其实是 ATMS 的 startActivityAsUser 方法
4. PackageManagerHelper. startDetailsActivityForInfo 客户端封装接口
packages/apps/Launcher3/src/com/android/launcher3/util/PackageManagerHelper.java
/*** Starts the details activity for {@code info}*/public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) {if (info instanceof ItemInfoWithIcon&& (((ItemInfoWithIcon) info).runtimeStatusFlags& ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {ItemInfoWithIcon appInfo = (ItemInfoWithIcon) info;mContext.startActivity(new PackageManagerHelper(mContext).getMarketIntent(appInfo.getTargetComponent().getPackageName()));return;}ComponentName componentName = null;if (info instanceof AppInfo) {componentName = ((AppInfo) info).componentName;} else if (info instanceof WorkspaceItemInfo) {componentName = info.getTargetComponent();} else if (info instanceof PendingAddItemInfo) {componentName = ((PendingAddItemInfo) info).componentName;} else if (info instanceof LauncherAppWidgetInfo) {componentName = ((LauncherAppWidgetInfo) info).providerName;}if (componentName != null) {try {mLauncherApps.startAppDetailsActivity(componentName, info.user, sourceBounds, opts);} catch (SecurityException | ActivityNotFoundException e) {Toast.makeText(mContext, R.string.activity_not_found, Toast.LENGTH_SHORT).show();Log.e(TAG, "Unable to launch settings", e);}}}
可以看出,最终调用的就是 LauncherApps.startAppDetailsActivity,
只不过这里对 具体的 组件名称 进行了解析
5. 应用详情 进入点 AppInfo.onClick
其中,AppInfo 是 SystemShortcut 的子类以及内部类。
packages/apps/Launcher3/src/com/android/launcher3/popup/SystemShortcut.java
/*** Represents a system shortcut for a given app. The shortcut should have a label and icon, and an* onClickListener that depends on the item that the shortcut services.** Example system shortcuts, defined as inner classes, include Widgets and AppInfo.* @param <T>*/
public abstract class SystemShortcut<T extends Context & ActivityContext> extends ItemInfoimplements View.OnClickListener {...public static class AppInfo<T extends Context & ActivityContext> extends SystemShortcut<T> {@Nullableprivate SplitAccessibilityInfo mSplitA11yInfo;public AppInfo(T target, ItemInfo itemInfo, View originalView) {super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,itemInfo, originalView);}@Overridepublic void onClick(View view) {dismissTaskMenuView(mTarget);Rect sourceBounds = Utilities.getViewBounds(view);new PackageManagerHelper(mTarget).startDetailsActivityForInfo(mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo).log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP);}
}
可以看到,这里 onClick 函数调用了上面的 PackageManagerHelper.startDetailsActivityForInfo。
当然,注释里也说明了,这个 AppInfo 只是一个例子,Launcher App也可以自定义。
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题



















