【安卓13】谷歌原生桌面launcher3源碼修改,修改桌面佈局(首屏應用、小部件、導航欄、大屏設備任務欄)

来源:https://www.cnblogs.com/lishilin-glut/archive/2023/11/09/17822610.html
-Advertisement-
Play Games

前言 近期接到一個關於谷歌EDLA認證的需求,我負責的是谷歌原生桌面佈局的修改,通過研究源碼,將涉及到了一些修改思路發出來,大家可以參考一下有沒有對你有用的信息。主要修改內容有: 1、搜索欄、底部導航欄未居中 2、中部應用未按要求排布,詳情請參考摹客 3、在原生Google桌面未添加中性S-writ ...


前言

近期接到一個關於谷歌EDLA認證的需求,我負責的是谷歌原生桌面佈局的修改,通過研究源碼,將涉及到了一些修改思路發出來,大家可以參考一下有沒有對你有用的信息。主要修改內容有:

1、搜索欄、底部導航欄未居中
2、中部應用未按要求排布,詳情請參考摹客
3、在原生Google桌面未添加中性S-write和投屏Kshare、歡迎頁應用

現狀圖:

參考圖:

一、谷歌搜索框的修改

涉及修改的地方有:

1、Launcher3\res\xml\device_profiles.xml

2、com/android/launcher3/Workspace.java

1、首先觀察device_profiles.xml代碼,一般大屏(平板)設備會載入6*5的佈局,手機設備會載入手機的佈局,該文件里定義了4個不同的佈局類型,如何確定設備載入哪個佈局呢?你可以在桌面長按應用圖標,然後觀察可以移動多少個格子,然後根據行列數找到要修改的佈局位置。比如我設備是載入6 * 5佈局,我修改這裡launcher:numSearchContainerColumns="5"修改谷歌搜索框占據5個格子(橫屏總共7個格子)

<--這個行數可以根據自己想要的效果修改,比如我就改了7*6佈局,6行7列--/>	
	<grid-option
        launcher:name="6_by_5"
        launcher:numRows="6" 
        launcher:numColumns="7"
        launcher:numSearchContainerColumns="5"
        launcher:numFolderRows="3"
        launcher:numFolderColumns="4"
        launcher:numHotseatIcons="0"
        launcher:hotseatColumnSpanLandscape="2"
        launcher:numAllAppsColumns="6"
        launcher:isScalable="true"
        launcher:inlineNavButtonsEndSpacing="@dimen/taskbar_button_margin_6_5"
        launcher:devicePaddingId="@xml/paddings_6x5"
        launcher:dbFile="launcher_6_by_5.db"
        launcher:defaultLayoutId="@xml/default_workspace_6x5"
        launcher:deviceCategory="tablet" >

        <display-option
            launcher:name="Tablet"
            launcher:minWidthDps="900"
            launcher:minHeightDps="820"
            launcher:minCellHeight="120"
            launcher:minCellWidth="102"
            launcher:minCellHeightLandscape="104"
            launcher:minCellWidthLandscape="120"
            launcher:iconImageSize="60"
            launcher:iconTextSize="14"
            launcher:borderSpaceHorizontal="16"
            launcher:borderSpaceVertical="64"
            launcher:borderSpaceLandscapeHorizontal="64"
            launcher:borderSpaceLandscapeVertical="16"
            launcher:horizontalMargin="54"
            launcher:horizontalMarginLandscape="120"
            launcher:allAppsCellWidth="96"
            launcher:allAppsCellHeight="142"
            launcher:allAppsCellWidthLandscape="126"
            launcher:allAppsCellHeightLandscape="126"
            launcher:allAppsIconSize="60"
            launcher:allAppsIconTextSize="14"
            launcher:allAppsBorderSpaceHorizontal="8"
            launcher:allAppsBorderSpaceVertical="16"
            launcher:allAppsBorderSpaceLandscape="16"
            launcher:hotseatBarBottomSpace="30"
            launcher:hotseatBarBottomSpaceLandscape="40"
            launcher:canBeDefault="true" />

    </grid-option>

