Gradle construire null objet de console
j'essaie d'obtenir mes compilations gradle pour demander à la console un mot de passe en utilisant des exemples de débordement de pile
Quand j'ai une déclaration telle que:
def password = System.console().readLine("Enter keystore password ")
Quand je le lance j'obtiens l'erreur
Cannot invoke method readLine() on null object
il semble que la console sort en tant que null
. Ce que j'ai lu cela nécessite java 6 qui si je vais à une invite de commande et que je tape java -version
j'exécute Java (TM) SE environnement D'exécution (construire 1.6.0_27-b07).
Cette question est suivie dans Gradle du dépôt Github: impossible d'utiliser le Système.console () avec le démon Grad .
10 réponses
pour une raison quelconque, exécuter gradle en mode démon provoque un objet console nul. Si vous spécifiez le drapeau de ligne de commande approprié,
./gradlew assembleRelease --no-daemon
ça va marcher.
j'ai trouvé une solution ici à https://www.timroes.de/2014/01/19/using-password-prompts-with-gradle-build-files et légèrement modifié. Néanmoins, tous les crédits vont à temps!
gradle.taskGraph.whenReady { taskGraph ->
if(taskGraph.hasTask(':app:assembleRelease')) {
def storePass = ''
def keyPass = ''
if(System.console() == null) {
new SwingBuilder().edt {
dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) {
vbox { // Put everything below each other
label(text: "Please enter store passphrase:")
def input1 = passwordField()
label(text: "Please enter key passphrase:")
def input2 = passwordField()
button(defaultButton: true, text: 'OK', actionPerformed: {
storePass = input1.password;
keyPass = input2.password;
dispose();
})
}
}
}
} else {
storePass = System.console().readPassword("\nPlease enter store passphrase: ")
keyPass = System.console().readPassword("\nPlease enter key passphrase: ")
}
if(storePass.size() <= 0 || keyPass.size() <= 0) {
throw new InvalidUserDataException("You must enter the passwords to proceed.")
}
storePass = new String(storePass)
keyPass = new String(keyPass)
android.signingConfigs.release.storePassword = storePass
android.signingConfigs.release.keyPassword = keyPass
}
}
quelque part dans le fichier de gradle, vous avez défini la configuration de la signature de publication.
android {
...
signingConfigs {
...
release {
storeFile file(System.getProperty("user.home")+"\android-key")
storePassword ''
keyAlias "standard"
keyPassword ''
}
}
...
}
(N'oubliez pas de import groovy.swing.SwingBuilder
.)
en ce qui concerne la deuxième partie, vous pouvez également comment créer un fichier APK signé en utilisant Gradle?
Ok, la raison pour laquelle ça n'a pas marché était stupide, mais juste au cas où quelqu'un d'autre le verrait, je pensais le poster.
j'exécutais la tâche via android studio et je ne savais pas que l'objet console serait toujours nul. Lors de l'exécution à partir de la ligne de commande, l'objet "command" n'est pas null et fonctionne correctement.
l'Exécution System.getConsole()
à partir de Gradle quand org.gradle.daemon
propriété true
, ou lorsqu'il est exécuté à partir d'un IDE comme Ide ou Android Studio il retourne null
. Ainsi par exemple do System.console().readLine()
devient impossible.
de plus à partir de Grad 3.0 gradle.daemon
est activé par défaut .
puis au lieu d'une solution de contournement d'utiliser System.getConsole()
je vise une alternative, utilisez ant.input
comme ainsi:
task avoidNullOnConsole << {
ant.input(message: 'Enter keystore password:', addproperty: 'userInputPassword', defaultValue : '1234')
def password = ant.properties.userInputPassword
}
dans ce cas, ant.input
indique message
et ajoute l'entrée de l'utilisateur dans ant.properties
en utilisant comme nom de propriété la valeur définie dans addProperty
. S'il n'y a pas d'entrée utilisateur, la valeur définie dans l'attribut default
est utilisée.
une fois exécuté, vous pouvez obtenir l'entrée de l'utilisateur en utilisant ant.properties.yourProperty
ou ant.properties['yourProperty']
.
vous pouvez vérifier le reste des ant.input
attributs ici .
Note: si vous voulez utiliser ant.input
plusieurs fois prendre en compte que vous ne pouvez pas outrepasser et propriété existante de sorte que addProperty
attribut doit être différent pour chacun.
jetez un oeil à ce billet de blog ( https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle / ).
décrit plusieurs façons de gérer la signature des configs et l'une d'elles est exactement votre question concernant l'entrée de la console pour le mot de passe.
la solution Simple à cela est de vérifier l'objet console pour null:
def password = null
def console = System.console()
if (console != null) {
password = console.readLine("Enter keystore password: ")
}
Android Studio ne se plaint plus du null object
.
pour masquer les caractères typographiques, utilisez readPassword()
au lieu de readLine()
:
password = new String(console.readPassword("\nEnter key password: "))
vous pouvez exécuter votre script aussi avec:
- Dorg.gradle.daemon=false
créer une fonction simple pour demander un mot de passe:
import javax.swing.JOptionPane
def askPass() {
def msg = 'Enter keystore password'
if (System.console() != null) {
return System.console().readLine(msg)
} else {
return javax.swing.JOptionPane.showInputDialog(msg)
}
}
ou si vous voulez O/N réponse:
import javax.swing.JOptionPane
def ask(msg) {
if (System.console() != null) {
return System.console().readLine(msg + ' [y/n]') == 'y'
} else {
def res = JOptionPane.showConfirmDialog(null, msg, "Confirm operation", JOptionPane.YES_NO_OPTION)
return res == JOptionPane.YES_OPTION
}
}
// usage:
task run() {
doFirst {
if (file('out.txt').exists() && !ask('overwrite output?')) {
System.exit(2)
}
}
...
}
Pour contourner ce problème, j'ai utilisé le flux d'entrée standard comme suivant:
println "Enter keystore password"
def password = System.in.newReader().readLine()
password System.console() != null ? System.console().readLine("\ password: ") : ""