web-dev-qa-db-ja.com

Gradleはnullコンソールオブジェクトを構築します

スタックオーバーフローの例を使用して、コンソールでパスワードを求めるプロンプトにgradleビルドを取得しようとしています

次のような文言がある場合:

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

実行するとエラーが発生します

Cannot invoke method readLine() on null object

コンソールはnullとして出てきているようです。私がこれを読んだことはJava 6を必要とします。これはコマンドプロンプトに行き、Java -version Java(TM)SEランタイム環境(ビルド1.6.0_27-b07)を実行しています。

この問題は、GradleのGithubリポジトリで追跡されています: System.console()をGradleデーモンと併用することはできません

42
Andrew

OK、これがうまくいかなかった理由はばかげていましたが、他の誰かがそれに出くわした場合に備えて、私は投稿したいと思いました。

タスクをAndroid studioで実行していましたが、コンソールオブジェクトが常にnullであることを認識していませんでした。コマンドラインから実行すると、「command」オブジェクトはnullではなく、 。

16
Andrew

何らかの理由で、デーモンモードでgradleを実行すると、nullコンソールオブジェクトが発生します。適切なコマンドラインフラグを指定すると、

./gradlew assembleRelease --no-daemon

動作します。

44
Jason Tu

私はここで解決策を見つけました 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を忘れないでください。)

2番目の部分については、 Gradleを使用してリリース署名済みapkファイルを作成する方法 もご覧ください。

20
Martin L.

org.gradle.daemonプロパティがtrueの場合、またはIntelliJのようなIDEから実行される場合、GradleからSystem.getConsole()を実行します。 Android Studionullを返します。たとえば、do System.console().readLine()は不可能になります。

さらに Gradle 3.gradle.daemonはデフォルトでオンになっています から始まります。

次に、System.getConsole()を使用する回避策の代わりに、代わりにant.inputを使用します。

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

この場合、ant.inputmessageを表示し、addPropertyで定義された値をプロパティ名として使用してant.propertiesにユーザー入力を追加します。ユーザー入力がない場合、default属性で定義された値が使用されます。

実行すると、ant.properties.yourPropertyまたはant.properties['yourProperty']を使用してユーザー入力を取得できます。

残りの ant.input属性はこちら で確認できます。

注:ant.inputを複数回使用する場合は、既存のプロパティをオーバーライドできないため、addProperty属性はそれぞれ。

9
albciff

このブログ投稿をご覧ください( https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/ )。

署名設定を処理する複数の方法について説明しますが、そのうちの1つは、パスワードのコンソール入力に関する質問です。

7
Michael Barany

次の方法でもスクリプトを実行できます。

-Dorg.gradle.daemon = false

3
ezgi

これに対する簡単な解決策は、コンソールオブジェクトの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: "))
_
3
petrsyn

この問題を回避するには、次のように標準入力ストリームを使用しました。

println "Enter keystore password"
def password = System.in.newReader().readLine()
3
Nicolas Filotto

パスワードを要求する簡単な関数を作成します。

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)
    }
  }
  ...
}
1
Grigory K