Buscar..


Introducción

Gradle es un sistema de compilación basado en JVM que permite a los desarrolladores escribir scripts de alto nivel que pueden utilizarse para automatizar el proceso de compilación y producción de aplicaciones. Es un sistema flexible basado en complementos, que le permite automatizar varios aspectos del proceso de construcción; incluyendo compilar y firmar un .jar , descargar y administrar dependencias externas, inyectar campos en el AndroidManifest o utilizar versiones específicas del SDK.

Sintaxis

  • apply plugin : los complementos que deberían usarse normalmente solo 'com.android.application' o 'com.android.library' .

  • android : la configuración principal de tu aplicación.

    • compileSdkVersion : la versión SDK de compilación
    • buildToolsVersion : la versión de herramientas de construcción
    • defaultConfig : la configuración predeterminada que puede ser sobrescrita por tipos y tipos de compilación
      • applicationId : el ID de la aplicación que usas, por ejemplo, en PlayStore, es casi igual al nombre de tu paquete
      • minSdkVersion : la versión mínima de SDK requerida
      • targetSdkVersion : la versión de SDK con la que compila (debe ser siempre la primera)
      • versionCode : el número de versión interna que debe ser mayor en cada actualización
      • versionName : el número de versión que el usuario puede ver en la página de detalles de la aplicación
    • buildTypes : ver en otro lugar (TODO)
  • dependencies : las dependencias locales o locales de su aplicación

    • compile una sola dependencia
    • testCompile : una dependencia para la unidad o pruebas de integración

Observaciones

Ver también

Gradle para Android - Documentación extendida:

Hay otra etiqueta donde puedes encontrar más temas y ejemplos sobre el uso de gradle en Android.
http://www.riptutorial.com/topic/2092

Un archivo build.gradle básico

Este es un ejemplo de un archivo build.gradle predeterminado en un módulo.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.3'

    signingConfigs {
        applicationName {
            keyAlias 'applicationName'
            keyPassword 'password'
            storeFile file('../key/applicationName.jks')
            storePassword 'keystorePassword'
        }
    }
    defaultConfig {
        applicationId 'com.company.applicationName'
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName '1.0'
        signingConfig signingConfigs.applicationName
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'

    testCompile 'junit:junit:4.12'
}

DSL (lenguaje específico de dominio)

Cada bloque en el archivo anterior se llama un DSL (lenguaje específico del dominio).


Complementos

La primera línea, apply plugin: 'com.android.application' , aplica el complemento de Android para Gradle a la compilación y hace que el bloque android {} esté disponible para declarar las opciones de compilación específicas de Android.

Para una aplicación de Android :

apply plugin: 'com.android.application'

Para una biblioteca de Android :

apply plugin: 'com.android.library'

Entendiendo los DSLs en el ejemplo anterior

La segunda parte, el bloque de android {...} , es el DSL Android que contiene información sobre su proyecto.

Por ejemplo, puede configurar el compileSdkVersion que especifica el nivel de la API de Android, que Gradle debe usar para compilar su aplicación.
El subbloque defaultConfig contiene los valores predeterminados para su manifiesto. Puede override con Sabores del producto .

Puedes encontrar más información en estos ejemplos:


Dependencias

El bloque de dependencies se define fuera del bloque de android {...} : Esto significa que no está definido por el complemento de Android, pero es Gradle estándar.
El bloque de dependencies especifica qué bibliotecas externas (normalmente las bibliotecas de Android, pero las bibliotecas de Java también son válidas) que desea incluir en su aplicación. Gradle descargará automáticamente estas dependencias por usted (si no hay una copia local disponible), solo necesita agregar líneas de compile similares cuando desee agregar otra biblioteca.

Veamos una de las líneas aquí presentes:

compile 'com.android.support:design:25.3.1'

Esta línea básicamente dice

agregar una dependencia de la biblioteca de diseño de soporte de Android a mi proyecto.

Gradle se asegurará de que la biblioteca esté descargada y presente para que pueda usarla en su aplicación, y su código también se incluirá en su aplicación.

Si está familiarizado con Maven, esta sintaxis es GroupId , dos puntos, ArtifactId , otros dos puntos, luego la versión de la dependencia que desea incluir, lo que le da un control total sobre las versiones.

Si bien es posible especificar versiones de artefactos usando el signo más (+), la mejor práctica es evitar hacerlo; puede llevar a problemas si la biblioteca se actualiza con cambios de última hora sin su conocimiento, lo que probablemente provocaría bloqueos en su aplicación.

Puedes agregar diferentes tipos de dependencias:

Se debe dedicar una atención particular a las dependencias planas .

Puede encontrar más detalles en este tema.

Nota sobre el -v7 en appcompat-v7