</profiles>

2、谷歌搜索框的位置在workspace.java裡面修改,在該類裡面查找這個方法:bindAndInitFirstWorkspaceScreen,定位到這裡

    public void bindAndInitFirstWorkspaceScreen() {
        if (!FeatureFlags.QSB_ON_FIRST_SCREEN) {
            return;
        }

        // Add the first page
        CellLayout firstPage = insertNewWorkspaceScreen(Workspace.FIRST_SCREEN_ID, getChildCount());
        // Always add a first page pinned widget on the first screen.
        if (mFirstPagePinnedItem == null) {
            // In transposed layout, we add the first page pinned widget in the Grid.
            // As workspace does not touch the edges, we do not need a full
            // width first page pinned widget.
            mFirstPagePinnedItem = LayoutInflater.from(getContext())
                    .inflate(R.layout.search_container_workspace, firstPage, false);
        }

        int cellHSpan = mLauncher.getDeviceProfile().inv.numSearchContainerColumns;
        //格子數從0開始算,這裡表示搜索框位置從X軸第2格子,y軸第3個格子算起,x軸占據5(cellHSpan)個格子,y軸占據1個格子
        CellLayoutLayoutParams lp = new CellLayoutLayoutParams(1, 2, cellHSpan, 1, FIRST_SCREEN_ID);
        lp.canReorder = false;
        if (!firstPage.addViewToCellLayout(
                mFirstPagePinnedItem, 0, R.id.search_container_workspace, lp, true)) {
            Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
            mFirstPagePinnedItem = null;
        }
    }

提示:如果一開始桌面沒有谷歌搜索框,可以使用微件的形式添加,添加微件這裡又分為兩種情況,具體使用哪種方式得看系統有沒有去讀取配置文件,沒有的話就使用第一種,一種是直接在佈局文件裡面添加,比如res/xml/default_workspace_6x5.xml裡面添加:

<appwidget
    container="-100"
    screen="0"
    x="1"
    y="2"
    spanX="5"
    spanY="1"
    packageName="com.google.android.googlequicksearchbox"
    className="com.google.android.googlequicksearchbox.SearchWidgetProvider"/>

另外一種方式是在google_gms包下的配置文件裡面添加:release\vendor\partner_gms\apps\GmsSampleIntegration\res_dhs_full\xml\partner_default_layout.xml,例如

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 Google Inc. All Rights Reserved. -->
<favorites>
  <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
  <!-- Dialer Messaging Calendar Contacts Camera -->
  <!--<favorite container="-101" screen="0" x="0" y="0" packageName="com.google.android.dialer" className="com.google.android.dialer.extensions.GoogleDialtactsActivity"/>-->
  <!--<favorite container="-101" screen="1" x="1" y="0" packageName="com.google.android.apps.messaging" className="com.google.android.apps.messaging.ui.ConversationListActivity"/>-->
  <!-- <favorite container="-101" screen="0" x="0" y="0" packageName="com.android.settings" className="com.android.settings.Settings"/> -->
  <!-- <favorite container="-101" screen="1" x="1" y="0" packageName="com.android.deskclock" className="com.android.deskclock.DeskClock"/> -->
  <!-- <favorite container="-101" screen="2" x="2" y="0" packageName="com.google.android.calendar" className="com.android.calendar.event.LaunchInfoActivity"/> -->
  <!-- <favorite container="-101" screen="3" x="3" y="0" packageName="com.google.android.contacts" className="com.android.contacts.activities.PeopleActivity"/> -->
  <!-- <favorite container="-101" screen="4" x="4" y="0" packageName="com.android.camera2" className="com.android.camera.CameraLauncher"/> -->
  <!-- In Launcher3, workspaces extend infinitely to the right, incrementing from zero -->
  <!-- Google folder -->
  <!-- Google, Chrome, Gmail, Maps, YouTube, (Drive), (Music), (Movies), Duo, Photos -->
  <folder title="@string/google_folder_title" screen="0" x="1" y="3">
    <favorite packageName="com.google.android.googlequicksearchbox" className="com.google.android.googlequicksearchbox.SearchActivity"/>
    <favorite packageName="com.android.chrome" className="com.google.android.apps.chrome.Main"/>
    <favorite packageName="com.google.android.gm" className="com.google.android.gm.ConversationListActivityGmail"/>
    <favorite packageName="com.google.android.apps.maps" className="com.google.android.maps.MapsActivity"/>
    <favorite packageName="com.google.android.youtube" className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"/>
    <favorite packageName="com.google.android.apps.docs" className="com.google.android.apps.docs.app.NewMainProxyActivity"/>
    <favorite packageName="com.google.android.apps.youtube.music" className="com.google.android.apps.youtube.music.activities.MusicActivity"/>
    <favorite packageName="com.google.android.videos" className="com.google.android.videos.GoogleTvEntryPoint"/>
    <favorite packageName="com.google.android.apps.tachyon" className="com.google.android.apps.tachyon.MainActivity"/>
    <favorite packageName="com.google.android.apps.photos" className="com.google.android.apps.photos.home.HomeActivity"/>
  </folder>
  <favorite screen="0" x="5" y="3" packageName="com.android.vending" className="com.android.vending.AssetBrowserActivity"/>
  
  <appwidget screen="0" x="2" y="0" packageName="com.android.deskclock" className="com.android.alarmclock.DigitalAppWidgetProvider" spanX="3" spanY="2" />
  <appwidget screen="0" x="1" y="2" packageName="com.google.android.googlequicksearchbox" className="com.google.android.googlequicksearchbox.SearchWidgetProvider" spanX="5" spanY="1" />
