Android10.0 Launcher3 启动和加载流程(下)

简介: 笔记

invDistWeightedInterpolate

调用这个方法时传进去的参数是当前手机真实的宽和高,以及经过排序后得到的与目标匹配度由高到低的profiles集合。具体的操作在代码中进行了注解,其实,很多手机型号一致的,计算的时候不算多,有些许差别,计算出来的偏差值也不多,所以这个偏差值纠正就分析到这里。

static DisplayOption invDistWeightedInterpolate(float width, float height,
              ArrayList<DisplayOption> points) {
      float weights = 0;
      DisplayOption p = points.get(0);
      if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) {
          return p;
      }
      DisplayOption out = new DisplayOption();
      out.name = "";
      for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) {
          p = points.get(i);
          float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER);
          weights += w;
          out.add(new DisplayOption().add(p).multiply(w));
          if (!TextUtils.isEmpty(out.name)) {
              out.name += "&";
          }
          out.name += "<" + (p.grid != null ? p.grid.name : "not found") + "," + p.name + ">";
      }
      return out.multiply(1.0f / weights);
  }

//获取默认的gridname,在该版本中返回的是空值
 private String getDefaultGridName(Context context) {
   String defaultGridName = "";
   DesktopGridController gridController = mMonitor.getDesktopGridController();
   if (gridController != null) {
       defaultGridName = gridController.getDefaultGridName();
       if (mMonitor.getSRController() != null
               && !gridController.isGridNameValid(defaultGridName)) {
           if (LogUtils.DEBUG) {
               LogUtils.d(TAG, "The default grid name configured is invalid:" + defaultGridName);
           }
           defaultGridName = mMonitor.getSRController().getGridNameFromStorage(context);
       }
       if (LogUtils.DEBUG) {
           LogUtils.d(TAG, "getDefaultGridName: defaultGridName = " + defaultGridName);
       }
   }
   return defaultGridName;

}

GridOption和DiaplayOption