compile 'com.android.support:appcompat-v7:25.3.1'

Esto simplemente significa que esta biblioteca ( appcompat ) es compatible con la API de Android de nivel 7 y appcompat .

Nota sobre el junit: junit: 4.12

Esta es la dependencia de prueba para la prueba de unidad.


Especificando dependencias específicas para diferentes configuraciones de compilación

Puede especificar que una dependencia solo se use para una determinada configuración de compilación o puede definir diferentes dependencias para los tipos de compilación o las versiones del producto (por ejemplo, depuración, prueba o lanzamiento) utilizando debugCompile , testCompile o releaseCompile lugar de la compile habitual .

Esto es útil para mantener las dependencias relacionadas con la prueba y la depuración fuera de su versión de lanzamiento, lo que mantendrá su APK versión lo más delgado posible y ayudará a garantizar que no se pueda usar ninguna información de depuración para obtener información interna sobre su aplicación.


firmaConfig

La signingConfig permite configurar su Gradle para incluir información del keystore y garantizar que el APK creado con estas configuraciones esté firmado y listo para la versión de Play Store.

Aquí puedes encontrar un tema dedicado .

Nota : no se recomienda mantener las credenciales de firma dentro de su archivo de Gradle. Para eliminar las configuraciones de firma, basta con omitir la signingConfigs parte.
Puedes especificarlos de diferentes maneras:

Consulte este tema para obtener más detalles: Firmar APK sin exponer la contraseña del almacén de claves .


Puede encontrar más información sobre Gradle para Android en el tema dedicado de Gradle .

Definición de sabores de producto.

Los sabores del producto se definen en el archivo build.gradle dentro del bloque de android { ... } como se ve a continuación.

...
android {
    ...
    productFlavors {
        free {
            applicationId "com.example.app.free"
            versionName "1.0-free"
        }
        paid {
            applicationId "com.example.app.paid"
            versionName "1.0-paid"
        }
    }
}

Al hacer esto, ahora tenemos dos sabores de productos adicionales: free y de paid . Cada uno puede tener su propia configuración y atributos específicos. Por ejemplo, nuestros dos nuevos sabores tienen un applicationId y versionName separados de nuestro main sabor existente (disponible por defecto, por lo que no se muestra aquí).

Adición de dependencias específicas del sabor del producto.

Se pueden agregar dependencias para un sabor de producto específico, similar a cómo se pueden agregar para configuraciones de compilación específicas.

Para este ejemplo, suponga que ya hemos definido dos sabores de productos llamados free y de paid (más información sobre cómo definir sabores aquí ).
Luego podemos agregar la dependencia de AdMob para el sabor free , y la biblioteca de Picasso para el paid como:

android {
    ...

    productFlavors {
        free {
            applicationId "com.example.app.free"
            versionName "1.0-free"
        }
        paid {
            applicationId "com.example.app.paid"
            versionName "1.0-paid"
        }
    }
}

...
dependencies {
    ...
    // Add AdMob only for free flavor
    freeCompile 'com.android.support:appcompat-v7:23.1.1'
    freeCompile 'com.google.android.gms:play-services-ads:8.4.0'
    freeCompile 'com.android.support:support-v4:23.1.1'

    // Add picasso only for paid flavor
    paidCompile 'com.squareup.picasso:picasso:2.5.2'
} 
...

Añadiendo recursos específicos del sabor del producto.

Se pueden agregar recursos para un sabor de producto específico.

Para este ejemplo, suponga que ya hemos definido dos tipos de productos llamados free y de paid . Para agregar recursos específicos del sabor del producto, creamos carpetas de recursos adicionales junto con la carpeta main/res , a la que luego podemos agregar recursos como de costumbre. Para este ejemplo, definiremos una cadena, status , para cada sabor de producto:

/ src / main /res/values/strings.xml

<resources>
    <string name="status">Default</string>
</resources>

/ src / free /res/values/strings.xml

<resources>
    <string name="status">Free</string>
</resources>

/ src / paid /res/values/strings.xml

<resources>
    <string name="status">Paid</string>
</resources>

Las cadenas de status específicas del sabor del producto anularán el valor del status en el sabor main .

Definir y usar los campos de configuración de construcción

BuildConfigField

Gradle permite que buildConfigField líneas buildConfigField definan constantes. Estas constantes serán accesibles en tiempo de ejecución como campos estáticos de la clase BuildConfig . Esto se puede usar para crear sabores definiendo todos los campos dentro del bloque defaultConfig , y luego reemplazándolos para crear sabores individuales según sea necesario.

Este ejemplo define la fecha de compilación y marca la compilación para la producción en lugar de la prueba:

