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

相关推荐
kejiashao1 小时前
Android View的绘制流程及事件分发机制
android
小蜜蜂嗡嗡2 小时前
flutter实现付费解锁内容的遮挡
android·flutter
进击的cc2 小时前
拒绝背诵!一文带你打穿 Android ANR 发生的底层全链路
android·面试
进击的cc2 小时前
App 启动优化全家桶:别再只盯着 Application 了,热启动优化你真的做对了吗?
android·面试
彭波3962 小时前
安卓手机端安装xapk、apkm软件!怎样安装xapk软件?安卓的apk和XAPK的区别?附教程
android·智能手机
Yang-Never3 小时前
ADB ->adb shell perfetto 抓取 trace 指令
android·开发语言·adb·android studio
2501_937189236 小时前
莫凡电视:地方台专属聚合 稳定直播播放工具
android·源码·源代码管理
耶叶7 小时前
Android 新权限申请模型(Activity Result API)
android
阿拉斯攀登7 小时前
【RK3576 安卓 JNI/NDK 系列 04】JNI 核心语法(下):字符串、数组与对象操作
android·驱动开发·rk3568·瑞芯微·rk安卓驱动·jni字符串操作
2501_915909067 小时前
不用越狱就看不到 iOS App 内部文件?使用 Keymob 查看和导出应用数据目录
android·ios·小程序·https·uni-app·iphone·webview