当前位置: 首页> 健康> 科研 > Launcher 背后的魔法:Gradle 构建与编译全攻略(超详细 + Android 14.0)

Launcher 背后的魔法:Gradle 构建与编译全攻略(超详细 + Android 14.0)

时间:2025/8/8 9:10:30来源:https://blog.csdn.net/pepsimaxin/article/details/142209682 浏览次数:0次

一、源码

可以在 Google Git 中找到 Launcher3 源码。

在这里插入图片描述

直接拉取 Launcher3 代码:

git clone https://android.googlesource.com/platform/packages/apps/Launcher3

你会看到很多分支,可以选你自己所需要的分支:

在这里插入图片描述

比如 android 14:

在这里插入图片描述


二、Gradle

切到对应分支后,我们用 Android Studio 打开 Launcher3 工程,等待自动构建,你会看到如下报错信息:

在这里插入图片描述

2.1 添加 Gradle 构建工具

Launcher3 默认添加了一些 build.gradle 文件,而这些文件是需要 Gradle 构建工具的,对于像 Launcher 这种采用 bp 源码编译的应用,默认是没有的,我们可以从别处 copy 一个构建工具过来(随你是你已有项目还是新建的项目),如下:

在这里插入图片描述

现在我们再 sync 一下:

在这里插入图片描述

2.2 优化 build.gradle

先前 build.gradle 无法解析的报错信息没有了,出现了新的报错:

Project with path ':UiTestsLibLauncher' could not be found in root project 'Gradle_Launcher3_AOSP'.

我们工程里面是没有 UiTestsLibLauncher 的,所以可以直接在 build.gradle 里面去掉:

📄 build.gradledependencies {implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"implementation "androidx.preference:preference:${ANDROID_X_VERSION}"implementation project(':IconLoader')// implementation project(':UiTestsLibLauncher')withQuickstepImplementation project(':SharedLibWrapper')...
}

再 sync:

在这里插入图片描述

报错原因是:protoc 编译器的版本没有指定多少,我们可以直接指定:

📄 build.gradleprotobuf {// Configure the protoc executableprotoc {// 指定 protoc 编译器的版本artifact = "com.google.protobuf:protoc:3.22.3"}generateProtoTasks {...}
}

再 sync:

在这里插入图片描述

此时 Gradle 开始 Download 所需要的各种库,我们等待它同步完成即可,最终会是下面这个样子:

在这里插入图片描述

此时,我们其实已经成功搭建号了 Launcher3 Gradle 编译所需要的环境!但其实,这只是万里长征的第一步,因为如果你想成功 build 出 apk,还有很多需要修改的地方。


三、第一阶段报错修复

现在我们来 build 一下 APK 试试:

在这里插入图片描述

开始报错:

在这里插入图片描述

我们看看在哪里用到的:

在这里插入图片描述

3.1 AGP 插件

我们需要修改下构建工具,不使用 Build Tools,改成 Android Gradle Plugin (AGP) ,如下:

在这里插入图片描述

3.2 无用引用

继续 build APK:

在这里插入图片描述

老样子,找不到 IconLoaderSharedWrapper,我们直接注掉:

📄 build.gradledependencies {implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"implementation "androidx.preference:preference:${ANDROID_X_VERSION}"// implementation project(':IconLoader')// implementation project(':UiTestsLibLauncher')// withQuickstepImplementation project(':SharedLibWrapper')...
}

同时我们需要修改 settings.gradle 文件:

📄 settings.gradle// 不需要了,直接注释掉//include ':IconLoader'
//project(':IconLoader').projectDir = new File(rootDir, 'iconloaderlib')//include ':SharedLibWrapper'
//project(':SharedLibWrapper').projectDir = new File(rootDir, 'SharedLibWrapper')

3.3 Recycleview 库

继续 build APK:

在这里插入图片描述

这里的报错就很有意思:

implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
ANDROID_X_VERSION=1+