</favorites>

註釋掉的內容是定義桌面的hotSeat顯示的應用,其中,添加小部件使用的是appwidget標簽,桌面時鐘就可以這樣添加,folder標簽定義的是一個桌面文件夾,裡面可以定義文件夾要存放的應用。

二、首屏應用位置修改

和谷歌搜索框一樣,也是在device_profiles.xml文件裡面定義桌面的行列數,然後根據系統是否會讀取partner_default_layout.xml佈局文件來決定修改的位置;(1)如果讀取,則在partner_default_layout.xml裡面定義應用的包名和類型以及位置信息例如<favorite screen="0" x="5" y="3" packageName="com.android.vending" className="com.android.vending.AssetBrowserActivity"/>表示在screen="0"(第一屏)的第6列格子,第4行格子添加谷歌商店app。(2)如果不讀取partner_default_layout.xml佈局文件,則在對應的X×X.xml裡面修改應用的位置。

三、底部任務欄和導航欄修改

如果設置了hotSeat應用在底部,即在partner_default_layout.xml定義的container="-101"的標簽(文件里被註釋掉的部分代碼),那麼在桌面是顯示的是底部固定的應用,不會展示最近任務欄,如果屏蔽掉了hotSeat固定的應用,則預設顯示最近任務欄去替換掉固定的應用,最近任務欄顯示圖標的數量與device_profiles.xml文件里的launcher:numHotseatIcons="0"屬性有關,這裡我設置numHotSeatIcon=0表示不顯示最近任務欄,如果你想去掉任務欄,可以使用這種方式,有其他博客去掉任務欄的方法是將isTablet的屬性設置為false,意思是將設備設置為手機屏幕,手機屏幕不顯示最近任務欄,導航欄也會預設居中,我試過該方法在大屏設備上行不通,達不到想要的效果,大家可以去看看他寫的:大屏設備底部導航欄居右
如果使用我的方法,即將hotSeat顯示的圖標數量設置為0,如果直接編譯,運行時會發生運行時異常,通過抓log發現,在源碼中有多處地方在計算佈局的時候,都會去除以numHotseatIcons,而我們知道,除數不能為0,所以報錯桌面閃退。這個時候,我們需要將引發異常的地方修改一下(註意numHotseatIcons也不能為1,因為有個地方對numHotseatIcons做了-1操作),修改位置如下:
com/android/launcher3/DeviceProfile.java
在這類裡面查找numShownHotseatIcons,將涉及到numShownHotseatIcons的計算都做一層判斷,如果為0,則換一種演算法

