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

相关推荐
狂浪天涯2 小时前
Android Security | SEAndroid 的主体
android
马 孔 多 在下雨5 小时前
安卓旋转屏幕后如何防止数据丢失-ViewModel入门
android
Just_Paranoid11 小时前
【Settings】恢复出厂设置密码校验
android·python·settings·sha256·hmac-sha256
肥肥呀呀呀13 小时前
flutter配置Android gradle kts 8.0 的打包名称
android·flutter
平生不喜凡桃李16 小时前
C++ 异常
android·java·c++
Propeller17 小时前
【Android】View 交互的事件处理机制
android·java
吴Wu涛涛涛涛涛Tao17 小时前
Flutter 实现「可拖拽评论面板 + 回复输入框 + @高亮」的完整方案
android·flutter·ios
雨声不在17 小时前
使用android studio分析cpu开销
android·ide·android studio
程序leo源19 小时前
Linux_基础指令(二)
android·linux·运维·服务器·青少年编程