Update build.gradle 3.3.0 Breaks applicationVariants.all apk Assembly - gradle

I have just upgraded an Android project's build.gradle to use build version 3.3.0
com.android.tools.build:gradle:3.3.0
Doing so has created this warning:
WARNING: API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getAssemble(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.
Affected Modules: app
It is caused by this code in the app build.gradle:
android.applicationVariants.all { variant ->
variant.assemble.doLast {
variant.outputs.each { output ->
def apk = variant.outputs[0].outputFile
File versionInfo = new File(apk.parent, "versionInfo.properties")
versionInfo.text = "versionCode=${android.defaultConfig.versionCode}\nversionName=${android.defaultConfig.versionName}"
copy {
from "${versionInfo}"
into "$project.projectDir/temp_archive"
}
}
}
}
I haven't been able to find where I can rewrite this to make the warning disappear. I tried to follow this Stack Overflow post, but didn't make any progress. Any suggestions would be greatly appreciated.

I found a potential solution that has resolved the warning. Below is the code I am using. Leaving the question for now in case there is a better solution.
android.applicationVariants.all { variant ->
variant.getAssembleProvider().get().doLast {
variant.outputs.each { output ->
def apk = variant.outputs[0].outputFile
File versionInfo = new File(apk.parent, "versionInfo.properties")
versionInfo.text = "versionCode=${android.defaultConfig.versionCode}\nversionName=${android.defaultConfig.versionName}"
copy {
from "${versionInfo}"
into "$project.projectDir/temp_archive"
}
}
}
}

Related

FileNotFoundException: `generated/source/apollo/generatedIR/main`

I try to generate my graphql schema using gradle apollo generateApolloClasses. So the first step is to generateMainApolloIR and it is working fine. It is generating a MainAPI.json under
/generated/source/apollo/generatedIR/main/src/main/graphql/client/backend/MainAPI.json. But the generateApolloClasses is failing with:
> java.io.FileNotFoundException: /Users/mctigg/Documents/Repositories/generated/source/apollo/generatedIR/main (Is a directory)
So it is looking into the wrong path! This is my gradle config:
apollo {
nullableValueType = "javaOptional"
outputPackageName = "generated.client.backend"
}
task generateBackendSchemaJson(type: ApolloSchemaIntrospectionTask) {
url = 'src/main/graphql/client/backend/schema.graphqls'
output = 'src/main/graphql/client/backend/schema.json'
}
tasks.findByName('generateMainApolloIR').dependsOn(['generateBackendSchemaJson'])
So how can I configure generateApolloClasses to look into:
/generated/source/apollo/generatedIR/main/src/main/graphql/client/backend/
Instead of
/generated/source/apollo/generatedIR/main/
May be you should set schema file path as follows:
apollo {
schemaFilePath = "/generated/source/apollo/generatedIR/main/src/main/graphql/client/backend/schema.json"
nullableValueType = "javaOptional"
outputPackageName = "generated.client.backend"
}

Ionic: Error: Module build failed: Error: ENOENT: no such file or directory

I am using Ionic, and get the following error:
Runtime Error Uncaught (in promise): Error: Module build failed:
Error: ENOENT: no such file or directory, open
'/Users/richardmarais/Development/ionic/theWhoZoo/src/pages/model/ratingModel.js'
The error is a result of this line of code:
this.ratingModel = new RatingModel();
When I remove this line, I don't get the error.
ratingModel.ts
import { Injectable } from "#angular/core";
import { PersonModel } from './personModel';
import { JobModel } from './jobModel';
#Injectable()
export class RatingModel {
public id: number = null;
public job: JobModel = null;
public review: string = null;
public rating: number = null;
public reviewDate: number = null;
public time: string = null;
public person: PersonModel = null;
public anonymous: number = null;
constructor() {
}
}
Reading other forums, people are getting this error due to the case not matching in their imports, but I have checked mine, and they do match.
import { RatingModel } from '../model/ratingModel';
However, I have noticed something strange in my IDE (Visual Studio Code):
As you can see, in the search results, there are two files for the object, ratingModel.ts and RatingModel.ts. But when I check the actual files system, there is only on file, ratingModel.ts:
Question
Does anyone know what and how to resolve what looks like possibly a bug or fault here?
Thanks
More info:
global packages:
#ionic/cli-utils : 1.0.0
Cordova CLI : 6.4.0
Ionic CLI : 3.0.0
local packages:
#ionic/app-scripts : 1.3.0
#ionic/cli-plugin-cordova : 1.0.0
#ionic/cli-plugin-ionic-angular : 1.0.0
Ionic Framework : ionic-angular 3.2.1
System:
Node : v7.10.0
OS : macOS Sierra
Xcode : Xcode 8.3.2 Build version 8E2002
ios-deploy : not installed
ios-sim : not installed
Apologies, my bad. I just found another file that was importing the object with the incorrect case. It does appear as if there is no issue, and I had a bug in my code.
import { RatingModel } from '../model/RatingModel';
This error occurred when your component can't be found with your app.module settings.
Follow these steps to solve your problem:
Right click on your web browser and select inspect (in this case I use chrome)
In the source tab, navigate to localhost:8100 (the default port for running ionic)
Go to src -> pages and open corresponded page(in this case 'model')
The name of .ts file and path must be as same as the name and path of the added import path in app.module.ts
In this case, there isn't model/ratingModel.ts
be aware :
The path is case sensitive (maybe the .ts file is RatingModel)

Qbs: How to run simple terminal command?

I'm used to working with Makefiles but my current project uses .qbs files. How do I run a simple terminal command through qbs without creating or requiring files? Similar to a phony rule in make.
The following works and shows "awesome" in my terminal.
import qbs 1.0
Project {
name: "cli"
Product {
name: "helloworld"
type: "application"
files: "TEST.c"
Depends { name: "cpp" }
}
Product {
type: ["custom-image"]
Depends { name: "helloworld" }
Rule {
inputsFromDependencies: ["application"]
Artifact {
fileTags: ["custom-image"]
}
prepare: {
var cmd = new Command("echo", "awesome")
return cmd
}
}
}
}
However I have to touch my dummy TEST.c file before each run. Without the helloworld dependency the Rule does not run.
Any ideas? Thank you very much!
It's buried in the documentation in a very non obvious place and further obscured by Command (which is not the correct way, lol). I've had your problem too.
What you need is this:
http://doc.qt.io/qbs/jsextension-process.html
I'm not sure what your end goal is but you could use Transformer{} instead of a Rule{}. The biggest difference between a Rule{} and a Transformer{} is you don't need any inputs for the Transformer{} to run.
Also see Transformer.alwaysRun property.
https://doc.qt.io/qbs/transformer-item.html

How to define and call custom methods in build.gradle?

As part of my project, I need to read files from a directory and do some operations all these in build script. For each file, the operation is the same(reading some SQL queries and execute it). I think its a repetitive task and better to write inside a method. Since I'm new to Gradle, I don't know how it should be. Please help.
One approach given below:
ext.myMethod = { param1, param2 ->
// Method body here
}
Note that this gets created for the project scope, ie. globally available for the project, which can be invoked as follows anywhere in the build script using myMethod(p1, p2) which is equivalent to project.myMethod(p1, p2)
The method can be defined under different scopes as well, such as within tasks:
task myTask {
ext.myMethod = { param1, param2 ->
// Method body here
}
doLast {
myMethod(p1, p2) // This will resolve 'myMethod' defined in task
}
}
If you have defined any methods in any other file *.gradle - ext.method() makes it accessible project wide. For example here is a
versioning.gradle
// ext makes method callable project wide
ext.getVersionName = { ->
try {
def branchout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branchout
}
def branch = branchout.toString().trim()
if (branch.equals("master")) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
} else {
return branch;
}
}
catch (ignored) {
return null;
}
}
build.gradle
task showVersion << {
// Use inherited method
println 'VersionName: ' + getVersionName()
}
Without ext.method() format , the method will only be available within the *.gradle file it is declared. This is the same with properties.
You can define methods in the following way:
// Define an extra property
ext.srcDirName = 'src/java'
// Define a method
def getSrcDir(project) {
return project.file(srcDirName)
}
You can find more details in gradle documentation Chapter 62. Organizing Build Logic
An example with a root object containing methods.
hg.gradle file:
ext.hg = [
cloneOrPull: { source, dest, branch ->
if (!dest.isDirectory())
hg.clone(source, dest, branch)
else
hg.pull(dest)
hg.update(dest, branch)
},
clone: { source, dest, branch ->
dest.mkdirs()
exec {
commandLine 'hg', 'clone', '--noupdate', source, dest.absolutePath
}
},
pull: { dest ->
exec {
workingDir dest.absolutePath
commandLine 'hg', 'pull'
}
},
]
build.gradle file
apply from: 'hg.gradle'
hg.clone('path/to/repo')
Somehow, maybe because it's five years since the OP, but none of the
ext.someMethod = { foo ->
methodBody
}
approaches are working for me. Instead, a simple function definition seems to be getting the job done in my gradle file:
def retrieveEnvvar(String envvar_name) {
if ( System.getenv(envvar_name) == "" ) {
throw new InvalidUserDataException("\n\n\nPlease specify environment variable ${envvar_name}\n")
} else {
return System.getenv(envvar_name)
}
}
And I call it elsewhere in my script with no prefix, ie retrieveEnvvar("APP_PASSWORD")
This is 2020 so I'm using Gradle 6.1.1.
#ether_joe the top-voted answer by #InvisibleArrow above does work however you must define the method you call before you call it - i.e. earlier in the build.gradle file.
You can see an example here. I have used this approach with Gradle 6.5 and it works.
With Kotlin DSL (build.gradle.kts) you can define regular functions and use them.
It doesn't matter whether you define your function before the call site or after it.
println(generateString())
fun generateString(): String {
return "Black Forest"
}
tasks.create("MyTask") {
println(generateString())
}
If you want to import and use a function from another script, see this answer and this answer.
In my react-native in build.gradle
def func_abc(y){return "abc"+y;}
then
def x = func_abc("y");
If you want to check:
throw new GradleException("x="+x);
or
println "x="+x;

