01Android之Gradle以及Groovy语法

Android之Gradle以及Groovy语法

一.groovy语法

1.注释符
与java一致
2.打印 , 字符串,单引号和双引号没有区别

groovy可以省略最后面的分号,以及()

println "Hello from the shebang line"
3.定义变量和全局遍历
    def i = 10  //相当于java 本地变量
    println i
    def s = 'hello world'
    println s



ext {    //相当于static
    gradleName = "gradleName"
}
task hello() {
    println "${gradleName}"
}
4.定义集合List集合和map集合

List集合

    def list = ['a','b'] //定义集合
    list << 'c' //添加元素
    println list[2] //打印
    println list.get(2) //等价

Map集合

    def map =['key1':'value1','key2':'value2'] //定义map集合
    map.key3 = 'value3' //如果存在赋值,如果不存在,添加
    map.key1 = 'v1' //赋值
    println map['key1'] //打印
    println map.get('key1') //等价
5.闭包

闭包原理:闭包实际是一个代码块,函数当作参数使用,也就是将函数当作对象来看,也有属性

函数参数用Closure使用

函数不带有参数

def b1 = {
    println 'hello'
}
def method1(Closure fun) {
    fun()
}
method1(b1)

带有参数的闭包

def b2 = { //只有一个参数时,可以用it代替,如同kotlin
    println it
}
def b3 = {
    a,c -> println "${a} ${c}"
}
def method2(Closure fun) {
    fun('a','b')
}
method2(b3)

也可以使用简写,匿名函数

method2 {
    c,d ->
        println "${c}${d}"
}
6.Task任务
task gradleWrapp(type:Wrapper) {
    gradleVersion = '2.0'
    println 'xxx'
}
7任务的拆分与聚合
8 switch
println "------------------switch--------------------"
def x = "a";
def result;
switch (x.class) { //这个相当于
    case "a":
        result = "我是 a"
        break
    case 'b':
        result = "我是 b"
        break
    case [4, 5, 6, 'c']://列表
        result = "我是个数组"
        break
    case 10..50://范围
        result = "我是10到50的数"
        break
    case Integer:
        result = "我是Integer类型"
        break
    case BigDecimal:
        result = "我是BigDecimal类型"
        break
    case String:
        result = "我是String类型"
        break
    default:
        result = "default"
        break

}
9 List for循环
def sum1=0;
task gradleWrapp() {
    for (int i in 1..5) {
        println i
    }

    for (i in [1,3,5,32,4,2,6,9,5,45,1]){
        sum1+=i;
    }
    println sum1//1
}
10 map循环
def sum2=0;
task gradleWrapp() {

    for (i in ['a':1,"b":2,"c":"ha"]){
        sum2+=i.value
    }
    println sum2//3ha
}
11.数据结构
def range=1..10;

task rangeWrap() {
    println range[0]//1
    println range.contains(10)//true
    println range.contains(11)//false
    println range.from//1
    println range.to//10
}
12 List遍历
    def list = ['a', 'b'] //定义集合
    list << 'c' //添加元素
    println list[2] //打印
    println list.get(2) //等价

    list.each {
        println it
    }
13.Map遍历
   def map = ['key1': 'value1', 'key2': 'value2'] //定义map集合
    map.key3 = 'value3' //如果存在赋值,如果不存在,添加
    map.key1 = 'v1' //赋值	   
	map.each {
        println it.value  //获取value值
    }

key和value都打印

   def map = ['key1': 'value1', 'key2': 'value2'] //定义map集合
    map.key3 = 'value3' //如果存在赋值,如果不存在,添加
    map.key1 = 'v1' //赋值	     
map.each {
      key,value->println "${key}${value}"
    }
14 String操作符 find
    String str = "love and 2 to be 1 love all 8 happiness"
    println str.find {
        String s -> s.isNumber()
    }   //2
println str.any {
    s -> s.isNumber()
}
/**
 * 要全部满足才返回true
 */
println str.every {
    s -> s.isNumber()
}

15定义内部类
/**
 * 定义了一个内部类
 */
class Person{
    def static classClouser={
        println "scriptClouser  this:"+this
        println "scriptClouser  owner:"+owner
        println "scriptClouser  delegate:"+delegate
    }
    def static say(){
        def classClouser={
            println "methodScriptClouser  this:"+this
            println "methodScriptClouser  owner:"+owner
            println "methodScriptClouser  delegate:"+delegate
        }
        classClouser.call()
    }
}
16创建一个对象
class Student{
    String name;
    def pretty ={
        "My name is ${name}"
    }
    String toString(){
        pretty.call()
    }
}
class Teacher{
    String name
}

def stu = new Student(name:"Student")
def tea = new Teacher(name: 'Teacher')
println stu.toString()//My name is Student
17委托
stu.pretty.delegate=tea
//修改委托策略(DELEGATE_FIRST,DELEGATE_ONLY......)
stu.pretty.resolveStrategy=Closure.DELEGATE_FIRST//有限寻找tea,找不到再找stu
println stu.toString()//My name is Teacher
18面向对象

1.创建接口

/**
 * 接口中不允许定义非public的方法
 */
interface Action {
    void eat()

    void drink()

    void play()
}

2.创建抽象类

/**
 * 类似于interface ,但是trait可以进行方法的实现(类似java中的abstract)
 */
trait DefaultAction {
    abstract void eat();
    void play1(){
        println 'DefaultAction'
    }
}

3.对象

def p2 = new Persion2(name: 'android', age: 26)
println p2.name

/**
 * 1.groovy中默认都是public类型
 */
class Persion2 implements Action, DefaultAction {
    String name
    Integer age

    def increaseAge(Integer years) {
        this.age = years
    }

    @Override
    void eat() {

    }

    @Override
    void drink() {

    }

    @Override
    void play() {

    }

    /**
     * 一个方法找不到时,调用它代替
     * @param name
     * @param args
     * @return
     */
    def invokeMethod(String name, Object args) {
        return "name=>${name},args=>${args}"
    }

    def methodMissing(String name, Object args){
        return "the method ${name} is missing"
    }
}
19json操作
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import objectorention.Persion

def list=[new Persion(name: 'huangxiaoguo1',age: 25),
          new Persion(name: 'huangxiaoguo2',age: 26),
          new Persion(name: 'huangxiaoguo3',age: 27),
          new Persion(name: 'huangxiaoguo4',age: 28)]
/**
 * 将对象转换为json
 */
println JsonOutput.toJson(list)

/**
 * 打印格式化的json串
 */
def json = JsonOutput.toJson(list)
println JsonOutput.prettyPrint(json)


/**
 * 将json串转换为实体对象
 */
def jsonSlpuer=new JsonSlurper()
def parse = jsonSlpuer.parseText(json)
println parse.toString()

println "--------------------------------groovy中进行网络请求---------------------------------------------"
def getNetworkData(String url){
    //发送http请求
    def connection=new URL(url).openConnection()
    connection.setRequestMethod('GET')
    connection.connect()
    def request = connection.content.text
    //将json转换为实体对象
    def jsonSlpuer=new JsonSlurper()
    return jsonSlpuer.parseText(request)
}
def reponse = getNetworkData("http://******/wsd/dictionary/getMapByDicflag?dicFlag=wsd.grade.type")
println reponse.data
20File操作
/**
 * 文件操作
 */
def file = new File('../../groovy.iml')
file.eachLine { line ->
    println line
}

println "-----------------------------------------------------------------------------------------"

def text = file.getText()
println text


println "-----------------------------------------------------------------------------------------"

def lines = file.readLines()
println lines


println "-----------------------------------------------------------------------------------------"
/**
 * 读取文件部分内容
 */
def reader = file.withReader { reader ->
    char[] buffer = new char[100]
    reader.read(buffer)
    return buffer
}

