最近出于工作需要,要将一个模块由gradle编译改为mk方式加入源码编译。遇到了一些问题,在这里记录一下。主要有以下几个问题:
- 项目中一些三方jar包的引用
- AIDL 文件的编译
- Dex 64K限制问题
- so 库文件的编译
- 根据编译版本类型编译不同的asset文件夹
1. 三方jar包的引用
# fresco:libs/fresco.jar, 冒号前面的名字是随便取得,无所谓,后面跟上对应的jar包的路径,多个jar之间空格隔开
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := fresco:libs/fresco.jar gson:libs/gson-2.3.1.jar
include $(BUILD_MULTI_PREBUILT)
在需要引用地方:
# 这里引用的时候只需要引用上面定义的别名即可
LOCAL_STATIC_JAVA_LIBRARIES := \
fresco \
gson\
这里还有个问题:在gradle方式中 通过 compile
方式应用的三方库,我们当时并没有下载 jar 文件放到libs 文件夹下啊,咋办?
- 其实 jar 包是被下载在项目的
External Libraries
目录下,找到引用的 jar包,点右键find in path
,就得到了 jar 包的文件地址,把它塞到libs
文件夹下,然后就在mk中像别的 jar 包一样处理就好了
2. AIDL 文件的编译
- 最初我是按照下面这种方式将aidl文件加入编译,但是始终编译不过。
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
src/main/aidl/com/test/module/IScanCallback.aidl \
src/main/aidl/com/test/module/IScanInterface.aidl \
Couldn't find import for class com.test.module.IScanCallback
但是以前我也有类似的经历,编译AIDL这么写是OK的啊,问题出在哪了呢?倒腾了几个小时,经查:
Android.mk在编译简单的AIDL,即传递的参数只有基本数据类型时,上面的写法没有问题。
- 我的AIDL代码如下:
// IScanCallback.aidl
package com.test.module;
interface IScanCallback {
boolean myXXX(boolean isOk);
}
// IScanInterface.aidl
package com.test.module;
import com.test.module.IScanCallback;
interface IScanInterface {
void startXXX(String filePath);
void registerCallback(IScanCallback cb);
void unregisterCallback(IScanCallback cb);
}
问题可能就出现在了 IScanInterface.aidl
中引用了com.test.module.IScanCallback
并作为参数传递了。
- 这种情况,正确的写法如下:
# 不仅要在LOCAL_SRC_FILES 标签后加入 aidl文件路径,还要加入LOCAL_AIDL_INCLUDES 标签
aidl_dirs = src/main/aidl
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
src/main/aidl/com/test/module/IScanCallback.aidl \
src/main/aidl/com/test/module/IScanInterface.aidl \
LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/$(aidl_dirs)
3. Dex 64K限制问题
ERROR: Dex writing phase: classes.dex has too many IDs. Try using multi-dex
DEX 64K 问题: 方法数超限65536
Android平台的Java虚拟机Dalvik执行Dex程序时,使用的是short类型来索引DEX文件中的方法。这就意味着单个Dex文件可被引用的方法总数被限制为64x1024, 即65536。其中包括:
Android Framework的方法 library的方法 我们自己写的方法 为突破这个限制,需要使用multidex来生成多个dex文件
在mk文件中添加以下两个标签即可
LOCAL_DX_FLAGS := --multi-dex
LOCAL_JACK_FLAGS := --multi-dex native
4. so 库文件的编译
和三方jar包的编译方式类似,只是标签不同
include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := libaaaa:libs/arm64-v8a/lib_aaaa.so
LOCAL_PREBUILT_LIBS += libbbbb:libs/arm64-v8a/lib_bbbb.so
include $(BUILD_MULTI_PREBUILT)
在需要引用的地方:
LOCAL_JNI_SHARED_LIBRARIES := libaaaa libbbbb
5. 根据编译版本类型编译不同的asset文件夹
这里主要是 LOCAL_ASSET_FILES
标签的使用
ifeq ($(YOUR_JUDGEMENT),true)
LOCAL_ASSET_FILES += assets/
else
LOCAL_ASSET_FILES += assets-debug/
endif
6. 附上完整的mk文件:
LOCAL_PATH := $(call my-dir)
############### 三方jar包和so库的编译 ########################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := gson:libs/gson-2.3.1.jar fresco:libs/fresco.jar
LOCAL_PREBUILT_LIBS := libaaaa:libs/arm64-v8a/lib_aaaa.so
LOCAL_PREBUILT_LIBS += libbbbb:libs/arm64-v8a/lib_bbbb.so
include $(BUILD_MULTI_PREBUILT)
#######################################
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
src/main/aidl/com/test/module/IScanCallback.aidl \
src/main/aidl/com/test/module/IScanInterface.aidl \
######## 解决AIDL编译的问题 #############
aidl_dirs = src/main/aidl
LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/$(aidl_dirs)
######## 根据需求编译不同的asset目录 ######
ifeq ($(YOUR_JUDGEMENT),true)
LOCAL_ASSET_FILES += assets/
else
LOCAL_ASSET_FILES += assets-debug/
endif
######## 三方jar包和so库文件的引用 #########
LOCAL_STATIC_JAVA_LIBRARIES := \
gson \
fresco \
LOCAL_JNI_SHARED_LIBRARIES := libaaaa libbbbb
LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v4 \
android-support-annotations \
android-support-v7-recyclerview \
android-support-v7-preference \
android-support-v7-cardview \
android-support-v7-appcompat \
android-support-v7-palette \
android-support-v14-preference \
android-support-v17-preference-leanback \
android-support-v17-leanback \
####### 解决 64K DEX限制问题 #######
LOCAL_DX_FLAGS := --multi-dex
LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_PACKAGE_NAME := XXXXX
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_PROGUARD_FLAG_FILES := proguard-rules.pro
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
具体 Android.mk 里面的标签还有很多,使用的过程中遇到问题的话会继续补充进来,使用方法网上相关的文章很多。