private static final class DisplayOption {
      private final GridOption grid;
      private String name;
      private final float minWidthDps;
      private final float minHeightDps;
      private final boolean canBeDefault;
      private float iconSize;
      private float landscapeIconSize;
      private float iconTextSize;
      ...
}
   public static final class GridOption {
       public static final String TAG_NAME = "grid-option";
       public final String name;
       public final int numRows;
       public final int numColumns;
       private final int numFolderRows;
       private final int numFolderColumns;
       private final int numHotseatIcons;
       private final int defaultLayoutId;
       private final int demoModeLayoutId;
       private final SparseArray<TypedValue> extraAttrs;

##com.android.launcher3.prefs.xml
这是Launcher3应用主要的sharedprefs文件,作为分析时的参考
`/data/data/com.android.launcher3/shared_prefs/com.android.launcher3.prefs.xml`
```                                                                             <
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="launcher.home_bounce_count" value="4" />
    <string name="migration_src_workspace_size">2,2</string>
    <boolean name="pref_add_icon_to_home" value="true" />
    <int name="migration_src_hotseat_count" value="0" />
    <boolean name="pref_add_icon_to_home_initialized" value="true" />
    <boolean name="sl_EMPTY_DATABASE_CREATED" value="true" />
    <int name="migration_src_density_dpi" value="140" />
    <string name="idp_grid_name">3_by_3</string>
</map>

MultiModeController.java


packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeController.java

import static com.android.launcher3.LauncherProvider.SCHEMA_VERSION; //28
   public static String getKeyByMode(Context context, String originalKey) {
       return getKeyByMode(context, originalKey, SCHEMA_VERSION, isSingleLayerMode(context));
   }
    //参数:key, 数据库版本,是单层还是双层显示
   public static String getKeyByMode(
           Context context, String originalKey, int dbVersion, boolean isSingleLayerMode) {
       initControllerIfNeeded(context);
       return MultiModeUtilities.getKeyByMode(originalKey, isSingleLayerMode, dbVersion);
   }
   public static String getKeyByPreMode(Context context, String originalKey) {
       return getKeyByMode(context, originalKey, SCHEMA_VERSION, !isSingleLayerMode(context));
   }
    public static boolean isSingleLayerMode() {
        throwIfControllerNotInited();
        return sIsSingleLayerMode; //返回变量sIsSingleLayerMode
    }
    public static void setSingleLayerMode(Context context, boolean isSingleMode) {
        MultiModeUtilities.syncSaveNewModel(context,
                isSingleMode ? MultiModeUtilities.SINGLE : MultiModeUtilities.DUAL);
        //sIsSingleLayerMode在构造方法中赋值
        sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context);
        sIsDefaultMode = MultiModeUtilities.isDefaultMode(context);
    }
   public MultiModeController(Context context, LauncherAppMonitor monitor) {
       super(context);
        //是否支持动态显示
       sIsSupportDynamicChange = MultiModeUtilities.isSupportDynamicHomeStyle(context);
        //是否是单层显示
       sIsSingleLayerMode = MultiModeUtilities.isSingleLayerMode(context);
       sIsDefaultMode = MultiModeUtilities.isDefaultMode(context);
       monitor.registerCallback(mAppMonitorCallback);
       LogUtils.d(TAG, this);
   }
    //是否支持动态变化
   public static boolean isSupportDynamicChange() {
       throwIfControllerNotInited();
       return sIsSupportDynamicChange;
   }
   public static void setSupportDynamicChange(boolean isSupport) {
       sIsSupportDynamicChange = isSupport;
   }

MultiModeUtilities


packages/apps/Launcher3/src/com/sprd/ext/multimode/MultiModeUtilities.java

static final String SINGLE = "single";
   static final String DUAL = "dual";
   static final String SL_PREFIX = "sl_";
    //判断是否是单层显示
   static boolean isSingleLayerMode(Context context) {
       return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get()
               && SINGLE.equals(getHomeScreenStylePrefValue(context));
   }
    //在sharepref中获取显示风格的值
   static String getHomeScreenStylePrefValue(Context context) {
       if (context == null) {
           return DUAL;
       }
       Resources res = context.getResources();
       return Utilities.getPrefs(context)
               .getString(LauncherSettingsExtension.PREF_HOME_SCREEN_STYLE_KEY,
                       res.getString(R.string.default_home_screen_style)); 
              //默认值为R.string.default_home_screen_style
   }
    // We add SL_PREFIX only single layer mode & support dynamic change.
    static String getKeyByMode(String originalKey, boolean isSingleMode, int dbVersion) {
        if (TextUtils.isEmpty(originalKey)) {
            throw new RuntimeException("getKeyByMode() the original key is empty!");
        }
        String outKey = originalKey;
        //如果支持多模式,再进行判断,如果不支持,则使用双层模式
        //我修改了show_home_screen_style_settings的值为false,outKey=idp_grid_name
        if (MultiModeController.isSupportDynamicChange()) {
            switch (dbVersion) {
                case 27:
                    // Android P db version is 27.
                    outKey = isSingleMode ? SINGLE + "_" + originalKey : DUAL + "_" + originalKey;
                    break;
                default:
                    //我的设备是单层显示,所以返回的是sl_idp_grid_name
                    outKey = isSingleMode ? SL_PREFIX + originalKey : originalKey;
                    break;
            }
        }
        return outKey;
    }
  //是否支持动态显示
   static boolean isSupportDynamicHomeStyle(Context context) {
       return FeatureOption.SPRD_MULTI_MODE_SUPPORT.get()
               && context.getResources().getBoolean(R.bool.show_home_screen_style_settings);
   }

LauncherSettingsExtension


packages/apps/Launcher3/src/com/sprd/ext/LauncherSettingsExtension.java

public static final String PREF_HOME_SCREEN_STYLE_KEY = "pref_home_screen_style";

FeatureOption


packages/apps/Launcher3/src/com/sprd/ext/FeatureOption.java

public static final TogglableFlag SPRD_MULTI_MODE_SUPPORT = new TogglableFlag(
          "SPRD_MULTI_MODE_SUPPORT", getProp("ro.launcher.multimode"),
          "enable user can select user aosp mode or singlelayer mode");
  public static final TogglableFlag SPRD_DESKTOP_GRID_SUPPORT = new TogglableFlag(
          "SPRD_DESKTOP_GRID_SUPPORT", getProp("ro.launcher.desktopgrid"),
          "enable allows customization of the columns and rows on the desktop");

config_ext.xml


packages/apps/Launcher3/res/values/config_ext.xml

//从上面分析可以得出结论
    <!--default value of launcher style allapps or singlelayer 是否显示单层/双层设置显示-->
    <bool name="show_home_screen_style_settings">false</bool>
    <!--The value must be dual or single 默认为单层还是双层-->
    <string name="default_home_screen_style" translatable="false">dual</string>

device_profiles.xml


位置:packages/apps/Launcher3/res/xml/device_profiles.xml

<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
    <grid-option
        launcher:name="2_by_2"
        launcher:numRows="2"
        launcher:numColumns="2"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="2"
        launcher:numHotseatIcons="3" 
        launcher:defaultLayoutId="@xml/default_workspace_3x3" >
        <display-option
            launcher:name="Super Short Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="300"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Shorter Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="400"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
    <grid-option
        launcher:name="3_by_3"
        launcher:numRows="3"
        launcher:numColumns="3"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="3"
        launcher:numHotseatIcons="3"
        launcher:defaultLayoutId="@xml/default_workspace_3x3" >
        <display-option
            launcher:name="Super Short Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="300"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Shorter Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="400"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
    <grid-option
        launcher:name="4_by_4"
        launcher:numRows="4"
        launcher:numColumns="4"
        launcher:numFolderRows="3"
        launcher:numFolderColumns="4"
        launcher:numHotseatIcons="4"
        launcher:defaultLayoutId="@xml/default_workspace_4x4" >
        <display-option
            launcher:name="Short Stubby"
            launcher:minWidthDps="275"
            launcher:minHeightDps="420"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Stubby"
            launcher:minWidthDps="255"
            launcher:minHeightDps="450"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus S"
            launcher:minWidthDps="296"
            launcher:minHeightDps="491.33"
            launcher:iconImageSize="48"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus 4"
            launcher:minWidthDps="359"
            launcher:minHeightDps="567"
            launcher:iconImageSize="54"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
        <display-option
            launcher:name="Nexus 5"
            launcher:minWidthDps="335"
            launcher:minHeightDps="567"
            launcher:iconImageSize="54"
            launcher:iconTextSize="13.0"
            launcher:canBeDefault="true" />
    </grid-option>
</profiles>


目录
相关文章
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
1042 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1006 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
730 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
530 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
10424 2
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
648 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
测试技术 Android开发 开发者
【03】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第三篇安卓APP上架华为商店后面的步骤-华为应用商店相对比较麻烦一些-华为商店安卓上架
【03】优雅草央千澈详解关于APP签名以及分发-上架完整流程-第三篇安卓APP上架华为商店后面的步骤-华为应用商店相对比较麻烦一些-华为商店安卓上架
360 16
|
Android开发
Android面试之Activity启动流程简述
Android面试之Activity启动流程简述
365 6
|
消息中间件 Android开发 索引
Android面试高频知识点(4) 详解Activity的启动流程
Android面试高频知识点(4) 详解Activity的启动流程
476 3

热门文章

最新文章