println reader


println "-----------------------------------------------------------------------------------------"

/**
 * 边读边写
 * @param sourcePath
 * @param desPath
 * @return
 */
def copy(String sourcePath, String desPath) {
    try {
        //创建目标文件
        def desFile = new File(desPath)
        if (!desFile.exists()) {
            desFile.createNewFile()
        }
        //copy
        new File(sourcePath).withReader { reade ->
            def lines = reade.readLines()
            desFile.withWriter { writer ->
                lines.each { line ->
                    writer.append(line + "\r\n")
                }

            }

        }
        return true
    } catch (Exception e) {
        e.printStackTrace()
    }
    return false
}

def result = copy("../../groovy.iml", "../../groovy2.iml")
println result


println "-----------------------------------------------------------------------------------------"



/**
 * 对象的读写
 */

def person = new Person(name: "huangxiaoguo",age: 18)

def saveObject(Object obj, String path) {
    try {
        //创建文件
        def desFile = new File(path)
        if (!desFile.exists()) {
            desFile.createNewFile()
        }
        desFile.withObjectOutputStream { out ->
            out.writeObject(obj)
        }
        return true
    } catch (Exception e) {
        e.printStackTrace()
    }
    return false
}

def readObject(String path) {
    def obj = null
    try {
        //创建文件
        def file = new File(path)
        if (file == null || !file.exists()) {
            return
        }
        //从文件中读取对象
        file.withObjectInputStream { input ->
            obj = input.readObject()
        }
    } catch (Exception e) {
        e.printStackTrace()
    }
    return obj

}

println saveObject(person,"../../person.txt")
def personr = (Person)readObject("../../person.txt")
println "name:${personr.name},age:${personr.age}"
21.注意一种操作,闭包自执行
/**
 * 闭包调用
 */
task hello2 {
    doLast {
        println "helloxxxxxx"
    }
}

//这种也会直接调用,省略了()
task getServer {
    println getSERVER2('release')
    println getSERVER2('debug')
}

二、Android中gradle解答

//表示先从maven {url} 中下载,如果有,则下载,没有,在google()中查找下载,链式关系   
repositories {
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
1.了解Android中build.gradle文件
buildscript {
    repositories {
    //依赖支持jcenter仓库获取
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
//当前的project的所有子模块,即settings.gradle中所有项目
subprojects{
    //共有配置
}
//当前project中所有项目均
allprojects {
    repositories {
        jcenter()
    }
}
//clean 任务可以帮助我们删除编译生成的build目录
task clean(type: Delete) {
    delete rootProject.buildDir
}
2.常见配置
//插件声明,这个也可以自定义
apply plugin: 'com.android.application'

//基本的android 配置
android {
    compileSdkVersion 23         //编译的sdk版本,debug
    buildToolsVersion "23.0.3"   //编译工具的版本
     //android的默认配置信息
    defaultConfig {
        //报名信息,可以没有,若没有会默认从manifest.xml中读取包名
        applicationId "com.hfcai.liferecord"   
        minSdkVersion 19
        targetSdkVersion 23   //正是版本,release
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
    //发布版
        release {
        //dex分包属性
            minifyEnabled false
            //混淆设置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        //测试版
       debug{

       //配置信息
       }
    }

    //apk签名配置
    signingConfigs {
        //测试版本
        release {
            //签名文件路径
            storeFile file('../keystore/personal.jks')
            //签名文件的密码
            storePassword 'personal'
            //用户名
            keyAlias 'personal'
            //用户名的密码
            keyPassword 'personal'
        }
    }

    //修改生成的apk名字
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            //定义无类型属性
            def oldFile = output.outputFile
           if (variant.buildType.name.equals('release')) {
                def releaseApkName = 'test.apk'
                output.outputFile = new File(oldFile.parent, releaseApkName)
            }
            if (variant.buildType.name.equals('debug')) {

            }
            output.assemble.doLast {
            //文件拷贝操作
                copy {
                    from output.outputFile.getAbsolutePath()
                    into('../Personal/out/apks/')
                }
            }
        }
    }
}

//android 的依赖管理配置
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:design:23.4.0'
    //Ivy依赖
    compile(name: 'AudienceNetwork', ext: 'aar')
}
3.解决debug版本与release版本网络地址配置问题

1.第一步,本地生成两个Properties文件(realse和debug),用于保存网络地址

为什么选取Properties文件而不是File文件,了解Properties特性,适合做配置文件,获取 =后面的值

debug

SERVER2 = "https://www.youku.com"

realse

SERVER2 = "https://www.baidu.com"

2.根据debug和release来分别获取网络地址

/**
 * 获取服务地址
 * @param str
 * @return
 */
def getSERVER2(String str) {
    def SERVER2
    Properties properties = new Properties()
    def proFile = file("src/main/filters/" + str + "/config.properties")
    if (proFile.canRead()) {
        try {
            InputStream is = new FileInputStream(proFile)
            properties.load(is)
            if (properties != null) {
                SERVER2 = properties['SERVER2']
            }
            is.close()
        } catch (Exception e) {
            e.printStackTrace()
        }
    }
    return SERVER2
}

3.需要将网络的参数,写道BuildConfig中,那么如何写进去了,通过buildConfigField配置参数

buildTypes: 编译时,确定是哪个版本debug,release或者更多


  buildTypes {
        debug {
            //第一个参数时传声明类型对象,第二个参数需要传名字,第三个参数就是属性的值
            buildConfigField 'String', 'SERVER2', getSERVER2('debug')
        }

        release {
            buildConfigField 'String', 'SERVER2', getSERVER2('release')
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

java中调用

    private void postServer() {
        String server = BuildConfig.SERVER2;
        Log.d("MainActivityxxx", server);
    }
4.多渠道打包并重新给apk命名

给apk添加,年月日时分秒以及版本文件名,方便测试去测试以及上架

1.添加flavorDimensions “versionCode”

    defaultConfig {
        applicationId "com.uih.gradledemo"
        minSdkVersion 28
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        flavorDimensions "versionCode"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

2.添加多渠道打包

    productFlavors {
        google {
            buildConfigField 'String', 'PLAT_FORM', "\"google\""
            manifestPlaceholders = [
                    SDKChannel: "google",
                    app_name  : "@string/app_name"
            ]
        }
        baidu {
            buildConfigField 'String', 'PLAT_FORM', "\"baidu\""
            manifestPlaceholders = [
                    SDKChannel: "baidu",
                    app_name  : "@string/app_name"
            ]
        }
        xiaomi {
            buildConfigField 'String', 'PLAT_FORM', "\"xiaomi\""
            manifestPlaceholders = [
                    UMENG_CHANNEL_VALUE: "xiaomi",
                    app_name  : "@string/app_name"
            ]
        }
    }

3.给apk重新命名

    android.applicationVariants.all { variant ->
        variant.outputs.all {
            println "SDK_${variant.flavorName}_${variant.buildType.name}_V${variant.versionName}_${buildTime()}.apk"
            //在这里修改apk文件名,引号内的字符串都可以随便定义
            outputFileName = "SDK_${variant.flavorName}_${variant.buildType.name}_V${variant.versionName}_${buildTime()}.apk"
        }
    }

   /**
 * 时间
 * @return
 */
def buildTime() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMddHHmmss')
    return formattedDate
}

说明:

  • {variant.flavorName}:渠道名称;

  • {variant.buildType.name}:release或debug包;

  • {variant.versionName}:版本名称; 等价于defaultConfig.versionName

  • {buildTime()}:当前时间;

5.自动签名

1.添加flavorDimensions

    defaultConfig {
        applicationId "com.uih.gradledemo"
        minSdkVersion 28
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        flavorDimensions "versionCode"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

2.buildType中确定使用签名 signingConfig signingConfigs.release

    buildTypes {
        debug {
            //第一个参数时传声明类型对象,第二个参数需要传名字,第三个参数就是属性的值
            buildConfigField 'String', 'SERVER2', getSERVER2('debug')
        }

        release {
            buildConfigField 'String', 'SERVER2', getSERVER2('release')
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
6.如何统计下载量
7.安全打包

我们的应用发布的时候需要使用一个keyStroe签名文件和签名密码,对于一个app来说,这个就是app的身份证,如果别人拿到了这些资料就可以重新打包应用,为了安全,我们应该把线上包的签名和密码与代码分开来保存。现在的一般做法就是把这些资源写在配置文件,再通过脚本来修改打包。

我们一般都使用这两个文件来保存密码,使用的方式有点不同。

第一种方式,在gradle.properties文件,直接在文件内定义变量即可

signname=key0
signPassword=123456

——————注意:key0和123456不要加双引号,否则在gradle.properties中,会当作是“key0”,

    //签名
    signingConfigs{
        release{
            storeFile file("E:\\TestJks\\test.jks")
            storePassword signPassword.toString()
            keyAlias signname.toString()
            keyPassword signPassword.toString()
        }
    }

整体代码

build.gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.1"
    defaultConfig {
        applicationId "com.uih.gradledemo"
        minSdkVersion 28
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        flavorDimensions "versionCode"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    //签名
    signingConfigs {
        release {
            storeFile file("E:\\TestJks\\test.jks")
            storePassword signPassword
            keyAlias signname
            keyPassword signPassword
        }
    }

    buildTypes {
        debug {
            //第一个参数时传声明类型对象,第二个参数需要传名字,第三个参数就是属性的值
            buildConfigField 'String', 'SERVER2', getSERVER2('debug')
        }

        release {
            buildConfigField 'String', 'SERVER2', getSERVER2('release')
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

    productFlavors {
        google {
            buildConfigField 'String', 'PLAT_FORM', "\"google\""
            manifestPlaceholders = [
                    UMENG_CHANNEL_VALUE: "google",
                    app_name           : "@string/app_name"
            ]
        }
        baidu {
            buildConfigField 'String', 'PLAT_FORM', "\"baidu\""
            manifestPlaceholders = [
                    UMENG_CHANNEL_VALUE: "baidu",
                    app_name           : "@string/app_name"
            ]
        }
        xiaomi {
            buildConfigField 'String', 'PLAT_FORM', "\"xiaomi\""
            manifestPlaceholders = [
                    UMENG_CHANNEL_VALUE: "xiaomi",
                    app_name           : "@string/app_name"
            ]
        }
    }

    android.applicationVariants.all { variant ->
        variant.outputs.all {
            println "SDK_${variant.flavorName}_${variant.buildType.name}_V${variant.versionName}_${buildTime()}.apk"
            //在这里修改apk文件名,引号内的字符串都可以随便定义
            outputFileName = "SDK_${variant.flavorName}_${variant.buildType.name}_V${variant.versionName}_${buildTime()}.apk"
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

task getServer {
    println getSERVER2('release')
    println getSERVER2('debug')
}

/**
 * 获取服务地址
 * @param str
 * @return
 */
def getSERVER2(String str) {
    def SERVER2
    Properties properties = new Properties()
    def proFile = file("src/main/filters/" + str + "/config.properties")
    if (proFile.canRead()) {
        try {
            InputStream is = new FileInputStream(proFile)
            properties.load(is)
            if (properties != null) {
                SERVER2 = properties['SERVER2']
            }
            is.close()
        } catch (Exception e) {
            e.printStackTrace()
        }
    }
    return SERVER2
}


/**
 * 时间
 * @return
 */
def buildTime() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMddHHmmss')
    return formattedDate
}

gradle.properties


signname=key0
signPassword=123456

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.uih.gradledemo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL_VALUE}" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

参考:https://blog.csdn.net/seemygoandroid?t=1

————————Gradle从入门到精通

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值