也可以先在device_profiles.xml裡面查找追蹤numHotseatIcons這個變數,一步步追蹤到DeviceProfile.java這個類,這樣會對整個流程更清楚

這裡是我修改的具體位置,截圖有行號,給大家參考:

註意到這個方法,裡面也用到了

修改這兩個計算方法

修改到這裡,我們已經把最近任務欄去掉啦!!

四、接下來就是要把導航欄居中

首先我們觀察device_profiles.xml文件,註意到有這個變數

查找這個變數,追蹤代碼發現,這個變數控制著底部導航欄距離右邊框的dp值,數值越大,越往中間靠攏,有了這個思路,讓導航欄居中也就不難實現了,首先我們知道,導航欄居右是因為系統判斷為大屏設備tablet,我們既然要保留tablet這個屬性,就不能通過改變設備為手機模式來控制導航欄居中,所以就可以控制右邊距啦!

而改變這個值很簡單,只需要改變引用的資源值即可

我們進入該文件,改變右邊距

這個值大家可以慢慢調試,我這裡是居中了。

五、總結

寫個總結:首先判斷系統是否載入partner_gms裡面的佈局文件,再修改佈局代碼,這個源碼我研究了一周多,網上關於安卓13的launcher3資料不全,最終還是得自己研究源碼追蹤代碼,期間編譯調試了幾十次吧!!
最終效果

