49

我正在尝试使用堆栈溢出中的示例让我的 gradle 构建在控制台提示输入密码

当我有这样的陈述时:

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

当我运行时,我得到了错误

Cannot invoke method readLine() on null object

似乎控制台以null. 我读到的这需要 java 6,如果我进入命令提示符并键入java -version我正在运行 Java(TM) SE 运行时环境(build 1.6.0_27-b07)。

Gradle 的 Github 存储库中正在跟踪此问题:Can't use System.console() with the Gradle Daemon

4

10 回答 10

47

出于某种原因,以守护程序模式运行 gradle 会导致控制台对象为空。如果您指定适当的命令行标志,

./gradlew assembleRelease --no-daemon

它会工作的。

于 2014-05-30T04:20:51.223 回答
21

我在https://www.timroes.de/2014/01/19/using-password-prompts-with-gradle-build-files找到了一个解决方案并稍作修改。尽管如此,所有的功劳都归于 Tim Roes!

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

关于第二部分,你也可以看看How to create a release signed apk file using Gradle?

于 2014-06-23T07:56:34.130 回答
16

好的,这不起作用的原因很愚蠢,但以防万一其他人遇到它,我想我会发布。

我正在通过 android studio 运行任务,但没有意识到控制台对象将始终为空。从命令行运行时,“命令”对象不为空,并且可以正常工作。

于 2013-10-24T06:11:08.730 回答
11

当属性为时System.getConsole()Gradle执行,或者当它从IntelliJAndroid Studio等 IDE 执行时返回。因此,例如 do变得不可能。org.gradle.daemontruenullSystem.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执行后,您可以使用or获取用户输入ant.properties['yourProperty']

您可以在此处检查其余ant.input属性

注意:如果您想ant.input多次使用,请考虑到您无法覆盖和现有属性,因此addProperty每个属性必须不同。

于 2017-03-08T10:13:05.250 回答
7

看看这篇博文(https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/)。

它描述了处理签名配置的多种方法,其中之一正是您关于控制台输入密码的问题。

于 2013-10-21T21:44:58.840 回答
7

为了解决这个问题,我使用了标准输入流作为下一个:

println "Enter keystore password"
def password = System.in.newReader().readLine()
于 2018-04-05T16:43:29.073 回答
3

您还可以使用以下命令执行脚本:

-Dorg.gradle.daemon=false

于 2016-12-23T11:41:24.740 回答
2

对此的简单解决方案是检查控制台对象是否为空:

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: "))
于 2014-03-10T22:19:35.723 回答
1

创建一个简单的函数来请求密码:

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)
    }
  }
  ...
}
于 2018-04-04T11:05:39.223 回答
-1
password System.console() != null ? System.console().readLine("\ password: ") : ""
于 2018-04-21T09:56:45.463 回答