本文基于 AOSP Android10_r41 源码环境。
如果提前阅读了以下文章,本文阅读起来会更加顺利:
# 1.添加 C/C++ 程序库
# 1.1 源码方式添加
在 device/Jelly/Rice14/
目录下创建以下的目录和文件
libmymath
├── Android.bp
├── my_math.cpp
└── my_math.h
2
3
4
libmymath 是一个动态库。其 Android.bp
内容如下:
cc_library_shared {
name: "libmymath",
srcs: ["my_math.cpp"],
export_include_dirs: ["."],
product_specific: true,
// 可编译出 32 64 位的 so 包
// compile_multilib: "both"
}
2
3
4
5
6
7
8
9
10
11
12
13
my_math.h 内容如下:
#ifndef __MY_MATH_H__
#define __MY_MATH_H__
int my_add(int a, int b);
int my_sub(int a, int b);
#endif
2
3
4
5
6
7
my_math.cpp 内容如下:
#include "my_math.h"
int my_add(int a, int b)
{
return a + b;
}
int my_sub(int a, int b)
{
return a - b;
}
2
3
4
5
6
7
8
9
10
11
接着修改我们之前添加的 hello 项目:
修改 hello.cpp
#include <cstdio>
#include "my_math.h" //添加头文件
int main()
{
printf("Hello Android %d \n", my_add(1,2)); //添加函数调用
return 0;
}
2
3
4
5
6
7
8
修改 Android.bp:
cc_binary {
name: "hello",
srcs: ["hello.cpp"],
cflags: ["-Werror"],
product_specific: true,
shared_libs: ["libmymath"] //添加动态库依赖
}
2
3
4
5
6
7
接下来编译系统:
source build/envsetup.sh
lunch Rice14-eng
make -j16
2
3
编译完成启动虚拟机后,就可以通过 adb shell 运行我们的 hello 程序了
emulator
adb shell hello
2
执行结果如下图所示:
# 1.2 so 包方式添加
在 device/Jelly/Rice14
目录下创建如下的文件与文件夹:
libmymathprebuild
├── Android.bp
├── include
│ └── my_math.h
└── lib
├── x86
│ └── libmymath.so
└── x86_64
└── libmymath.so
2
3
4
5
6
7
8
9
- 其中 libmymath.so 是上一节中的编译产物,x86/libmymath.so 拷贝自 out/target/product/Rice14/system/product/lib/libmymath.so
- x86_64/libmymath.so 拷贝自 out/target/product/Rice14/system/product/lib64/libmymath.so
- my_math.h 是上一节中 libmymath 模块中拷贝过来的头文件
Android.bp 的内容如下:
cc_prebuilt_library_shared {
name: "libmymathprebuild",
arch: {
x86: {
srcs: ["lib/x86/libmymath.so"],
},
x86_64: {
srcs: ["lib/x86_64/libmymath.so"],
}
},
export_include_dirs: ["include"],
product_specific: true,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
为了避免冲突,我们把上一节添加的 libmymath
移出系统源码目录或者删除。
接下来,编译整个系统,开启虚拟机
source build/envsetup.sh
lunch Rice14-eng
make -j16
emulator
2
3
4
接下来执行 hello 程序
adb shell hello
执行结果如下图所示:
# 2. 添加 Java 库
# 2.1 源码方式添加
在 device/Jelly/Rice14/
目录下创建以下的目录和文件:
libmymathjava
├── Android.bp
└── com
└── yuandaima
└── mymath
└── MyMath.java
2
3
4
5
6
libmymathjava 是一个 java 库。其 Android.bp 内容如下:
java_library {
name: "libmymathjava",
installable: false,
product_specific: true,
srcs: ["**/*.java"],
sdk_version: "current"
}
2
3
4
5
6
7
如果不指定 installable: true, 则编译出来的 jar 包里面是 .class 文件。这种包是没法安装到系统上的,只能给其他 java 模块作为 static_libs 依赖。最终生成的 jar 包不会被直接存放到 Android 的文件系统中,而是打包进依赖于当前模块的其他模块中。
MyMath.java 内容如下:
package com.yuandaima.mymath;
public class MyMath
{
public MyMath() {
}
public int add(int a, int b)
{
return (a+b);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
接着我们把 helllojavajar 删除,将之前写好的 hellojava 模块移动到 device/Jelly/Rice14
目录下,并做以下修改:
修改 helljava/Android.bp:
java_library {
name: "hellojava",
installable: true,
product_specific: true,
srcs: ["**/*.java"],
sdk_version: "current",
static_libs: ["libmymathjavajar"]
}
2
3
4
5
6
7
8
在 device/Jelly/Rice14/Rice14.mk
中添加:
PRODUCT_PACKAGES += hellojava
接下来编译系统:
source build/envsetup.sh
lunch Rice14-eng
make -j16
2
3
编译完成启动虚拟机后:
# 进入模拟器shell
adb shell
# 配置 classpath
export CLASSPATH=/product/framework/hellojava.jar
app_process /product/framework/ com.ahaoyuandaima.main.HelloJava
2
3
4
5
执行结果如下图所示:
# 2.2 Jar 包方式添加
在系统源码目录下执行:
source build/envsetup.sh
lunch Rice14-eng
2
接下来编译获得 jar 包:
cd device/Jelly/Rice14/libmymathjava
mm
#编译完成后,会打印出编译产物路径 out/target/product/Rice14/obj/JAVA_LIBRARIES/libmymathjava_intermediates/javalib.jar
2
3
为避免冲突我们把 device/Jelly/Rice14/libmymathjava
移动到源码以外的目录或者删除
在 device/Jelly/Rice14/
下重新创建如下的目录结构:
libmymathjavajar
├── Android.bp
└── libmymathjava.jar
2
3
其中 libmymathjava.jar
是拷贝自编译产物 out/target/product/Rice14/obj/JAVA_LIBRARIES/libmymathjava_intermediates/javalib.jar
,并改名为 libmymathjava.jar
Android.bp 的内容如下:
java_import {
name: "libmymathjavajar",
installable: false,
jars: ["libmymathjava.jar"],
product_specific: true,
}
2
3
4
5
6
接着修改 hellojava 模块的依赖:
java_library {
name: "hellojava",
installable: true,
product_specific: true,
srcs: ["**/*.java"],
sdk_version: "current",
static_libs: ["libmymathjavajar"] //修改这里
}
2
3
4
5
6
7
8
编译系统,并启动模拟器:
source build/envsetup.sh
lunch Rice14-eng
make -j16
emulator
2
3
4
验证 libmymathjavajar 模块是否被正确编译到 hellojava 模块中。
# 进入模拟器shell
adb shell
# 配置 classpath
export CLASSPATH=/product/framework/hellojava.jar
app_process /product/framework/ com.ahaoyuandaima.main.HelloJava
2
3
4
5
执行结果如下:
# 参考资料
- How to include prebuilt library in Android.bp file? (opens new window)
- Android系统开发入门-5.添加预编译模块 (opens new window)
- Android.bp 文件中引入aar、jar、so库正确编译方法(值得收藏) (opens new window)
- 在AOSP中添加jar包和aar包依赖 (opens new window)
- Android系统开发入门-4.添加自定义模块 (opens new window)
- Android 10 根文件系统和编译系统(十九):Android.bp各种模块编译规则 (opens new window)
- Soong Modules Reference (opens new window)
- Android.bp编译提示ninja: error: unknown target ‘MODULES-IN-xxx‘终极指南 (opens new window)
- Failing builds for Lineage-19.0 due to artifact path requirement (opens new window)
- 自定义 SELinux (opens new window)
- Android系统build阶段签名机制 (opens new window)
- android系统源码中添加app源码(源码部署移植) (opens new window)
# 关于
我叫阿豪,2015 年本科毕业于国防科学技术大学指挥信息系统专业,毕业后从事信息化装备的研发工作,主要研究方向是 Android Framework 与 Linux Kernel。
如果你对 Android Framework 感兴趣或者正在学习 Android Framework,可以关注我的微信公众号和抖音,我会持续分享我的学习经验,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或者你的经验想要分享给大家可以添加我的微信,我拉你进技术交流群。