服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - 浅谈Gradle 常用配置总结

浅谈Gradle 常用配置总结

2022-08-01 12:01叶应是叶 Android

这篇文章主要介绍了浅谈Gradle 常用配置总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

这里分享下我在日常开发中对 gradle 的常用配置规则

一、版本号配置

当项目逐渐演进的过程中,主工程依赖的 module 可能会越来越多,此时就需要统一配置各个 module 的编译参数了

在工程的根目录下新建一个 gradle 文件,命名为 config.gradle ,在此文件中统一声明工程的编译属性和依赖库的版本号

浅谈Gradle 常用配置总结

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ext {
  compilesdkversion = 28
  minsdkversion = 15
  targetsdkversion = 28
  versioncode = 1
  versionname = '1.0'
 
  dependencies = [
      appcompatv7   : 'com.android.support:appcompat-v7:28.0.0-rc02',
      constraintlayout: 'com.android.support.constraint:constraint-layout:1.1.3',
      junit      : 'junit:junit:4.12',
      testrunner   : 'com.android.support.test:runner:1.0.2',
      espressocore  : 'com.android.support.test.espresso:espresso-core:3.0.2'
  ]
 
}

默认情况下, app modulebuild.gradle 文件的默认配置如下所示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apply plugin: 'com.android.application'
 
