Android Studio 如何通过gradle实现同一套代码的开发不同特性的apk

本文介绍如何利用Gradle的ProductFlavor和SourceSets功能,在一个工程中开发不同特性的APK,如免费版与付费版,并实现各自不同的进度条样式、应用名称和图标。

如何通过Gradle实现一套代码开发不同特性的APK

Android tools团队于去年底最终发布了Android Studio1.0正式版及gradle plugin for android 1.0正式版,然后业余时间就研究了一下Gradle,前段时间也在公司内部做了一个相关分享,感觉gradle带来的最大便利就是通过 Product Flavor实现在一个工程中开发不同特性的apk,以及更方便的依赖管理,下面通过一个小demo来演示这些:
这个demo对应两个版本免费版及收费版。主要区别在于免费版中使用的是普通的loading圈,收费版中使用的是google风格的progressbar,最终效果如下:

仔细观察上面的视频,你会发现这两个应用除了progressbar的样式不一样之外,它们对应的app-name,app-icon也不同,而且我将它们同时安装到了一台设备上,这就说明它们的包名也不一样。而这些差异我可以通过ProductFlavor及Source sets轻松实现。

首先,介绍一下Productflavor,它是gradle plugin for android中的一个dsl type通过它你可以定义不同的app 变种,这里定义了两种 free 及 pay 。通过Productflavor你可以配置此flavor对应的包名,签名信息,版本名, 版本号等,具体可配置项可以到这里查看,如果你对Productflavor不了解可以到这里查看.下面是我的完整的build.gradle 文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    signingConfigs {
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
    }
    defaultConfig {
        applicationId "me.ghui.gradledemo"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            zipAlignEnabled false
        }
    }
    productFlavors {
        pay {
            applicationId "me.ghui.gradledemo.pay"
        }
        free {}
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.2'
    compile 'com.jpardogo.googleprogressbar:library:+'
    compile 'com.mcxiaoke.volley:library:1.0.+'
    compile 'com.jakewharton:butterknife:6.1.0'
}

我对pay flavor中的包名做了修改,free中没有做单独设置它会使用defaultconfig中定义的包名,这就解释了为什么我可以同时将这两个apk装到手机上。
那么如何实现pay , free 对应不同的特性呢,这里要引入另外一个概念—— “SourceSets”可以到这里了解,每个flavor都可以对应一个Sourceset,你可以在与src/main同级的目录下新建另外两个目录pay,free这里面可以放各自特性相关的代码,然后这些代码会与main下面的代码按照一定的规则进行合并,最终组成当前variant对应的完整代码。main,pay,free就是3个Sourceset 如下图:
这里写图片描述

你最终能编译出的apk的数量是由productflavor与BuildType决定的,虽然我这里没有定义Buildtype但gradle默认提供了两种buildType —— debug,release,所以,一共可以编译出4种apk,你可以到Android Studio 的BuildVariants面板中查看如下图:
这里写图片描述

实际上在你上图中的面板中切换variant时,Android视图下对应的代码是会发生变化的,这里显示出的代码就是你当前variant所拣取的代码,可以看到这里我选择编译paydebug上面的代码就由main+pay下面的代码组成了

在pay下面的ImgViewer中我使用了googleprogressbar而在free下的ImgViewer中我使用了普通的Progressbar,代码如下:

    GoogleProgressBar mProgressBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_img_viewer);
        mProgressBar = (GoogleProgressBar) findViewById(R.id.google_progress);
        mProgressBar.setIndeterminateDrawable(getRandomProgressDrawable());
        onLoadImg();
    }

当然了pay与free下面对应的Imgviewer的布局文件也是不同的在各自的下面都有一个activity_img_viewer.xml pay下面是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context="me.ghui.gradledemo.ImgViewer">
    <ImageView
            android:id="@+id/networkImageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:src="@drawable/waitting"
            android:layout_centerHorizontal="true" />
    <com.jpardogo.android.googleprogressbar.library.GoogleProgressBar
            android:id="@+id/google_progress"
            android:layout_centerInParent="true"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center"
            />
</RelativeLayout>

free下面就是普通的progressbar,这里就不再贴了。 至于为什么app-name与app-icon不同那是因为我在pay ,free下面都各自添加了不同的app-name 与app-icon,在编译对应variant时gradle会去做选取。实际上buildtype也可以对应自己的sourceset,也可以有自己的代码。

上面说到了合并规则,下面总结一下:

图片、音频、 XML 类型的 Drawable 等资源文件,将会进行文件级的覆盖 字符串、颜色值、整型等资源以及 AndroidManifest.xml ,将会进行元素级的覆盖 代码资源,同一个类, buildTypes 、 productFlavors 、 main 中只能存在一次,否则会有类重复的错误 覆盖等级为:buildTypes > productFlavors > main

如果你还有不懂可以到这里将代码clone下来自己跑一下就明白了。

最后,说一下在gradle中新的依赖管理方式:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.2'
    compile 'com.jpardogo.googleprogressbar:library:+'
    compile 'com.mcxiaoke.volley:library:1.0.+'
    compile 'com.jakewharton:butterknife:6.1.0'
}

