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() 我们简单理解为入库就行,到此位置,数据库里已经有了默认布局的数据。

相关推荐
zhaoyufei1337 小时前
Android13删除Taskbar
android
6***B489 小时前
存储过程(SQL)
android·数据库·sql
学困昇10 小时前
C++中的异常
android·java·c++
Jerry11 小时前
问题记录 - Android IdleHandler 没有执行
android
没有了遇见11 小时前
Android ButterKnife Android 35情况下 适配 Gradle 8.+
android
方白羽11 小时前
Android多层嵌套RecyclerView滚动
android·java·kotlin
菜就多学12 小时前
SurfaceControlViewHost 实现跨进程UI渲染
android·设计
2501_9151063213 小时前
iOS App 测试工具全景分析,构建从开发调试到线上监控的多阶段工具链体系
android·测试工具·ios·小程序·uni-app·iphone·webview
小羊在奋斗14 小时前
MySQL表的约束:从基础到核心(附场景+案例)
android·数据库·mysql
e***193514 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb