当前位置: 移动技术网 > IT编程>移动开发>Android > 浅谈Gradle 常用配置总结

浅谈Gradle 常用配置总结

2019年08月02日  | 移动技术网IT编程  | 我要评论

陈龙象,服务器代理ip,詹sir踩过界

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

一、版本号配置

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

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

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 文件的默认配置如下所示

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 配置文件中才引用得到当中的属性值

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

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 文件中声明签名文件路径以及签名密码

sdk.dir=c\:\\software\\sdk
key.keystorepath=..\\doc\\key.jks
key.keyalias=leavesc
key.keypassword=987654321
key.storepassword=123456789

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

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

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 类型

 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 文件

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

三、多渠道打包

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

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

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

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

#默认配置
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 文件中的指定占位符了

 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]
    }
  }

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

 @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);
  }

四、打包时指定 apk 名字

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

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

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"
    }
  }

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

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

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

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

static def buildtime() {
  return new date().format("yyyy-mm-dd hh:mm:ss")
}

static def hostname() {
  return system.getproperty("user.name") + "@" + inetaddress.localhost.hostname
}
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() + "\""
  }

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

@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);
  }

六、替换资源文件

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

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网