【學以致用】android功能實現7---android8.0 Launcher獲取快捷方式原始碼分析(3)
獲取完快捷方式的資訊之後,便是如何具體的將快捷方式的名字,圖示和開啟方式放置到桌面上。
最後一步addAndBindAddedWorkspaceItems(
new LazyShortcutsProvider(context.getApplicationContext(), items));
先將獲取的LazyShortcutsProvider,是將PendingInstallShortcutInfo放在LazyShortcutsProvider,然後傳入addAndBindAddedWorkspaceItems。
這裡實際是做了一個任務,工作包括獲取 workspaceApps = mAppsProvider.get()。
分配該快捷方式的位置Pair<Long, int[]> coords = findSpaceForItem(app, dataModel, workspaceScreens, addedWorkspaceScreensFinal, item.spanX, item.spanY);
以及程式碼裡面註釋提到的這兩句。
// Add the shortcut to the db
// Save the ShortcutInfo for binding in the workspace
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
List<ItemInfo> workspaceApps = mAppsProvider.get();
if (workspaceApps.isEmpty()) {
return;
}
Context context = app.getContext();
final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<>();
// Get the list of workspace screens. We need to append to this list and
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
// called.
ArrayList<Long> workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context);
synchronized(dataModel) {
for (ItemInfo item : workspaceApps) {
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;
}
}
// Find appropriate space for the item.
Pair<Long, int[]> coords = findSpaceForItem(app, dataModel, workspaceScreens,
addedWorkspaceScreensFinal, item.spanX, item.spanY);
long screenId = coords.first;
int[] cordinates = coords.second;
ItemInfo itemInfo;
if (item instanceof ShortcutInfo || item instanceof FolderInfo ||
item instanceof LauncherAppWidgetInfo) {
itemInfo = item;
} else if (item instanceof AppInfo) {
itemInfo = ((AppInfo) item).makeShortcut();
} else {
throw new RuntimeException("Unexpected info type");
}
// Add the shortcut to the db
getModelWriter().addItemToDatabase(itemInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId,
cordinates[0], cordinates[1]);
// Save the ShortcutInfo for binding in the workspace
addedItemsFinal.add(itemInfo);
}
}
}
獲取到的workspaceApps = mAppsProvider.get()的內容是pendingInfo.getItemInfo()。
最終返回的藏在PendingInstallShortcutInfo中的itemInfo引數,getItemInfo()通過從外界獲取的資訊轉化成的相容性ShortcutInfoCompat生成Launcher可用的ShortcutInfo 並且傳入icon引數
} else if (shortcutInfo != null) {
ShortcutInfo si = new ShortcutInfo(shortcutInfo, mContext);
si.iconBitmap = LauncherIcons.createShortcutIcon(shortcutInfo, mContext);
return si;
}
這裡獲取外來資訊的圖片資訊。
LauncherAppState app = LauncherAppState.getInstance(context);
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context)
.getShortcutIconDrawable(shortcutInfo, app.getInvariantDeviceProfile().fillResIconDpi);
其方法是:通過getShortcutInfo和螢幕的density資訊,通過LauncherApps在手機中獲取對應的圖片,也就是快捷方式的圖片是存在手機裡的,獲取的時候,通過傳入的shortcut資訊獲取。
public Drawable getShortcutIconDrawable(ShortcutInfoCompat shortcutInfo, int density) {
if (Utilities.ATLEAST_NOUGAT_MR1) {
try {
Drawable icon = mLauncherApps.getShortcutIconDrawable(
shortcutInfo.getShortcutInfo(), density);
mWasLastCallSuccess = true;
return icon;
} catch (SecurityException|IllegalStateException e) {
Log.e(TAG, "Failed to get shortcut icon", e);
mWasLastCallSuccess = false;
}
}
return null;
}
根據以上操作,按照Launcher的標準流程,建立快捷方式,從建立快捷方式這一步來說,獲取label和icon。就可以完成
但是為了後面還能夠開啟這個應用,需要獲取了外來資訊的package name和shortcut ID。在之前提到的makeIntent中,將ID,package name,這兩個重要引數通過intent存到資料庫中。
8.0不再將快捷方式的具體地址儲存到資料庫中,改用shortcut ID。接來下是啟動流程
桌面的activity會有onClick方法,點選在桌面的操作均會被該方法截獲。
如果是點選在快捷方式上,則會呼叫startAppShortcutOrInfoActivity方法,而深入下去,會發現我們之前建立的快捷方式叫做deepShortcut,而啟用deepShortcut是和查詢是通用的引數,通過ID和packageName:
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
String id = ((ShortcutInfo) info).getDeepShortcutId();
String packageName = intent.getPackage();
DeepShortcutManager.getInstance(this).startShortcut(
packageName, id, intent.getSourceBounds(), optsBundle, info.user);
}
最終呼叫DeepShortcutManager的startShortcut方法,這是一個api高於25才能使用的方法。
@TargetApi(25)
public void startShortcut(String packageName, String id, Rect sourceBounds,
Bundle startActivityOptions, UserHandle user) {
if (Utilities.ATLEAST_NOUGAT_MR1) {
try {
mLauncherApps.startShortcut(packageName, id, sourceBounds,
startActivityOptions, user);
mWasLastCallSuccess = true;
} catch (SecurityException | IllegalStateException e) {
Log.e(TAG, "Failed to start shortcut", e);
mWasLastCallSuccess = false;
}
}
}
以上,就是桌面建立一個快捷方式的原始碼分析。