Android mk 引用 jar 包、so 库、aar 包,系统签名

Stella981
• 阅读 818

写在最前面

刚开始在 Ubuntu 编译系统源码的时候, 需要在 mk 文件里面配置各种东西,对比在 AndroidStudio 敲代码,那可真的是 TMD 麻烦(那时候内心仿佛有千万只马奔腾),不过后面心态渐渐变好了,每个人都是一样,刚开始对于新的并且暂时不理解又看不到优点的东西,内心总是抗拒的,总会第一时间抗拒它,否定他。其实,这往往会影响我们的成长,对于各种新的东西,我们应该是去面对他们,而不是去逃避他们,这才能够真正让我们成长起来。

哈哈, 不扯蛋了,下面开始进入正题。

Android mk 简介

什么是 mk 文件

Android.mk 文件用来告知 NDK Build 系统关于 Source 的信息。 它是GNU Makefile的一部分,且将被 Build System 解析一次或多次。


简单示例

首先我们先来看一下最简单的例子,编译一个普通的 apk。

  1. LOCAL_PATH := $(call my-dir)

  2. include $(CLEAR_VARS)

  3. # 是否开启混淆

  4. LOCAL_PROGUARD_ENABLED := disabled

  5. LOCAL_MODULE_TAGS := optional

  6. # 使用 platform 签名

  7. LOCAL_CERTIFICATE := platform

  8. # 指定 src 目录

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

  10. # 指定 res 目录

  11. LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res

  12. # 指定 apk 编译

  13. LOCAL_PACKAGE_NAME := AppDemo

  14. include $(BUILD_PACKAGE)

解释说明

  • LOCAL_PATH := $(call my-dir)

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

  • include $(CLEAR_VARS)

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

例如:LOCALMODULE, LOCALSRCFILES, LOCALSTATICLIBRARIES等等。但不清理LOCALPATH.

  • LOCALMODULETAGS :

表示在什么版本情况下会编译该版本

  1. LOCAL_MODULE_TAGS :=user eng tests optional

  2. user: 指该模块只在user版本下才编译

  3. eng: 指该模块只在eng版本下才编译

  4. tests: 指该模块只在tests版本下才编译

  5. optional:指该模块在所有版本下都编译

  • include $(BUILD_PACKAGE) 表示生成一个 apk,它可以多多种类型
  1. BUILD_SHARED_LIBRARY #生成一个动态库

  2. BUILD_STATIC_LIBRARY #生成一个静态的库

  3. BUILD_PACKAGE #生成一个APK


指定生成的 apk 存放的目录

默认情况

不指定 apk 生成目录时,默认的目录为 system/app/{LOCALPACKAGENAME}/{LOCALPACKAGENAME}.apk.

比如,我们上面的例子 LOCALPACKAGENAME 为 AppDemo,这样生成的 apk 目录为

  1. system/app/AppDemo/AppDemo.apk

指定目录

如果想指定生成的 apk 目录,我们可以通过 LOCALMODULEPATH 来配置,比如,我们想指定生成的 aok 目录为 system/vendor/operator/app,我们可以这样配置

  1. LOCAL_MODULE_PATH := $(TARGET_OUT)/vendor/operator/app

$(TARGET_OUT) 代表 /system ,这样在 、system/vendor/operator/app 可以看到我们生成的 apk。

假如我们想让我们生成的 apk 放到 system/priv-app 目录下,有什么方法呢?

第一种方法,指定 LOCALMODULEPATH ,在上面的讲解中,我们已经知道 $(TARGET_OUT) 代表 /system,那么生成的 apk 想放到 system/priv-app,我们可以这样配置。

  1. LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app

第二种方法,我们也可以直接这样配置,这样生成的 apk 也会放到 system/priv-app

  1. LOCAL_PRIVILEGED_MODULE := true

假如我们想让我们生成的 apk 放到 data/app 目录下,有什么方法呢?

我们可以直接这样指定,这样生成的 apk 就会放到 data/app 目录下

  1. LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)/

引用第三方 jar 包

引用一个 jar 包

比如,我们当前目录下的 libs 有 CommonUtil.jar jar 包,我们想引用它,需要两个步骤

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

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

  1. include $(CLEAR_VARS)

  2. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := CommonUtil:/libs/CommonUtil.jar

  3. include $(BUILD_MULTI_PREBUILT)

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

引用我们上面声明的 CommonUtil

  1. LOCAL_STATIC_JAVA_LIBRARIES := CommonUtil

引用多个 jar 包

引用多个 jar 包的方式其实跟引用 一个 jar 包的方式是一样的,只不过我们需要注意一下语法而已。

