当前位置:   article > 正文

Android13 Launcher3 App列表隐藏单个或多个apk_android 13 launcher 应用列表adapter

android 13 launcher 应用列表adapter

1 需求概述

       当业务需求要求要主页面不显示特定的一个或多个apk时,我们需要在launcher中隐藏此apk。本文以隐藏 Aqua Mail,Calculator,FileCommander三个apk为例来详细讲解。

2 实现功能核心类

  代码路径

 packages\apps\Launcher3\src\com\android\launcher3\model\LoaderTask.java

packages\apps\Launcher3\quickstep\src\com\android\launcher3\appprediction\PredictionRowView.java

3 核心代码分析

 3.1 LoaderTask加载allapps流程

    加载apk列表是在LoaderTask中进行加载的,我们只需要在加载所有apk列表的地方,屏蔽我们业务需要的apk即可实现此功能。看run()方法

  1. public void run() {
  2. synchronized (this) {
  3. // Skip fast if we are already stopped.
  4. if (mStopped) {
  5. return;
  6. }
  7. }
  8. Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
  9. TimingLogger logger = new TimingLogger(TAG, "run");
  10. LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
  11. try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
  12. List<ShortcutInfo> allShortcuts = new ArrayList<>();
  13. Trace.beginSection("LoadWorkspace");
  14. try {
  15. loadWorkspace(allShortcuts, memoryLogger);
  16. } finally {
  17. Trace.endSection();
  18. }
  19. logASplit(logger, "loadWorkspace");
  20. // Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
  21. // sanitizeData should not be invoked if the workspace is loaded from a db different
  22. // from the main db as defined in the invariant device profile.
  23. // (e.g. both grid preview and minimal device mode uses a different db)
  24. if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
  25. verifyNotStopped();
  26. sanitizeData();
  27. logASplit(logger, "sanitizeData");
  28. }
  29. verifyNotStopped();
  30. mResults.bindWorkspace(true /* incrementBindId */);
  31. logASplit(logger, "bindWorkspace");
  32. mModelDelegate.workspaceLoadComplete();
  33. // Notify the installer packages of packages with active installs on the first screen.
  34. sendFirstScreenActiveInstallsBroadcast();
  35. logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
  36. // Take a break
  37. waitForIdle();
  38. logASplit(logger, "step 1 complete");
  39. verifyNotStopped();
  40. // second step
  41. Trace.beginSection("LoadAllApps");
  42. List<LauncherActivityInfo> allActivityList;
  43. try {
  44. allActivityList = loadAllApps();
  45. } finally {
  46. Trace.endSection();
  47. }
  48. logASplit(logger, "loadAllApps");
  49. verifyNotStopped();
  50. mResults.bindAllApps();
  51. logASplit(logger, "bindAllApps");
  52. verifyNotStopped();
  53. IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
  54. setIgnorePackages(updateHandler);
  55. updateHandler.updateIcons(allActivityList,
  56. LauncherActivityCachingLogic.newInstance(mApp.getContext()),
  57. mApp.getModel()::onPackageIconsUpdated);
  58. logASplit(logger, "update icon cache");
  59. if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
  60. verifyNotStopped();
  61. logASplit(logger, "save shortcuts in icon cache");
  62. updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
  63. mApp.getModel()::onPackageIconsUpdated);
  64. }
  65. // Take a break
  66. waitForIdle();
  67. logASplit(logger, "step 2 complete");
  68. verifyNotStopped();
  69. // third step
  70. List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
  71. logASplit(logger, "loadDeepShortcuts");
  72. verifyNotStopped();
  73. mResults.bindDeepShortcuts();
  74. logASplit(logger, "bindDeepShortcuts");
  75. if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
  76. verifyNotStopped();
  77. logASplit(logger, "save deep shortcuts in icon cache");
  78. updateHandler.updateIcons(allDeepShortcuts,
  79. new ShortcutCachingLogic(), (pkgs, user) -> { });
  80. }
  81. // Take a break
  82. waitForIdle();
  83. logASplit(logger, "step 3 complete");
  84. verifyNotStopped();
  85. // fourth step
  86. List<ComponentWithLabelAndIcon> allWidgetsList =
  87. mBgDataModel.widgetsModel.update(mApp, null);
  88. logASplit(logger, "load widgets");
  89. verifyNotStopped();
  90. mResults.bindWidgets();
  91. logASplit(logger, "bindWidgets");
  92. verifyNotStopped();
  93. updateHandler.updateIcons(allWidgetsList,
  94. new ComponentWithIconCachingLogic(mApp.getContext(), true),
  95. mApp.getModel()::onWidgetLabelsUpdated);
  96. logASplit(logger, "save widgets in icon cache");
  97. // fifth step
  98. if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
  99. loadFolderNames();
  100. }
  101. verifyNotStopped();
  102. updateHandler.finish();
  103. logASplit(logger, "finish icon update");
  104. mModelDelegate.modelLoadComplete();
  105. transaction.commit();
  106. memoryLogger.clearLogs();
  107. } catch (CancellationException e) {
  108. // Loader stopped, ignore
  109. logASplit(logger, "Cancelled");
  110. } catch (Exception e) {
  111. memoryLogger.printLogs();
  112. throw e;
  113. } finally {
  114. logger.dumpToLog();
  115. }
  116. TraceHelper.INSTANCE.endSection(traceToken);
  117. }

