一个android工程代码多个差异化项目管理方法探讨
核心提示:
1、工程代码中尽量不要使用产品名称、设备名称之类的东西来区分,尽量以功能名称来区分,在工程独立的配置文件中再去配置这个文件;
2、在c/C++代码里可以在Android.mk文件中传进去一下宏,用宏来区分代码,这个宏就是功能的代名词,宏的名称尽量达意一些;
3、在java代码中尽量使用系统的property来做区分,设置系统属性来解决;
4、 UI显示定制的XML文件,无法做到兼容的话,就把文件拷贝到每个产品的device目录下,在编译的时候拷贝过去覆盖;
5、在底层代码中,kernel中本来就有一个config文件,这个可以增加配置选择,每个项目反正都有自己的config文件,代码里还是尽量不要用产品名称之类来区分;
6、 把硬件差异化配置尽量放到system_config1.fex里面去配置,全志把这一点发挥到极致了;
/*****************************************************************************************************/声明:本博内容均由http://blog.csdn.net/sundesheng125原创,转载请注明出处,谢谢!/*****************************************************************************************************/
在项目开发中,我们经常遇到在一套代码里要做多个产品,而每个产品或多或少都有一些功能不一样,有些硬件配置不一样,客户需求不一样,国内国外版本定制不一样、语言不一样,导致我们不得不在工程代码里去做差异化处理。在android项目开发中,从系统架构上也考虑一些这方面的需求,一般在device顶层目录下,针对每一个产品都有一个目录用来存放只跟自己相关的东西,笔者以全志平台为例,自己的产品为EW1021。
在device\softwinner\crane-EW1021-A目录中就存放了一些跟这个产品相关的东西,比如init.sun4i.rc里面就可以加载自己产品需要的驱动ko文件,启动自己需要的service;在crane_xxx.mk文件中也可以存放一些自己需要加载到系统中的资源文件,比如预装的音视频小文件、图片等,在这里面也可以设置好自己需要的语言设置,比如定制成英语为默认语言还是中文简体为系统默认语言,这些在设置property就可以搞定。
笔者以一个实际例子来做一下介绍,笔者做的是车载互动娱乐系统,就以里面的通道设置来学习一下我的做法。在实际产品中,存在几种音频输出的可能,从喇叭出,从耳机出,从FM发射出,从红外出,还可以从线性出,强调一下线性输出一般输出到功放音响,比如原厂带的音响,可以获得高品质的听觉效果。有一个A项目这5种输出都有,B项目没有喇叭,从耳机出,从FM发射出,从红外出,还可以从线性出,而C项目只有从耳机出,从FM发射出,还可以从线性出。从这个要求上来说,我们知道在UI显示上肯定是完全不一样的,这就要求我们把ui显示的XML放到各个产品的device目录下,编译的时候拷贝过来,这就解决了UI的控制问题。然而,ABC项目三个客户要求默认的输出通道又不一样,A默认喇叭,B默认红外,C默认线性,这怎么解决呢?总不能再代码的处理中用ABC的名称来区分吧!那样后面再增加一个项目就比较麻烦了。笔者想到的就是增加一个系统属性,这个属性就用来配置系统默认的音频通道值。比如:
PRODUCT_PROPERTY_OVERRIDES += \
persist.sys.usb.config=mass_storage,adb \
persist.service.adb.enable=1 \
persist.sys.timezone=Asia/Shanghai \
persist.sys.language=zh \
persist.sys.country=CN \
ro.sf.lcd_density=120 \
ro.property.tabletUI=true \
ro.product.firmware=1.5 \
ro.product.def_audio_out_val=3 \
ro.product.need_ctl_audioin_vol=1 \
sys.sdcardmounted=0
增加的ro.product.def_audio_out_val可以配置不同的值,这个值可以按约定的表示方法来确定,比如0代表喇叭,1代表耳机,2代表FM发射,以此类推。利用系统属性确实能解决很多问题。
除了系统属性,在android代码中还有一个利器就是利用功能宏配置。比如有一个应用是CSIIN的应用,这个应用是用来解决视频输出鲜果的问题,但是有些客户要求做低成本的,就不需要这个硬件,当然这个应用也就没有用了,但是在Android.mk文件中用产品名称来区分也不好,笔者自己增加了一个配置宏就可以很好的解决这个问题配置为:
#csi apk
SW_BOARD_CSI_IN_APK := true
而在Android.mk中就可以这样写了,如下:
ifeq ($(SW_BOARD_CSI_IN_APK), true)LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional eng
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := CSIIN
LOCAL_CERTIFICATE := platform
LOCAL_OVERRIDES_PACKAGES := Home
include $(BUILD_PACKAGE)
endif
当然还有很多在hardware层需要做区分的,比如不同的屏,系统设置整体效果的亮度、对比度、色饱和度这些都不一样,那我们可以利用产品名称来区分,但是笔者建议还是以屏来区分,这样更有代表性,这样就不需要很长的一串宏来区分,比如笔者开始用产品名称来隔开的,这样做起来,确实也能解决问题,但是不利于维护,特别是产品成型的时候,稍微改一改又要做给另外一个客户的时候,每个地方都需要改,而如果利于屏来区分,就可以再配置里面搞定比如:
#10 inch project
SW_BOARD_LCD_1280_800_10INCH := true
代码里就轻松了。在Android.mk可以写一个
+ifeq ($(SW_BOARD_LCD_1280_800_10INCH), true)
+LOCAL_CFLAGS += -DLCD_1280_800_10INCH
+endif
下面看一下,两者在代码中修改对比:
-#if defined(crane_ew1021) || defined(crane_EW1021_A) || defined(crane_ew1021tsd)|| defined(crane_PD1099_A) || \
-defined(crane_PD1099_C) || defined(crane_EVBJEAVOX) || defined(crane_EW1021H_A) || defined(crane_EW1021H_C) || defined(crane_EW1023_Cemmc)
+/*10 Inch product board*/
+#ifdef LCD_1280_800_10INCH
LOGD("Workaround call: display_getsaturation()\n");
display_getsaturation(dev, 0);
display_getsaturation(dev, 1);
@@ -1664,8 +1664,8 @@ static int display_setmode(struct display_device_t *dev,int mode,struct display_ ctx->valid_width[0] = display_getvalidwidth(ctx,0,para->d0type,para->d0format); ctx->valid_height[0] = display_getvalidheight(ctx,0,para->d0type,para->d0format);
-#if defined(crane_ew1021) || defined(crane_EW1021_A) || defined(crane_ew1021tsd)|| defined(crane_PD1099_A) || \
-defined(crane_PD1099_C) || defined(crane_EVBJEAVOX) || defined(crane_EW1021H_A) || defined(crane_EW1021H_C) || defined(crane_EW1023_Cemmc)
+/*10 Inch product board*/
+#ifdef LCD_1280_800_10INCH
ctx->width[1] = 1280;//display_getwidth(ctx,1,para->d1type,para->d1format); ctx->height[1] =720;// display_getheight(ctx,1,para->d1type,para->d1format); #else //E901-902
这样一对比,一看就知道了用屏的宏来隔开差异化代码比用产品名称来隔开要好很多,这样增加项目的时候就不修改这里面的代码,只要在device下面的目录下增加一个宏配置就好了。
笔者结合多年的实践经验认为工程代码里越少出现产品名称来区分功能差异化、配置差异化最好,扩展项目的时候最方便省事,也利于维护。