android {
    ...
    defaultConfig {
        ...
        // defining the build date
        buildConfigField "long", "BUILD_DATE", System.currentTimeMillis() + "L"
        // define whether this build is a production build
        buildConfigField "boolean", "IS_PRODUCTION", "false"
        // note that to define a string you need to escape it
        buildConfigField "String", "API_KEY", "\"my_api_key\""
    }

    productFlavors {
        prod {
            // override the productive flag for the flavor "prod"
            buildConfigField "boolean", "IS_PRODUCTION", "true"
            resValue 'string', 'app_name', 'My App Name'
        }
        dev {
            // inherit default fields
            resValue 'string', 'app_name', 'My App Name - Dev'
        }
    }
}

El <package_name> generado automáticamente. BuildConfig .java en la carpeta gen contiene los siguientes campos basados ​​en la directiva anterior:

public class BuildConfig {
    // ... other generated fields ...
    public static final long BUILD_DATE = 1469504547000L;
    public static final boolean IS_PRODUCTION = false;
    public static final String API_KEY = "my_api_key";
}

Los campos definidos ahora se pueden usar dentro de la aplicación en tiempo de ejecución accediendo a la clase BuildConfig generada:

public void example() {
    // format the build date
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    String buildDate = dateFormat.format(new Date(BuildConfig.BUILD_DATE));
    Log.d("build date", buildDate);
    
    // do something depending whether this is a productive build
    if (BuildConfig.IS_PRODUCTION) {
        connectToProductionApiEndpoint();
    } else {
        connectToStagingApiEndpoint();
    }
}

Valorar

El resValue en los productFlavors crea un valor de recursos. Puede ser cualquier tipo de recurso ( string , dimen , color , etc.). Esto es similar a definir un recurso en el archivo apropiado: por ejemplo, definir una cadena en un archivo strings.xml . La ventaja es que el definido en gradle se puede modificar en función de su productFlavor / buildVariant. Para acceder al valor, escriba el mismo código como si estuviera accediendo a una resolución desde el archivo de recursos:

getResources().getString(R.string.app_name)

Lo importante es que los recursos definidos de esta manera no pueden modificar los recursos existentes definidos en los archivos. Solo pueden crear nuevos valores de recursos.


Algunas bibliotecas (como la API de Android de Google Maps) requieren una clave API proporcionada en el manifiesto como una etiqueta de meta-data . Si se necesitan claves diferentes para la depuración y las compilaciones de producción, especifique un marcador de posición manifiesto completado por Gradle.

En su archivo AndroidManifest.xml :

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${MAPS_API_KEY}"/>

Y luego establezca el campo correspondiente en su archivo build.gradle :

android {
    defaultConfig {
        ...
        // Your development key
        manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
    }

    productFlavors {
        prod {
            // Your production key
            manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
        }
    }
}

El sistema de compilación de Android genera una serie de campos automáticamente y los coloca en BuildConfig.java . Estos campos son:

Campo Descripción
DEBUG un Boolean indica si la aplicación está en modo de depuración o lanzamiento
APPLICATION_ID una String contiene el ID de la aplicación (por ejemplo, com.example.app )
BUILD_TYPE una String contiene el tipo de compilación de la aplicación (generalmente debug o release )
FLAVOR una String contiene el sabor particular de la construcción
VERSION_CODE un int contiene el número de versión (compilación).
Esto es lo mismo que versionCode en build.gradle o versionCode en AndroidManifest.xml
VERSION_NAME una String contiene el nombre de la versión (compilación).
Este es el mismo como versionName en build.gradle o versionName en AndroidManifest.xml

Además de lo anterior, si ha definido múltiples dimensiones de sabor, entonces cada dimensión tendrá su propio valor. Por ejemplo, si tiene dos dimensiones de sabor para el color y el size , también tendrá las siguientes variables:

Campo Descripción
FLAVOR_color una String contiene el valor para el sabor 'color'.
FLAVOR_size una String contiene el valor para el sabor 'tamaño'.

Centralizando dependencias a través del archivo "dependencies.gradle"

Cuando se trabaja con proyectos de múltiples módulos, es útil centralizar las dependencias en una sola ubicación en lugar de tenerlos distribuidos en muchos archivos de compilación, especialmente para bibliotecas comunes como las bibliotecas de soporte de Android y las bibliotecas Firebase .

Una forma recomendada es separar los archivos de compilación de Gradle, con un build.gradle por módulo, así como uno en la raíz del proyecto y otro para las dependencias, por ejemplo:

root
  +- gradleScript/
  |     dependencies.gradle
  +- module1/
  |     build.gradle
  +- module2/
  |     build.gradle
  +- build.gradle

Entonces, todas sus dependencias se pueden ubicar en gradleScript/dependencies.gradle :

