Adding release keys in the experimental Gradle plugin for Android - android

Hey I am having some issues adding a signing my release build variant. Currently I am using the experimental gradle 2.5 with the new android gradle plugin version 0.1.0.
build.gradle:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 15
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "com.testcom.test"
minSdkVersion.apiLevel = 14
targetSdkVersion.apiLevel = 14
versionCode = 1
versionName = "1.0"
}
compileOptions.with {
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
}
}
android.ndk {
...
}
android.signingConfigs {
signed {
keyAlias = "meow"
keyPassword = "**"
storeFile = file("meow-key.keystore")
storePassword = "**"
}
}
android.buildTypes {
release {
isMinifyEnabled = false
proguardFiles += file('proguard-rules.pro')
signingConfig = signingConfigs.signed
}
debug {
isDebuggable = true
isJniDebuggable = true
}
}
// You can modify the NDK configuration for each variant.
components.android {
binaries.afterEach { binary ->
binary.mergedNdkConfig.cppFlags.add(
"-DVARIANT=\"" + binary.name + "\"")
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
My root build.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.1.0'
}
}
allprojects {
repositories {
jcenter()
}
}
The error that I am getting when running ./gradlew assembleRelease is:
> Exception thrown while executing model rule: model.android.buildTypes > named(release)
> Attempt to read a write only view of model of type 'java.lang.Object' given to rule 'model.android.buildTypes'
Has anyone had a similar issue with the experimental gradle plugin? Help would be greatly appreciated. :)

This workaround works for me and does not require -Dorg.gradle.model.dsl=true
model {
def signConf
android.buildTypes {
release {
signingConfig = signConf
}
}
android.signingConfigs {
create("signed") {
keyAlias = "meow"
keyPassword = "**"
storeFile = file("meow-key.keystore")
storePassword = "**"
storeType = "jks"
signConf = it
}
}
}
However, it only works if you only have one signingConfig.

You should be able to add the release keys with a script like this:
model {
android.buildTypes {
release {
signingConfig = $("android.signingConfigs.signed")
}
}
android.signingConfigs {
create("signed") {
keyAlias = "meow"
keyPassword = "**"
storeFile = file("meow-key.keystore")
storePassword = "**"
storeType = "jks"
}
}
}
Currently it seems to be a bug in the plugin.
You need to specify -Dorg.gradle.model.dsl=true when you run your gradle command.
Also you should have an issue with proguard.
In this case you can use new File("path/to/proguard-rules.pro") instead of file('proguard-rules.pro')

The right way to do this with the latest version of the Android plugin (0.6.0-alpha3) is as follows:
android.signingConfigs {
create("release") {
storeFile = file("../keys.keystore")
storePassword = "st0r3pa$$"
keyAlias = "SecretKey"
keyPassword = "k3ypa$$"
}
}
android.buildTypes {
release {
signingConfig = $.android.signingConfigs.get("release")
}
}
In Gradle 2.9 which is used by this version of the plugin, the declared rules can depend on each other using a special syntax: $.<path-to-element>. The trick is to create the signing config as usual, then assign it to a field in a different rule using this syntax. Gradle will realize that the signing configuration is an input dependency and will let you access it.

Related

Gradle can't see product flavors. How can I add them?

When I try to add a flavor to my project, Gradle simply don't want to sync and even if I sync it I can't see the flavor in Build Variats. What can cause this problem? The project has a few modules, I need to add flavors to the app. My file:
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.24.4'
}
}
repositories {
maven { url 'https://maven.fabric.io/public' }
}
def keystorePropertiesFile = "${rootDir}${File.separator}keystore.properties" as File
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
dexOptions {
javaMaxHeapSize "4g"
}
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId ""
minSdkVersion 21
targetSdkVersion 25
versionCode 9999
versionName "17.2 (9999)"
}
productFlavors {
testFlavor {
applicationId "com.volodymyr.mobiletest"
}
}
def keystoreFilePath = "${System.properties['user.home']}${File.separator}${keystoreProperties['storeFile']}"
signingConfigs {
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreFilePath)
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
}
debug {
}
}
splits {
abi {
enable true
reset()
include 'armeabi-v7a', 'arm64-v8a'//, 'x86', 'x86_64'
universalApk true
}
}
lintOptions {
lintConfig file("lint.xml")
check "WrongConstant"
abortOnError true
}
}
tasks.whenTaskAdded { task ->
if(task.name.equals("assembleDebug")){
task.dependsOn(lint)
}
}
dependencies {
}
I deleted some info from here, like dependencies, id and so on just to show a structure.
Error:(15, 0) ProductFlavor names cannot start with 'test'
You should use another flavor name
The problem was in that that this gradle file is using only for CI. To change gradle config I needed to improve build file at settings.gradle.