第一步:先声明多个 jar 包的位置

  1. include $(CLEAR_VARS)

  2. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := MeituCloudHelper:/libs/CommonUtil.jar \

  3. BaiduLBS:/libs/BaiduLBS_Android.jar \

  4. logger:/libs/logger.jar

  5. include $(BUILD_MULTI_PREBUILT)

第二步:引用我们声明的多个 jar 包的变量

  1. LOCAL_STATIC_JAVA_LIBRARIES := CommonUtil \

  2. BaiduLBS \

  3. logger

为了方便大家理解,这里先贴出部分 mk 文件

  1. LOCAL_PATH := $(call my-dir)

  2. include $(CLEAR_VARS)

  3. # 是否开启混淆

  4. LOCAL_PROGUARD_ENABLED := disabled

  5. LOCAL_MODULE_TAGS := optional

  6. # 使用 platform 签名

  7. LOCAL_CERTIFICATE := platform

  8. # 指定 src 目录

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

  10. # 指定 res 目录

  11. LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res

  12. # 本地编译目录

  13. LOCAL_PACKAGE_NAME := AppDemo

  14. LOCAL_STATIC_JAVA_LIBRARIES := CommonUtil \

  15. BaiduLBS \

  16. logger

  17. include $(BUILD_PACKAGE)

  18. include $(CLEAR_VARS)

  19. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := CommonUtil:/libs/CommonUtil.jar \

  20. BaiduLBS:/libs/BaiduLBS_Android.jar \

  21. logger:/libs/logger.jar

  22. include $(BUILD_MULTI_PREBUILT)


引用 so 库

假如我们当前目录下的 lib 目录下 有 armeabi-v7a,arm64-v8a 目录,里面分别有 libBaiduMapSDKbasev421.so, libBaiduMapSDKbasev421.so 。如果我们在编译 apk 的时候,想把这些 so 库 打包进去,在 mk 文件中要怎样配置呢?

一般来说,会有以下两种写法

第一种写法

第一步,直接在 mk 文件中配置以下内容,配置我们 so 库文件的所在位置,可以在文件的开头或者结尾。

  1. #====================================================

  2. include $(CLEAR_VARS)

  3. LOCAL_MODULE_TAGS := optional

  4. LOCAL_MODULE_SUFFIX := .so

  5. LOCAL_MODULE := libBaiduMapSDK_base_v4_2_1

  6. LOCAL_MODULE_CLASS := SHARED_LIBRARIES

  7. LOCAL_SRC_FILES_arm :=libs/armeabi-v7a/libBaiduMapSDK_base_v4_2_1.so

  8. LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/libBaiduMapSDK_base_v4_2_1.so

  9. LOCAL_MODULE_TARGET_ARCHS:= arm arm64

  10. LOCAL_MULTILIB := both

  11. include $(BUILD_PREBUILT)

  12. #====================================================

  13. #====================================================

  14. include $(CLEAR_VARS)

  15. LOCAL_MODULE_TAGS := optional

  16. LOCAL_MODULE_SUFFIX := .so

  17. LOCAL_MODULE := libBaiduMapSDK_map_v4_2_1

  18. LOCAL_MODULE_CLASS := SHARED_LIBRARIES

  19. LOCAL_SRC_FILES_arm :=libs/armeabi-v7a/libBaiduMapSDK_map_v4_2_1.so

  20. LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/libBaiduMapSDK_map_v4_2_1.so

  21. LOCAL_MODULE_TARGET_ARCHS:= arm arm64

  22. LOCAL_MULTILIB := both

  23. include $(BUILD_PREBUILT)

第二步: 引用我们的 so 库

在include $(CLEARVARS) 和 include $(BUILDPACKAGE) 之间添加以下内容

  1. LOCAL_REQUIRED_MODULES := libBaiduMapSDK_base_v4_2_1 \

  2. libBaiduMapSDK_map_v4_2_1 \

  3. LOCAL_JNI_SHARED_LIBRARIES := libBaiduMapSDK_base_v4_2_1\

  4. libBaiduMapSDK_map_v4_2_1\

配置完以后 mk 文件的形式大概是这样的

  1. include $(CLEAR_VARS)

  2. ----

  3. # 省略若干内容

  4. LOCAL_REQUIRED_MODULES := libBaiduMapSDK_base_v4_2_1 \

  5. libBaiduMapSDK_map_v4_2_1 \

  6. LOCAL_JNI_SHARED_LIBRARIES := libBaiduMapSDK_base_v4_2_1\

  7. libBaiduMapSDK_map_v4_2_1\

  8. include $(BUILD_PACKAGE)