ext {
    // Version
    supportVersion = '24.1.0'

    // Support Libraries dependencies
    supportDependencies = [
            design:            "com.android.support:design:${supportVersion}",
            recyclerView:      "com.android.support:recyclerview-v7:${supportVersion}",
            cardView:          "com.android.support:cardview-v7:${supportVersion}",
            appCompat:         "com.android.support:appcompat-v7:${supportVersion}",
            supportAnnotation: "com.android.support:support-annotations:${supportVersion}",
    ]

    firebaseVersion = '9.2.0';

    firebaseDependencies = [
            core:         "com.google.firebase:firebase-core:${firebaseVersion}",
            database:     "com.google.firebase:firebase-database:${firebaseVersion}",
            storage:      "com.google.firebase:firebase-storage:${firebaseVersion}",
            crash:        "com.google.firebase:firebase-crash:${firebaseVersion}",
            auth:         "com.google.firebase:firebase-auth:${firebaseVersion}",
            messaging:    "com.google.firebase:firebase-messaging:${firebaseVersion}",
            remoteConfig: "com.google.firebase:firebase-config:${firebaseVersion}",
            invites:      "com.google.firebase:firebase-invites:${firebaseVersion}",
            adMod:        "com.google.firebase:firebase-ads:${firebaseVersion}",
            appIndexing:  "com.google.android.gms:play-services-appindexing:${firebaseVersion}",
    ];
}

Que luego se puede aplicar desde ese archivo en el archivo de nivel superior build.gradle así:

// Load dependencies
apply from: 'gradleScript/dependencies.gradle'

y en el module1/build.gradle como tal:

// Module build file
dependencies {
    // ...
    compile supportDependencies.appCompat
    compile supportDependencies.design
    compile firebaseDependencies.crash
}

Otro enfoque

Se puede lograr un enfoque menos detallado para centralizar las versiones de las dependencias de la biblioteca declarando el número de versión como una variable una vez, y usándolo en todas partes.

En el espacio de trabajo root build.gradle agregue esto:

ext.v = [
    supportVersion:'24.1.1',
]

Y en cada módulo que use la misma biblioteca agregue las bibliotecas necesarias

compile "com.android.support:support-v4:${v.supportVersion}"
compile "com.android.support:recyclerview-v7:${v.supportVersion}"
compile "com.android.support:design:${v.supportVersion}"
compile "com.android.support:support-annotations:${v.supportVersion}"

Estructura de directorio para recursos específicos de sabor

Diferentes tipos de compilaciones de aplicaciones pueden contener diferentes recursos. Para crear un recurso de sabor específico, cree un directorio con el nombre en minúsculas de su sabor en el directorio src y agregue sus recursos de la misma manera que lo haría normalmente.

Por ejemplo, si tuviera un Development sabor y quisiera proporcionar un ícono de src/development/res/drawable-mdpi distinto, crearía un directorio src/development/res/drawable-mdpi y dentro de ese directorio crearía un archivo ic_launcher.png con su ícono específico de desarrollo.

La estructura del directorio se verá así:

src/
  main/
    res/
      drawable-mdpi/
        ic_launcher.png  <-- the default launcher icon
  development/
    res/
      drawable-mdpi/
        ic_launcher.png  <-- the launcher icon used when the product flavor is 'Development'

(Por supuesto, en este caso, también crearías íconos para drawable-hdpi, drawable-xhdpi, etc. ).

¿Por qué hay dos archivos build.gradle en un proyecto de Android Studio?

<PROJECT_ROOT>\app\build.gradle es específico para el módulo de la aplicación .

<PROJECT_ROOT>\build.gradle es un "archivo de compilación de nivel superior" donde puede agregar opciones de configuración comunes a todos los subproyectos / módulos.

Si usa otro módulo en su proyecto, como biblioteca local tendrá otro archivo build.gradle : <PROJECT_ROOT>\module\build.gradle

En el archivo de nivel superior puede especificar propiedades comunes como el bloque de buildscript o algunas propiedades comunes.

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
       classpath 'com.android.tools.build:gradle:2.2.0'
       classpath 'com.google.gms:google-services:3.0.0'
    }
}

ext {
    compileSdkVersion = 23
    buildToolsVersion = "23.0.1"
}

En la app\build.gradle usted define solo las propiedades para el módulo:

apply plugin: 'com.android.application'


android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
}

dependencies {
    //.....
}

Ejecutando un script de shell desde gradle

Un script de shell es una forma muy versátil de ampliar su compilación a básicamente cualquier cosa que se pueda imaginar.

Como ejemplo, aquí hay un script simple para compilar archivos protobuf y agregar los archivos java de resultados al directorio de origen para una compilación adicional:

def compilePb() {
    exec {
        // NOTICE: gradle will fail if there's an error in the protoc file...
        executable "../pbScript.sh"
    }
}