在此方法里面跟下去,找到loadAllApps(),这里就是具体执行加载所有apk的方法了,继续跟踪

  1. private List<LauncherActivityInfo> loadAllApps() {
  2. final List<UserHandle> profiles = mUserCache.getUserProfiles();
  3. List<LauncherActivityInfo> allActivityList = new ArrayList<>();
  4. // Clear the list of apps
  5. mBgAllAppsList.clear();
  6. List<IconRequestInfo<AppInfo>> iconRequestInfos = new ArrayList<>();
  7. for (UserHandle user : profiles) {
  8. // Query for the set of apps
  9. final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
  10. // Fail if we don't have any apps
  11. // TODO: Fix this. Only fail for the current user.
  12. if (apps == null || apps.isEmpty()) {
  13. return allActivityList;
  14. }
  15. boolean quietMode = mUserManagerState.isUserQuiet(user);
  16. // Create the ApplicationInfos
  17. for (int i = 0; i < apps.size(); i++) {
  18. LauncherActivityInfo app = apps.get(i);
  19. AppInfo appInfo = new AppInfo(app, user, quietMode);
  20. boolean isHideApk = HideApkUtils.getInstall().isHidedApkPackageName(app.getComponentName().getPackageName());
  21. if(isHideApk){
  22. continue;
  23. }
  24. iconRequestInfos.add(new IconRequestInfo<>(
  25. appInfo, app, /* useLowResIcon= */ false));
  26. mBgAllAppsList.add(
  27. appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
  28. }
  29. allActivityList.addAll(apps);
  30. }
  31. if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
  32. // get all active sessions and add them to the all apps list
  33. for (PackageInstaller.SessionInfo info :
  34. mSessionHelper.getAllVerifiedSessions()) {
  35. AppInfo promiseAppInfo = mBgAllAppsList.addPromiseApp(
  36. mApp.getContext(),
  37. PackageInstallInfo.fromInstallingState(info),
  38. !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
  39. if (promiseAppInfo != null) {
  40. iconRequestInfos.add(new IconRequestInfo<>(
  41. promiseAppInfo,
  42. /* launcherActivityInfo= */ null,
  43. promiseAppInfo.usingLowResIcon()));
  44. }
  45. }
  46. }
  47. if (FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get()) {
  48. Trace.beginSection("LoadAllAppsIconsInBulk");
  49. try {
  50. mIconCache.getTitlesAndIconsInBulk(iconRequestInfos);
  51. iconRequestInfos.forEach(iconRequestInfo ->
  52. mBgAllAppsList.updateSectionName(iconRequestInfo.itemInfo));
  53. } finally {
  54. Trace.endSection();
  55. }
  56. }
  57. mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED,
  58. mUserManagerState.isAnyProfileQuietModeEnabled());
  59. mBgAllAppsList.setFlags(FLAG_HAS_SHORTCUT_PERMISSION,
  60. hasShortcutsPermission(mApp.getContext()));
  61. mBgAllAppsList.setFlags(FLAG_QUIET_MODE_CHANGE_PERMISSION,
  62. mApp.getContext().checkSelfPermission("android.permission.MODIFY_QUIET_MODE")
  63. == PackageManager.PERMISSION_GRANTED);
  64. mBgAllAppsList.getAndResetChangeFlag();
  65. return allActivityList;
  66. }

这里面就是加载所有apk逻辑了,我们只需要添加我们需要隐藏的业务逻辑即可。

    // Create the ApplicationInfos
    for (int i = 0; i < apps.size(); i++) {
        LauncherActivityInfo app = apps.get(i);
        AppInfo appInfo = new AppInfo(app, user, quietMode);

        boolean isHideApk =   HideApkUtils.getInstall().isHidedApkPackageName(app.getComponentName().getPackageName());
        if(isHideApk){
            continue;
        }
        iconRequestInfos.add(new IconRequestInfo<>(
                appInfo, app, /* useLowResIcon= */ false));
        mBgAllAppsList.add(
                appInfo, app, !FeatureFlags.ENABLE_BULK_ALL_APPS_ICON_LOADING.get());
    }
    allActivityList.addAll(apps);
}

标红的即我们加的业务逻辑,此功能就实现了。但是需要注意的是,在配每一屏显示与Hotseat显示的apk列表中,不要把我们需要隐藏的apk加入这表中即可(如何配置每一屏显示的apk与Hotseat显示的apk,请看系列文章会详细讲解)

以下是HideApkUtils.java类

  1. package com.android.launcher3.util;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. /**
  5. * by Hogan 2023.3.17
  6. * 功能:隐藏指定的apk列表
  7. */
  8. public class HideApkUtils {
  9. private static final List<String> mHiddenPackageMap = new LinkedList<>();
  10. private HideApkUtils() {
  11. addHideAppList();
  12. }
  13. //需要隐藏的apk包名,添加到这里
  14. private void addHideAppList() {
  15. mHiddenPackageMap.add("org.kman.AquaMail");
  16. mHiddenPackageMap.add("com.google.android.calculator");
  17. mHiddenPackageMap.add("com.mobisystems.fileman");
  18. // mHiddenPackageMap.add("com.mobisystems.office");
  19. // mHiddenPackageMap.add("com.hht.factory");
  20. }
  21. private static class HideApkUtilsHolder {
  22. private static final HideApkUtils INSTALL = new HideApkUtils();
  23. }
  24. public static HideApkUtils getInstall() {
  25. return HideApkUtilsHolder.INSTALL;
  26. }
  27. public boolean isHidedApkPackageName(String apkPkg) {
  28. return mHiddenPackageMap.contains(apkPkg);
  29. }
  30. }

 3.2  PredictionRowView 加载显示搜索框下的搜索预测行视图流程

   1. 找到setPredictedApps()方法,此方法是用于设置预测选项的内容并更新视图的:

    

  1. public void setPredictedApps(List<ItemInfo> items) {
  2. if (!FeatureFlags.ENABLE_APP_PREDICTIONS_WHILE_VISIBLE.get()
  3. && !mActivityContext.isBindingItems()
  4. && isShown()
  5. && getWindowVisibility() == View.VISIBLE) {
  6. mPendingPredictedItems = items;
  7. return;
  8. }
  9. applyPredictedApps(items);
  10. }

   在这个方法里面调用了 applyPredictedApps()方法

  1. private void applyPredictedApps(List<ItemInfo> items) {
  2. List<ItemInfo> itemInfoList =new ArrayList<>();
  3. for(int i=0;i<items.size();i++){
  4. String pkg = items.get(i).getTargetPackage();
  5. boolean isHideApk = HideApkUtils.getInstall().isHidedApkPackageName(pkg);
  6. if(isHideApk){
  7. continue;
  8. }
  9. itemInfoList.add(items.get(i));
  10. }
  11. mPendingPredictedItems = null;
  12. mPredictedApps.clear();
  13. mPredictedApps.addAll(itemInfoList.stream()
  14. .filter(itemInfo -> itemInfo instanceof WorkspaceItemInfo)
  15. .map(itemInfo -> (WorkspaceItemInfo) itemInfo).collect(Collectors.toList()));
  16. applyPredictionApps();
  17. }

这正是加载搜索预测apk,我们可以在这里加上业务逻辑代码即可:

private void applyPredictedApps(List<ItemInfo> items) {
    List<ItemInfo> itemInfoList =new ArrayList<>();

    for(int i=0;i<items.size();i++){
        String pkg = items.get(i).getTargetPackage();
        boolean isHideApk = HideApkUtils.getInstall().isHidedApkPackageName(pkg);
        if(isHideApk){
            continue;
        }
        itemInfoList.add(items.get(i));
    }
    mPendingPredictedItems = null;
    mPredictedApps.clear();
    mPredictedApps.addAll(itemInfoList.stream()
            .filter(itemInfo -> itemInfo instanceof WorkspaceItemInfo)
            .map(itemInfo -> (WorkspaceItemInfo) itemInfo).collect(Collectors.toList()));
    applyPredictionApps();
}

标红的代码就是加入修改之处。

4 完成业务效果图

    4.1 未隐藏前图,红线标注为需要隐藏的apk

 

4.2 隐藏后的效果图

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/569840
推荐阅读
相关标签
  

闽ICP备14008679号