一、如何编译Jar包
要在 Android 项目中编译生成 Jar 包,你需要在 Android.mk
文件中使用 BUILD_STATIC_JAVA_LIBRARY
或者 BUILD_SHARED_JAVA_LIBRARY
来定义一个 Java 库模块。以下是一个示例:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 定义模块名称和源文件
LOCAL_MODULE := myjavamodule
LOCAL_SRC_FILES := MyClass1.java MyClass2.java
# 以下二选一:
# 1. 生成静态的jar包
include $(BUILD_STATIC_JAVA_LIBRARY)
# 2. 生成动态的jar包
include $(BUILD_JAVA_LIBRARY)
在这个示例中,我们使用了 BUILD_STATIC_JAVA_LIBRARY
来定义一个静态 Java 库模块。你可以在 LOCAL_SRC_FILES
中指定你的 Java 源文件列表,然后执行 ndk-build
命令来编译生成 Jar 包。
请注意,使用 BUILD_STATIC_JAVA_LIBRARY
生成的 Jar 包是静态的,意味着其中的类文件将被打包成一个 Jar 文件,但不会包含依赖的库。如果你的项目依赖其他的 Jar 包,你需要手动添加它们。
如果你想生成一个动态 Java 库,可以使用 BUILD_SHARED_JAVA_LIBRARY
,但在 Android NDK r20 版本之后,Google 移除了对动态 Java 库的支持,因此建议使用静态 Java 库。
二者的区别:
静态jar包里面包含的都是.class文件,可以在任何JVM中运行
动态jar包里面包含的都是.dex文件,所以只能运行在Dalvik 虚拟机(Android 4.4 及更早版本)或 ART 虚拟机(Android 5.0 及更高版本)
二、如何编译Apk
使用 ndk-build
或者 mm
命令来执行编译和构建过程。
以下是一个简单的 Android.mk
文件示例,用于构建一个包含 Java 源文件和资源文件的 APK:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 定义模块名称和源文件
LOCAL_MODULE := mymodule
LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
# 编译生成的Apk名字
LOCAL_PACKAGE_NAME := YOU_APK_NAME
# 添加资源文件
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
# 指定依赖的系统库
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
include $(BUILD_PACKAGE)
# 指定系统库的路径
$(call import-module,build/libs/android-support-v4)
在这个示例中,我们假设项目的 Java 源文件位于 src/main/java
目录下,资源文件位于 src/main/res
目录下。我们使用了 all-java-files-under
函数来自动查找 Java 源文件。我们还指定了一个名为 android-support-v4
的系统库作为静态 Java 库的依赖项。
你可以使用 ndk-build
命令来构建 APK 文件:
ndk-build
执行完成后,你将会在项目的 libs
目录下找到生成的 APK 文件。请注意,使用 Android.mk
文件构建 APK 的方法相对复杂,通常情况下推荐使用 Android Studio 或 Gradle 构建系统来构建 APK。
生成的Apk文件名为YOU_APK_NAME.apk
三、Apk中导入Jar包和库文件
在 Android.mk
文件中引用 Jar 包,使用 LOCAL_STATIC_JAVA_LIBRARIES
或者 LOCAL_SHARED_JAVA_LIBRARIES
变量来指定依赖的 Java 库。以下是一个示例:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 定义模块名称和源文件
LOCAL_MODULE := mymodule
LOCAL_SRC_FILES := file1.cpp file2.cpp
# 添加头文件包含路径
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
# 指定依赖的系统库
LOCAL_LDLIBS := -llog
# 指定依赖的 Java 库
LOCAL_STATIC_JAVA_LIBRARIES := myjava_lib
include $(BUILD_SHARED_LIBRARY)
# 指定要引用的 Jar 包
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := myjava_lib:libs/myjava_lib.jar
include $(BUILD_MULTI_PREBUILT)
在这个示例中,我们首先使用 LOCAL_STATIC_JAVA_LIBRARIES
变量指定了一个名为 myjava_lib
的 Java 库作为静态依赖项。然后,我们使用 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
变量指定了 myjava_lib
Jar 包的路径。最后,我们使用 BUILD_MULTI_PREBUILT
来添加预构建的 Java 库。
你需要将 myjava_lib.jar
放置在 libs
目录下,并确保 libs
目录在 Android.mk
文件的相对路径中。这样,当执行 ndk-build
命令时,构建系统将会将 Jar 包与本地代码一起打包到最终的 APK 文件中。
四、预编译Jar包
要在 Android.mk
文件中使用预编译的 Jar 包,你可以使用 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
或者 LOCAL_PREBUILT_SHARED_JAVA_LIBRARIES
变量来指定预编译的 Jar 包。以下是一个示例:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 定义模块名称和源文件
LOCAL_MODULE := mymodule
LOCAL_SRC_FILES := file1.cpp file2.cpp
# 添加头文件包含路径
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
# 指定依赖的系统库
LOCAL_LDLIBS := -llog
# 指定预编译的 Java 库
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := myjava_lib:libs/myjava_lib.jar
include $(BUILD_SHARED_LIBRARY)
在这个示例中,我们使用 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
变量来指定了一个名为 myjava_lib
的预编译静态 Java 库。myjava_lib.jar
文件需要位于 libs
目录下,构建系统会自动将其打包到最终的 APK 文件中。
确保 myjava_lib.jar
文件存在于 libs
目录下,并且在执行 ndk-build
命令时能够被构建系统正确地识别和使用。
五、Android.mk中如何加判断语句选择不同的编译类型
在 Android.mk
文件中,你可以使用 GNU Make 提供的条件语句来添加判断语句。以下是一些常见的条件语句用法:
ifeq/ifneq:用于比较两个变量是否相等或不相等。
ifeq ($(TARGET_ARCH),arm) # 在目标架构为 ARM 时执行的命令 endif ifneq ($(TARGET_ARCH),x86) # 在目标架构不为 x86 时执行的命令 endif
ifdef/ifndef:用于检查变量是否已经定义或未定义。
ifdef TARGET_ARCH # 如果 TARGET_ARCH 已经定义,则执行的命令 endif ifndef TARGET_ARCH # 如果 TARGET_ARCH 未定义,则执行的命令 endif
ifeq/ifneq (多行):条件语句也可以跨多行书写。
ifeq ($(TARGET_ARCH),arm) # 在目标架构为 ARM 时执行的命令 \ 可以在这里写多行命令 endif
条件语句中的逻辑运算:可以使用逻辑运算符
&&
、||
和!
结合多个条件。ifeq ($(TARGET_ARCH),arm) && ($(TARGET_CPU),cortex-a9) # 在目标架构为 ARM 且 CPU 为 cortex-a9 时执行的命令 endif
这些条件语句可以让你根据不同的条件执行不同的命令或设置不同的变量。请注意,在条件语句中,变量名和条件之间需要使用括号括起来,并且条件语句的结束
六、Android.mk常用语法
Android.mk
文件是 Android NDK 中用于构建 C/C++ 代码的 Makefile 文件。它基于 GNU Make 语法,并提供了一些特定于 Android 开发的扩展。以下是一些常用的 Android.mk
文件语法和用法:
变量定义:
- 使用
:=
赋值符号定义变量,例如MY_VARIABLE := value
。 - 使用
+=
赋值符号向变量追加值,例如MY_VARIABLE += new_value
。
- 使用
包含其他 Makefile:
- 使用
include
指令可以包含其他 Makefile 文件,例如include $(CLEAR_VARS)
。
- 使用
清除变量:
- 使用
$(CLEAR_VARS)
来清除之前的变量定义,例如include $(CLEAR_VARS)
。
- 使用
条件语句:
- 使用
ifeq
,ifneq
,ifdef
,ifndef
来进行条件判断。 - 使用
endif
结束条件语句块。
- 使用
模块定义:
- 使用
LOCAL_PATH
定义当前模块的路径,例如LOCAL_PATH := $(call my-dir)
。 - 使用
LOCAL_MODULE
定义模块名称,例如LOCAL_MODULE := mymodule
。 - 使用
LOCAL_SRC_FILES
定义模块的源文件列表,例如LOCAL_SRC_FILES := file1.cpp file2.cpp
。
- 使用
编译标志:
- 使用
LOCAL_CFLAGS
定义 C/C++ 编译标志,例如LOCAL_CFLAGS := -Wall -Werror
。 - 使用
LOCAL_CPPFLAGS
定义 C++ 编译标志,例如LOCAL_CPPFLAGS := -std=c++11
。
- 使用
链接库:
- 使用
LOCAL_LDLIBS
定义链接库,例如LOCAL_LDLIBS := -llog
。 - 使用
LOCAL_STATIC_LIBRARIES
定义静态库依赖,例如LOCAL_STATIC_LIBRARIES := somelib
。 - 使用
LOCAL_SHARED_LIBRARIES
定义动态库依赖,例如LOCAL_SHARED_LIBRARIES := somelib
。
- 使用
构建指令:
- 使用
include $(BUILD_SHARED_LIBRARY)
构建动态库。 - 使用
include $(BUILD_STATIC_LIBRARY)
构建静态库。 - 使用
include $(BUILD_EXECUTABLE)
构建可执行文件。 - 使用
include $(BUILD_PREBUILT)
构建预编译文件。
- 使用
这些是 Android.mk
文件中常用的一些语法和用法。使用这些语法和指令,你可以编写 Android.mk
文件来管理和构建你的 C/C++ 项目。