Android 系统预置 APP 是做 Framework 应用开发经常经常会遇到的工作,预置 APP 分为两种,一种是直接预置 APK,一种是预置带有源码的 APP。

预置 apk

示例说明

以 Shadowsocks.apk 示例,在 AOSP/packages/apps 新建名为 Shadowsocks 的文件,放入 Shadowsocks.apk,再新建 Android.mk,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE := < your app folder name >

# 签名
LOCAL_CERTIFICATE := < desired key > # 指定 src 目录
LOCAL_SRC_FILES := < app apk filename > LOCAL_MODULE_CLASS := APPS # 该模块的后缀,不用定义
#LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) include $(BUILD_PREBUILT)

解释:

  • LOCAL_PATH := $(call my-dir)

每个 Android.mk 文件必须以定义 LOCAL_PATH 为开始,它用于在开发 tree 中查找源文件。

  • include $(CLEAR_VARS)

CLEAR_VARS 变量由 Build System 提供,并指向一个指定的 GNU Makefile,由它负责清理很多 LOCAL_xxx。

例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES 等等,但不清理 LOCAL_PATH。

  • LOCAL_MODULE_TAGS := user eng tests optional

可选定义,表示在什么版本情况下编译该版本,默认 optional

user: 指该模块只在 user 版本下才编译
eng: 指该模块只在 eng 版本下才编译
tests: 指该模块只在 tests 版本下才编译
optional:指该模块在所有版本下都编译
  • LOCAL_MODULE

模块名,可不用定义,默认 = $(LOCAL_PACKAGE_NAME),不能和既有模块相同,如果该变量未设置,则使用 LOCAL_PACKAGE_NAME,如果再没有,就会编译失败。

  • LOCAL_CERTIFICATE

在什么情况下签名。

testkey:普通 APK,默认情况下使用。

platform:该 APK 完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,

这种方式编译出来的 APK 所在进程的 UID 为 system,可以参见 Settings。

shared:该 APK 需要和 home/contacts 进程共享数据,可以参见 Launcher。

media:该 APK 是 media/download 系统中的一环,可以参见 Gallery。

  • LOCAL_MODULE_CLASS

指定模块的类型,可不用定义。

# 编译 apk 文件
LOCAL_MODULE_CLASS := APPS # 编译 jar 包
LOCAL_MODULE_CLASS := JAVA_LIBRAYIES # 定义动态库文件
LOCAL_MODULE_CLASS := SHARED_LIBRAYIES # 编译可执行文件
LOCAL_MODULE_CLASS := EXECUTABLES
  • include $(BUILD_PACKAGE)

表示生成一个 apk,它可以是多种类型

BUILD_PACKAGE(既可以编apk,也可以编资源包文件,但是需要指定LOCAL_EXPORT_PACKAGE_RESOURCES:=true)

BUILD_JAVA_LIBRARY(java共享库)

BUILD_STATIC_JAVA_LIBRARY(java静态库)

BUILD_EXECUTABLE(执行文件)

BUILD_SHARED_LIBRARY(native共享库)

BUILD_STATIC_LIBRARY(native静态库)

完整示例

Shadowsocks.apk 对应如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE := Shadowsocks

# 系统签名
LOCAL_CERTIFICATE := PRESIGNED LOCAL_SRC_FILES := $(LOCAL_MODULE).apk LOCAL_MODULE_CLASS := APPS #LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) include $(BUILD_PREBUILT)

更改 device.mk 文件

AOSP/build/target/board/lunch的版本/device.mk 文件,我编的是 aosp_x86-eng,所以增加或者更新 AOSP/build/target/board/generic_x86/device.mk:

PRODUCT_PACKAGES += \
Shadowsocks \

使用 mmm 命令来编译指定的模块:

mmm packages/apps/Shadowsocks

编译好模块后,还要重新打包一下 system.img 文件:

make snod

完成后就可以烧录了。

问题

1、如何将 APK 预置到 system/priv-app 里?