project.afterEvaluate {
    compilePb()
}

El script de shell 'pbScript.sh' para este ejemplo, ubicado en la carpeta raíz del proyecto:

#!/usr/bin/env bash
pp=/home/myself/my/proto

/usr/local/bin/protoc -I=$pp \
 --java_out=./src/main/java \
  --proto_path=$pp \
 $pp/my.proto \
 --proto_path=$pp \
 $pp/my_other.proto

Depurando tus errores de Gradle

El siguiente es un extracto de Gradle: ¿Qué es un valor de salida distinto de cero y cómo puedo solucionarlo? , verlo para la discusión completa.

Digamos que está desarrollando una aplicación y obtiene un error de Gradle que parece que, en general, se verá así.

:module:someTask FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':module:someTask'.
> some message here...  finished with non-zero exit value X
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: Y.ZZ secs

Busca tu problema aquí en StackOverflow, y la gente dice que debes limpiar y reconstruir tu proyecto, o habilitar MultiDex , y cuando lo intentas, simplemente no está solucionando el problema.

Hay formas de obtener más información , pero la salida de Gradle en sí misma debería apuntar al error real en las pocas líneas sobre ese mensaje entre: module:someTask FAILED y el último :module:someOtherTask que pasó. Por lo tanto, si hace una pregunta sobre su error, edite sus preguntas para incluir más contexto al error.

Entonces, obtienes un "valor de salida distinto de cero". Bueno, ese número es un buen indicador de lo que debes tratar de arreglar. Aquí hay algunos que ocurren con más frecuencia.

  • 1 es solo un código de error general y el error es probable en la salida de Gradle
  • 2 parece estar relacionado con la superposición de dependencias o la configuración errónea del proyecto.
  • 3 parece ser por incluir demasiadas dependencias, o un problema de memoria.

Las soluciones generales para lo anterior (después de intentar limpiar y reconstruir el proyecto) son:

  • 1 - Abordar el error que se menciona. En general, este es un error en tiempo de compilación, lo que significa que parte del código de su proyecto no es válido. Esto incluye tanto XML como Java para un proyecto de Android.
  • 2 y 3 : muchas respuestas aquí le dicen que habilite multidex . Si bien puede solucionar el problema, es muy probable que sea una solución. Si no entiende por qué lo está utilizando (vea el enlace), probablemente no lo necesite. Las soluciones generales implican reducir su uso excesivo de las dependencias de la biblioteca (como todos los Servicios de Google Play, cuando solo necesita usar una biblioteca, como Mapas o Iniciar sesión, por ejemplo).

Especificar diferentes ID de aplicación para tipos de compilación y sabores de producto

Puede especificar diferentes ID de aplicación o nombres de paquetes para cada buildType o productFlavor utilizando el atributo de configuración applicationIdSuffix:

Ejemplo de sufijo del applicationId para cada buildType :

defaultConfig {
    applicationId "com.package.android"
    minSdkVersion 17
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}

buildTypes {
    release {
        debuggable false      
    }

    development {
        debuggable true
        applicationIdSuffix ".dev"
    }

    testing {
        debuggable true
        applicationIdSuffix ".qa"
    }
}

Nuestra applicationIds resultante sería ahora:

  • com.package.android para el release
  • com.package.android. dev para development
  • com.package.android. qa para la testing

Esto también se puede hacer para productFlavors :

productFlavors {
    free {
        applicationIdSuffix ".free"
    }
    paid {
        applicationIdSuffix ".paid"
    }
}

Las applicationIds resultantes serían:

  • com.package.android. Gratis para el sabor free
  • com.package.android. pagado por el sabor paid

Firmar APK sin exponer la contraseña del keystore

Puede definir la configuración de firma para firmar el apk en el archivo build.gradle usando estas propiedades:

  • storeFile : el archivo de almacén de claves
  • storePassword : la contraseña del almacén de claves
  • keyAlias : un nombre de alias de clave
  • keyPassword : una contraseña de alias de clave

En muchos casos, es posible que deba evitar este tipo de información en el archivo build.gradle .

Método A: configure la firma de liberación utilizando un archivo keystore.properties

Es posible configurar build.gradle su aplicación para que lea la información de configuración de firma de un archivo de propiedades como keystore.properties .

Configurar la firma de esta manera es beneficioso porque:

  • Su información de configuración de firma es independiente de su archivo build.gradle
  • No tiene que intervenir durante el proceso de firma para proporcionar contraseñas para su archivo de almacén de claves
  • Puede excluir fácilmente el archivo keystore.properties del control de versiones

Primero, cree un archivo llamado keystore.properties en la raíz de su proyecto con contenido como este (reemplazando los valores con los suyos):

storeFile=keystore.jks
storePassword=storePassword
keyAlias=keyAlias
keyPassword=keyPassword

