写在前面

在编译系统时,难免会需要添加一些自己的应用。方便集成也好,或者为了提升应用权限也好。总之都需要在构建时添加进去,这样可以做到开机即用,足够简单。同时也可以在编译时就直接odex化,提升应用的性能。

如何实现?

首先你需要确定你是要为所有的设备都添加,还是为某一个特定的设备来添加。

为所有的设备都添加

如果你打算为所有的设备都添加,那就在系统的源码里做修改。

路径在packages/apps/下面

首先在这里新建一个文件夹,比如我要集成一个应用商店。

那就是

mkdir Appmarket

然后把你下载的应用商店apk复制到这个文件夹里,并且重命名为Appmarket.apk

接下来我们要告诉编译系统要如何构建这个应用:

1、使用Android.mk的方式

在Appmarket目录里新建一个Android.mk文件

里面粘贴如下内容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := Appmarket    #你模块的名字
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := appmarket.apk #要用的apk文件
LOCAL_CERTIFICATE := PRESIGNED   
LOCAL_MODULE_CLASS := APPS
LOCAL_PRIVILEGED_MODULE := true   #这里可以指定apk在系统中的位置,这个选项表示在/system/priv-app下面
LOCAL_OPTIONAL_USES_LIBRARIES := org.apache.http.legacy hwkeystore
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)

上面的各个选线你都可以使用搜索引擎找到,有具体的详解,这里就不多说了。

声明有了,接下来我们还要告诉编译系统要使用。

我这里是在vendor/kscope/target/product/package.mk
lineage则在vendor/lineage/config/common.mk

里面找到这种类似的格式:

PRODUCT_PACKAGES += \
    Chromium \
    ExactCalculator \
    Gboard \
    KscopeSetupWizard \
    KscopeThemesStub \
    Raindrop \
    SimpleDeviceConfig \
    ThemePicker

然后把你的模块儿加进去:

PRODUCT_PACKAGES += \
    Chromium \
    ExactCalculator \
    Gboard \
    KscopeSetupWizard \
    KscopeThemesStub \
    Raindrop \
    SimpleDeviceConfig \
    ThemePicker \
    Appmarket

然后保存即可

2、使用Android.bp的方式

语法一般是这样的:

soong_namespace {
}

android_app_import {
	name: "Appmarket",
	owner: "nubia",
	apk: "Appmarket.apk",
	presigned: true,
	dex_preopt: {
		enabled: false,
	},
	product_specific: true,
}

同样的,你还是需要再去package.mk添加一下。

单一的设备添加

直接在设备树的根目录创建上面的文件夹和文件,格式都是一样的。

然后在设备树中的device.mk中添加你要构建的模块名:

#Huaweiappstore
PRODUCT_PACKAGES += \
    Appmarket

权限的配置

经过了上面的配置,apk已经可以正常的被安装到系统了,但是因为是系统应用,我们还需要配置权限声明,不然会无法开机。

解决方法也很简单,先用make命令构建一遍。

然后使用:

development/tools/privapp_permissions/privapp_permissions.py

默认情况下,privapp_permissions.py脚本会生成输出,自动授予特权应用所请求的任何权限。

然后列出一个清单出来。

大概类似这样:

<!--
    This XML file declares which signature|privileged permissions should be
    granted to privileged apps that come with the platform
    -->
    <permissions>
<privapp-permissions package="com.android.backupconfirm">
    <permission name="android.permission.BACKUP"/>
    <permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
<privapp-permissions package="com.android.cellbroadcastreceiver">
    <!-- don't allow application to interact across users -->
    <deny-permission name="android.permission.INTERACT_ACROSS_USERS"/>
    <permission name="android.permission.MANAGE_USERS"/>
    <permission name="android.permission.MODIFY_PHONE_STATE"/>
    <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
    <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
</privapp-permissions>
    ...

然后我们创建一个Appmarket.xml

放入上面脚本输出的内容。

现在,我们需要让编译系统把这个声明文件拷贝到指定的位置。

在设备树中或者上面的package.mk里加上这个:

PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/configs/permissions/appmarket.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/appmarket.xml

$(LOCAL_PATH)/configs/permissions/appmarket.xml是你的xml文件在电脑上的路径

(TARGET_COPY_OUT_SYSTEM)表示的则是输出到手机的system分区

etc/permissions/appmarket.xml则是权限文件的存放目录。

** 注意!应用在哪个分区,那对应的权限就应该在哪个分区的etc/permissions/
**

最后再 m bacon重新打包一下就好了。

Q.E.D.