加入 priv-app 方法:在 Android.mk 中增加 LOCAL_PRIVILEGED_MODULE := true

预置有源码 APP

预置有源码 APP 比预置 APK 要麻烦很多,可能会涉及 jar 包和 so 库等。现在基本都是基于 Android Studio 的项目 MyTestProject1,我们先在 AOSP/packages/apps 新建名为 MyTestProject2 的文件夹,在新建 MyTestProject2/libs、MyTestProject2/res、MyTestProject2/src,分别将 MyTestProject1 下 jar 包和 so 库拷到 MyTestProject2/libs 和 MyTestProject2/libs/armeabi,将 MyTestProject1/app/src/main/res 拷到 MyTestProject2/res,将 MyTestProject1/app/src/main/java 下文件拷到 MyTestProject2/src 下。

引用第三方 jar 包

假设,我们当前目录下的 libs 有 AndroidUtil.jar包,我们想引用它,需要做两个步骤:

第一步、 声明我们 jar 包所在的目录

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := AndroidUtil:libs/AndroidUtil.jar

这行代码的意思大概可以理解成这样,声明一个变量 AndroidUtil,它的 value 是 libs/AndroidUtil.jar

include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := AndroidUtil:libs/AndroidUtil.jar
include $(BUILD_MULTI_PREBUILT)

第二步、 引用我们声明 jar 包的变量

include $(CLEAR_VARS)
# 省略其他
LOCAL_STATIC_JAVA_LIBRARIES := \
AndroidUtil
# 省略其他
include $(BUILD_PACKAGE)

引用 so 库

假设,我们当前目录下的 libs/armeabi 有 libBaiduMapSDK1.so、libBaiduMapSDK1.so,libs/arm64-v8a 有 libBaiduMapSDK1.so、libBaiduMapSDK1.so,我们想引用它,有两种方法,可以在根目录 Android.mk 引用 so 库,也可以在 libs 下再建个 Android.mk 配置好 so 库,然后 include,推荐第二种方式。

libs/Android.mk

#====================================================
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libBaiduMapSDK1
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_SRC_FILES_arm :=libs/armeabi/$(LOCAL_MODULE).so
LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/$(LOCAL_MODULE).so
LOCAL_MODULE_TARGET_ARCHS:= arm arm64
LOCAL_MULTILIB := both
include $(BUILD_PREBUILT)
#==================================================== #====================================================
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libBaiduMapSDK2
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_SRC_FILES_arm :=libs/armeabi/$(LOCAL_MODULE).so
LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/$(LOCAL_MODULE).so
LOCAL_MODULE_TARGET_ARCHS:= arm arm64
LOCAL_MULTILIB := both
include $(BUILD_PREBUILT)

引用 so 库

include $(CLEAR_VARS)
# 省略其他
LOCAL_JNI_SHARED_LIBRARIES := \
libBaiduMapSDK1 \
libBaiduMapSDK2
# 省略其他
include $(BUILD_PACKAGE) ##########引用第三方 so 库##########
include $(LOCAL_PATH)/libs/Android.mk

完整示例

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_PACKAGE_NAME := TestName

LOCAL_CERTIFICATE := platform

# 引入系统资源文件
LOCAL_USE_AAPT2 := true # Java文件
LOCAL_SRC_FILES := $(call all-java-files-under, src) # 资源文件,可选定义,推荐不定义
#LOCAL_RESOURCE_DIR = \
# $(LOCAL_PATH)/res \
# frameworks/support/v7/appcompat/res \
# frameworks/support/design/res # 可以使用系统 hide api
LOCAL_PRIVATE_PLATFORM_APIS := true # 导入系统依赖
LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-design \
android-support-v4 \
android-support-v7-appcompat \
android-support-v7-recyclerview LOCAL_STATIC_JAVA_LIBRARIES := \
AndroidUtil LOCAL_JNI_SHARED_LIBRARIES := \
libBaiduMapSDK1 \
libBaiduMapSDK2 # R资源生成别名,--extra-packages 是为资源文件设置别名:意思是通过该应用包名+R,com.android.test1.R 和 com.android.test2.R 都可以访问到资源
LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_AAPT_FLAGS += --extra-packages android.support.v4
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat
LOCAL_AAPT_FLAGS += --extra-packages android.support.design
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.recyclerview # 制定编译的工程,不要使用代码混淆的工具进行代码混淆
LOCAL_PROGUARD_ENABLED := disabled
# 指定不需要混淆的native方法与变量的proguard.flags文件
LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE) ##########引用第三方 jar 包##########
include $(CLEAR_VARS) LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := AndroidUtil:libs/AndroidUtil.jar include $(BUILD_MULTI_PREBUILT) ##########引用第三方 so 库##########
include $(LOCAL_PATH)/libs/Android.mk

