将SystemUI导入AS编译运行

将SystemUI导入AS编译运行

前期准备

以Android9.0源码(我这里用的是MT2712,win10环境,AS 4.1.3)为例

首先需要将源码进行一次编译,因为导出的SystemUI之后会引入一些编译后生成的库。

SystemUI代码路径为mt2712/frameworks/base/packages/SystemUI

SystemUI代码拉到本地,删除代码中test和example相关目录
即删除shared/tests/、plugin/ExamplePlugin/和tests/三个目录。

同样的,将mt2712/frameworks/base/packages/SettingsLibpackage/service/Car/car_libframework/support/car下拉到本地,删除其中的test目录。

SystemUI项目搭建

创建SystemUI项目

使用AS创建一个包名为com.android.systemui的No Activity项目


1.png

SystemUI目录中的AndroidManifest.xmlAndroid.mk文件、resres-keyguardsrc目录下的所有文件移到刚创建的app目录的的src/main/java目录下,移动完目录结构如下:

  • app
    • src
      • main
        • java
          • com.android.keyguard
          • com.android.systemui
        • res
        • res-keyguard
        • Android.mk
        • AndroidManifest.xml

在build.gradle文件内添加

    sourceSets {
        main {
            res.srcDirs += "src/main/res-keyguard"
        }
    }

引用res-keyguard目录下的资源

创建Module

根据SystemUI源代码目录下的AndroidManifest.xml文件数量可以看出部分需要创建的Module(library形式的),我这里需要创建两个:

2.png
  1. shared:com.android.systemui.shared
  2. plugins:com.android.systemui.plugins

此外还有两个需要创建

  1. settingsLib:com.android.settingslib
  2. car_support:androidx.car
3.png
  1. 删除Modulesrc目录下的自动生成的目录(如test
  2. SystemUI/shardSystemUI/pluginSettingsLibcar目录中的AndroidManifest.xmlAndroid.mk文件(没有则不用)和src目录下的所有文件移到对应Module的src/main/java目录下。

移动完毕后得到的目录结构如下(只列出了转移的文件):

  • plugin
    • src
      • main
        • java
          • com.android.systemui.plugins
        • Android.mk
        • AndroidManifest.xml
  • shared
    • src
      • main
        • java
          • com.android.systemui.shared
        • Android.mk
        • AndroidManifest.xml
  • SettingsLib
    • src
      • main
        • java
          • com.android.systemui.shared
        • res
        • Android.mk
        • AndroidManifest.xml
  • car_support
    • src
      • main
        • java
          • androidx.car
        • res
        • AndroidManifest.xml

SystemUI库的引入

Android.mk中的库

下面是plugin和shared的Android.mk文件:

########### plugin Android.mk ###########
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
....
LOCAL_MODULE := SystemUIPluginLib
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_JAR_EXCLUDE_FILES := none

include $(BUILD_STATIC_JAVA_LIBRARY)
....
########### shared Android.mk ###########
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
....
LOCAL_MODULE := SystemUISharedLib

LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_JAR_EXCLUDE_FILES := none

include $(BUILD_STATIC_JAVA_LIBRARY)
....

可以看出pluginshared分别产生SystemUIPluginLibSystemUISharedLib库。这两个库会被SystemUI所使用到。因为我们已经将这两部分以Module形式提出,所以直接在SystemUI****的build.gradle中引入即可。

    implementation project(':plugin')
    implementation project(':shared')

根据Android.mk文件中LOCAL_STATIC_ANDROID_LIBRARIESLOCAL_STATIC_JAVA_LIBRARIESLOCAL_JAVA_LIBRARIES属性,可以了解到SystemUI引用到了哪些库,然后需要将这些库都找到放入app/libs目录下,然后在build.gradle文件中引入。

其中v4、v7、v14、v17的库可以先不引入,之后会将SystemUI中使用到这些库转成AndroidX的库,不引入可以减少一些麻烦。

SystemUI根目录Android.mk文件资源相关内容和对应的jar包如下:

# LOCAL_STATIC_ANDROID_LIBRARIES 里面引用到的库,大部分都可以在
# platform\out\soong\.intermediates\prebuilts\sdk\current目录下找到
# 比如android-support-car,对应的就是platform\out\soong\.intermediates\prebuilts\sdk\current\support\android-support-car\android_common\turbine-combined\android-support-car.jar
LOCAL_STATIC_ANDROID_LIBRARIES := \
    SystemUIPluginLib \  # 对应plugin Module
    SystemUISharedLib \  # 对应shared Module
    android-support-car \  # android-support-car.jar
    android-support-v4 \  # android-support-v4.jar
    android-support-v7-recyclerview \  #  android-support-v7-recyclerview.jar
    android-support-v7-preference \  # 之后以此类推
    android-support-v7-appcompat \
    android-support-v7-mediarouter \
    android-support-v7-palette \
    android-support-v14-preference \
    android-support-v17-leanback \
    android-slices-core \
    android-slices-view \
    android-slices-builders \
    android-arch-core-runtime \
    android-arch-lifecycle-extensions \

# LOCAL_JAVA_LIBRARIES  里面的jar,是只在编译的时候引用即可,不需要打包进apk
# 这些jar是系统本身的jar,所以我们build.gradle以compileOnly方式引用
LOCAL_JAVA_LIBRARIES := telephony-common \
    android.car

这些库中有一些是必须引入的,下方列出了库和其在源码中对应的jar包路径

导入framework.jar

framework.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar

将其放入app/libs文件目录下,然后在根目录build.gradleallproject下添加

tasks.withType(JavaCompile) {
    options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\framework.jar')
}

appsharedpluginSettingsLib,car_support目录下的build.gradle下添加

preBuild {
    doLast {
        def imlFile = file(project.name + ".iml")
        println('Change ' + project.name + '.iml order')
        try {
            def parsedXml = (new XmlParser()).parse(imlFile)
            def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
            parsedXml.component[1].remove(jdkNode)
            def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
            new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
            groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
        } catch (FileNotFoundException e) {
            // nop, iml not found
        }
    }
}

这样就能优先使用我们导入的framework.jar

导入telephony-common.jar

telphont-common.jar
文件路径为:out/target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates/classes-header.jar

导入core-libart.jar

core-libart.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\core-libart_intermediates\classes.jar

导入core-oj.jar

core-oj.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\core-oj_intermediates\classes.jar

导入car-lib.jar

car-lib.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\android.car_intermediates\classes.jar

导入android-slices-view.jar

android-slices-view.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\android-slices-view_intermediates\classes.jar

导入android-slices-builders.jar

android-slices-builders.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\android-slices-builders_intermediates\classes.jar

导入android-slices-view.jar

android-slices-view.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\android-slices-view_intermediates\classes.jar

导入systemui-tags.jar

systemui-tags.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\SystemUI-tags_intermediates\classes.jar

导入systemui-proto.jar

systemui-proto.jar
文件路径为:out\target\common\obj\JAVA_LIBRARIES\SystemUI-proto_intermediates\classes.jar

最后贴上我个人引入

常见错误

Found item Attr/longIntent more than one time

删除xml中重复的定义,非常多,需要花些时间。

AAPT: warn: multiple substitutions specified in non-positional format

将%s 改为 %1$s

AAPT: error: resource previously defined here.

文件中定义的属性与系统的属性值重名了,删掉即可。

AAPT: error: resource (color/dimen)/xxxxx (aka com.android.systemui:(color/dimen)/xxxx) not found.

在源码中找到对应的color值,写入res/values/colors.xml或者dimens.xml中中。

Error:Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'
4.png

gradle版本改成其他版本,我这里Android9.0,从4.1.3改为3.6.0就可以编译通过了。

classpath "com.android.tools.build:gradle:4.1.3"
->
classpath "com.android.tools.build:gradle:3.6.0"

程序包android.support.annotation、android.arch.lifecycle不存在等问题

可以尝试将这些包转成androidx,systemui项目和SettingsLibMoudle都有部分需要转换,可以通过AS的Refactor->Migrate to AndroidX转换。

程序包libcore.util不存在

这个可以直接取消引用,对应调用方法返回值设置为null就可以了,如果有用到就要去找对应的库。

AAPT: error: resource android:dimen/notification_extra_margin_ambient not found.

类似以下这种资源在framework/core/res/res/values/dimens.xml文件内的情况:

    # 引用非 public 资源文件 (没在 public.xml 中声明的资源)
    # xml: @*android:<resource_type>/<resource_name>
    # code: com.android.internal.R.<resource_type>.<resource_name>
    <dimen name="group_overflow_number_extra_padding_dark">@*android:dimen/notification_extra_margin_ambient</dimen>

将每个模块的 build.grale 中属性配置为当前 API 级别

compileSdkVersion 28
buildToolsVersion '28.0.1'

AAPT: error: duplicate value for resource 'attr/xxxx' with config ''.

删除attr.xml文件中对应的定义即可

Duplicate class android.xxx.xxxx found in modules

引入的jar包存在重复的类,删除重复的jar包

style attribute 'attr/passwordStyle (aka com.android.systemui:attr/passwordStyle)' not found.

在attrs.xml中添加对应的属性,例:

    // 对应的fromat要对应
    <attr name="passwordStyle" format="reference" />

resource style/PasswordTheme (aka com.android.systemui:style/PasswordTheme) not found.

与上面的问题类似,这个要在styles.xml中添加对应的style,例:

    <style name="PasswordTheme" parent="Theme.SystemUI">
        <item name="android:textColor">?attr/wallpaperTextColor</item>
        <item name="android:colorControlNormal">?attr/wallpaperTextColor</item>
        <item name="android:colorControlActivated">?attr/wallpaperTextColor</item>
    </style>

no default product defined for resource com.android.systemui:string/power_remaining_duration_only_shutdown_imminent.

将values/string.xml中对应值的product改为default

import com.android.systemui.shared.recents.IOverviewProxy;/错误: 程序包IRecentsSystemUserCallbacks不存在

systemUI和module shared包内部有aidl文件,在src/main下创建aidl文件夹,将对应的文件按照源文件夹包名路径转过去即可,我这边转移后目录结构如下:

  • app
    • src
      • main
        • aidl
          • com.android.systemui.recents
            • IRecentsNonSystemUserCallbacks.aidl
            • IRecentsSystemUserCallbacks.aidl
        • java
  • shared
    • src
      • main
        • aidl
          • com.android.systemui.shared
            • recents
              • IOverviewProxy.aidl
              • ISystemUiProxy.aidl
            • system
              • GraphicBufferCompat.aidl
        • java

找不到符号:Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler)/Thread.getUncaughtExceptionPreHandler()

Thread.getUncaughtExceptionPreHandler() -> Thread.getDefaultUncaughtExceptionHandler()
Thread.setUncaughtExceptionPreHandler -> Thread.setDefaultUncaughtExceptionHandler

找不到符号import com.xxxx.xxx

因为我们转成androidx,所以引入的类的包名会有一些变动,重新引入即可。

com.android.tools.r8.errors.b: Absent Code attribute in method that is not native or abstract

将对应的jar包换成combined目录的jar包

多次引用的问题

有些我们从源码拿出来的jar包,内部其实有很多重复的类,比如android和androidx包内的一些类,这种情况可以统一将这些类删除,使用压缩工具打开jar包直接删除内部的包就可以了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容