首页 > 代码库 > 厦门之旅第一篇Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)

厦门之旅第一篇Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)

我不是诗人,写不出厦门的美;我不是歌手,唱不出厦门的情;我不是画家,画不出厦门的景。

我只是一名程序员,我只能用我的眼,我的心去看去感受,那久违的海风吹拂着脸颊,好似内心那一份烦躁与沉重也随着海风飘向了远方 . . . . . .

一、Gradle多渠道打包之缘由

时间要追溯到两年前,当时我还在使用 eclipse 开发工具。兄弟事业部有款产品需要封包(使用webview打包成app),并提出了相关的需求:

  • 针对不同商家地址(webview加载url),App名称,应用图标,欢迎页背景,状态栏颜色(背景同色)都不同,以及版本号不同。

  • 针对不同的商家都必须打包成独立的App,不会出现覆盖安装。

针对以上的需求每次打包都需要替换App名称,应用图标,背景等资源,还必须修改包名(带来的一系列报错)。后期又提出了升级功能,又得把资源、包名修改回去,一番折腾真的欲仙欲死。后来我干脆每次都新建项目打包,业务逻辑没有变化只是资源发生了改变,代码是拷贝了一份又一份,而且商家一多,维护起来真的是找得死去活来的,加之客户提出新功能,我每个商家都需要撸一遍 . . . 神啊,谁来拯救我啊

二、自我拯救之路

在后来接触到AndroidStudio(简称AS),逐渐的转到了AS开发,确实比 eclipse高效快速方便。 gradle 构建功能真心非常强大,默认有 debug ,release 版本,我们可以针对不同版本做不同配置,这不正好解决我所遇到的问题。gradle提供了productFlavors节点针对不同的版本做不同的配置。

比如有【四季易购】【仁仁家】【库乐购】商家需要打包。

技术分享

我在每个分支下面都重新配置applicationId这个属性,从而使打包出来的apk的包名不一样,避免了覆盖安装。

当然针对不同的商家 App名称,图标不一样。这个时候我们就需要配置manifestPlaceholders属性,manifestPlaceholders是一个类似HashMap的容器,因此在manifestPlaceholders可以配置多个属性。如下我们可以这样配置:

gradle配置:

技术分享

AndroidManifest配置:

技术分享

注意:节点 meta-data 的配置。

${icon}${app_name} 引用 manifestPlaceholders 容器中 iconapp_name 的值。

客户的需求不仅仅更改App名称与图标,还需要修改webview加载地址,欢迎页背景图片等等,具体配置如下图:

技术分享

注意:新增的配置同样需要在清单文件中添加 meta-data节点。

        <meta-data
            android:name="welcome_bg"
            android:value=http://www.mamicode.com/"${welcome_bg}"/>

        <meta-data
            android:name="tint_color"
            android:value=http://www.mamicode.com/"${tint_color}"/>

        <meta-data
            android:name="load_url"
            android:value=http://www.mamicode.com/"${load_url}"/>

我们可以通过 Java 代码获取到 meta-data节点下 android:value的值。

一般在 MyApplication 获取节点的值:

    ApplicationInfo info = null;
    try {
        info = this.getPackageManager().getApplicationInfo(getPackageName(), PackageManager
                .GET_META_DATA);
        int tintColor = info.metaData.getInt("tint_color");
        String loadUrl=info.metaData.getString("load_url");
        String welcomePath = info.metaData.getString("welcome_bg");

    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

注意:设置welcome_bg:"@mipmap/klg_welcome",我这里以int welcomeRes = info.metaData.getInt("welcome_bg");去取值,每次都返回0,但tint_color的值就正常。按正常思维@mipmap/klg_welcome返回的是 int 值,后来我换成getString还真获取到了值:res/mipmap-hdpi-v4/sjyg_welcome.png。获取到路径值,背景的图片资源就不能直接使用。

那么我们把路径资源转换成int资源,这里就用到了 Java 的反射。具体代码如下:

    Class c = R.mipmap.class;
    Field[] fields = c.getFields();
    for (Field field : fields) {
        if (field.getName().equals(welcomePath.substring(welcomePath.lastIndexOf("/") + 1,
                welcomePath.lastIndexOf(".")))) {
            this.welcomeBgRes = (int) field.get(c.newInstance());
            break;
        }
    }

截取路径字符串获取图片的【名称】,根据【名称】在【R.mipmap.class】类中查找,找到则返回该属性的值。

这样我们就把不同的配置信息保存到了MyApplication中,使用的时候直接调用。

还有一种方式在Java代码中可以方便获取到gradle配置文件的数据:

技术分享

通过代码:context.getResources().getString(R.string.key);获取值。

注意通过此方式 strings.xml 文件下不能有同名的 key 属性。不然会报相同资源引用错误。

三、生成APK

如果你想生成所有渠道的包:

Terminal命令输入如下指令:

gradlew assembleRelease

构建成功请在以下目录查看:

技术分享

如果你想针对某个渠道打包:

方式一:

技术分享

配置不同渠道基础信息。

方式二:

技术分享

更改 applicationId ,添加 manifestPlaceholders集合。

多渠道打包,并不需要更改百度、高德等第三方的key

多渠道打包,解决了以往深深的忧伤。

技术分享

源码地址

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    厦门之旅第一篇Gradle多渠道打包(动态设定App名称,应用图标,背景图片,状态栏颜色)