一.环境准备
首先需要特定版本的AndroidStudio,由于AndroidStudio与gradle版本相关联,所以也需要注意gradle版本,如下是我的AndroidStudio与gradle版本
在gradle-wrapper.properties中配置gradle版本如下:
#Sun Aug 2214:48:51CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
在Settings中的build.gradle中gradle配置如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.8.10'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.17'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add("-Xbootclasspath/p:${project.rootDir}/libs/framework.jar")
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
如果没有上面AndroidStudio版本可以进行下载,不用卸载原先的AndroidStudio,是可以运行多个不同版本的AndroidStudio的,AndroidStudio下载地址:Android Studio 下载文件归档 | Android 开发者 | Android Developers
Java版本如下:
二.理解Settings Android.bp文件里面的依赖关系
首先我们找到Settings项目位置:QCM6125_Android13.0_R04_r020\QSSI.13\packages\apps\Settings
然后分析Settings里面的Android.bp文件
package{
default_applicable_licenses: ["packages_apps_Settings_license"],
}
// Added automatically by a large-scale-change
// See:http://go/android-license-faq
license {
name: "packages_apps_Settings_license",
visibility: [":__subpackages__"],
license_kinds: [
"SPDX-license-identifier-Apache-2.0",
],
license_text: [
"NOTICE",
],
}
java_library {
name: "settings-logtags",
srcs: ["src/**/*.logtags"],
}
genrule {
name: "statslog-settings-java-gen", //此模块是调用命令,生成auto generating code
tools: ["stats-log-api-gen"],
cmd: "$(location stats-log-api-gen) --java $(out) --module settings"
+ " --javaPackage com.android.settings.core.instrumentation --javaClass SettingsStatsLog",
out: ["com/android/settings/core/instrumentation/SettingsStatsLog.java"],
}
java_library {
name: "statslog-settings", //此模块使用自动生成的代码,生成statslog-settings.jar包
srcs: [
":statslog-settings-java-gen",
],
}
soong_config_module_type_import {
from: "device/qcom/qssi/Android.bp",
module_types: [
"bredr_vs_btadva_java_defaults",
],
}
bredr_vs_btadva_java_defaults {
name: "btadva_settings_java_defaults",
soong_config_variables: {
bredr_or_btadva: {
btadva: {
srcs: [
":settings-bluetooth-adva-srcs",
],
}
}
}
}
// Build the Settings APK //生成APK相关内容
android_library { //此模块是生成一个JAR LIBRARY
name: "Settings-core", //生成的模块名称为:Settings-core
platform_apis: true, //获取访问@hide API的权限,谷歌发布的SDK是不包含隐藏API的
defaults: [
"SettingsLibDefaults", //使用名为SettingsLibDefaults的模块defaults配置,从名字得知还需要引入SettingsLib相关模块
"SettingsLib-search-defaults", //使用名为SettingsLib-search-defaults的模块defaults配置
"framework-wifi-vendor-hide-access-defaults", //使用名为framework-wifi-vendor-hide-access的模块defaults配置
"btadva_settings_java_defaults", //使用名为btadva_settings_java的模块defaults配置
],
srcs: ["src/**/*.java", "src/**/*.kt"],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.slice_slice-builders",
"androidx.slice_slice-core",
"androidx.slice_slice-view",
"androidx.core_core",
"androidx.appcompat_appcompat",
"androidx.cardview_cardview",
"androidx.preference_preference",
"androidx.recyclerview_recyclerview",
"androidx.window_window",
"com.google.android.material_material",
"setupcompat",
"setupdesign",
"androidx.lifecycle_lifecycle-runtime",
"androidx.lifecycle_lifecycle-extensions",
"guava",
"jsr305",
"net-utils-framework-common",
"settings-contextual-card-protos-lite",
"settings-log-bridge-protos-lite",
"settings-telephony-protos-lite",
"contextualcards",
"settings-logtags",
"statslog-settings",
"zxing-core-1.7",
"android.hardware.dumpstate-V1.0-java",
"android.hardware.dumpstate-V1.1-java",
"lottie",
"WifiTrackerLib",
"SettingsLibActivityEmbedding",
],
libs: [ //# Settings-core 模块依赖的动态库列表
"telephony-common",
"ims-common",
"app-compat-annotations",
"telephony-ext",
"extphonelib",
],
}
platform_compat_config {
name: "settings-platform-compat-config",
src: ":Settings-core", //依赖Settings-core模块
system_ext_specific: true, //编译生成的文件将存放到/system/system_ext/ 目录
}
android_app { //生成APK的模块
name: "Settings", //生成的APK名为:Settings.apk
defaults: ["platform_app_defaults"],
platform_apis: true, //授权使用@hide API
certificate: "platform", //采用系统签名
system_ext_specific: true, //结合privilege:true,编译生成的文件,将存放到/system/system_ext/pri-app中
privileged: true, //是否存放在priv-app 目录
required: [
"privapp_whitelist_com.android.settings",
"settings-platform-compat-config",
],
static_libs: ["Settings-core"], //静态依赖于Settings-core 模块
uses_libs: ["org.apache.http.legacy"],
resource_dirs: [],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
libs: [
"extphonelib"
],
}
android_library_import {
name: "contextualcards", //名为contextualcards.aar模块
aars: ["libs/contextualcards.aar"],
}
filegroup {
name: "Settings_proguard_flags",
srcs: ["proguard.flags"],
}
// The sources for Settings need to be exposed to SettingsGoogle, etc.
// so they can run the com.android.settingslib.search.IndexableProcessor
// over all the sources together.
filegroup {
name: "Settings_srcs",
srcs: ["src/**/*.java"],
}
filegroup {
name: "Settings_manifest",
srcs: ["AndroidManifest.xml"],
}
分析结果:
1.生成Settings.apk的android_app编译配置,通过Settings-core间接依赖于srcs:["src/**/*java"]
所以未直接使用自己目录下的源码来生成
若依照此配置构建AS工程,则工程中没有Settings源码,而是由各种库组成
我们构建AS工程,本身是为了调试Settings源码,所以jar就失去了构建AS工程的意义
结论:我们构建的Settings AS工程,其Settings.app的build.gradle将直接依赖源码,而不是Settings-core.jar
2.从Settings-core模块的defaults应用得知,我们还需要依赖模块:SettiingsLibDefaults和SettingsLib-search-defaults
从后续SettingsLib的依赖分析得知,Settings需要依赖于SettingsLib,所以我们还得继续分析SettingsLib的Android.bp
3.以androidx开头的,均为安卓的支持库,通过Maven远程仓库获取
三.理解SettingsLib中的Android.bp文件中依赖关系
上面说了Settings中需要依赖SettingsLib,首先我们找到SettingsLib的位置:\\10.66.100.21\disk1\project\QCM6125_Android13.0_R04_r020\QSSI.13\frameworks\base\packages\SettingsLib
然后分析里面的Android.bp文件
package{
// See:http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
}
soong_config_module_type_import {
from: "device/qcom/qssi/Android.bp",
module_types: [
"bredr_vs_btadva_java_defaults",
],
}
bredr_vs_btadva_java_defaults {
name: "btadva_settings_lib_java_defaults",
soong_config_variables: {
bredr_or_btadva: {
btadva: {
srcs: [
":framework-settingslib-adva-srcs",
],
}
}
}
}
android_library {
name: "SettingsLib", //模块名称 SettingsLib.jar
defaults: [
"framework-wifi-vendor-hide-access-defaults", //引用名
"btadva_settings_lib_java_defaults", //引用名
],
static_libs: [ //静态依赖,SettingsLib都需要依赖下面模块
"androidx.annotation_annotation",
"androidx.legacy_legacy-support-v4",
"androidx.recyclerview_recyclerview",
"androidx.preference_preference",
"androidx.appcompat_appcompat",
"androidx.lifecycle_lifecycle-runtime",
"androidx.mediarouter_mediarouter-nodeps",
"com.google.android.material_material",
"iconloader",
"WifiTrackerLib",
"WifiTrackerLibRes",
"SettingsLibHelpUtils",
"SettingsLibRestrictedLockUtils",
"SettingsLibActionBarShadow",
"SettingsLibAppPreference",
"SettingsLibSearchWidget",
"SettingsLibSettingsSpinner",
"SettingsLibIllustrationPreference",
"SettingsLibLayoutPreference",
"SettingsLibMainSwitchPreference",
"SettingsLibActionButtonsPreference",
"SettingsLibEntityHeaderWidgets",
"SettingsLibBarChartPreference",
"SettingsLibProgressBar",
"SettingsLibAdaptiveIcon",
"SettingsLibRadioButtonPreference",
"SettingsLibSelectorWithWidgetPreference",
"SettingsLibDisplayDensityUtils",
"SettingsLibUtils",
"SettingsLibEmergencyNumber",
"SettingsLibTopIntroPreference",
"SettingsLibBannerMessagePreference",
"SettingsLibFooterPreference",
"SettingsLibUsageProgressBarPreference",
"SettingsLibCollapsingToolbarBaseActivity",
"SettingsLibTwoTargetPreference",
"SettingsLibSettingsTransition",
"SettingsLibButtonPreference",
"setupdesign",
"zxing-core-1.7",
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
// LOCAL_SHARED_JAVA_LIBRARIES := androidx.lifecycle_lifecycle-common
resource_dirs: ["res"],
srcs: [
"src/**/*.java",
"src/**/*.kt",
],
min_sdk_version: "29",
}
// NOTE: Keep this module in sync with ./common.mk
java_defaults {
name: "SettingsLibDefaults", //"Settings-core"模块默认引用的一组名为SettingsLibDefaults的配置
static_libs: [
"androidx.annotation_annotation",
"androidx.lifecycle_lifecycle-common",
"androidx.legacy_legacy-support-v4",
"androidx.lifecycle_lifecycle-runtime",
"androidx.recyclerview_recyclerview",
"androidx.preference_preference",
"androidx.appcompat_appcompat",
"androidx.legacy_legacy-preference-v14",
"SettingsLib", //“Settings-core”通过"SettingsLibDefaults"间接引用了"SettingsLib"
],
}
分析结果
1.因为"Settings-core"模块默认引用的一组名为"SettingsLibDefaults"的配置,所以我们需要先解决"SettingsLibDefaults"
2.通过对"SettingsLibDefaults"分析,我们得知,需要引入"SettingsLib"的模块,此模块负责编译srcs:["src//*.java","src//*.kt"]
3.“SettingsLib”依赖于WifiTrackerLib、WifiTrackerLibRes模块
4.“SettingsLib”模块还依赖于一连串的子模块,例如:"SettingsLibHelpUtils"..."SettingsLibButtonPreference"
5.“SettingsLib”模块还依赖于一些其他模块,"setupdesign"、"zxing-core-1.7"、"iconloader"
6."SettingsLib"模块依赖于一些Androidx为安卓支持库,可以直接通过maven仓获取。
四.静态库与动态库的依赖方式
1.静态链接库:static_libs
静态库特点:
每一个被static_libs命名的模块,他的数据都会被合并到目标apk中
同时,这些static_libs还将承担编译时被引用符号的解析工作
例如:
static_libs: ["android.hardware.dumpstate-V1.1-java"],
转换成build.gradle:
implementation files('../libs/android.hardware.dumpstate-V1.1-java.jar')
2.动态库链接:shared_libs、libs
与静态链接库的区别,动态库为所有程序都可使用,在运行时由对应的进程映射、加载到自己的内存空间
所以动态链接库的内容,只是在编译时参与链接,它的数据则不会被合并到目标APK中
例如:
libs: ["ims-common"],
转换成build.gradle
compileOnly files('../libs/ims-common.jar')
五.移植整体流程概述及思路
1.需要完成的前置工作
首先环境,最好用我上面的AndroidStudio版本及gradle配置
将代码整编得到out产物
2.移植的基本思路和步骤
分析android.bp和AndroidManifest.xml文件,了解Settings、SettingsLib等依赖情况、包名、版本号等重要信息
根据AndroidManifest.xml文件获得包名,创建同名的AS项目或者模块
根据android.bp分析对应的build.gradle内容
根据android.bp的依赖配置,到out目录下复制对应的名称classes.jar,重命名后复制到libs目录下
根据android.bp的依赖配置,补全其他可从网络获取的依赖,如:androidx依赖、zxing依赖
解决其他模块的编译错误、依赖问题、并编译通过
解决SettingsLib模块的编译错误、依赖问题,并编译通过
解决Settings模块的编译错误、依赖问题,并编译通过
解决Settings.app模块的编译错误,特别是依赖问题,有依赖缺失、依赖冲突是主要问题
对Settings.app模块进行签名、运行到设备上,解决运行时错误,验证各个主要菜单功能正常,不发生闪退、崩溃
搞定!!!
六.创建一个与Settings同包名的AS项目
1.AS创建新项目
2.选择[No Activity]
3.填写包名,完成创建
Name:Settings
Package name:com.android.settings
最后,点击【Finish】
4.删除新建的Settings AS项目中的src与res目录
删除后的目录结构如下
.
├── app
│ ├── build.gradle
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest(删除)
│ │ └── java(删除)
│ ├── main(保留目录)
│ │ ├── AndroidManifest.xml(用source_org/Settings 目录下的同名文件覆盖)
│ │ ├── java(保留目录)
│ │ └── res(保留res目录,删除其目录下的所有文件)
│ └── test(删除)
│ └── java(删除)
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
12directories, 11files
5.将原版的Settings中src、res、libs、AndroidManifest.xml文件复制到AS相应目录下(这一步可以放到最后和添加Settings.gradle的依赖一起做)
如下图内容复制到AndroidStudio的Settings对应目录下面
复制后对应的Settings项目中如下:
注意values可以按照需要保存相应的文件夹,我这边是只保留默认的values和中文的values的
其实这些步骤也可以放到最后将所有模块导入差不多了在做Settings模块,不然会有很多报错,这里我暂时不说Settings的gradle配置的了,这些都放到最后来说
七.移植SettingsLib模块
1.创建New Module
2.选择Android Library类型,填写包名com.android.settingslib,模块名:SettingsLib
然后点击Finish
3.将原版的文件和配置移植到SettingsLib中
和Settings一样,将res,src,xml移植到SettingsLib中
找到原版的SettingsLib的位置
位置:\QCM6125_Android13.0_R04_r020\QSSI.13\frameworks\base\packages\SettingsLib
然后将目录的内容移植到SettingsLib中
然后分析Android.bp文件,将依赖配置添加到SettingsLib的gradle中,最终效果如下图: