在一个Android系统中,尤其是开发各个app模块的开发人员,可能会用到同一个第三方的sdk,比如xutils、volley、gson、amap、imageloader等。目前大家通常的做法是把第三方sdk集成到自己的app中,与app一起打包生成一个apk。这样做固然没有问题,但是会给系统带来一些额外的不好影响:比如多个app都用了同一个sdk,造成了sdk的冗余,增大了整个系统ota包的大小;在写Andriod.mk时,需要注意声明使用的sdk是否与系统中其他app使用的sdk重名;不同的app可能使用了不同版本的sdk,导致sdk版本不统一。那是否有一种方案能解决这个问题呢?答案是肯定的,而且Android系统本身就给我们提供了这钟机制,那就是“uses-library”。"uses-library"只是解决了使用的问题,具体还涉及到系统源码和编译脚本的一些修改,下边就来具体说一说,如何做到解决编译时依赖、运行时动态加载sdk的问题:
1、在系统源码里声明sdk,其实是sdk中的jar包。这个可以参考编译好的rom中的/system/etc/permission/xxx.xml,我们可以考虑修改/framework/base/data/etc/platform.xml,可以添加以下内容:
<!-- This is a list of all the amap libraries available for application code to link against. --> <library name="android.amap.location" file="/system/framework/android.amap.location.jar" /> <library name="android.amap.services" file="/system/framework/android.amap.services.jar"/> <library name="android.amap.map" file="/system/framework/android.amap.map.jar"/> <library name="android.amap.2dmap" file="/system/framework/android.amap.2dmap.jar"/>
2、将第三方sdk的jar包集成到系统的/system/framework/下,这个可以在vendor/xxx/prebuilt/(不同的项目对应的目录可能不同)中新建一个项目,把第三方sdk的jar和so提取出来,编写Android.mk脚本,以android.amap.map为例,
include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, .) LOCAL_NO_STANDARD_LIBRARIES := true LOCAL_STATIC_JAVA_LIBRARIES := amap_loc LOCAL_MODULE := android.amap.location LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_NO_EMMA_INSTRUMENT := true LOCAL_NO_EMMA_COMPILE := true LOCAL_DX_FLAGS := --core-library include $(BUILD_JAVA_LIBRARY) ################################################# include $(CLEAR_VARS) LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := amap_loc:libs/AMap_Location_v1.4.0_20150830.jar include $(BUILD_MULTI_PREBUILT) ################################################# include $(CLEAR_VARS) LOCAL_MODULE := libamapv304 LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_CERTIFICATE := PRESIGNED LOCAL_MODULE_SUFFIX := .so LOCAL_SRC_FILES := so/libamapv304.so include $(BUILD_PREBUILT)
3、在以上步骤之后,还需要将编译出来的module集成到系统中,也就是在prebuilt.mk或者其他什么地方PRODUCT_PACKAGES中添加上对应的module name,不然系统编译没有问题,生成的rom包中确没有对应的文件内容。
4、修改完系统的编译问题后,接下来需要解决APP的编译问题,将Android.mk中声明的JAVA_STATIC_LIBRARIES依赖去除,改为使用LOCAL_JAVA_LIBRARIES,如下:
LOCAL_JAVA_LIBRARIES := android.amap.location
5、最后要修改的是AndroidManifest.xml中使用library问题,在application元素内声明如下,一定要在application标签内哦:
<uses-library android:name="android.amap.location" />
最后,需要注意一个坑:如果jar包中有asset怎么办?比如map sdk中有一些依赖的asset资源,在之前静态编译依赖时没有问题,但是使用uses-library方式时,由于jar包是动态加载,asset资源在运行时无法被找到,所以解决方法是:事先将sdk中的asset解压出来放到app的asset中,系统集成的sdk中可以将asset目录删除了。
原文:http://my.oschina.net/kingguary/blog/530975