从官方仓库拉的最新的 RecyeleView 库的最新版本是 1.4.0-beta01,本来之前所有的 Launcher3 项目是不会抱这个错的,但是就在最近,官方加了一个说明:

在这里插入图片描述

所以,我们就直接指定 RecycleView 的版本号吧:

implementation "androidx.recyclerview:recyclerview:1.4.0-alpha01"

3.4 资源报错

继续 build APK:

在这里插入图片描述

你会发现一堆报错,不急,我们慢慢改,比如以下报错:

1: Task failed with an exception.
-----------
* What went wrong:
Some problems were found with the configuration of task ':extractAospProto' (type 'ProtobufExtract').- In plugin 'com.google.protobuf' type 'com.google.protobuf.gradle.ProtobufExtract' property 'destDir' is missing an input or output annotation.Reason: A property without annotation isn't considered during up-to-date checking.Possible solutions:1. Add an input or output annotation.2. Mark it as @Internal.Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#missing_annotation for more details about this problem.- In plugin 'com.google.protobuf' type 'com.google.protobuf.gradle.ProtobufExtract' property 'isTest' is missing an input or output annotation.Reason: A property without annotation isn't considered during up-to-date checking.Possible solutions:1. Add an input or output annotation.2. Mark it as @Internal.Please refer to https://docs.gradle.org/7.4/userguide/validation_problems.html#missing_annotation for more details about this problem.

我们需要升级 protobuf-gradle-plugin 插件版本:

📄 gradle.properties# PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.8.8
PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.9.4

继续 build APK:

在这里插入图片描述

这个报错表明你的项目中存在重复的类定义,这是因为不同版本的 Kotlin 标准库依赖被引入到你的项目中。具体来说,这些重复类来自以下两个依赖项:

1.	org.jetbrains.kotlin:kotlin-stdlib:1.8.22
2.	org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.0 和 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0

解决办法:

📄 build.gradlebuildscript {repositories {mavenCentral()google()}dependencies {classpath 'com.android.tools.build:gradle:7.3.1'classpath GRADLE_CLASS_PATHclasspath PROTOBUF_CLASS_PATH// 1. 声明 Kotlin Gradle 插件的依赖classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"}
}apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf'
apply plugin: 'kotlin-android'    // 2. 应用 Kotlin Android 插件
apply plugin: 'kotlin-kapt'       // 3. 应用 Kotlin Kapt 插件android {...// 4. 设置 Kotlin 编译器的选项kotlinOptions {// 设置 Kotlin 代码编译后生成的字节码目标版本为 Java 8。// 即使你使用的是较新的 JDK(例如 JDK 17),编译后的字节码也会兼容 Java 8jvmTarget = '1.8'freeCompilerArgs = ["-Xjvm-default=all"]}
}

经过如上 4 步修改,即可编译过,我们继续 Build APK,修复其它报错:

在这里插入图片描述

我们定位到代码里,比如:materialColorPrimaryFixedDim

在这里插入图片描述

是标红的,改法很简单,去掉 androidprv:

<color name="work_turn_on_stroke">?attr/colorAccentSecondaryVariant</color>
<color name="work_fab_bg_color">?attr/materialColorPrimaryFixedDim</color>
<color name="work_fab_icon_color">?attr/materialColorOnPrimaryFixed</color>

