【学以致用】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的标准流程,创建快捷方式,从创建快捷方式这一步来说,获取labelicon。就可以完成

但是为了后面还能够打开这个应用,需要获取了外来信息的package nameshortcut ID。在之前提到的makeIntent中,将IDpackage name,这两个重要参数通过intent存到数据库中。

8.0不再将快捷方式的具体地址储存到数据库中,改用shortcut ID。接来下是启动流程

桌面的activity会有onClick方法,点击在桌面的操作均会被该方法截获。

 

如果是点击在快捷方式上,则会调用startAppShortcutOrInfoActivity方法,而深入下去,会发现我们之前创建的快捷方式叫做deepShortcut,而启用deepShortcut是和查询是通用的参数,通过IDpackageName

 

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);
}

 

最终调用DeepShortcutManagerstartShortcut方法,这是一个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;
        }
    }
}

以上,就是桌面创建一个快捷方式的源码分析。

猜你喜欢

转载自blog.csdn.net/dax120/article/details/78905362