上面我分别依赖了support包,googleprogressbar开源库,volley,butterknife,我只需添加以上几行compile命令,gradle 就会去jcenter仓库帮我完成依赖的下载、添加到classpath等一系统操作,而且这些依赖会在gradld第一次编译时缓存到~/.gradle/caches下面,以后再编译就直接去引用了,而且还有最重要的一点,通过这种方式你的工程与依赖就完全分开了,这些依赖也不会再混入到你的git仓库中了,它们之间的耦合性也降到了最低,以后如果不再需要某个依赖可以直接删除对应的compile即可

原文地址:(http://ghui.me/blog/20150310/create-several-variants-of-an-app-in-gradle/

登录后台:/admin 管理员及密码都为:admin 2008.8.15 1.修正采集数据时图片出错 2.修改相关动漫的图片 3.修下相关链接的错误 4.增加生成SiteMap地图功能 2008.7.23 1.修正后台不能删除文件错误 2.修改动态播放页错位 3.修下相关链接的错误 2008.7.22 1.增加集数链接标签:{videourlnum} 2.增加当前播放集数标签:{maxz_nv} 3.增加总集数(自动获取最多集数的地址库):{maxz_num} 4.增加相关影片集{maxz_related} 5.增加下载模块 6.增加上下集数标签,让用户播放更方便 7.增加顶踩模块,用户体验 8.优化生成HTML的速度 9.增加专题模块(暂没开放) 10.增加无限重分类(暂没开放) 2008.7.3 1.增加三重分类 2.增加可以生成全部集码生成播放HTML页面 3.增加可显示更新到第几集,两组地址库自动显示最新集数 幻影动漫网视频系统CMS1.0正式版标签及安装使用说明文档 核心是马克斯CMS1.0正式稳定版所有兼容原Max原所有的标签的使用 幻影动漫网视频系统主要更新功能如下: 1、增加影片数量统计函数。 2、改进侧边栏及首页列表第一数据是否显示图片的函数。 3、加入AJAX留言插件。 4、加入AJAX评论插件,后台可设置是否开启,后台可分别按IP,留言者,影片名显示留言,并可以批量删除,留言和评论插件后台均有相关参数设置。 5、改进点播列表集数过多则自动限制在一定范围。 6、增加数据批量替换功能。 7、增加分类合并功能。 8、后台增加HTML状态判断,没有生成的自动选中,可直接批量生成。 9、后台增加人气显示,可以分别按人气,ID,时间排序,并显示当前影片评论数量,多来源数据将显示多个来源。 10、增加DZ编辑器,添加影片介绍更得心应手。 11、改进播放器选项为下拉式,并标有详细来源提示,更贴近新手。 12、改进后台登录模块,防止他人用COOKIES欺骗登录后台,为了绝对安全,建议还是改名。 13、重新增加播放前广告。 14、广告管理增加JS转换工具,凡是JS被编辑时下面均显示转换工具。 15、增加后台添加数据时重复数据检测。 16、不选播放器可以直接添加跳转地址,例如填KU6的。 幻影动漫网视频系统CMS1.0-1.1正式版标签及安装使用说明文档 1.分类列表标签 {maxz_loop:itemloopvTypeid} 自由排版区 {/maxz_loop} 参数 vTypeid:为数字类型,值为0时显示所有一级分类,其它值为指定某个一级分类的ID 自由排版区可用的变量 {zt_typename}一级分类名称 {zt_typeid}一级分类ID {zt_en}一级分类英文名称 {zt_typename_2}二级分类名称 {zt_typeid_2}二级分类ID {zt_en_2}二级分类英文名称 示例: {maxz_loop:itemloop0} <li> {/maxz_loop} 2.友情链接列表标签 {maxz_loop:linklooplinktype} 自由排版区 {/maxz_loop} 参数 Linktype:为数字类型,值为0时显示文字链接,值为1时显示图片链接 自由排版区可用的变量 {link_title}站点名称 {link_url}链接网址 {link_pic}链接图片 {link_content}站点简介 示例: {maxz_loop:linkloop1} </li><li> {/maxz_loop} 3.关键字列表标签 {maxz_loop:keyloop} 自由排版区 {/maxz_loop} 参数:暂无 自由排版区可用的变量: {keywords}关键词 示例: {maxz_loop:keyloop} {/maxz_loop} 4.视频调用标签 {maxz_loop:videoloopvOrder,vTypeid,vNum,vLen,vLen1,vLen2,vRecommendID,vTime} 自由排版区 {/maxz_loop} 参数 vOrder:视频列表排序方式,数字类型,值为0按照时间排序,为1按照推荐排序,为2按照点击量排序,为3按照顶过量排序,为2按照踩量排序,为2按照ID排序 vTypeid:视频列表所在的分类ID,数字类型,值为-1表示当前分类,为0表示全部分类,其它为指定某个分类ID vNum:视频列表数量,数字类型,值为0时表示取出所有,其他值表示指定数量 vLen:每条视频的标题字符长度,数字类型 vLen1:每条视频的演员字符长度,数字类型 vLen2:每条信息的内容简介字符长度,数字类型 vRecommendID:视频的推荐种类,数字类型,-2为全部视频,-1为全部推
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值