其它的资源报错类似的(?androidprv:attr/***),一并按照这个方式修改,修改完后,我们继续 Build APK:

在这里插入图片描述

这里的报错涉及到好几个修改点,我们一个个解决:

  1. 先来看:colorAccentPrimaryVariantcolorAccentSecondaryVariant 找不到。
📄 res/values/attrs.xml<!-- 添加, start -->
<attr name="colorAccentPrimaryVariant" format="color"/>
<attr name="colorAccentSecondaryVariant" format="color"/>
<!-- 添加, end --><attr name="materialColorOnSecondaryFixedVariant" format="color" />
<attr name="materialColorOnTertiaryFixedVariant" format="color" />
<attr name="materialColorSurfaceContainerLowest" format="color" />
  1. 再来看主题错误:
error: resource style/Theme.MaterialComponents.DayNight (aka com.android.launcher3:style/Theme.MaterialComponents.DayNight) not found.
com.android.launcher3-mergeAospWithQuickstepDebugResources-28:/values-v31/values-v31.xml:126: error: style attribute 'attr/elevationOverlayColor (aka com.android.launcher3:attr/elevationOverlayColor)' not found.
com.android.launcher3-mergeAospWithQuickstepDebugResources-28:/values-v31/values-v31.xml:127: error: style attribute 'attr/elevationOverlayEnabled (aka com.android.launcher3:attr/elevationOverlayEnabled)' not found.

在这里插入图片描述

我们需要在 build.gradle 里面添加 material 依赖:

📄 build.gradledependencies {implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"// noinspection GradleDependencyimplementation "androidx.recyclerview:recyclerview:1.4.0-alpha01"implementation "androidx.preference:preference:${ANDROID_X_VERSION}"// 添加 material 依赖implementation 'com.google.android.material:material:1.11.0'// implementation project(':IconLoader')// implementation project(':UiTestsLibLauncher')// withQuickstepImplementation project(':SharedLibWrapper')...
}
  1. 最后来看 disabledIconAlphaloadingIconColor 找不到的问题:

这两个属性是 iconloaderlib 库中的,它是 Android 系统和应用程序中处理图标加载和渲染的一个库。它在 Launcher 中用于加载、缓存、缩放和渲染应用程序图标,以确保在不同屏幕分辨率和设备环境下显示一致的图标质量。

3.5 iconloaderlib

现在我们是缺失这个库的,我们看看如何已模块的方式引进来(这样我们可以直接修改它的代码,Launcher 调试更方便)。

在这里插入图片描述

按照这个路径找到 iconloaderlib 包,直接 copy 到 Launcher 工程中,并且在工程的 build.gradle 里面进行一些配置:

在这里插入图片描述

现在我们继续 Build APK:

在这里插入图片描述

资源重复问题,如下:

📄 iconloaderlib/res/values/dimens<dimen name="profile_badge_size">24dp</dimen>📄 res/values/dimens<dimen name="profile_badge_size">24dp</dimen>

我们只需要把多余的删除即可,继续 Build APK:

在这里插入图片描述

恭喜你,到这里,我们就进入第二阶段(实际代码 API 调用错误)的报错修复之路了。


四、第二阶段报错修复

具体代码的报错信息,我就不给大家一个个分析了,究其原因就是缺了很多依赖库(Android.bp 里面引用的那些),所以这里直接告诉大家需要怎么做即可。

4.1 animationlib

和 iconloaderlib 一样,找到 animationlib 的包,copy 到 Launcher 工程:

在这里插入图片描述

并且也需要在 build.gradle 里面配置:

📄 build.gradlejava.srcDirs = ['src','src_plugins','iconloaderlib/src','iconloaderlib/src_full_lib','animationlib/src']    // 加进来

4.2 tests

📄 build.gradlejava.srcDirs = ['src','src_plugins','iconloaderlib/src','iconloaderlib/src_full_lib','animationlib/src','tests/shared']    // 加进来// 注释掉 test 模块其他资源引用
//        androidTest {
//            res.srcDirs = ['tests/res']
//            java.srcDirs = ['tests/src', 'tests/tapl']
//            manifest.srcFile "tests/AndroidManifest-common.xml"
//        }
//
//        androidTestDebug {
//            manifest.srcFile "tests/AndroidManifest.xml"
//        }

4.3 SystemUISharedLib

out/soong/.intermediates/frameworks/base/packages/SystemUI/shared/SystemUISharedLib/android_common/combined
拷贝 SystemUISharedLib.jar 并引入到 libs:

在这里插入图片描述

修改工程 build.gradle 配置:

📄 build.gradledependencies {implementation fileTree(dir: "libs", include: ['*.jar', '*.aar'])
}

4.4 SystemUIUnfoldLib

out/soong/.intermediates/frameworks/base/packages/SystemUI/unfold/SystemUIUnfoldLib/android_common/combined
拷贝 SystemUIUnfoldLib.jar 并引入到 libs:

在这里插入图片描述

4.5 SystemUIAimationLib

copy frameworks/base/packages/SystemUI/animation/ 目录的代码到 Launcher 工程,我们定一一个模块名为:SystemUIAimationLib,如下:

在这里插入图片描述

4.6 PluginCoreLib

out/soong/.intermediates/frameworks/base/packages/SystemUI/plugin_core/PluginCoreLib/android_common/javac
拷贝 PluginCoreLib 并引入到 libs:

在这里插入图片描述

4.7 core-animation

引入 androidx.core:core-animation 库到 Android 项目中:

📄 build.gradledependencies {implementation 'androidx.core:core-animation:1.0.0-rc01'
}

4.8 注释标红代码

📄 src/com/android/launcher3/logging/StartupLatencyLoggerif (!BuildConfig.IS_STUDIO_BUILD && !isInTest) {return true
}有两处,全部注释掉!

4.9 protobuf

build.gradle 添加依赖:

📄 build.gradledependencies {sourceSets {main {...proto {// srcDirs = ['protos/', 'protos_overrides/']// 修改srcDirs = ['protos/','quickstep/protos_overrides/']}}...implementation 'com.google.protobuf:protobuf-javalite:3.22.3'
}

4.10 JDK 调整

📄 build.gradledependencies {compileOptions {// sourceCompatibility JavaVersion.VERSION_1_8// targetCompatibility JavaVersion.VERSION_1_8sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}kotlin {jvmToolchain(17)}
}

4.11 turbine 包引入

之前我们引入了 SystemUISharedLib 和 SystemUIUnfoldLib 的 jar 包,但他们是 combined 包下的,我们需要另外再引入 turbine-combined 下的 jar 包,如下:

out/soong/.intermediates/frameworks/base/packages/SystemUI/shared/SystemUISharedLib/android_common/turbine-combined
拷贝 SystemUISharedLib.jar 并引入到 libs,由于包名相同,我们重命名为:SystemUISharedLib-turbine.jar

out/soong/.intermediates/frameworks/base/packages/SystemUI/unfold/SystemUIUnfoldLib/android_common/turbine-combined
拷贝 SystemUIUnfoldLib.jar 并引入到 libs,由于包名相同,我们重命名为:SystemUIUnfoldLib-turbine.jar

在这里插入图片描述

4.12 SystemUI-statsd

out/soong/.intermediates/frameworks/base/packages/SystemUI/shared/SystemUI-statsd/android_common/javac
拷贝 SystemUI-statsd.jar 并引入到 libs:

在这里插入图片描述

4.13 Slice 库

添加依赖:

📄 build.gradledependencies {implementation 'androidx.slice:slice-core:1.0.0'implementation 'androidx.slice:slice-builders:1.0.0'
}

4.14 viewcapturelib

在这里插入图片描述

和 iconloaderlib 一样的路径,我们找到 viewcapturelib 包,直接 copy 到 Launcher 工程中,并且在工程的 build.gradle 里面进行一些配置:

在这里插入图片描述

到这里,我们再次 Build APK 试试:

在这里插入图片
blog描述


五、运行

到目前为止,Launcher 的 APK 文件我们已经可以编译出来了,不妨试试?push 到你的设备里面,你会发现 Launcher 黑屏,是起不来的。

别慌,我们继续解决报错。

5.1 报错 1

首先,你可能会看到以下报错:

09-13 08:05:14.899  8505  8529 E AndroidRuntime: FATAL EXCEPTION: UiThreadHelper
09-13 08:05:14.899  8505  8529 E AndroidRuntime: Process: com.android.launcher3, PID: 8505
09-13 08:05:14.899  8505  8529 E AndroidRuntime: java.lang.IllegalAccessError: Method 'void com.android.launcher3.views.ActivityContext.lambda$hideKeyboard$2(android.view.inputmethod.InputMethodManager, android.os.IBinder)' is inaccessible to class 'com.android.launcher3.views.ActivityContext$$ExternalSyntheticLambda1' (declaration of 'com.android.launcher3.views.ActivityContext$$ExternalSyntheticLambda1' appears in /data/app/~~cpByXOaM5sPPePJ4cFVhKQ==/com.android.launcher3-3K34Q-5lZ3pccyDjykl43Q==/base.apk!classes14.dex)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at com.android.launcher3.views.ActivityContext$$ExternalSyntheticLambda1.run(Unknown Source:6)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:958)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:99)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:205)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:294)
09-13 08:05:14.899  8505  8529 E AndroidRuntime: 	at android.os.HandlerThread.run(HandlerThread.java:67)

解决方法:

📄 定位到:ActivityContext.java// 注释掉这部分
//        if (imm != null && token != null) {
//            UI_HELPER_EXECUTOR.execute(() -> {
//                if (imm.hideSoftInputFromWindow(token, 0)) {
//                    // log keyboard close event only when keyboard is actually closed
//                    MAIN_EXECUTOR.execute(() ->
//                            getStatsLogManager().logger().log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED));
//                }
//            });
//        }

5.2 报错 2

再次运行,报错信息如下:

09-13 08:09:58.574 21935 21962 E AndroidRuntime: FATAL EXCEPTION: launcher-loader
09-13 08:09:58.574 21935 21962 E AndroidRuntime: Process: com.android.launcher3, PID: 21935
09-13 08:09:58.574 21935 21962 E AndroidRuntime: java.lang.IllegalAccessError: Method 'int com.android.launcher3.util.FlagOp.lambda$removeFlag$2(int, int)' is inaccessible to class 'com.android.launcher3.util.FlagOp$$ExternalSyntheticLambda2' (declaration of 'com.android.launcher3.util.FlagOp$$ExternalSyntheticLambda2' appears in /data/app/~~smscPfmSXdORUMxSIVSXWA==/com.android.launcher3-htSGu13r7cEsjDxCWxbHeA==/base.apk!classes3.dex)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.util.FlagOp$$ExternalSyntheticLambda2.apply(Unknown Source:4)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.BitmapInfo.withFlags(BitmapInfo.java:85)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.cache.BaseIconCache.getDefaultIcon(BaseIconCache.java:378)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.cache.BaseIconCache.isDefaultIcon(BaseIconCache.java:397)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.IconCache.loadIconSubsection(IconCache.java:456)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.IconCache.lambda$getTitlesAndIconsInBulk$16(IconCache.java:404)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.IconCache.$r8$lambda$5-QJc-TjC50rjAxnltzqbHffkpc(Unknown Source:0)
09-13 08:09:58.574 21935 21962 E AndroidRuntime: 	at com.android.launcher3.icons.IconCache$$ExternalSyntheticLambda13.accept(Unknown Source:6)

解决方法:定位到 iconloaderlib/src/com/android/launcher3/util/FlagOp.java,如下修改:

在这里插入图片描述

修改后如下:

    /*** Returns a new OP which adds the provided flag after applying all previous operations*/default FlagOp addFlag(int flag) {//return i -> apply(i) | flag;return new FlagOp() {@Overridepublic int apply(int i) {return FlagOp.this.apply(i) | flag;}};}/*** Returns a new OP which removes the provided flag after applying all previous operations*/default FlagOp removeFlag(int flag) {//return i -> apply(i) & ~flag;return new FlagOp() {@Overridepublic int apply(int i) {return FlagOp.this.apply(i) & ~flag;}};}

至此,恭喜你,你的 Launcher3 源码已经成功转型为 Gradle 编译,并且可以完美起来,看个图吧:

在这里插入图片描述

关键字:Launcher 背后的魔法:Gradle 构建与编译全攻略(超详细 + Android 14.0)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: