一次代码,建立多次

前言

大家可能会有类似这样的需求:同一个APP发布不同的版本,修改里面的主题、icon、applicationId。这应该怎么弄呢?很多同学都是重新check一份工程直接修改的。但其实是不必要的,android studio 的gradle就可以帮我们做到。

1、Build Variants(构建变量)

让我们从一般的概念入手,构建变量。 gradle允许您定义多个构建变量定义的构建变体由一个特定的所有属性生成类型加入到一个特定的所有属性的 product flavors 里面。 Build variants, build types, product flavors?虽然有点陌生,让我们接下来一一了解一下。 a、build types 你已经在你的项目中使用了不同的构建类型。检查您的应用程序的build.gradle文件。一个名为:defaultConfig,当你创建一个新的项目自动设置了两个build types (构建类型)debug和release。如图所示:

image.png

所以这里咱们是可以切换debug和release类型的。

2、Product Flavors(产品偏好)

对于每一个调试类型(debug/release),可以指定不同的内容,也就是product favours,例如,如果你希望你的程序有付费版本和免费版本,这个两个(免费、付费)代表你应用程序的product flavors。 所以回到构建变量,这里我们生成4个构建变量: a、freeDebug b、paidDebug c、freeRelease d、paidRelease

例子

现在我们看看如果实现product flavors。 首先你需要一个product flavors在你的项目的build.gradle文件里面。

app-gradle-and-product-flavors.png

如果“同步工程与gradle文件”,

sync-project.png

那么你就会看到新的 build variants(构建变体)。

all-build-variants.png

在这里你可以添加特定于每个变体的属性。 例如,如果你希望能在同一个设备上安装应用程序的两种版本(免费、付费),或者你想在应用商店发布他们2个,那么你需要做的第一件事情就是来区分他们的包名。为此,你需要使用applicationId属性。

productFlavors {
  free{
       applicationId "antoniocappiello.com.buildvariantsexample.free"
  }
  paid{
       applicationId "antoniocappiello.com.buildvariantsexample.paid"
  }
}

Sync/Rebuild项目,以便使更改生效。 现在,你可以选择freeDebug和paidDebug在构建变量面板和设备上运行他们。 之后,你就会在设备上看到应用程序的两种变体,但你仍无法辨认他们,因为缺少了相关属性设置。

apps.png

一个快速的发放来区分是什么呢?就是改变启动图标。创建新的src目录,我们要区分product favours的名称,例如“免费”,这个新的目录也创建了"res/drawable"。而内绘制了一个新的图标,在这个例子中我们使用了默认的启动印有文字的“自由”。

launcher-free.png

通过重建,并再次运行这两个变体,你将会看到设备上有2个不同的应用程序。

launcher-2.png

在这里,你可以设置更多的样式属性,例如“主题”、“部分文本的颜色”

更改颜色.png

更换文本.png

通过再次运行freeDebug变体和paidDebug变体,你就可以清楚的看到他们之间的区别。

对比.png

除了这些审美的变化,你可能还希望有不同的功能,以适于每种变体。一个简单的方法来实现这一目标是通过将在运行时被读取的product flavors配置中定义的变量。例如用EXTRA_FEATURE变量做如下补充,你可以在你的应用程序中使用if-else来做简单的判断。

productFlavors {
  free{
         applicationId "antoniocappiello.com.buildvariantsexample.free"
         buildConfigField 'boolean', 'EXTRA_FEATURES', "false"
      }
   paid{
         applicationId "antoniocappiello.com.buildvariantsexample.paid"
         buildConfigField 'boolean', 'EXTRA_FEATURES', "true"
      }
}

public class MainActivity extends AppCompatActivity {
        private Toast basicToast;
        private Toast coolToast;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
        basicToast = Toast.makeText(this, "This is just a free app",Toast.LENGTH_SHORT);
        coolToast = Toast.makeText(this, "This is the paid app", Toast.LENGTH_SHORT); 
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener(){
              @Override
              public void onClick(View view) {
                  if(BuildConfig.EXTRA_FEATURES) {
                          executeCoolMethod();
             }else {
                  executeBasicMethod();
             }
          }
      });
   }
 
        private void executeBasicMethod() {
              basicToast.show();
        }
 
        private void executeCoolMethod() {
              coolToast.show();
        }
}

