1. 概述
Android系统的Launcher改造在国内算是一个不算很低频的需求,尤其是相当多的三方硬件设备以及部分手机厂商的个性化ROM等,受限于国内整体的开源环境,网上能找到相关的开发资源并不多,最近公司有相关业务需求的开发,就自己涉及到的改造点作一些分享。
我也在网上找过很多博文,如何隐藏单个APP的图标展示,提供的修改方法包括更改AppFilter的shouldShowApp方法、修改LoadTask的loadAllApps()方法&添加PackageUpdatedTask的excute方法过滤,但实测发现并不能满足我的要求,尤其是在workspace区域已有该图标的前提下,无法隐藏。经过自己的摸索及追踪源码成功解决。涉及到的改动点如下:
-
在往workspace区域添加item时,忽略掉需要隐藏的APP,以解决初次加载时的隐藏。
-
绑定workspace的时机,移除需要隐藏的APP,以解决更新时对该图标的隐藏。
2. 涉及到的类及接口等
主要是改动添加item的任务类AddWorkspaceItemsTask和绑定workspace的result类BaseLoaderResults
com.android.launcher3.model.AddWorkspaceItemsTask
com.android.launcher3.model.BaseLoaderResults
3. Show the code
-
在添加item任务中添加过滤
AddWorkspaceItemsTask.java
public class AddWorkspaceItemsTask extends BaseModelUpdateTask { private final List<Pair<ItemInfo, Object>> mItemList; /** * @param itemList items to add on the workspace */ public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) { mItemList = itemList; //少了"设置"、"lawnchair设置",原因在BgDataModel里少了俩 } @Override public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { if (mItemList.isEmpty()) { return; } final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>(); final IntArray addedWorkspaceScreensFinal = new IntArray(); synchronized(dataModel) { IntArray workspaceScreens = dataModel.collectWorkspaceScreens(); List<ItemInfo> filteredItems = new ArrayList<>(); for (Pair<ItemInfo, Object> entry : mItemList) { ItemInfo item = entry.first; Log.e("item=====",item.getTargetComponent().getPackageName() + " , " + item.title); if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { // Short-circuit this logic if the icon exists somewhere on the workspace if (shortcutExists(dataModel, item.getIntent(), item.user)) { continue; } // b/139663018 Short-circuit this logic if the icon is a system app if (PackageManagerHelper.isSystemApp(app.getContext(), item.getIntent())) { continue; } //====修改start==== //只能保证新装有用,后续升级加筛选不会生效。 if("com.example.aaaa.bbbb".equals(item.getTargetComponent().getPackageName())){ continue; } //====修改end==== } if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { if (item instanceof AppInfo) { item = ((AppInfo) item).makeWorkspaceItem(); } } if (item != null) { filteredItems.add(item); } } InstallSessionHelper packageInstaller = InstallSessionHelper.INSTANCE.get(app.getContext()); LauncherApps launcherApps = app.getContext().getSystemService(LauncherApps.class); for (ItemInfo item : filteredItems) { // Find appropriate space for the item. // ... // } } //...// } }
-
绑定workspace时过滤
BaseLoaderResults.java
/** * Binds all loaded data to actual views on the main thread. */ public void bindWorkspace() { // Save a copy of all the bg-thread collections ArrayList<ItemInfo> workspaceItems = new ArrayList<>(); ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<>(); final IntArray orderedScreenIds = new IntArray(); synchronized (mBgDataModel) { //====修改start==== //只能保证更新有用,初次安装反而不会生效。 mBgDataModel.workspaceItems.removeIf(aI -> "com.example.aaaa.bbbb".equals(aI.getTargetComponent().getPackageName())); //====修改end==== workspaceItems.addAll(mBgDataModel.workspaceItems); appWidgets.addAll(mBgDataModel.appWidgets); orderedScreenIds.addAll(mBgDataModel.collectWorkspaceScreens()); mBgDataModel.lastBindId++; mMyBindingId = mBgDataModel.lastBindId; } for (Callbacks cb : mCallbacksList) { new WorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId, workspaceItems, appWidgets, orderedScreenIds).bind(); } }
4. 结语
在试过了网上找到的解决方法仍无法解决之后,追踪workspace区域的各种加载绑定及展示相关代码,最终找到合适的位置添加过滤逻辑从而解决该问题,供参考。