Ahora, en el archivo build.gradle su aplicación, configure el bloque de signingConfigs configuración de la siguiente manera:

android {
...

    signingConfigs {
        release {
            def propsFile = rootProject.file('keystore.properties')
            if (propsFile.exists()) {
                def props = new Properties()
                props.load(new FileInputStream(propsFile))
                storeFile = file(props['storeFile'])
                storePassword = props['storePassword']
                keyAlias = props['keyAlias']
                keyPassword = props['keyPassword']
            }
        }
    }
}

Eso es todo lo que hay en ello, pero no olvide excluir tanto su archivo de almacén de claves como su archivo de keystore.properties del control de versiones .

Un par de cosas a anotar:

  • La ruta de storeFile especificada en el archivo keystore.properties debe ser relativa al archivo build.gradle su aplicación. Este ejemplo asume que el archivo de almacén de claves está en el mismo directorio que el archivo build.gradle la aplicación.
  • Este ejemplo tiene el archivo keystore.properties en la raíz del proyecto. Si lo coloca en otro lugar, asegúrese de cambiar el valor en rootProject.file('keystore.properties') a su ubicación, en relación con la raíz de su proyecto.

Método B: utilizando una variable de entorno

Lo mismo se puede lograr también sin un archivo de propiedades, lo que hace que la contraseña sea más difícil de encontrar:

android {

  signingConfigs {
    release {
        storeFile file('/your/keystore/location/key')
        keyAlias 'your_alias'
        String ps = System.getenv("ps")
        if (ps == null) {
             throw new GradleException('missing ps env variable')
        }
        keyPassword ps
        storePassword ps
    }
}

La variable de entorno "ps" puede ser global, pero un enfoque más seguro puede ser agregándolo a la shell de Android Studio solamente.
En Linux, esto se puede hacer editando la Desktop Entry Android Studio

Exec=sh -c "export ps=myPassword123 ; /path/to/studio.sh"

Puede encontrar más detalles en este tema .

Versiones de sus compilaciones a través del archivo "version.properties"

Puedes usar Gradle para incrementar automáticamente la versión de tu paquete cada vez que lo construyas. Para ello, cree un archivo version.properties en el mismo directorio que su build.gradle con el siguiente contenido:

VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1

(Cambiando los valores para mayor y menor como mejor le parezca). Luego, en tu build.gradle agrega el siguiente código a la sección de android :

// Read version information from local file and increment as appropriate
def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
  def Properties versionProps = new Properties()

  versionProps.load(new FileInputStream(versionPropsFile))

  def versionMajor = versionProps['VERSION_MAJOR'].toInteger()
  def versionMinor = versionProps['VERSION_MINOR'].toInteger()
  def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1

  // Update the build number in the local file
  versionProps['VERSION_BUILD'] = versionBuild.toString()
  versionProps.store(versionPropsFile.newWriter(), null)

  defaultConfig {
    versionCode versionBuild
    versionName "${versionMajor}.${versionMinor}." + String.format("%05d", versionBuild)
  }
}

Se puede acceder a la información en Java como una cadena BuildConfig.VERSION_NAME para completar {major}. { BuildConfig.VERSION_NAME }. { BuildConfig.VERSION_CODE } y como un entero BuildConfig.VERSION_CODE solo para el número de compilación.

Cambiar el nombre del apk de salida y agregar el nombre de la versión:

Este es el código para cambiar el nombre del archivo de la aplicación de salida (.apk). El nombre se puede configurar asignando un valor diferente a newName

android {

    applicationVariants.all { variant ->
        def newName = "ApkName";
        variant.outputs.each { output ->
            def apk = output.outputFile;

            newName += "-v" + defaultConfig.versionName;
            if (variant.buildType.name == "release") {
                newName += "-release.apk";
            } else {
                newName += ".apk";
            }
            if (!output.zipAlign) {
                newName = newName.replace(".apk", "-unaligned.apk");
            }

            output.outputFile = new File(apk.parentFile, newName);
            logger.info("INFO: Set outputFile to " 
                        + output.outputFile 
                        + " for [" + output.name + "]");
        }
    }
}

Deshabilite la compresión de imágenes para un tamaño de archivo APK más pequeño

Si está optimizando todas las imágenes manualmente, desactive APT Cruncher para un tamaño de archivo APK más pequeño.

android {
    
    aaptOptions {
        cruncherEnabled = false
    }
}

Habilitar Proguard usando gradle

Para habilitar las configuraciones de Proguard para su aplicación, necesita habilitarla en su archivo de nivel de módulo. minifyEnabled establecer el valor de minifyEnabled en true .

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

