gradle android-gradle build.gradle

Objeto de consola null de construcción de Gradle



android-gradle build.gradle (10)

Eche un vistazo a esta publicación de blog ( https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/ ).

Describe varias formas de administrar las configuraciones de firma y una de ellas es exactamente su pregunta sobre la entrada de la consola para la contraseña.

Estoy intentando hacer que mis compilaciones gradle soliciten una contraseña en la consola usando ejemplos del desbordamiento de la pila

Cuando tengo una declaración como:

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

Cuando corro obtengo el error

Cannot invoke method readLine() on null object

Parece que la consola está saliendo como null . Lo que he leído esto requiere java 6, que si voy a un símbolo del sistema y java -version , estoy ejecutando Java (TM) SE Runtime Environment (compilación 1.6.0_27-b07).

Este problema está siendo rastreado en el repositorio Github de Gradle: No se puede usar System.console () con el Gradle Daemon .


Ejecutando System.getConsole() desde Gradle cuando la propiedad org.gradle.daemon es true , o cuando se ejecuta desde un IDE como IntelliJ o Android Studio devuelve null . Entonces, por ejemplo, System.console().readLine() no es posible.

Además, a partir de Gradle 3.0 gradle.daemon está activado de manera predeterminada .

Luego, en lugar de una solución alternativa para usar System.getConsole() propongo una alternativa, use ant.input manera:

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

En este caso, ant.input muestra el message y agrega la entrada del usuario en ant.properties usando como nombre de propiedad el valor definido en addProperty . Si no hay entrada de usuario, entonces se usa el valor definido en default atributo default .

Una vez ejecutado, puede obtener la entrada del usuario utilizando ant.properties.yourProperty o ant.properties[''yourProperty''] .

Puede consultar el resto de los atributos ant.input aquí .

Nota: Si desea utilizar ant.input varias veces, tenga en cuenta que no puede anular y la propiedad existente, por addProperty atributo addProperty debe ser diferente para cada uno.


Encontré una solución aquí en https://www.timroes.de/2014/01/19/using-password-prompts-with-gradle-build-files y la modifiqué ligeramente. Sin embargo, todos los créditos van a 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 } }

En algún lugar del archivo de algún gradle, tiene definida la configuración para la firma del lanzamiento.

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

(No olvide import groovy.swing.SwingBuilder ).

Con respecto a la segunda parte, también puede echarle un vistazo a ¿Cómo crear un archivo apk de lanzamiento firmado usando Gradle?


Ok, la razón por la que esto no funcionó fue una tontería, pero por si acaso alguien más se entera, pensé en publicarla.

Estaba ejecutando la tarea a través de Android Studio y no me di cuenta de que el objeto de la consola siempre sería nulo. Cuando se ejecuta desde la línea de comando, el objeto "comando" no es nulo y funciona bien.


Para solucionar este problema, utilicé el flujo de entrada estándar como siguiente:

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


Por alguna razón, ejecutar gradle en modo daemon provoca un objeto de consola nulo. Si especifica el indicador de línea de comando apropiado,

./gradlew assembleRelease --no-daemon

Funcionará


Puedes ejecutar tu script también con:

-Dorg.gradle.daemon = falso


Una solución simple para esto es verificar el objeto de la consola para nulo:

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

Android Studio ya no tiene quejas sobre el null object .

Para ocultar caracteres readPassword() use readPassword() lugar de readLine() :

password = new String(console.readPassword("/nEnter key password: "))


crea una función simple para solicitar una contraseña:

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

o si quieres respuesta de 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) } } ... }


password System.console() != null ? System.console().readLine("/ password: ") : ""