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

相关推荐
maki0774 小时前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架4 小时前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid8 小时前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl9 小时前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
旷野说10 小时前
Android Studio Narwhal 3 特性
android·ide·android studio
maki07716 小时前
VR大空间资料 01 —— 常用VR框架对比
android·ue5·游戏引擎·vr·虚幻·pico
xhBruce20 小时前
InputReader与InputDispatcher关系 - android-15.0.0_r23
android·ims
领创工作室20 小时前
安卓设备分区作用详解-测试机红米K40
android·java·linux
hello_ludy20 小时前
Android 中的 mk 和 bp 文件编译说明
android·编译
maki0771 天前
VR大空间资料 03 —— VRGK使用体验和源码分析
android·vr·虚幻·源码分析·oculus·htc vive·vrgk