运用 Android Studio 开发体系 App
本文根据 AOSP Android10_r41 源码环境。
假如提早阅读了以下文章,本文阅读起来会愈加顺畅:
- Ubuntu 运用快速入门
- AOSP 极速上手
- 体系开发东西
- Make 构建东西入门
- 增加 Product
- AOSP 中增加 C/C++、Java 可履行程序
- AOSP 中增加 C/C++、Java 库
- AOSP 增加装备文件与删去已有模块
- AOSP 增加体系 App 源码
1. 编译 Android framework
体系运用能够调用隐藏的API,这需求咱们引入包含被隐藏 API 的 jar 包。
为了得到这个 jar 包,咱们需求在源码下编译 Framework 模块:
source
lunch Rice14-eng
# Android10 及曾经
make framework
# Android11 及以后
#make framework-minus-apex
编译完成后,咱们在 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates
目录下找到 classes.jar
文件,为方便识别,咱们将该文件拷贝到其他地方,并将文件名修正为 framework.jar
。
2. 创立体系 App 项目
运用 Android Studio 创立一个 Empty Activity 空项目。接着把之前准备好的 framework.jar 拷贝到项目的 app/libs
文件夹中。
接着修正项目根目录下的 build.gradle,增加如下内容:
allprojects{
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
Set<File> fileSet
if (options.bootstrapClasspath != null ) {
fileSet = options.bootstrapClasspath.getFiles()
}else {
fileSet = new HashSet<>()
}
List<File> newFileList = new ArrayList<>();
newFileList.add(new File("./app/libs/framework.jar"))
newFileList.addAll(fileSet)
options.bootstrapClasspath = files(
newFileList.toArray()
)
}
}
}
接着修正 app/build.gradle:
dependencies {
compileOnly files('libs/framework.jar')
//.......
}
然后在项目的 AndroidManifest.xml 中增加:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="android.uid.system"
android:sharedUserMaxSdkVersion="32">
接着咱们需求制作体系签名,这儿运用 keytool-importkeypair 签名东西。
将 keytool-importkeypair clone 到本地,并将其间的 keytool-importkeypair 文件增加到 PATH 途径。
接着进入体系源码下的 build/target/product/security
途径,接着履行:
keytool-importkeypair -k ./platform.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform
k 表明要生成的 keystore 文件的姓名,这儿命名为 platform.keystore -p 表明要生成的 keystore 的密码,这儿是 android -pk8 表明要导入的 platform.pk8 文件 -cert 表明要导入的platform.x509.pem -alias 表明给生成的 platform.keystore 取一个别号,这是命名为 platform
接着,把生成的签名文件 platform.keystore 拷贝到 Android Studio 项目的 app 目录下,然后在 app/build.gradle 中增加签名的装备信息:
android {
signingConfigs {
sign {
storeFile file('platform.keystore')
storePassword 'android'
keyAlias = 'platform'
keyPassword 'android'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign
}
debug {
minifyEnabled false
signingConfig signingConfigs.sign
}
}
}
至此,咱们在 AS 中就建立好了咱们的体系 App
3. 体系 APP 的编译运转
在开发过程中,大部分情况下,咱们能够直接点击 Android Stuido 中的运转按钮来运转咱们的装备好的 App。当咱们的 App 开发完成,咱们需求将其预制到体系中:
咱们在体系源码下的 device/Jelly/Rice14
目录下,创立如下的文件与文件夹:
AsSystemApp
├── Android.mk
└── app.apk
其间 app.apk 是咱们用 Android Studio 打包好的 apk 安装包。Android.mk 的内容如下(Android10 下,Android.bp 貌似还不支持引入 apk,实测 Android13 是没问题的,这儿就运用 Android.mk 了):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := AsSystemApp
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := app.apk
LOCAL_MODULE_CLASS := APPS
LOCAL_PRODUCT_MODULE := true
include $(BUILD_PREBUILT)
接着修正 device/Jelly/Rice14/Rice14.mk
PRODUCT_PACKAGES += \
AsSystemApp
然后编译体系,启动虚拟机,就能够看到咱们的 App 了。
source build/envsetup.sh
lunch Rice14-eng
make -j16
emulator
4. 体系 App 特色
4.1 体系 app 能够履行三方 App 不能履行的 Api
一些 API 只能又体系 App 调用,比如:
SystemClock.setCurrentTimeMillis(0)
假如在普通 App 中运用,就会报以下的过错:
E/SystemClock: Unable to set RTC
java.lang.SecurityException: setTime: Neither user 10099 nor current process has android.permission.SET_TIME.
网络上很多文章教你在 App 如何调用 Hide 的 Api,在体系 App 中能够直接运用这些 Hide Api:
//SystemClock 整个类被标记为 hide
import android.os.SystemClock
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
SystemClock.setCurrentTimeMillis(0)
intent = Intent(this, TestService::class.java)
startService(intent)
//在体系 App 中能够正常运用
Log.d("MainActivity", "" + AudioSystem.STREAM_ACCESSIBILITY)
}
}
4.2 进程保活
为了保活,开发者不知道加了多少班,掉了多少头发。在体系 App 这儿,能够说保活不要太简略了:
在 AndroidManifest.xml 中增加:
<application
android:persistent="true"
增加一个 Service:
class TestService : Service() {
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
Thread() {
while (true) {
Log.d("TestService", "this is TestService")
Thread.sleep(2000)
}
}.start()
}
}
在 MainActivity 中启动 Service:
intent = Intent(this, TestService::class.java)
startService(intent)
最终不要忘了在 AndroidManifest.xml 中增加 Service 的声明:
<service
android:name=".TestService"
android:enabled="true"
android:exported="true">
</service>
最终直接点击运转按钮启动咱们的 App,能够看到 Service 一直再打 Log。
咱们运用 ps -ef | grep "AsSystemApp"
查找到咱们 App 关于的 pid,然后运用 kill 命令将其强杀掉,通过时间短的等候后,Log 窗口又开端打 Log 了,说明咱们的 App 在强杀后,被体系重新拉起运转。
4.3 体系 App 权限
比较三方 App,体系 App 能够运用更多的权限。由于这部分内容触及较多体系权限相关的基础知识。咱们就在体系权限部分再来解说体系 App 权限相关的内容吧。
关于
假如你对 Android Framework 感兴趣,能够继续重视:
- 渠道个人技术博客
- 我的个人公众号
- 我的个人微信(能够加我微信进 Android Framework 交流群)