android {
  compilesdkversion 28
  defaultconfig {
    applicationid "leavesc.hello.gradlesamples"
    minsdkversion 15
    targetsdkversion 28
    versioncode 1
    versionname "1.0"
    testinstrumentationrunner "android.support.test.runner.androidjunitrunner"
  }
  buildtypes {
    release {
      minifyenabled false
      proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}
 
dependencies {
  implementation filetree(dir: 'libs', include: ['*.jar'])
  implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
  implementation 'com.android.support.constraint:constraint-layout:1.1.3'
  testimplementation 'junit:junit:4.12'
  androidtestimplementation 'com.android.support.test:runner:1.0.2'
  androidtestimplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

这里将其改为引用 config.gradle 文件的形式

首先,需要在根目录下的 build.gradle 文件中应用 config.gradle 文件,这样在 module 配置文件中才引用得到当中的属性值

浅谈Gradle 常用配置总结

此时就可以修改应用版本号以及依赖库的声明方式了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apply plugin: 'com.android.application'
 
def globalconfiguration = rootproject.ext
def presentationdependencies = globalconfiguration.dependencies
 
android {
  compilesdkversion globalconfiguration["compilesdkversion"]
  defaultconfig {
    applicationid "leavesc.hello.gradlesamples"
    minsdkversion globalconfiguration["minsdkversion"]
    targetsdkversion globalconfiguration["targetsdkversion"]
    versioncode globalconfiguration["versioncode"]
    versionname globalconfiguration["versionname"]
    testinstrumentationrunner "android.support.test.runner.androidjunitrunner"
  }
 
  buildtypes {
    release {
      minifyenabled false
      proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}
 
dependencies {
  implementation filetree(include: ['*.jar'], dir: 'libs')
  implementation presentationdependencies.appcompatv7
  implementation presentationdependencies.constraintlayout
  testimplementation presentationdependencies.junit
  androidtestimplementation presentationdependencies.testrunner
  androidtestimplementation presentationdependencies.espressocore
}

这样,即使以后工程中包含多个 module ,只要配置的属性都是来自于 config.gradle 文件,就可以做到统一修改编译属性与依赖库版本了

二、签名属性配置

通常,应用的签名类型会分为 releasedebug 两类,并分别使用不同的签名文件

为了安全考虑以及实现自动化打包,可以通过 gradle 来声明签名配置,包括签名文件路径、签名别名、签名密码等

local.properties 文件中声明签名文件路径以及签名密码

?
1
2
3
4
5
sdk.dir=c\:\\software\\sdk
key.keystorepath=..\\doc\\key.jks
key.keyalias=leavesc
key.keypassword=987654321
key.storepassword=123456789

根据配置可知,签名文件是放在工程的 doc 文件夹内

浅谈Gradle 常用配置总结

通过代码获取到签名的各个配置项

?
1
2
3
4
5
6
7
properties properties = new properties()
properties.load(project.rootproject.file('local.properties').newdatainputstream())
def keystorepath_ = properties.getproperty("key.keystorepath")
def storepassword_ = properties.getproperty("key.storepassword")
def keyalias_ = properties.getproperty("key.keyalias")
def keypassword_ = properties.getproperty("key.keypassword")
def storefile_ = file(keystorepath_)

配置不同的签名属性以及 build 类型

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
signingconfigs {
   release {
     storefile storefile_
     storepassword storepassword_
     keyalias keyalias_
     keypassword keypassword_
     v1signingenabled true
     v2signingenabled true
   }
   debug {
     storefile storefile_
     storepassword storepassword_
     keyalias keyalias_
     keypassword keypassword_
     v1signingenabled true
     v2signingenabled true
   }
 }
 
 buildtypes {
   debug {
     minifyenabled false
     proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
     signingconfig signingconfigs.debug
   }
   release {
     minifyenabled true
     proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro'
     signingconfig signingconfigs.release
   }
 }

此处,我配置了两种不同的 buildtypedebugrelease ,并对应不同的签名文件

以后只要选定不同的 build variant ,即可打包具体签名的 apk 文件

浅谈Gradle 常用配置总结

local.properties 文件可以保存到服务器来实现远程打包,从而保证了隐私安全

三、多渠道打包

有时候,为了方便进行精准营销,会有生成不同渠道包的要求,此时就需要在同个应用上打上不同的渠道id(channelid),这可以通过 productflavors 来实现

先在 androidmanifest.xml 文件中配置占位符, appkey 即对应各个渠道的 id 值

?
1
2
3
<meta-data
     android:name="app_key"
     android:value="${appkey}" />

gradle.properties 文件中声明需要的 channelid 以及对应的 applicationid ,在此文件中声明的属性可以直接在 build.gradle 中直接获取到

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#默认配置
defaultapplicationid=leavesc.hello.gradlesamples
##各个渠道的配置
#应用宝
yingyongbaochannelid="yingyongbao"
yingyongbaoapplicationid=leavesc.hello.gradlesamples.yingyongbao
yingyongbaoappkey=appkey_yingyongbao
#豌豆荚
wandoujiachannelid="wandoujia"
wandoujiaapplicationid=leavesc.hello.gradlesamples.wandoujia
wandoujiaappkey=appkey_wandoujia
#小米
xiaomichannelid="xiaomi"
xiaomiapplicationid=leavesc.hello.gradlesamples.xiaomi
xiaomiappkey=appkey_xiaomi

productflavors 可以理解为是对同个产品的不同“风味要求”,可以根据配置项生成特定风味的产品(app)

例如,此处就为不同渠道设定了不同的 applicationid

buildconfigfield 属性则用于在 buildconfig.java 文件中生成特定类型的字段,此处就生成了一个类型为 string ,名为 channelid 的字段,用于方便在应用运行过程中判断当前应用的渠道类型

manifestplaceholders 就是用于替换 androidmanifest.xml 文件中的指定占位符了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
productflavors {
   yingyongbao {
     applicationid yingyongbaoapplicationid
     buildconfigfield "string", "channelid", yingyongbaochannelid
     manifestplaceholders = [appkey: yingyongbaoappkey]
   }
   wandoujia {
     applicationid wandoujiaapplicationid
     buildconfigfield "string", "channelid", wandoujiachannelid
     manifestplaceholders = [appkey: wandoujiaappkey]
   }
   xiaomi {
     applicationid xiaomiapplicationid
     buildconfigfield "string", "channelid", xiaomichannelid
     manifestplaceholders = [appkey: xiaomiappkey]
   }
 }

浅谈Gradle 常用配置总结

在主布局文件中展示当前应用的各项属性值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@override
 protected void oncreate(bundle savedinstancestate) {
   super.oncreate(savedinstancestate);
   setcontentview(r.layout.activity_main);
   stringbuilder sb = new stringbuilder();
   sb.append("applicationid: ");
   sb.append(getapplicationinfo().packagename);
   sb.append("\n");
   sb.append("applicationname: ");
   sb.append(getstring(getapplicationinfo().labelres));
   sb.append("\n");
   sb.append("channelid: ");
   sb.append(buildconfig.channelid);
   sb.append("\n");
   try {
     applicationinfo appinfo = getpackagemanager().getapplicationinfo(getpackagename(), packagemanager.get_meta_data);
     string appkey = appinfo.metadata.getstring("app_key");
     sb.append("appkey: ");
     sb.append(appkey);
   } catch (packagemanager.namenotfoundexception e) {
     e.printstacktrace();
   }
   textview tv_appinfo = findviewbyid(r.id.tv_appinfo);
   tv_appinfo.settext(sb);
   imageview iv_log = findviewbyid(r.id.iv_log);
   iv_log.setimageresource(getapplicationinfo().icon);
 }

浅谈Gradle 常用配置总结

四、打包时指定 apk 名字

为了方便标识各个测试包的版本已经打包时间,可以通过 gradle 来指定生成的 apk 文件的命名规则

例如,以下配置就根据 buildtype、flavorname编译时间 来命名 apk 文件

?
1
2
3
4
5
6
7
8
applicationvariants.all { variant ->
    def buildtype = variant.buildtype.name
    def flavorname = variant.flavorname
    def createtime = new date().format("yyyy-mm-dd_hh_mm_ss", timezone.gettimezone("gmt+08:00"))
    variant.outputs.all {
      outputfilename = flavorname + "_" + buildtype + "_v" + defaultconfig.versionname + "_" + createtime + ".apk"
    }
  }

浅谈Gradle 常用配置总结

五、生成属性字段与资源文件值

上边讲过, buildconfigfield 属性可用于在 buildconfig.java 文件中生成特定类型的字段,此处可以利用其来记录应用的编译时间

此外,也可以利用 resvalue 来生成一个 id 引用类型的 string 字符串

首先,声明两个方法,分别用于获取当前时间以及当前电脑的用户信息

?
1
2
3
4
5
6
7
static def buildtime() {
  return new date().format("yyyy-mm-dd hh:mm:ss")
}
 
static def hostname() {
  return system.getproperty("user.name") + "@" + inetaddress.localhost.hostname
}
?
1
2
3
4
5
6
7
8
9
10
11
defaultconfig {
    applicationid defaultapplicationid
    minsdkversion globalconfiguration["minsdkversion"]
    targetsdkversion globalconfiguration["targetsdkversion"]
    versioncode globalconfiguration["versioncode"]
    versionname globalconfiguration["versionname"]
    testinstrumentationrunner "android.support.test.runner.androidjunitrunner"
    flavordimensions '1'
    resvalue "string", "build_host", hostname()
    buildconfigfield "string", "build_time", "\"" + buildtime() + "\""
  }

用代码来获取这两个属性值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    stringbuilder sb = new stringbuilder();
    sb.append("applicationid: ");
    sb.append(getapplicationinfo().packagename);
    sb.append("\n");
    sb.append("applicationname: ");
    sb.append(getstring(getapplicationinfo().labelres));
    sb.append("\n");
    sb.append("channelid: ");
    sb.append(buildconfig.channelid);
    sb.append("\n");
    sb.append("buildtime: ");
    sb.append(buildconfig.build_time);
    sb.append("\n");
    sb.append("builduser: ");
    sb.append(getstring(r.string.build_host));
    sb.append("\n");
    try {
      applicationinfo appinfo = getpackagemanager().getapplicationinfo(getpackagename(), packagemanager.get_meta_data);
      string appkey = appinfo.metadata.getstring("app_key");
      sb.append("appkey: ");
      sb.append(appkey);
    } catch (packagemanager.namenotfoundexception e) {
      e.printstacktrace();
    }
    textview tv_appinfo = findviewbyid(r.id.tv_appinfo);
    tv_appinfo.settext(sb);
    imageview iv_log = findviewbyid(r.id.iv_log);
    iv_log.setimageresource(getapplicationinfo().icon);
  }

浅谈Gradle 常用配置总结

六、替换资源文件

在多渠道打包时,除了需要在应用中打上特定的标签外,也可能需要使之使用不同的资源文件,例如应用图标和应用名称

此时可以以各个 productflavor 的名称来命名相应的文件夹,并在其中放置相应的图标文件以及声明了应用名称的 string.xml 文件,这样在多渠道打包时,gradle 就会自动引用相应的资源文件

浅谈Gradle 常用配置总结

浅谈Gradle 常用配置总结

上述所有的示例代码可以在这里获取: gradlesamples

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/leavesC/p/9624397.html

延伸 · 阅读

精彩推荐