Instant App crashes when attempting to load Google Maps

We are preparing to publish our instant app, however, we are experiencing a security exception when attempting to initialize Google Maps. Below is the error that is occurring. After multiple attempts to resolve the issue and countless google searches, we have yet to find a solution. This issue is not happening for the installed app. Any help would be appreciated.
06-20 11:10:57.263 13891-13891/com.myapp.example.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.example.debug, PID: 13891
java.lang.SecurityException: Failed to find provider com.google.android.gsf.gservices for user 0; expected to find a valid ContentProvider for this authority
The build.gradle file associated with the instant app:
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.22.2'
}
}
apply plugin: 'com.android.instantapp'
apply plugin: 'io.fabric'
repositories {
jcenter()
flatDir {
dirs '../libs'
}
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
}
android {
compileSdkVersion rootProject.compileSdk
buildToolsVersion rootProject.buildTools
def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()
defaultConfig {
minSdkVersion rootProject.minSdk
targetSdkVersion rootProject.compileSdk
}
signingConfigs {
flavor1Release {
storeFile file('../publish/flavor1-release.keystore')
storePassword System.getenv("FLAVOR_1_STORE_PASSWORD")
keyAlias "flavor1"
keyPassword System.getenv("FLAVOR_1_KEY_PASSWORD")
v2SigningEnabled true
}
flavor2Release {
storeFile file('../publish/flavor2-release.keystore')
storePassword System.getenv("FLAVOR_2_STORE_PASSWORD")
keyAlias "flavor2"
keyPassword System.getenv("FLAVOR_2_KEY_PASSWORD")
v2SigningEnabled true
}
debug {
storeFile file('../publish/debug.keystore')
}
}
flavorDimensions rootProject.flavorDimensions
productFlavors {
flavor1 {
applicationId rootProject.flavor1PackageName
versionCode rootProject.flavor1VersionCode
versionName rootProject.flavor1VersionName
dimension rootProject.flavorDimensions
}
flavor2 {
applicationId rootProject.flavor2PackageName
versionCode rootProject.flavor2VersionCode
versionName rootProject.flavor2VersionName
dimension rootProject.flavorDimensions
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
versionNameSuffix "-debug-${gitSha}"
signingConfig signingConfigs.debug
}
release {
productFlavors.flavor1.signingConfig signingConfigs.flavor1Release
productFlavors.flavor2.signingConfig signingConfigs.flavor2Release
}
}
}
dependencies {
implementation project(':features:base')
implementation project(':features:auth')
implementation project(':features:chat')
implementation project(':features:filter')
implementation project(':features:search')
implementation project(':features:message')
}
Edit:
Resolved after updating gms libraries to 11.0.2

Gradle, 'could not find property'