El código anterior aplicará sus configuraciones de Proguard contenidas en el SDK de Android predeterminado combinado con el archivo "proguard-rules.pro" en su módulo a su apk liberado.

Habilitar el soporte experimental del complemento NDK para Gradle y AndroidStudio

Habilite y configure el complemento experimental de Gradle para mejorar el soporte NDK de AndroidStudio. Comprueba que cumples los siguientes requisitos:

  • Gradle 2.10 (para este ejemplo)
  • Android NDK r10 o posterior
  • Android SDK con herramientas de compilación v19.0.0 o posterior

Configurar el archivo MyApp / build.gradle

Edite la línea dependencies.classpath en build.gradle desde, por ejemplo,

classpath 'com.android.tools.build:gradle:2.1.2'

a

classpath 'com.android.tools.build:gradle-experimental:0.7.2'

(v0.7.2 era la última versión en el momento de la redacción. Verifique la última versión usted mismo y adapte su línea en consecuencia)

El archivo build.gradle debería verse similar a esto:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle-experimental:0.7.2'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Configurar el archivo MyApp / app / build.gradle

Edite el archivo build.gradle para que se vea similar al siguiente ejemplo. Sus números de versión pueden parecer diferentes.

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion 19
        buildToolsVersion "24.0.1"

        defaultConfig {
            applicationId "com.example.mydomain.myapp"
            minSdkVersion.apiLevel 19
            targetSdkVersion.apiLevel 19
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file('proguard-android.txt'))
            }
        }
        ndk {
            moduleName "myLib"
            
            /* The following lines are examples of a some optional flags that 
               you may set to configure your build environment
            */ 
            cppFlags.add("-I${file("path/to/my/includes/dir")}".toString())
            cppFlags.add("-std=c++11")
            ldLibs.addAll(['log', 'm'])
            stl = "c++_static"
            abiFilters.add("armeabi-v7a")
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Sincronice y verifique que no haya errores en los archivos de Gradle antes de continuar.

Probar si el plugin está habilitado

Primero asegúrese de haber descargado el módulo NDK de Android. Luego cree una nueva aplicación en AndroidStudio y agregue lo siguiente al archivo ActivityMain:

public class MainActivity implements Activity {
    onCreate() {
        // Pregenerated code. Not important here
    }
    static {
        System.loadLibrary("myLib");
    }
    public static native String getString();
}

La parte getString() debe resaltarse en rojo diciendo que no se pudo encontrar la función JNI correspondiente. Mueva el mouse sobre la función de llamada hasta que aparezca una bombilla roja. Haga clic en la bombilla y seleccione create function JNI_... Esto debería generar un archivo myLib.c en el directorio myApp / app / src / main / jni con la llamada a la función JNI correcta. Debería verse similar a esto:

#include <jni.h>

JNIEXPORT jstring JNICALL 
Java_com_example_mydomain_myapp_MainActivity_getString(JNIEnv *env, jobject instance)     
{
    // TODO

    return (*env)->NewStringUTF(env, returnValue);
}

Si no se ve así, entonces el complemento no se ha configurado correctamente o el NDK no se ha descargado

Mostrar todas las tareas del proyecto Gradle

gradlew tasks -- show all tasks

 

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
extractDebugAnnotations - Extracts Android annotations for the debug variant into the archive file
extractReleaseAnnotations - Extracts Android annotations for the release variant into the archive file
jar - Assembles a jar archive containing the main classes.
mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'LeitnerBoxPro'.
components - Displays the components produced by root project 'LeitnerBoxPro'. [incubating]
dependencies - Displays all dependencies declared in root project 'LeitnerBoxPro'.
dependencyInsight - Displays the insight into a specific dependency in root project 'LeitnerBoxPro'.
help - Displays a help message.
model - Displays the configuration model of root project 'LeitnerBoxPro'. [incubating]
projects - Displays the sub-projects of root project 'LeitnerBoxPro'.
properties - Displays the properties of root project 'LeitnerBoxPro'.
tasks - Displays the tasks runnable from root project 'LeitnerBoxPro' (some of the displayed tasks may belong to subprojects)
.

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

Other tasks
-----------
assembleDefault
clean
jarDebugClasses
jarReleaseClasses
transformResourcesWithMergeJavaResForDebugUnitTest
transformResourcesWithMergeJavaResForReleaseUnitTest

Eliminar "no alineado" apk automáticamente

Si no necesita archivos apk generados automáticamente con sufijo unaligned (que probablemente no necesite), puede agregar el siguiente código al archivo build.gradle :

// delete unaligned files
android.applicationVariants.all { variant ->
  variant.assemble.doLast {
    variant.outputs.each { output ->
        println "aligned " + output.outputFile
        println "unaligned " + output.packageApplication.outputFile

        File unaligned = output.packageApplication.outputFile;
        File aligned = output.outputFile
        if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
            println "deleting " + unaligned.getName()
            unaligned.delete()
        }
    }
  }
}

