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 .

40
demandé sur ben3000 2013-10-21 10:27:06

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.

42
répondu Jason Tu 2014-05-30 04:20:51

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?

18
répondu Martin L. 2017-05-23 12:10:43

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.

16
répondu Andrew 2013-10-24 06:11:08

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.

9
répondu albciff 2017-03-23 21:13:11

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.

7
répondu Michael Barany 2013-10-21 21:44:58

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: "))
3
répondu petrsyn 2014-03-10 22:25:24

vous pouvez exécuter votre script aussi avec:

- Dorg.gradle.daemon=false

3
répondu ezgi 2016-12-23 11:41:24

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)
    }
  }
  ...
}
1
répondu Grigory K 2018-04-04 11:05:39

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()
1
répondu Nicolas Filotto 2018-04-05 16:43:29
password System.console() != null ? System.console().readLine("\ password: ") : ""
-1
répondu Yacine ELgoub 2018-04-21 11:30:53