Хобрук: Ваш путь к мастерству в программировании

Gradle создает нулевой консольный объект

Я пытаюсь заставить мои сборки gradle запрашивать на консоли пароль, используя примеры из переполнения стека.

Когда у меня есть заявление, такое как:

def password = System.console().readLine("Enter keystore password ")

Когда я запускаю, я получаю ошибку

Cannot invoke method readLine() on null object

Кажется, консоль выходит как null. То, что я прочитал, требует java 6, что, если я зайду в командную строку и наберу java -version, я запускаю Java (TM) SE Runtime Environment (сборка 1.6.0_27-b07).

Эта проблема отслеживается в репозитории Github Gradle: Не удается использовать System.console() с демоном Gradle. .


Ответы:


1

По какой-то причине запуск gradle в режиме демона приводит к нулевому объекту консоли. Если вы укажете соответствующий флаг командной строки,

./gradlew assembleRelease --no-daemon

это сработает.

30.05.2014
  • Лол, это сработало в проекте, но не в другом. 23.08.2014
  • Не работает с использованием gradle 4.2 › Невозможно вызвать метод readPassword() для нулевого объекта 31.10.2017

  • 2

    Я нашел решение здесь по адресу https://www.timroes.de/2014/01/19/using-password-prompts-with-gradle-build-files и немного изменил его. Тем не менее, все заслуги Тима Роуза!

    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
        }
    }
    

    Где-то в каком-то файле gradle у вас есть конфигурация для подписания выпуска.

    android {
    ...
    signingConfigs {
        ...
        release {
            storeFile file(System.getProperty("user.home")+"\\android-key")
            storePassword ''
            keyAlias "standard"
            keyPassword ''
        }
    }
    
    ...
    }
    

    (Не забудьте import groovy.swing.SwingBuilder.)

    Что касается второй части, вы также можете взглянуть на Как создать apk-файл с подписью выпуска с помощью Gradle?

    23.06.2014
  • Решение Tim Roes для этого отличное 08.01.2015
  • очень хорошая, готовая к производству модификация, спасибо. не забудьте import groovy.swing.SwingBuilder 05.06.2015
  • AS теперь показывает ошибку о import groovy.swing.SwingBuilder. К счастью, он по-прежнему будет выполнять отладочную сборку, а gradlew из командной строки по-прежнему может импортировать groovy. См. stackoverflow.com/q/43423331/1682419. 15.04.2017
  • ничего себе, просто используйте: def pass = javax.swing.JOptionPane.showInputDialog (пароль, пожалуйста :) 04.04.2018
  • У меня не работает, я получаю Failed to create component for 'dialog' reason: java.awt.HeadlessException > java.awt.HeadlessException (no error message) 07.05.2020

  • 3

    Хорошо, причина, по которой это не сработало, была глупой, но на случай, если кто-то еще столкнется с этим, я решил опубликовать.

    Я выполнял задачу через студию Android и не понимал, что объект консоли всегда будет нулевым. При запуске из командной строки объект «команда» не равен нулю, и он работает нормально.

    24.10.2013
  • Вы нашли обходной путь, чтобы это работало при запуске из обоих мест? 21.08.2014
  • В моем случае объект является нулевым, даже если он работает через терминал. Я не пытаюсь запустить через AS. 01.09.2020

  • 4

    Выполнение System.getConsole() из Gradle, когда свойство org.gradle.daemon равно true, или когда оно выполняется из IDE, такой как IntelliJ или Android Studio, возвращается null. Так например сделать System.console().readLine() становится невозможным.

    Кроме того, начиная с Gradle 3.0 gradle.daemon включен по умолчанию.

    Затем вместо обходного пути для использования System.getConsole() я использую альтернативу, используя ant.input следующим образом:

    task avoidNullOnConsole << {
        ant.input(message: 'Enter keystore password:', addproperty: 'userInputPassword', defaultValue : '1234')
        def password = ant.properties.userInputPassword
    }
    

    В этом случае ant.input показывает message и добавляет пользовательский ввод в ant.properties, используя в качестве имени свойства значение, определенное в addProperty. Если пользовательский ввод отсутствует, используется значение, определенное в атрибуте default.

    После выполнения вы можете получить пользовательский ввод, используя ant.properties.yourProperty или ant.properties['yourProperty'].

    Вы можете проверить остальные атрибуты ant.input здесь.

    Примечание. Если вы хотите использовать ant.input несколько раз, учтите, что вы не можете переопределить существующее свойство, поэтому атрибут addProperty должен быть разным для каждого из них.

    08.03.2017
  • Это хорошо работает, есть ли способ скрыть то, что печатает пользователь? 28.02.2018
  • Если вы используете ant.version > 1.8, кажется, что добавление handler(type:'secure') к ant.input должно работать... Я проверяю использование <input message="Enter some user input data?" addproperty="userInput" defaultValue="nothing"><handler type="secure"/></input> в build.xml и работает хорошо, однако в build.gradle эквивалент ant.input(message: 'Enter some user input data?', addproperty: 'userInput', defaultValue : 'nothing'){ handler(type: 'secure') } не скрывает пользовательский ввод :( 28.02.2018

  • 5

    Взгляните на этот пост в блоге (https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/).

    В нем описывается несколько способов обработки конфигураций подписи, и один из них — это как раз ваш вопрос о консольном вводе пароля.

    21.10.2013

    6

    Чтобы обойти эту проблему, я использовал стандартный поток ввода следующим образом:

    println "Enter keystore password"
    def password = System.in.newReader().readLine()
    
    05.04.2018
  • Работает. Howeber, как прочитать пароль? readPassword() является функцией класса Console. 04.03.2019
  • @galcyurio, что дает тебе readPassword() такого, чего не дает readLine()? Он просто скрывает ввод? 24.10.2019

  • 7

    Вы также можете выполнить свой скрипт с помощью:

    -Dorg.gradle.daemon=false

    23.12.2016

    8

    Простое решение — проверить объект консоли на значение null:

    def password = null
    def console = System.console()
    if (console != null) {
        password = console.readLine("Enter keystore password: ")
    }
    

    Android Studio больше не жалуется на файл null object.

    Чтобы скрыть введенные символы, используйте readPassword() вместо readLine():

    password = new String(console.readPassword("\nEnter key password: "))
    
    10.03.2014
  • Это не решает проблему отсутствия консоли. Вы хотите ввести пароль через командную строку или консоль. Теперь у вас будет проблема с нулевым паролем. 15.07.2014

  • 9

    создайте простую функцию для запроса пароля:

    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)
      }
    }
    

    или если вы хотите ответ Y/n:

    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)
        }
      }
      ...
    }
    
    04.04.2018
  • Кажется, это официальное решение: stackoverflow.com/a/25187990/103412 18.09.2018

  • 10
  • Не установка пароля вообще не помогает. 21.05.2021
  • Новые материалы

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

    Обзор 20 основных и современных методов работы с массивами в JavaScript
    Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

    Да, но я чувствую необходимость указать, что это или не единственные два.
    Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.