Groovy SwingBuilder() apple.awt.CToolkit exception

I am using newest Mac OS X and I am creating a GUI element inside a Gradle file. I am currently using jdk1.7.0_55 and I have imported groovy.swing.SwingBuilder, when I run the project I am getting the following error:
java.awt.AWTError: "Toolkit not found: apple.awt.CToolkit
I have tried running the script as a headless server using System.setProperty('java.awt.headless', 'true')
I would like to have a solution that I can include directly in the Gradle project file, instead of trying to figure out what is in my accesibilities.properties file (that may not exist on a particular system, like it does not on my system).
Also the project must use an internal solution, external libraries are not allowed.
Would really appreciate any help on this matter.
Edited: Sample Code
gradle.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(':CustomApp:assembleRelease')) {
def pass = ''
if(System.console() == null) {
new SwingBuilder().edt { // Error occurs here.
dialog(modal: true,
alwaysOnTop: true,
resizable: false,
locationRelativeTo: null,
pack: true,
show: true
)
{
vbox {
label(text: "Enter password:")
input = passwordField()
button(defaultButton: true, text: 'OK', actionPerformed: {
pass = input.password;
dispose();
})
}
}
}
}
}
I've faced same issue with Android Studio 0.8.6 and solved it with custom gradle installation.
Just downloaded gradle 1.12 and set path to it in preferences.
The question is a few years old, but with the following gradle build file (which is essentially the same as the OPs):
import groovy.swing.SwingBuilder
task doit {}
gradle.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(doit)) {
def pass = ''
new SwingBuilder().edt { // Error occurs here.
dialog(modal: true,
alwaysOnTop: true,
resizable: false,
locationRelativeTo: null,
pack: true,
show: true)
{ vbox
{ label(text: "Enter password:")
input = passwordField()
button(defaultButton: true, text: 'OK', actionPerformed: {
pass = input.password;
dispose();
})
}
}
}
}
}
executing:
~> gradle doit
results in the following screen:
in other words, at least with this version of gradle, operating system, java etc this seems to work.

Resources