screen-shot-2015-10-21-at-23-48-34.png

当然你的代码应该还会需要其他类型变量,如“字符串”,比如“BaseUrl”

android {
...
defaultConfig {
...
}
 
productFlavors {
    free {
          applicationId "yourpackagename.free"
          buildConfigField 'boolean', 'EXTRA_FEATURES', "false"
          buildConfigField 'String', 'BaseUrl', '"www.baidu.com"';
     }
    paid {
          applicationId "yourpackagename.paid"
          buildConfigField 'boolean', 'EXTRA_FEATURES', "true"
          buildConfigField 'String', 'BaseUrl', '"www.google.com"';
    }
  }
}

product flavors 有更多的属性,这通常是结合defaultConfig的。你可能已经看到上面的gradle文件里面的元素了,当你创建一个新的项目时,这里是自动创建的。 当你在productFlavors使用这些属性时,他们将自动覆盖相同属性的值defaultConfig元素。 你已经看到了applicationId属性,它实际上市属于defaultConfig的元素,但在上面的例子中,我们已经在我们的productFlavors覆盖它。 如果你有兴趣了解更多的有关可用属性的defaultConfig,那么你可以在这里阅读官方文档: https://developer.android.com/studio/build/index.html .

总结到目前为止,你所学到的现在可以:

  • 添加productFlavor配置您的gradle这个文件;
  • 覆盖现有的构建属性,如的applicationID
  • 像添加字符串和布尔自定义属性;
  • 安装在一个设备上相同的应用程序的两个不同的构建变体;
  • 自动改变的行为和你的应用程序从该是建立根据变种的外观和感觉。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Sorrower的专栏

界面无小事(六):来做个好看得侧拉菜单!

932
来自专栏LeoXu的博客

[翻译]Android教程-保存数据-保存键值对

http://developer.android.com/training/basics/data-storage/index.html

571
来自专栏项勇

笔记89 | Canbus升级程序指南

为方便客户升级,我们定了将升级文件拷至U盘根目录,插到机器USB接口,点击我们的升级程序就可以进行升级

662
来自专栏代码散人

Android Lifecycle框架介绍

Lifecycle 是属于 Android Architecture Components 的一个组件, 而Android Architecture Compo...

411
来自专栏向治洪

Android 进程回收之LowMemoryKiller原理篇

在前面的文章Android进程保活一文中,对于LowMemoryKiller的概念做了简单的提及。LowMemoryKiller简称低内存杀死机制。简单来说,L...

3557
来自专栏青蛙要fly的专栏

项目需求讨论-APP中提交信息及编辑信息界面及功能

好久好久没写文章了,这次我们来讨论下一些具有填写很多资料的界面,或者详情编辑界面等如何做起来更方便。 (PS:我写的可能不好,希望大家不好喷,哈哈,可以留言)

862
来自专栏玩转全栈

flutter接入现有的app详细介绍

接入的方式,我是参考的官方的介绍文档,我这里尝试的是android的接入方式,还算比较顺利。

2893
来自专栏Android干货

Android项目实战(二十八):Zxing二维码实现及优化

3116
来自专栏北京马哥教育

史上最全 Python 爬虫抓取的技巧总结

学用python也有3个多月了,用得最多的还是各类爬虫脚本:写过抓代理本机验证的脚本,写过在discuz论坛中自动登录自动发贴的脚本,写过自动收邮件的脚本,写过...

2985
来自专栏非著名程序员

一种新的 HeaderView + RecyclerView 实现方式

在 GitHub 开源了一种新的 Header View + RecyclerView 实现方式,使用 CoordinatorLayout 把 header 抽...

1876

扫码关注云+社区