スタックオーバーフローの例を使用して、コンソールでパスワードを求めるプロンプトに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デーモンと併用することはできません 。
OK、これがうまくいかなかった理由はばかげていましたが、他の誰かがそれに出くわした場合に備えて、私は投稿したいと思いました。
タスクをAndroid studioで実行していましたが、コンソールオブジェクトが常にnullであることを認識していませんでした。コマンドラインから実行すると、「command」オブジェクトはnullではなく、 。
何らかの理由で、デーモンモードでgradleを実行すると、nullコンソールオブジェクトが発生します。適切なコマンドラインフラグを指定すると、
./gradlew assembleRelease --no-daemon
動作します。
私はここで解決策を見つけました 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ファイルを作成する方法 もご覧ください。
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.input
はmessage
を表示し、addProperty
で定義された値をプロパティ名として使用してant.properties
にユーザー入力を追加します。ユーザー入力がない場合、default
属性で定義された値が使用されます。
実行すると、ant.properties.yourProperty
またはant.properties['yourProperty']
を使用してユーザー入力を取得できます。
残りの ant.input
属性はこちら で確認できます。
注:ant.input
を複数回使用する場合は、既存のプロパティをオーバーライドできないため、addProperty
属性はそれぞれ。
このブログ投稿をご覧ください( https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/ )。
署名設定を処理する複数の方法について説明しますが、そのうちの1つは、パスワードのコンソール入力に関する質問です。
次の方法でもスクリプトを実行できます。
-Dorg.gradle.daemon = false
これに対する簡単な解決策は、コンソールオブジェクトの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: "))
_
この問題を回避するには、次のように標準入力ストリームを使用しました。
println "Enter keystore password"
def password = System.in.newReader().readLine()
パスワードを要求する簡単な関数を作成します。
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)
}
}
...
}