第二种写法

第二种写法其实跟第一种写法差不多,只不过是将 so 库的 声明提取出来而已

第一步:比如我们将下面的代码提取到 lib/baidumap.mk mk 文件

  1. #====================================================

  2. include $(CLEAR_VARS)

  3. LOCAL_MODULE_TAGS := optional

  4. LOCAL_MODULE_SUFFIX := .so

  5. LOCAL_MODULE := libBaiduMapSDK_base_v4_2_1

  6. LOCAL_MODULE_CLASS := SHARED_LIBRARIES

  7. LOCAL_SRC_FILES_arm :=libs/armeabi-v7a/libBaiduMapSDK_base_v4_2_1.so

  8. LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/libBaiduMapSDK_base_v4_2_1.so

  9. LOCAL_MODULE_TARGET_ARCHS:= arm arm64

  10. LOCAL_MULTILIB := both

  11. include $(BUILD_PREBUILT)

  12. #====================================================

  13. #====================================================

  14. include $(CLEAR_VARS)

  15. LOCAL_MODULE_TAGS := optional

  16. LOCAL_MODULE_SUFFIX := .so

  17. LOCAL_MODULE := libBaiduMapSDK_map_v4_2_1

  18. LOCAL_MODULE_CLASS := SHARED_LIBRARIES

  19. LOCAL_SRC_FILES_arm :=libs/armeabi-v7a/libBaiduMapSDK_map_v4_2_1.so

  20. LOCAL_SRC_FILES_arm64 :=libs/arm64-v8a/libBaiduMapSDK_map_v4_2_1.so

  21. LOCAL_MODULE_TARGET_ARCHS:= arm arm64

  22. LOCAL_MULTILIB := both

  23. include $(BUILD_PREBUILT)

第二步,在原来的 Android.mk 文件中增加以下语句,表示将 /lib/baidumap.mk 文件 include 进来

  1. include $(LOCAL_PATH)/lib/baidumap.mk

第三步: 引用我们 的 so 库

  1. include $(CLEAR_VARS)

  2. ----

  3. # 省略若干内容

  4. LOCAL_REQUIRED_MODULES := libBaiduMapSDK_base_v4_2_1 \

  5. libBaiduMapSDK_map_v4_2_1 \

  6. LOCAL_JNI_SHARED_LIBRARIES := libBaiduMapSDK_base_v4_2_1\

  7. libBaiduMapSDK_map_v4_2_1\

  8. include $(BUILD_PACKAGE)

其实第一种写法和第二种写法并没有多大区别,第二种方法相对于第一种方法而言,只是将 so 库文件的配置独立到 mk 文件中。不过,我更推荐使用第二种方法,毕竟更符合面向对象的思维,以后复用以比较方便。


引用 aar 包

第一步:先声明 aar 包的位置

  1. include $(CLEAR_VARS)

  2. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += inveno_meitu_ui_sdk:libs/meitu_sdk-release_201709291605.aar

  3. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += inveno_detail_info_sdk:libs/detail_info_sdk-release.aar

  4. include $(BUILD_MULTI_PREBUILT)

第二步:引用我们声明的 aar 变量

  1. LOCAL_STATIC_JAVA_AAR_LIBRARIES += inveno_meitu_ui_sdk

  2. LOCAL_STATIC_JAVA_AAR_LIBRARIES += inveno_detail_info_sdk

第三步:添加引用的 aar 包里面的资源

  1. LOCAL_AAPT_FLAGS += \

  2. --auto-add-overlay \

  3. --extra-packages com.inveno.basics \

  4. --extra-packages com.inveno.detailinfosdk \


Android mk 文件配置签名

我们知道在 build/target/product/security 目录中有四组默认签名供,Android.mk在编译APK使用:

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

  • 2、platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试, 这种方式编译出来的APK所在进程的UID为system。

  • 3、shared:该APK需要和home/contacts进程共享数据。

  • 4、media:该APK是media/download系统中的一环。

举例说明一下。

  1. 系统中所有使用android.uid.system作为共享UID的APK,

  2. 都会首先在manifest节点中增加android:sharedUserId="android.uid.system",

  3. 然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可以参见Settings等

  4. 系统中所有使用android.uid.shared作为共享UID的APK,

  5. 都会在manifest节点中增加android:sharedUserId="android.uid.shared",

  6. 然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可以参见Launcher等

  7. 系统中所有使用android.media作为共享UID的APK,

  8. 都会在manifest节点中增加android:sharedUserId="android.media",

  9. 然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。

本文分享自微信公众号 - 徐公码字(stormjun94)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
待兔 待兔
2个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
8个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这