问题

1、LOCAL_PRIVATE_PLATFORM_APIS 和 LOCAL_SDK_VERSION 有什么区别?

LOCAL_PRIVATE_PLATFORM_APIS := true

设置后,会使用 sdk 的 hide 的 api 来编译。

LOCAL_SDK_VERSION 这个编译配置,就会使编译的应用不能访问 hide 的 api,有时一些系统的 class 被 import 后编译时说找不到这个类,就是这个原因造成的。

2、如果直接用 mmm 编译然后 adb install -r xxx.apk 大概会出现如下错误:

Failed to install out/target/product/p212/system/app/xxx/xxx.apk: Failure [INSTALL_FAILED_INVALID_APK: Package couldn't be installed in /data/app/com.droidlogic.mboxlauncher-1: Package /data/app/com.droidlogic.mboxlauncher-1/base.apk code is missing]

解决方法:

在对应 app 的 Android.mk 文件中加入

LOCAL_DEX_PREOPT := false

关闭 dex 优化来提高调试过程,把编译后的 APK 直接替换安装 adb install -r XXX.apk,不然 APK 得 Push 到 system/app,重启设备。

3、在 Android Studio Gradle 方式中通过 implementation 方式加载的三方库,并没有下载 jar 文件放到 libs 文件夹下啊,该如何集成?

其实 jar 包有被下载到项目的 External Libraries 目录下,找到引用的 jar 包,点右键 Show in Files,就能得到了 jar 包的文件地址,然后把它拷到 libs 文件夹下,就能像别的 jar 包一样处理了。

另外在 External Libraries 目录还能看到隐藏的 jar,比如 retrofit,其实它有引用 okhttp,okhttp 又引用了 okio,这些也是需要的,一并拷到 libs 文件夹下。

4、第三方无法定位?

第三方定位如百度、高德,申请 SDK 时会需要填写包名和打包签名等信息,如何正确地预置源码 APP 可以定位,除了配置LOCAL_CERTIFICATE := platform使用系统的签名,还得在项目的AndroidMainfest.xml 根节点配置android:sharedUserId="android.uid.system"

公众号

我的公众号:吴小龙同学,欢迎关注交流~

AOSP 预置 APP的更多相关文章

  1. android系统添加预置APP(so库自动释放)

    将APK直接放入系统目录中,会导致APK找不到so文件.正常情况下的安装是使用PackageManager,它会将so文件拷贝到系统读取的so目录(system/lib或system/lib64)下, ...

  2. 预置app/apk到系统 && 预置so库进系统 && 预置普通文件和文件夹进系统

    https://blog.csdn.net/zhandoushi1982/article/details/4695460

  3. (转)应用内存优化之OnLowMemory&OnTrimMemory

    1.应用内存onLowMemory& onTrimMemory优化 onLowMemory& onTrimMemory简介:OnLowMemory是Android提供的API,在系统内 ...

  4. Android应用开发编译框架流程与IDE及Gradle概要

    1 背景 建议阅读本文之前先阅读<Android Studio入门到精通>和<Groovy脚本基础全攻略>及<Gradle脚本基础全攻略>三篇博客作为背景知识,这样 ...

  5. 几款开源的hybird移动app框架分析

    几款开源的Hybrid移动app框架分析 Ionic Onsen UI 与 ionic 相比 jQuery Mobile Mobile Angular UI 结论 很多移动开发者喜欢使用原生代码开发, ...

  6. Play Framework 完整实现一个APP(八)

    创建Tag标签 1.创建Model @Entity @Table(name = "blog_tag") public class Tag extends Model impleme ...

  7. App Extension

    一.扩展概述 扩展(Extension)是iOS 8中引入的一个非常重要的新特性.扩展让app之间的数据交互成为可能.用户可以在app中使用其他应用提供的功能,而无需离开当前的应用. 在iOS 8系统 ...

  8. Android系统自带APP分析——短信app

    Android操作系统本身就是一个巨大的开源软件仓库,熟悉它既可以了解到Android系统的设计框架,也可以获得高效的应用程序编写方式.本文所分析的源码来自于Google官方的AOSP源码4.0.1_ ...

  9. 不通过App Store实现ios应用分发下载安装

    最近公司的项目准备着手宣传工作了,宣传手册上要印制App的下载地址二维码,但是客户端应用还未上线,需要一种临时的方案解决应用分发下载问题,通常ios应用必须通过苹果应用商店才能下载安装,但是也可以看到 ...

随机推荐

  1. C语言学习书籍推荐《学通C语言的24堂课》下载

    下载地址:点我 编辑推荐 <学通C语言的24堂课>:用持续激励培养良好习惯以良好习惯铸就伟大梦想——致亲爱的读者朋友在开始学习<学通C语言的24堂课>的同时,强烈建议读者朋友同 ...

  2. maven打包报错问题解析

    1. 场景描述 Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:3.1.0:clean (default-clea ...

  3. 使用kubectl管理k8s集群(二十九)

    前言 在搭建k8s集群之前,我们需要先了解下kubectl的使用,以便在集群部署出现问题时进行检查和处理.命令和语法记不住没有关系,但是请记住主要的语法和命令以及帮助命令的使用. 在下一篇,我们将讲述 ...

  4. MyBatis从入门到精通:各个实体类

    SysUser类: package tk.mybatis.simple.model; import java.util.Date; public class SysUser { public Long ...

  5. [原创]Rsync搭建和使用

    rsync服务的搭建和使用 ***下载安装: #wget https://download.samba.org/pub/rsync/src/rsync-3.1.2.tar.gz #tar -zxvf ...

  6. Excel催化剂开源第47波-Excel与PowerBIDeskTop互通互联之第一篇

    当国外都在追求软件开源,并且在GitHub等平台上产生了大量优质的开源代码时,但在国内却在刮着一股收割小白智商税的知识付费热潮,实在可悲. 互联网的精神乃是分享,让分享带来更多人的受益. 在Power ...

  7. 个人永久性免费-Excel催化剂功能第34波-提取中国身份证信息、农历日期转换相关功能

    这两天又被刷朋友圈,又来了一个自主研发红芯浏览器,国产啊国产,这是谁的梦.就算国产了,自主了,无底线的夸大吹嘘无道德,企业如是,国家如是,大清已亡!再牛B的技术落在天天删敏感信息.无法治.无安全感可言 ...

  8. Redis(四)--- Redis的命令参考

    1.简述 数据类型也称数据对象,包含字符串对象(string).列表对象(list).哈希对象(hash).集合对象(set).有序集合对象(zset). 2.String数据类型命令 string  ...

  9. helm安装MINIO文件服务器

    MinIO Quickstart Guide MinIO 是一个基于Apache License v2.0开源协议的对象存储服务.它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例 ...

  10. 基于kubernetes自研容器管理平台的技术实践

    一.容器云的背景 伴随着微服务的架构的普及,结合开源的Dubbo和Spring Cloud等微服务框架,宜信内部很多业务线逐渐了从原来的单体架构逐渐转移到微服务架构.应用从有状态到无状态,具体来说将业 ...