APP环境分离的实现:ANDROID篇
2018-03-21 18:43
411 查看
概念解析
本文的实现方案是基于Gradle的,因此,有几个概念需要先了解清楚。applicationId
没有Gradle之前,我们都知道,包名是Android程序的唯一标识,通过在AndroidManifest.xml文件中定义package属性。同时,这个包名也是引用资源的路径名,即R资源文件的包名。引入Gradle之后,就多了一个applicationId的概念。官方解释是:applicationId是程序的唯一标识,而package则用来引用R类以及解析相关的activity/service注册操作。因此,可以设置多个不同的applicationId,对应多个不同版本的apk,而package则保持一致。新建的项目默认applicationId和package是一样的。Product Flavors
通过Product Flavors可以创建不同的产品渠道版本,网上流行的多渠道打包方案大部分都是通过添加多个渠道的Flavors来实现的。Flavors一般设置的属性如下图,当然,实际上不只是这些,例如manifestPlaceholders就不在此设置界面里。默认有defaultConfig这个Flavors。![](http://keeganlee.me/Architecture/_image/20160329/18-38-04.jpg)
Build Types
Build Types则是构建类型。默认提供debug和release两种类型,如下图所示。主要提供是否可调试、是否混淆等构建打包时的相关配置。![](http://keeganlee.me/Architecture/_image/20160329/16-00-40.jpg)
Build Variants
Product Flavors和Build Types的组合形成了多个Build Variant,例如,如果有两个Product Flavors版本:productFlavors { free { ... } enterprise { ... } }而Build Types也有两种类型:
buildTypes { debug { ... } release { ... } }那么,组合出来的Build Variant就有四个版本了:freeDebug
freeRelease
enterpriseDebug
enterpriseRelease
环境分离实现
相关概念都了解清楚了,那么,环境分离具体如何实现呢?其实,实现方案不止一个,这里,我提供两个方案,一个可以使用Product Flavors实现,一个可以使用Build Types来实现。方案一
Product Flavors用来定义产品渠道,假如我们有两个环境:测试环境和生产环境。那么,定义两个Flavors分别对应测试环境和生产环境,并且applicationId不同,可以如下定义:productFlavors { beta { applicationId 'com.domain.productname.beta' } production { applicationId 'com.domain.productname' } }这样,测试环境和生产环境实际上等于是已经分开的两个app了,已经可以在同一个设备里同时安装测试版本和生产版本了。但这样是不够的,两个app将会一模一样,很难区分。因此,我们也要修改两个环境版本的应用名称,同时还要使用不同的应用图标。怎么做呢?在app模块,src目录下,新建一个与main目录同级的beta目录,beta目录的结构如下图:
![](http://keeganlee.me/Architecture/_image/20160329/16-17-55.jpg)
新建的beta目录对应于productFlavors的beta版本,beta版本目录下的图片资源ic_launcher.png对应于beta版本的应用图标,这要与main目录的ic_launcher.png保持一致的位置和名称,只是图片不同。而beta版本的strings.xml则只需要包含一个属性,如下:
<resources> <string name="app_name">appNameBeta</string> </resources>至此,当运行beta版的Build Variant时,则会看到beta版的应用图标和应用名称也与生产版的不同了。这里要说明一下原理。首先,productFlavors定义的每个渠道是会继承自defaultConfig的,就是说上面定义的beta和production都继承了defaultConfig。然后,productFlavors每个渠道里自定义的属性会覆盖defaultConfig相应的属性,beta和production定义了applicationId,则会覆盖了defaultConfig的applicationId。这里,因为production自定义的applicationId和defaultConfig的applicationId是一样的,所以其实也可以取消applicationId的自定义。而对于源代码部分,当运行beta版的Build Variant时,默认会引用main目录的资源文件,而beta目录下的资源会覆盖main目录相应位置的资源,例如上面beta目录下的mipmap目录的ic_launcher.png就会覆盖main目录下相应位置的ic_launcher.png;同样的,beta下的strings.xml里定义的app_name就会覆盖main目录下的strings.xml定义的app_name。但对于java类则不同,beta里定义的java类并不会覆盖main目录里相应的java类。事实上,两个目录的java类只能有一份,否则会出现类重复的错误。如果beta和production版本需要有同个页面不同的实现,例如有一个Activity需要不同的实现,那么,只能新建一个production版本目录,然后该Activity类在beta和production都有一份拷贝,代码实现可以不同,但main目录下则不能有该Activity类。
方案二
前面就已经说过,Build Types默认提供了debug和release两种类型,其实也可以分别对应于测试和生产环境。在Build Types的设置界面中,可以看到有个Application Id Suffix的设置选择,这个可以用来设置applicationId的后缀。这个后缀是相对于Flavors来说的,比如我们定义了一个如下的productFlavors:productFlavors { free { applicationId 'com.domain.productname.free' } enterprise { applicationId 'com.domain.productname' } }而debug类型的Application Id Suffix设置为“.debug”,那么对应的freeDebug版本的applicationId就是'com.domain.productname.free.debug',而enterpriseDebug版本的applicationId则是'com.domain.productname.debug'。对于本方案二来说,并不需要再定义额外的productFlavors,使用默认的即可。那么,debug类型的Application Id Suffix可设置为".debug",release类型则无需设置。接着,src目录下新建一个debug目录,和方案一的beta目录完全一样,只是目录名称不同。另外,如果两个版本需要有同个页面不同的实现,那么,也和方案一一样,需要新建个release目录,和production目录一样。
写在最后
如果只是从环境分离来说的话,我更倾向于方案二,因为系统默认就提供了debug和release两个版本,而对应的Build Variant也只有两个。如果采用方案一,那么将产生四个Build Variant,这显得有点多余。相关文章推荐
- Android 利用Gradle实现app的环境分离
- Android实现APP环境分离(利用Gradle)
- Android 利用Gradle实现app的环境分离
- Android 利用Gradle实现app的环境分离
- Android 利用Gradle实现app的环境分离
- Android 利用Gradle实现app的环境分离
- 【Android】检测是否处于Wifi环境,利用WebView实现浏览器app
- App环境分离的实现:iOS篇,正式版 与 beta版本的快速分离
- 三种方案实现Android应用的环境分离
- 【Android】检测是否处于Wifi环境,利用WebView实现浏览器app
- AndroidManifest占位符(实现根据正式还是测试环境设置不同的app名称)
- Android 开发环境配置--实现第一个app “hello world!”
- android 首次使用app时的使用教程的功能的实现
- Android app“版本更新”功能的前后端实现
- 重写android.app.ProgressDialog实现自定义进度条弹出框布局
- Android 通过 XMPP 实现聊天功能,App Engine Assisted Group Chat (开源)
- Android快速搭建模拟器环境另类方法(绕过了官网SDK Manager下载)和 实现静默安装与卸载应用
- Android中实现Launcher功能之二 ----- 添加窗口小部件以及AppWidget的创建详解
- 解读android源码APP之一 ---- 环境设置
- Android关机AppWidget的实现