本文來自博客園,作者:小李不背鍋,轉載請註明原文鏈接:https://www.cnblogs.com/lishilin-glut/p/17822610.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在使用事務的時候需要添加@EnableTransactionManagement註解來開啟事務,Spring事務底層是通過AOP來實現的,所以啟用事務後,同樣會向容器中註入一個代理對象創建器,AOP使用的是AnnotationAwareAspectJAutoProxyCreator,事務使用的是In ...
  • 前言: 繼上篇:Taurus .Net Core 微服務開源框架:Admin 插件【4-3】 - 配置管理 - Mvc【Plugin-MicroService 微服務】 本篇繼續介紹下一個內容: 系統配置節點:Mvc - Plugin - CORS 跨域界面: 界面如下: 跨域功能相關配置說明如下: ...
  • 目錄 Welcome to YARP - 1.認識YARP並搭建反向代理服務 Welcome to YARP - 2.配置功能 2.1 - 配置文件(Configuration Files) 2.2 - 配置提供者(Configuration Providers) 2.3 - 配置過濾器(Confi ...
  • 前言 由於業務需要,需要多台雲伺服器,但是公有雲的帶寬價格不菲,所以不可能給所有的雲伺服器都配上公網IP,一方面是成本的問題,另一方面也是公網安全的問題。 所以通過其它的方式使用無公網的雲伺服器來來實現對外資源的訪問。 一、操作步驟 至少需要有一臺具有公網IP的雲伺服器! 1、開啟ECS的路由轉發功 ...
  • 近幾年IT界軟硬體“國產化”搞得很密集,給很多公司帶來了商機。但是有些公司拿國外的代碼改改換個皮膚,就是“自主知識產權”的國產軟體,光明正大賣錢,這個有點...,還經常有醜聞露出,譬如某星瀏覽器、C某-IDE... 話不多說,最近有個項目需要國產化改造,業主方推薦了國產資料庫 瀚高資料庫,我們原來用 ...
  • 本文分享自華為雲社區《淺析KV存儲之長尾時延問題,華為雲 GeminiDB Redis 探尋行業更優解決方案!》,作者:華為雲資料庫GaussDB NoSQL團隊。 目前,KV存儲的廣泛使用極大程度上源於快速訪問的業務需求,而這種業務通常對時延敏感度高,在較好的平均性能下,還需要解決特定場景下的性能 ...
  • 在之前的實時湖倉系列文章中,我們已經介紹了實時湖倉對於當前企業數字化轉型的重要性,實時湖倉的功能架構設計,以及實時計算和數據湖結合的應用場景。 在本篇文章中,將介紹袋鼠雲數棧在構建實時湖倉系統上的探索與落地實踐,及未來規劃。 數棧為什麼選擇實時湖倉 數棧作為一個數據開發平臺,在未引入實時湖倉之前提供 ...
  • 資料庫底層實現博大精深,本文所述,根據線上場景進行了一些研究和探討,希望能為相關場景提供一些啟示。文章中難免會有不足之處,希望讀者能給予寶貴的意見和建議 ...
一周排行
    -Advertisement-
    Play Games
  • 通過WPF的按鈕、文本輸入框實現了一個簡單的SpinBox數字輸入用戶組件並可以通過數據綁定數值和步長。本文中介紹了通過Xaml代碼實現自定義組件的佈局,依賴屬性的定義和使用等知識點。 ...
  • 以前,我看到一個朋友在對一個系統做初始化的時候,通過一組魔幻般的按鍵,調出來一個隱藏的系統設置界面,這個界面在常規的菜單或者工具欄是看不到的,因為它是一個後臺設置的關鍵界面,不公開,同時避免常規用戶的誤操作,它是作為一個超級管理員的入口功能,這個是很不錯的思路。其實Winform做這樣的處理也是很容... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他的程式每次關閉時就會自動崩潰,一直找不到原因讓我幫忙看一下怎麼回事,這位朋友應該是第二次找我了,分析了下 dump 還是挺經典的,拿出來給大家分享一下吧。 二:WinDbg 分析 1. 為什麼會崩潰 找崩潰原因比較簡單,用 !analyze -v 命 ...
  • 在一些報表模塊中,需要我們根據用戶操作的名稱,來動態根據人員姓名,更新報表的簽名圖片,也就是電子手寫簽名效果,本篇隨筆介紹一下使用FastReport報表動態更新人員簽名圖片。 ...
  • 最新內容優先發佈於個人博客:小虎技術分享站,隨後逐步搬運到博客園。 創作不易,如果覺得有用請在Github上為博主點亮一顆小星星吧! 博主開始學習編程於11年前,年少時還只會使用cin 和cout ,給單片機點點燈。那時候,類似async/await 和future/promise 模型的認知還不是 ...
  • 之前在阿裡雲ECS 99元/年的活動實例上搭建了一個測試用的MINIO服務,以前都是直接當基礎設施來使用的,這次準備自己學一下S3相容API相關的對象存儲開發,因此有了這個小工具。目前僅包含上傳功能,後續計劃開發一個類似圖床的對象存儲應用。 ...
  • 目錄簡介快速入門安裝 NuGet 包實體類User資料庫類DbFactory增刪改查InsertSelectUpdateDelete總結 簡介 NPoco 是 PetaPoco 的一個分支,具有一些額外的功能,截至現在 github 星數 839。NPoco 中文資料沒多少,我是被博客園群友推薦的, ...
  • 前言 前面使用 Admin.Core 的代碼生成器生成了通用代碼生成器的基礎模塊 分組,模板,項目,項目模型,項目欄位的基礎功能,本篇繼續完善,實現最核心的模板生成功能,並提供生成預覽及代碼文件壓縮下載 準備 首先清楚幾個模塊的關係,如何使用,簡單畫一個流程圖 前面完成了基礎的模板組,模板管理,項目 ...
  • 假設需要實現一個圖標和文本結合的按鈕 ,普通做法是 直接重寫該按鈕的模板; 如果想作為通用的呢? 兩種做法: 附加屬性 自定義控制項 推薦使用附加屬性的形式 第一種:附加屬性 創建Button的附加屬性 ButtonExtensions 1 public static class ButtonExte ...
  • 在C#中,委托是一種引用類型的數據類型,允許我們封裝方法的引用。通過使用委托,我們可以將方法作為參數傳遞給其他方法,或者將多個方法組合在一起,從而實現更靈活的編程模式。委托類似於函數指針,但提供了類型安全和垃圾回收等現代語言特性。 基本概念 定義委托 定義委托需要指定它所代表的方法的原型,包括返回類 ...