Android Framework-Launcher-默认布局的加载

Android Framework-Launcher-InvariantDeviceProfile

在上一篇我们对device_profiles.xml 进行了解析,获取了其中的属性,本篇主要看一下默认布局的加载。

launcher:defaultLayoutId="@xml/default_workspace_5x5" 默认桌面布局的XML资源路径,定义了首次使用该方案时,系统预装应用(如电话、短信)的默认位置。

这里我们先跳过基础流程直接进入到 LoaderTask

LoaderTask继承 Runnable,直接进入对应的run方法。

java 复制代码
//packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java
public void run() 
//省略...
try {
    loadWorkspace(allShortcuts, memoryLogger);
} finally {
    Trace.endSection();
}
//省略...
}
// 调用到-->
LauncherSettings.Settings.call(contentResolver,
        LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);
        
        
//-->
LauncherProvider 中的call 方法中的

case LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES: {
    loadDefaultFavoritesIfNecessary();
    return null;
}

loadDefaultFavoritesIfNecessary 负责多种布局的加载,其中包括 auto ,partner,和默认布局。 默认情况下走默认布局,国内基本没有autopartner是一种默认占位方法。

java 复制代码
synchronized private void loadDefaultFavoritesIfNecessary() {
    SharedPreferences sp = LauncherPrefs.getPrefs(getContext());

    if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
        Log.d(TAG, "loading default workspace");

        LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
        AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction(widgetHolder);
        if (loader == null) {
            loader = AutoInstallsLayout.get(getContext(), widgetHolder, mOpenHelper);
        }
        if (loader == null) {
            final Partner partner = Partner.get(getContext().getPackageManager());
            if (partner != null) {
                int workspaceResId = partner.getXmlResId(RES_PARTNER_DEFAULT_LAYOUT);
                if (workspaceResId != 0) {
                    loader = new DefaultLayoutParser(getContext(), widgetHolder,
                            mOpenHelper, partner.getResources(), workspaceResId);
                }
            }
        }

        final boolean usingExternallyProvidedLayout = loader != null;
        if (loader == null) {
            loader = getDefaultLayoutParser(widgetHolder);
        }

      
        mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
        // Populate favorites table with initial favorites
        if ((mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), loader) <= 0)
                && usingExternallyProvidedLayout) {
            // Unable to load external layout. Cleanup and load the internal layout.
            mOpenHelper.createEmptyDB(mOpenHelper.getWritableDatabase());
            mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(),
                    getDefaultLayoutParser(widgetHolder));
        }
        clearFlagEmptyDbCreated();
        widgetHolder.destroy();
    }
}

getDefaultLayoutParser()idp.demoModeLayoutId 这一句,我们在之前InvariantDeviceProfile 可以知道,defaultLayoutId 其实就是之前布局里获取到的default_workspace_5x5.xml。最终构建一个可以解析xml文件属性的 Parser 返回。

java 复制代码
private DefaultLayoutParser getDefaultLayoutParser(LauncherWidgetHolder widgetHolder) {
    InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
    int defaultLayout = mDefaultWorkspaceLayoutOverride > 0
            ? mDefaultWorkspaceLayoutOverride : idp.defaultLayoutId;

    if (getContext().getSystemService(UserManager.class).isDemoUser()
            && idp.demoModeLayoutId != 0) {
        defaultLayout = idp.demoModeLayoutId;
    }

    return new DefaultLayoutParser(getContext(), widgetHolder,
            mOpenHelper, getContext().getResources(), defaultLayout);
}

我们看一下该xml文件,该文件决定了首页布局。

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
    <!-- Dialer, Messaging, [Maps/Music], Browser, Camera -->
    <resolve
        launcher:container="-101"
        launcher:screen="0"
        launcher:x="0"
        launcher:y="0" >
        <favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
        <favorite launcher:uri="tel:123" />
        <favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
    </resolve>

    <resolve
        launcher:container="-101"
        launcher:screen="1"
        launcher:x="1"
        launcher:y="0" >
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
        <favorite launcher:uri="sms:" />
        <favorite launcher:uri="smsto:" />
        <favorite launcher:uri="mms:" />
        <favorite launcher:uri="mmsto:" />
    </resolve>

    <resolve
        launcher:container="-101"
        launcher:screen="2"
        launcher:x="2"
        launcher:y="0" >
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;end" />
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
    </resolve>

    <resolve
        launcher:container="-101"
        launcher:screen="3"
        launcher:x="3"
        launcher:y="0" >
        <favorite
            launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
        <favorite launcher:uri="http://www.example.com/" />
    </resolve>

    <resolve
        launcher:container="-101"
        launcher:screen="4"
        launcher:x="4"
        launcher:y="0" >
        <favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
        <favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
    </resolve>

    <!-- Bottom row -->
    <resolve
        launcher:screen="0"
        launcher:x="0"
        launcher:y="-1" >
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />
        <favorite launcher:uri="mailto:" />

    </resolve>

    <resolve
        launcher:screen="0"
        launcher:x="1"
        launcher:y="-1" >
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />
        <favorite launcher:uri="#Intent;type=images/*;end" />

    </resolve>

    <resolve
        launcher:screen="0"
        launcher:x="4"
        launcher:y="-1" >
        <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />
        <favorite launcher:uri="market://details?id=com.android.launcher" />
    </resolve>

</favorites>

基础属性

  • className 一般就是主页名称可以通过adb命令拿到

  • packageName 应用包名

  • launcher:xlauncher:y

    在屏幕的坐标位置 ,比如 5X5,就是横竖5个格子,x代表横坐标,y代表纵坐标。

  • screen

    屏幕 0 是主屏幕 ,在hotset上是顺序排列从0开始。

  • spanXspanY

    占据的格子数量 可以理解为5*5就是横着5个格子 竖着5个格子

  • appwidget

    桌面小组件

  • favorite

    应用,底部快捷(hotset)也使用favorite,只是需要container 需要写-101

  • folder

    文件夹 title 就是文件夹名称

    文件夹里的的应用为favorite, 需要两个上才可以构建文件夹。

在构建loader 成功以后, mOpenHelper.loadFavorites() 我们简单理解为入库就行,到此位置,数据库里已经有了默认布局的数据。

相关推荐
行稳方能走远39 分钟前
Android C++ 学习笔记
android·c++
2501_9462309841 分钟前
Cordova&OpenHarmony用户账户管理
android·javascript
x66ccff43 分钟前
Claude Code 安装方法
android·java·数据库
码农搬砖_20201 小时前
【一站式学会compose】 Android UI体系之 Image的使用和介绍
android·image·compose·content·contentscale·scaletype
粤M温同学1 小时前
Android Room数据库的基本使用
android·数据库
lkbhua莱克瓦242 小时前
基础-约束
android·开发语言·数据库·笔记·sql·mysql·约束
戴西软件2 小时前
CAxWorks.VPG车辆工程仿真软件:打造新能源汽车安全的“数字防线“
android·大数据·运维·人工智能·安全·低代码·汽车
ljt27249606612 小时前
Compose笔记(六十三)--SegmentedButton
android·笔记·android jetpack
Android系统攻城狮2 小时前
Android ALSA驱动进阶之设置共享内存snd_pcm_lib_mmap_iomem:用法实例(九十九)
android·pcm·音频进阶·alsa驱动·android驱动
ZHANG13HAO2 小时前
Android 13 系统源码定制的保活方案,
android