I've tried to look for similar questions, but
no luck.
I'm building my Gradle project from the command line,
and supply the passwords in the gradle release command line
using -P.
Here's my build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.3'
}
}
apply plugin: 'android'
android {
signingConfigs {
release {
storeFile file("C:/Android/Dev/keystore/dm.keystore")
keyAlias KEY_ALIAS
storePassword STORE_PASSWORD
keyPassword KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
compileSdkVersion 'android-13'
buildToolsVersion '22.0.1'
buildTypes {
release {
minifyEnabled false
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
}
When I try to do a clean, it gives me:
Could not find property 'KEY_ALIAS' on SigningConfig_Decorated{name=release, storeFile=C:\Android\dev\keystore\dm.keystore, storePassword=null, keyAlias=null, keyPassword=null, storeType=C:\Android\dev\keystore\dm.keystore}.
Someone said that the 'signingConfigs' should come before the
'buildTypes', and it does.
Is there any way that I can keep the 'signingConfigs'
in there, but maybe modified somehow, and not have it complain?
If I take 'signingConfigs' out, and add it before I do the release
it works.
Thanks!
try this
def key="default"
def storePass="default"
def keyPass="default"
if (project.hasProperty("KEY_ALIAS")) {
key = KEY_ALIAS
}
if (project.hasProperty("STORE_PASSWORD")) {
storePass = STORE_PASSWORD
}
if (project.hasProperty("KEY_PASSWORD")) {
keyPass = KEY_PASSWORD
}
signingConfigs {
release {
storeFile file("C:/Android/Dev/keystore/dm.keystore")
keyAlias key
storePassword storePass
keyPassword keyPass
}
}
i also recommend you to store your signing information in separate file

Gradle for Android, how to replace content on XML files for a given variant

I am quite new with Gradle and I haven't got much experience with Maven either.
I have a build script that creates different flavours and different versions (debug, preprod, release).
I have already changed values dynamically using buildConfig class, but now I need to the value DEBUG to ERROR in the producion version in both flavours src/main/res/xml/config.xml.
config.xml file:
<?xml version="1.0" encoding="utf-8"?>
<log level="DEBUG"/>
build.gradle file:
task wrapper(type: Wrapper) {
gradleVersion = '1.8'
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
android {
compileSdkVersion 18
buildToolsVersion "19.0.1"
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionName "1.0"
}
signingConfigs {
release {
storeFile file("keystore")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
preprod {
storeFile file("keystore")
storePassword "xxx"
keyAlias "xxx"
keyPassword "xxx"
}
}
buildTypes {
debug {
def variable_1 = 'xxx'
buildConfig "public static final String VARIABLE_1 = \"$variable_1\";";
}
preprod {
def variable_1 = 'yyy'
buildConfig "public static final String VARIABLE_1 = \"$variable_1\";";
}
release {
def variable_1 = 'zzz'
buildConfig "public static final String VARIABLE_1 = \"$variable_1\";";
signingConfig signingConfigs.releas
}
productFlavors {
one {
packageName "com.test.one"
}
two {
packageName "com.test.two"
}
}
android.sourceSets.one{
res {
srcDir 'one'
}
assets {
srcDir 'one/assets'
}
manifest {
srcFile "src/one/AndroidManifest.xml"
}
}
android.sourceSets.two {
res {
srcDir 'two'
}
assets {
srcDir 'two/assets'
}
manifest {
srcFile "src/two/AndroidManifest.xml"
}
}
}
}
dependencies {
compile files('libs/android-support-v4.jar')
}

Signing product flavors with gradle

I am tyring to migrate my projects to gradle. One of my projects has multiple product flavors and each one of them has to be signed with a different signingConfig in its release version. So this is what I tried so far:
buildscript {
...
}
apply plugin: 'android'
android {
compileSdkVersion 17
buildToolsVersion '17'
signingConfigs {
flavor1 {
storeFile file("keystore")
storePassword "secret"
keyAlias "aliasForFlavor1"
keyPassword "secretFlavor1"
}
flavor2 {
storeFile file("keystore")
storePassword "secret"
keyAlias "aliasForFlavor2"
keyPassword "secretFlavor2"
}
}
productFlavors {
flavor1 {
signingConfig signingConfigs.flavor1
}
flavor1 {
signingConfig signingConfigs.flavor2
}
}
}
dependencies {
...
}
When I run gradle build I get a groovy.lang.MissingFieldException and the following error message:
No such field: signingConfigs for class: com.android.build.gradle.internal.dsl.GroupableProductFlavorFactory
So I assume the productFlavors.* part of the Gradle script is not the right place to put code signing configurations.
You can declare signing config for each flavor in buildType. Here is my gradle file for release signing flavors with different keystores.
android {
signingConfigs {
configFirst {
keyAlias 'alias'
keyPassword 'password'
storeFile file('first.keystore')
storePassword 'password'
}
configSecond {
keyAlias 'alias'
keyPassword 'password'
storeFile file('second.keystore')
storePassword 'password'
}
}
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
}
productFlavors{
flavor1 {
applicationId "com.test.firstapp"
}
flavor2 {
applicationId "com.test.secondapp"
}
}
buildTypes {
release {
productFlavors.flavor1.signingConfig signingConfigs.configFirst
productFlavors.flavor2.signingConfig signingConfigs.configSecond
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
buildTypes block should be placed after productFlavors block, I mean order is important.
Per the user guide, signingConfigs for flavors are supported.
The problem here has to do with the scope of the signingConfigs object. I just assigned it to a variable inside the productFlavors block, but outside the flavor1 flavor block to fix the issue:
productFlavors {
def flavor1SigningVariable = signingConfigs.flavor1
flavor1 {
...
signingConfig flavor1SigningVariable
...
}
The gradle plugin for android only supports signing per build type, not per flavor. The reason for this is that any given variant (build type + flavors) can only be signed by one key, but can be a combination of several flavor groups. For example your flavor groups could be cpu (x86/arm) and version (free/paid), that's four different variants right there.
The solution you're looking for is to create separate build types for your different release versions. For example, your build types might be debug, release, release-beta, like this:
...
android {
...
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.release
}
release-beta {
initWith release
signingConfig signingConfigs.release-beta
}
}
}
The initWith above just tells gradle that release-beta should be a copy of the release build type, only signed with a different key.
Maybe another interesting solution with dynamic flavor signing configs and other advantages
Im fine with defining app id and app name of flavors in gradle (it is clear and just 2 lines for each flavor) but I do not want to define separate signing configs (gradle file would be too long when adding flavors)
I also do not want to have sensitive signing information placed in gradle because of commiting it
Bonus advantage is that debug build has another app id and app name.
.gitignore
...
/keystore.properties
.keystore.properties
storeFile=../mystore.jks
storePassword=...
keyAliasFlavor1=...
keyPasswordFlavor1=...
keyAliasFlavor2=...
keyPasswordFlavor2=...
app/build.gradle
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(rootProject.file('keystore.properties')))
android {
...
buildTypes {
debug {
...
manifestPlaceholders = [appNameSuffix: " Dev"]
applicationIdSuffix ".dev"
}
release {
...
manifestPlaceholders = [appNameSuffix: ""]
productFlavors.all { flavor ->
flavor.signingConfig = android.signingConfigs.create("${flavor.name}")
flavor.signingConfig.storeFile = rootProject.file(keystoreProperties["storeFile"])
flavor.signingConfig.storePassword = keystoreProperties["storePassword"]
flavor.signingConfig.keyAlias = keystoreProperties["keyAlias${flavor.name}"]
flavor.signingConfig.keyPassword = keystoreProperties["keyPassword${flavor.name}"]
}
}
}
productFlavors {
Flavor1 {
applicationId "..."
manifestPlaceholders = [appNameBase: "MyApp 1"]
}
Flavor2 {
applicationId "..."
manifestPlaceholders = [appNameBase: "MyApp 2"]
}
// ... and many other flavors without taking care about signing configs
// (just add two lines into keystore.properties for each new flavor)
}
}
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application android:label="${appNameBase}${appNameSuffix}" ...>
...
</application>
</manifest>
This is the Kotlin DSL equivalent of ashakirov's answer:
// See https://stackoverflow.com/q/60474010
fun getLocalProperty(key: String) = gradleLocalProperties(rootDir).getProperty(key)
fun String?.toFile() = file(this!!)
// Could also use System.getenv("VARIABLE_NAME") to get each variable individually
val environment: Map<String, String> = System.getenv()
android {
signingConfigs {
create("MyFirstConfig") {
keyAlias = getLocalProperty("signing.keyAlias") ?: environment["SIGNING_KEY_ALIAS"]
storeFile = (getLocalProperty("signing.storeFile") ?: environment["SIGNING_STORE_FILE"]).toFile()
keyPassword = getLocalProperty("signing.keyPassword") ?: environment["SIGNING_KEY_PASSWORD"]
storePassword = getLocalProperty("signing.storePassword") ?: environment["SIGNING_STORE_PASSWORD"]
enableV1Signing = true
enableV2Signing = true
}
create("MySecondConfig") {
keyAlias = getLocalProperty("signing.keyAlias2") ?: environment["SIGNING_KEY_ALIAS2"]
storeFile = (getLocalProperty("signing.storeFile2") ?: environment["SIGNING_STORE_FILE2"]).toFile()
keyPassword = getLocalProperty("signing.keyPassword2") ?: environment["SIGNING_KEY_PASSWORD2"]
storePassword = getLocalProperty("signing.storePassword2") ?: environment["SIGNING_STORE_PASSWORD2"]
enableV1Signing = true
enableV2Signing = true
}
}
productFlavors {
create("flavor1") {
// ...
}
create("flavor2") {
// ...
}
}
buildTypes {
getByName("release") { // OR simply release { in newer versions of Android Gradle Plugin (AGP)
productFlavors["flavor1"].signingConfig = signingConfigs["MyFirstConfig"]
productFlavors["flavor2"].signingConfig = signingConfigs["MySecondConfig"]
// OR alternative notation
// productFlavors {
// getByName("flavor1") {
// signingConfig = signingConfigs["MyFirstConfig"]
// }
// getByName("flavor2") {
// signingConfig = signingConfigs["MySecondConfig"]
// }
// }
}
}
}
Split signing configs between Gms and Hms builds
Just for future ref if anyone has to split their signing configs between Gms and Hms builds.
This adds on the the answer listed here:
Maybe another interesting solution with dynamic flavor signing configs and other advantages
build.gradle
Option 1
gradle.startParameter.getTaskNames().each()
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
signingConfigs {
release {
storeFile file(keystoreProperties["RELEASE_STORE_FILE"])
storePassword keystoreProperties["RELEASE_STORE_PASSWORD"]
keyAlias keystoreProperties["RELEASE_KEY_ALIAS"]
keyPassword keystoreProperties["RELEASE_KEY_PASSWORD"]
}
releaseHms {
storeFile file(keystoreProperties["RELEASE_HMS_STORE_FILE"])
storePassword keystoreProperties["RELEASE_STORE_PASSWORD"]
keyAlias keystoreProperties["RELEASE_KEY_ALIAS"]
keyPassword keystoreProperties["RELEASE_KEY_PASSWORD"]
}
debug {
// use default debug key to sign
}
}
buildTypes {
release {
...
gradle.startParameter.getTaskNames().each { task ->
if (task.toLowerCase().contains("gms")) {
signingConfig signingConfigs.release
}
if (task.toLowerCase().contains("hms") {
signingConfig signingConfigs.releaseHms
}
}
}
debug {
...
gradle.startParameter.getTaskNames().each { task ->
if (task.toLowerCase().contains("gms")) {
signingConfig signingConfigs.debug
}
if (task.toLowerCase().contains("hms") {
signingConfig signingConfigs.releaseHms
}
}
flavorDimensions "serviceplatform"
productFlavors {
hms {
dimension "serviceplatform"
applicationIdSuffix ".huawei"
versionNameSuffix "-huawei"
}
gms {
dimension "serviceplatform"
applicationIdSuffix ".android"
}
}
sourceSets {
main {
res.srcDirs = [
"src/main/res",
"src/main/res/layout/toolbar",
"src/main/res/layout/fragment",
"src/main/res/layout/activity"
]
}
gms {
java.srcDir("src/gms/java")
}
hms {
java.srcDir("src/hms/java")
}
}
Option 2
productFlavors.gms.signingConfig
Ensure your flavorDimensions is before buildTypes
flavorDimensions "serviceplatform"
productFlavors {
hms {
...
}
gms {
...
}
}
buildTypes {
release {
...
productFlavors.gms.signingConfig signingConfigs.release
productFlavors.hms.signingConfig signingConfigs.releaseHms
}
debug {
...
productFlavors.gms.signingConfig signingConfigs.debug
productFlavors.hms.signingConfig signingConfigs.releaseHms
}
}

Categories

Resources