Desde aqui

Ignorando la variante de construcción

Por algunas razones, es posible que desee ignorar las variantes de compilación. Por ejemplo: tiene un sabor de producto 'simulado' y lo usa solo para fines de depuración, como pruebas de unidad / instrumentación.

Ignoremos la variante mockRelease de nuestro proyecto. Abra el archivo build.gradle y escriba:

    // Remove mockRelease as it's not needed.
    android.variantFilter { variant ->
        if (variant.buildType.name.equals('release') && variant.getFlavors().get(0).name.equals('mock')) {
            variant.setIgnore(true);
        }
    }

Viendo arbol de dependencias

Usa las dependencias de la tarea. Dependiendo de cómo estén configurados los módulos, puede ser ./gradlew dependencies o ver las dependencias del uso de la aplicación del módulo ./gradlew :app:dependencies

El siguiente ejemplo del archivo build.gradle

dependencies {
    compile 'com.android.support:design:23.2.1'
    compile 'com.android.support:cardview-v7:23.1.1'

    compile 'com.google.android.gms:play-services:6.5.87'
}

Producirá el siguiente gráfico:

Parallel execution is an incubating feature.
:app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------
. . .
_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:design:23.2.1
|    +--- com.android.support:support-v4:23.2.1
|    |    \--- com.android.support:support-annotations:23.2.1
|    +--- com.android.support:appcompat-v7:23.2.1
|    |    +--- com.android.support:support-v4:23.2.1 (*)
|    |    +--- com.android.support:animated-vector-drawable:23.2.1
|    |    |    \--- com.android.support:support-vector-drawable:23.2.1
|    |    |         \--- com.android.support:support-v4:23.2.1 (*)
|    |    \--- com.android.support:support-vector-drawable:23.2.1 (*)
|    \--- com.android.support:recyclerview-v7:23.2.1
|         +--- com.android.support:support-v4:23.2.1 (*)
|         \--- com.android.support:support-annotations:23.2.1
+--- com.android.support:cardview-v7:23.1.1
\--- com.google.android.gms:play-services:6.5.87
     \--- com.android.support:support-v4:21.0.0 -> 23.2.1 (*)

. . .

Aquí puede ver que el proyecto incluye directamente com.android.support:design versión 23.2.1, que a su vez trae com.android.support:support-v4 con la versión 23.2.1. Sin embargo, com.google.android.gms:play-services sí mismo depende del mismo support-v4 pero con una versión anterior 21.0.0, que es un conflicto detectado por gradle.

(*) se utilizan cuando gradle se salta el subárbol porque esas dependencias ya estaban listadas anteriormente.

Use gradle.properties para central versionnumber / buildconfigurations

Puede definir la información de configuración central en

o hazlo con el archivo raíz gradle.properties

la estructura del proyecto

root
  +- module1/
  |     build.gradle
  +- module2/
  |     build.gradle
  +- build.gradle
  +- gradle.properties

configuración global para todos los submódulos en gradle.properties

# used for manifest
# todo increment for every release
appVersionCode=19
appVersionName=0.5.2.160726

# android tools settings
appCompileSdkVersion=23
appBuildToolsVersion=23.0.2

uso en un submódulo

apply plugin: 'com.android.application'
android {
    // appXXX are defined in gradle.properties
    compileSdkVersion = Integer.valueOf(appCompileSdkVersion)
    buildToolsVersion = appBuildToolsVersion

    defaultConfig {
        // appXXX are defined in gradle.properties
        versionCode = Long.valueOf(appVersionCode)
        versionName = appVersionName
    }
}

dependencies {
    ...
}

Nota: Si desea publicar su aplicación en la tienda de aplicaciones F-Droid, tiene que usar números mágicos en el archivo de gradle porque, de lo contrario, el robot f-droid no puede leer la versión actual para detectar / verificar los cambios de versión.

Mostrar información de firma

En algunas circunstancias (por ejemplo, la obtención de una clave API de Google) debe encontrar la huella digital del almacén de claves. Gradle tiene una tarea conveniente que muestra toda la información de firma, incluidas las huellas digitales del almacén de claves:

./gradlew signingReport

Esta es una salida de muestra:

:app:signingReport
Variant: release
Config: none
----------
Variant: debug
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugAndroidTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugUnitTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: releaseUnitTest
Config: none
----------

Definiendo tipos de compilación

Puede crear y configurar tipos de compilación en el archivo build.gradle nivel de build.gradle dentro del bloque android {} .

    android {
        ...
        defaultConfig {...}
    
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
    
            debug {
                applicationIdSuffix ".debug"
            }
        }
    }


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow