百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Android 系统如何预置 APP?

bigegpt 2024-08-07 17:49 4 浏览

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,我们想引用它,有两种方法,可以在根目录 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 :=libs/armeabi/$(LOCAL_MODULE).so
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 :=libs/armeabi/$(LOCAL_MODULE).so
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"。

相关推荐

php-fpm的配置和优化

目录概述php-fpm配置php-fpm进程优化配置慢日志查询配置php7进阶到架构师相关阅读概述这是关于php进阶到架构之php7核心技术与实战学习的系列课程:php-fpm的配置和优化学习目标:理...

成功安装 Magento2.4.3最新版教程「技术干货」

外贸独立站设计公司xingbell.com经过多次的反复实验,最新版的magento2.4.3在oneinstack的环境下的详细安装教程如下:一.vps系统:LinuxCentOS7.7.19...

十分钟让你学会LNMP架构负载均衡

业务架构、应用架构、数据架构和技术架构一、几个基本概念1、pv值pv值(pageviews):页面的浏览量概念:一个网站的所有页面,在一天内,被浏览的总次数。(大型网站通常是上千万的级别)2、u...

php从远程URL获取(mp4 mp3)音视频的流媒体数据

/***从远程URL中获取媒体(如mp4mp3)的内容*@parammixed$file_url*@parammixed$media_type...

Zabbix5.0安装部署

全盘展示运行状态,减轻运维人员的重复性工作量,提高系统排错速度,加速运维知识学习积累。1.png1、环境安装关闭SELinux并重启系统2.png安装httpd、mariadb、php运行yum-...

php 常见配置详解

以下是PHP常见的配置项及其含义:error_reporting:设置错误报告级别,可以控制PHP显示哪些错误。例如,设置为E_ALL将显示所有错误,而设置为0将禁止显示任何错误。displa...

实践分享|基于基石智算 DeepSeek API + WordPress 插件自动生成访客回复

基石智算举办的DeepSeek案例大赛汇集了不少基于CoresHubDeepSeekAPI服务或模型部署服务的精彩实践。本次我们将分享个人实践:通过DeepSeekAPI+Word...

如何在Eclipse中搭建Zabbix源码的调试和开发环境

Zabbix是一款非常优秀的企业级软件,被设计用于对数万台服务器、虚拟机和网络设备的数百万个监控项进行实时监控。Zabbix是开放源码和免费的,这就意味着当出现bug时,我们可以很方便地通过调试源码来...

MySQL自我保护参数

#头条创作挑战赛#之前(MySQL自我保护工具--pt-kill)提到用pt-kill工具来kill相关的会话,来达到保护数据库的目的,本文再通过修改数据库参数的方式达到阻断长时间运行的SQL的目...

Python闭包深度解析:掌握数据封装的高级技巧

闭包作为Python高级编程特性之一,为开发者提供了一种优雅的方式来实现数据封装和状态保持。这一概念源于函数式编程理论,在现代Python开发中发挥着重要作用。理解和掌握闭包的使用不仅能够提升代码的表...

Java服务网格故障注入与熔断实战

在分布式系统的高可用性挑战中,服务网格的故障注入与熔断机制是检验系统韧性的终极试金石。以下是10道逐步升级的"地狱关卡",每个关卡都对应真实生产环境中可能遇到的致命场景,并附具体场景示...

MySQL数据库性能优化全攻略:程序员必知的七大核心策略

作为程序员,我们每天都要与数据库打交道。当系统用户量突破百万级时,数据库往往成为性能瓶颈的首要怀疑对象。本文将深入探讨MySQL优化的七大核心策略,并提供可直接落地的优化方案,助您构建高效稳定的数据库...

如何在 Windows 11 上使用单个命令安装 XAMPP

XAMPP是一种广泛使用的软件,用于在Windows操作系统上快速运行LAMP服务器包,包括Windows11。尽管LAMP通常用于Linux系统,但XAMPP并不使用Li...

uTorrent怎样将bt种子转换为磁力

如何用uTorrent把BT种子转为磁力链接?以下方法希望能帮到你。1、在uTorrent窗口里,点击工具栏的按钮,所示。2、在打开窗口里,选取要转为磁力的种子文件,然后点击打开按钮,参照图示操作...

支持向量机SVM 分类和回归的实例

支持向量机(SupportVectorMachine)是Cortes和Vapnik于1995年首先提出的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他...