Launcher3自定义桌面应用【Android13版本】

概要

Launcher3项目地址:AOSP源码/packages/apps/Launcher3

Launcher3自定义桌面应用,我目前实践有两种方式:

  • 更改默认的布局文件,指定主屏幕添加哪些应用
  • 代码中动态添加app到主屏幕中(包括删除原先的应用icon、新增)

更改默认布局

提示:要根据屏幕大小自己去找哪个布局文件

1、进入launcher3布局的源码路径(packages/apps/Launcher3/res/xml)找到要修改的default_workspace_axb.xml
在这里插入图片描述
重点关注下:devices_profiles.xml ,在这个文件里面指定加载那些default_workspace_axb.xml

更简单的方法:aosp编译后,运行模拟器,在launcher桌面下,长按图标拖动,一个格子一个格子的数,就可以知道当前项目中用的是几行几列的布局了

比如我的设备应用的是default_workspace_5x5.xml,打开这个文件,显示如下:
在这里插入图片描述
标签就是指定应用的,其中的launcher:container="-101"代表加入到hotseat中的应用,launcher:x=“0” 指定第几列,launcher:y="0"指定第几行,因此在这里就可以更改hotseat中应用及其位置关系。

往下看:
在这里插入图片描述
这里没有launcher:container=“-101” 的就代表workspace(主屏幕)中的应用,因此在这里更改launcher:uri的内容即可更换应用。同时修改launcher:screen="0"代表在哪个屏幕,x,y代表在哪个位置(-1是默认值:第一行或者第一列)

综上所述:更改布局文件后,重新编译aosp即可看到launcher屏幕中的应用已经被修改了。

如果你修改了布局文件,但是重新编译后运行模拟器,发现桌面应用并没有改变,有可能是launcher的database没有更新,因为这些布局文件的内容,在launcher第一次开机启动时会创建database并保存数据到其中,后续有使用直接从db读取,而不用重复读布局文件
adb root
adb shell rm /data/data/com.android.launcher3/databases/launcher.db
再重启模拟器即可生效

数据库中记录的主屏幕应用信息如下:
在这里插入图片描述

代码中动态添加app到主屏幕

有这种功能:用户在All apps界面(也就是那个上拉抽屉界面)选择几个应用,需要添加到主屏幕,这种只能通过代码的形式来动态添加了

修改地址:/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

假设已经有了需要添加的应用列表List<AppInfo>和对应的响应事件changeWorkspaceItems

第一步:
删除原先workspace中的应用,Launcher.java中已经提供了相关的方法removeItem()

/**
* Launcher中默认已经提供了删除应用的方法
* @param v 要移除的应用的view 应用图标以BubbleTextView的形式显示的,具体可以去看这个类咋操作的
* @param itemInfo 要移除的应用信息,根据这个信息去db中删除对应的元素
* @param deleteFromDb 是否要删除数据库中的数据
*/
public boolean removeItem(View v, final ItemInfo itemInfo, boolean deleteFromDb) {
        return removeItem(v, itemInfo, deleteFromDb, null);
}

(1)我们只需要构建一个哈希表去存储主屏幕应用信息以及其对应的view即可。
在Launcher.java中新建HashMap并在onCreate()中创建该对象
private Map<ItemInfo, View> homeIconMap;
Launcher#bindItems() 方法中收集主屏幕应用信息到哈希表中
在这里插入图片描述
在有了哈希表后,就可以在后续需要删除的时候使用这个方法。

(2)在Launcher.java中新建删除方法removeWorkspaceItems

public void removeWorkspaceItems(HashMap<ItemInfo, View> orignItemsMap){
	Set<ItemInfo> itemInfos = orignItemsMap.keySet();
    for (ItemInfo info: itemInfos){
        View icon = orignItemsMap.get(info);
        // 调用launcher中原生的方法删除应用,底层就是调的contentProvider来删除对应的数据表信息
        removeItem(icon, info, true);
    }
}

第二步:在Launcher.java中新建新增方法addToWorkspace

public void addToWorkspace(List<AppInfo> appInfoList){
	// AppInfo就是all apps界面中的每个应用的对应的数据结构
	// 具体可以看:
	// 1、LoaderTask#loadAllApps()  这些all apps数据怎么来的
	// 2、Launcher#bindAllApplications()  怎么添加到all apps界面的

	// 获取用户信息,默认就一个
	UserManager mUserManager = getSystemService(UserManager.class);
    final List<UserHandle> profiles = mUserManager.getUserProfiles();
	
	// 遍历添加集合,添加到主屏幕中
	for(AppInfo appInfo: appInfoList){
		// 得到包名
		String packageName = appInfo.componentName.getPackageName();
		ItemInstallQueue.INSTANCE.get(mContext)
                                .queueItem(packageName, profiles.get(0));
	}

}

第三步:组装上面第一步和第二步的方法到添加事件中:changeWorkspaceItems

public void changeWorkspaceItems(){
	// 1 删除原先应用 homeIconMap在Launcher启动时我们已经收集好信息
	removeWorkspaceItems(homeIconMap);
	
	// 2 添加新的应用
	// 一般可以通过这个去获取: AppInfo[] allInfo = mModel.mBgAllAppsList.copyData();
	List<AppInfo> listView = "我们事先准备好的集合"
	addToWorkspace(listView);
}

至于changeWorkspaceItems这个方法的调用就取决于个人了,比如写个button的点击事件去响应等等。
经过我的踩坑,changeWorkspaceItems不要写在子线程中,因为:删除、新增方法最终会在相关的handler去执行,本身就是异步的,所以不要多此一举去开子线程执行了,否则可能会报错。

小结

添加应用到主屏幕中,我所尝试的这两种方式均可以。
方法二:用代码动态添加app到主屏幕,只是我自己阅读源码找到的方案,可能还有其他方案也能实现,这里只是提供一个参考吧。

大家有什么疑问或者建议欢迎向我留言,本人技术有限,如果有误也请不吝赐教~~。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值