实际开发中经常遇到这样的需求:一个应用打不同的包时,不同的包 的logo、 应用名,或者应用中的某些标志性的图片、显示的文字内容、欢迎语什么的都要做出相应的改变。 对此,我们不可能将原工程复制出来再重新建立一个工程,然后替换成不同的资源再打包。 那么本文为读者提供一种相对简便的方法,有这种需求的友友就可以接着看下去了...
编译时合并与替换资源,主要用到aapt命令工具:
先看一下aapt命令 跟不同参数时的作用:
命令行界面切换到 aapt 命令所在目录,输入aapt 如下:
可以看出, -s 可以指定寻找资源的目录,而 overlay 可以合并资源:
比如 ,工程中原有的res 里面有个字符串 :app_name(Menifest.xml中配置的应用名)
<string name="app_name">九秀美女直播</string>,
在工程中新建两个资源文件夹res2和res3,里面分别有两个字符串: app_name,more
//res2
<string name="app_name">9秀直播</string>
<string name="more">更多2</string>,
//res3
<string name="app_name">MM直播</string><string name="more">更多3</string>,并在build.grandle里配置如下
aaptOptions { additionalParameters '-S', 'G:/wkplace/AS/NineShow3.0/res2', '-S', 'G:/wkplace/AS/NineShow3.0/res3', '--auto-add-overlay' noCompress 'foo', 'bar' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' }运行后,应用名会显示res里的app_name:“九秀美女直播”。这是因为: -s 可以指定多个资源目录,我们通过-s 将 res2,res3都指定为了资源目录,寻找资源时会先寻找系统默认的res目录,若找不到,就会接着去寻找-s指定的目录寻找。系统会加载最先找到的那个同名资源。 如果删除res里的app_name 则应用名会显示“9秀直播”;若把 build.grandle里的配置顺序 res2与res3颠倒一下,则运行后会显示“MM直播”。 如果应用中需要加载一个textView="@String/more",则会显示“更多2”<-s res2 -s res3>。如果没有 -auto-add-overlay ,即配置改为如下:
aaptOptions { additionalParameters '-S', 'G:/wkplace/AS/NineShow3.0/res2',//9秀直播 '-S', 'G:/wkplace/AS/NineShow3.0/res3'//MM直播 // '--auto-add-overlay' // noCompress 'foo', 'bar' // ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' }则 build工程的时候会报错,比如:
类似上面错误种种,大致意思就是说 找不到某些资源,关于出现这种情况的原因,很多开发者都说是因为-s指定的资源目录中存在基础包(res)里没有定义的资源id,其实这样说并不全面,根据笔者全方位无死角的测试证明,只要基础包与overlay指定的资源目录中存在不同的资源 都会报类似错误。 解决办法就是 加上-auto-add-overlay
![]()
就会自动得把voerlay指定的资源目录中出现的基础包中不存在的资源增加进去(官方文档字面意思)。
这样说不贴切,实际上 有了-auto-add-overly命令后 ,可以理解为:
打包的时候,把基础包中所有的资源(res) + overlay资源目录中(即-s指定目录)第一份出现的新资源id = 最终的资源包(取所有资源目录的并集,相同资源只取第一份)
比如:
res中存在anim、drawable、values/dimens、values/string等文件 其中,string中定义了 app_name,tittle,text_show 三个变量,
res2中只有values/string ,string中定义了 text_show,text_hello 两个变量
res3中只有values/string ,string中定义了 app_name,text_show,text_hello,message 四个个变量
则根据前面overlay配置的顺序 res2 在前,res3在后,则最终打包时候生成的资源包中 包含了res中的所有资源,并在string中增加 res2的text_hello 与 res3的message。所以,我们多途径打包时候 想要实现 不途径的apk用不同的包名与资源的效果,可以 将共同的资源放在基础包中的资源目录(res),需要替换的资源放在不同路径对应的资源目录中。最后上实例如下:需求 打包时需要打两个不同的渠道包:其一,包名为com.ninexiu.sixninexiu 的apk,手机上显示的图标为,应用名为:九秀美女直播;
其二,包名为 com.show.mmlive 的apk,手机上显示的图标为,应用名为:MM直播 。
实现:Menifest.xml配置文件如下:
删除工程目录中 res/values/string中的label的定义,与res/drawble 目录中的logo图片新建两个与res同等级的资源目录:res2资源文件为:drawable中名字为logo的图片,string中<string name="app_name">九秀美女直播</string>;
res3资源文件为:drawable中名字为logo的图片,string中<string name="app_name">MM直播</string>;
打渠道一包:
build.gradle 中相关的配置如下时productFlavors{ nineshow{ applicationId "com.ninexiu.sixninexiu" } // mmlive{ // applicationId "com.show.mmlive" // } } aaptOptions { additionalParameters '-S', 'G:/wkplace/AS/NineShow3.0/res2',//9秀直播 '-S', 'G:/wkplace/AS/NineShow3.0/res3',//MM直播 '--auto-add-overlay' noCompress 'foo', 'bar' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' }打包出来的apk为包名为com.ninexiu.sixninexiu 的apk,手机上显示的图标为,应用名为:九秀美女直播;
打渠道二包:
build.gradle 中相关的配置如下时:productFlavors{ // nineshow{ // applicationId "com.ninexiu.sixninexiu" // } mmlive{ applicationId "com.show.mmlive" } } aaptOptions { additionalParameters '-S', // 'G:/wkplace/AS/NineShow3.0/res2',//9秀直播 // '-S', 'G:/wkplace/AS/NineShow3.0/res3',//MM直播 '--auto-add-overlay' noCompress 'foo', 'bar' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' }打包出来的apk为包名为 com.show.mmlive的apk,手机上显示的图标为,应用名为:MM直播 。
替换其他更多的资源,做法同上。
多渠道打包时合并与替换资源,以上只是一种做法,看到过网上似乎还有其他做法,当时没看太明白,就先分享出这一种;但由于该方法每次打包时都需要在gradle中注释掉不同的配置内容 一个包一个包的来打,略显麻烦。若有更好方法的友友可以分享给我^ ^ 知识在于分享
e_mail: schruanjian@126.com.
参考内容:
http://www.open-open.com/lib/view/open1455888339167.html#articleHeader1http://blog.zhaiyifan.cn/2016/02/13/android-reverse-2/
http://blog.csdn.net/maosidiaoxian/article/details/42671999