【问题标题】:assembleRelease task dependency - Ask for keystore passwordassembleRelease 任务依赖 - 询问密钥库密码
【发布时间】:2013-06-17 10:01:53
【问题描述】:

为了避免以纯文本形式写入密钥库密码,我正在尝试将依赖项添加到由 android Gradle 插件创建的 assembleRelease 任务中。

我已经检查了 Gradle 文档 Manipulating existing tasks,但我无法将依赖项放在应有的位置

这是我的任务,在 android 插件上方的 $root$/myApp/build.gradle 中定义。

task readPasswordFromInput << {
    def console = System.console()

    ext.keystorePassword = console.readLine('\n\n\n> Enter keystore password: ')
}

apply plugin: 'android'

然后,我尝试了 Gradle 提供的两种可能性:task.dependsOntask.doFirst,但都没有。后者似乎被忽略了,而 dependsOn 确实添加了依赖项,但在依赖项链中为时已晚。运行 ./gradlew tasks --all 会打印出这个

:assembleRelease - Assembles all Release builds [libs:ActionBarSherlock:bundleRelease, libs:DataDroid:bundleRelease, libs:SlidingMenu:bundleRelease]
    :compileRelease
    ...
    [SEVERAL TASKS]
    ...
    :packageRelease
    ...
    [SEVERAL TASKS]
    ...
    :readPasswordFromInput

问题是,任务packageRelease

中需要keystore密码

顺便说一句,这可以按我的意愿工作

buildTypes {
        release {
            def console = System.console()

            ext.keystorePassword = console.readLine('\n\n\n> IF building release apk, enter keystore password: ')

            debuggable false

            signingConfigs.release.storePassword = ext.keystorePassword
            signingConfigs.release.keyPassword = ext.keystorePassword

            signingConfig signingConfigs.release
        }
    }

但每次使用 gradlew 时它都会要求输入密码,无论是 clean 还是 assemble

谢谢!

编辑

感谢@Intae Kim,这是我的 build.gradle 2.0 版

task readPasswordFromInput << {
    def console = System.console()

    ext.keystorePassword = console.readLine('\n\n\n> Enter keystore password: ')

    android.signingConfigs.release.storePassword = ext.keystorePassword
    android.signingConfigs.release.keyPassword = ext.keystorePassword
}

tasks.whenTaskAdded { task ->
    if (task.name == 'validateReleaseSigning') {
        task.dependsOn readPasswordFromInput
    }
}

apply plugin: 'android'

然后,构建类型

release {
    debuggable false

    signingConfig signingConfigs.release

    runProguard true
    proguardFile 'my-file.txt'
}

Gradle 执行正确,但它只生成一个 release-unsigned.apk

【问题讨论】:

    标签: android gradle


    【解决方案1】:

    尝试:

    tasks.whenTaskAdded { task ->
        if (task.name == 'packageRelease') {
            task.dependsOn readPasswordFromInput
        }
    }
    

    与您的 readPasswordFromInput 任务。

    更新:

    这样你就可以看到下面的代码有效了。

    def runTasks = gradle.startParameter.taskNames
    if ('assemble' in runTasks || 'assembleRelease' in runTasks || 'a' in runTasks || 'aR' in runTasks) {
        android.signingConfigs.releaseSign.storeFile = file('/path/to/keystore')
        android.signingConfigs.releaseSign.storePassword = System.console().readLine('KeyStore Password: ')
        android.signingConfigs.releaseSign.keyAlias = ...
        android.signingConfigs.releaseSign.keyPassword = System.console().readLine('Alias Password: ')
        android.buildTypes.release.signingConfig = android.signingConfigs.releaseSign
    }
    

    如果你遇到构建失败,可能需要在android.signingConfig上分配一个空的keysign配置:

    android {
        ...
        signingConfigs {
            releaseSign
        }
        ...
    

    【讨论】:

    • 非常感谢!我对这个失去了所有希望^^。我将用我的最终代码来回答,现在我将你的作为接受的答案。
    • 感谢 Intae,我可以读取密码,但 gradle 似乎在第一遍就读取了它并且不生成签名的 apk
    • This github gist link 可以帮到你。
    • 成功了 :) 请更新您的答案,以便我接受。原来的 gist 没有立即生效,我不得不做一些小修改:gist.github.com/Maragues/5974337
    • 用另一种方法更新。我目前正在使用外部脚本进行密钥签名,但仅使用 build.gradle 可能会更好。
    【解决方案2】:

    这是我发布密钥签名的完整解决方案。

    1. 它会检测控制台是否在守护程序模式下不可用。
    2. 它隐藏了密码。

    如果您使用的是守护程序模式,请使用gradle --no-daemon assembleRelease

    buildscript {
        repositories {
            mavenCentral()
        }
    
        dependencies {
            classpath 'com.android.tools.build:gradle:0.5.+'
        }
    }
    
    tasks.whenTaskAdded { task ->
        if (task.name == 'validateReleaseSigning')
            task.dependsOn keystoreInfo
    }
    
    apply plugin: 'android'
    
    repositories {
        mavenCentral()
    }
    
    android {
        compileSdkVersion 18
        buildToolsVersion '18.0.1'
    
        defaultConfig {
            minSdkVersion 7
            targetSdkVersion 18
        }
    
        signingConfigs {
            release {
                release {
                    storeFile file('release.keystore')
                    storePassword ''
                    keyAlias ''
                    keyPassword ''
                }
            }
    
            buildTypes {
                release {
                    debuggable false
                    signingConfig signingConfigs.release
                }
            }
        }
    }
    
    task keystoreInfo << {
        def console = System.console()
        if (console == null)
            throw new IllegalStateException('no console available, use --no-daemon flag')
    
        def storeFile = console.readLine('Keystore: ')
        def storePassword = console.readPassword('Keystore password: ')
        def keyAlias = console.readLine('Key alias: ')
        def keyPassword = console.readPassword('Key password: ')
    
        android.signingConfigs.release.storeFile = file(storeFile)
        android.signingConfigs.release.storePassword = new String(storePassword)
        android.signingConfigs.release.keyAlias = keyAlias
        android.signingConfigs.release.keyPassword = new String(keyPassword)
    }
    

    要点http://gist.github.com/grzegorz-zur/6416924

    【讨论】:

      【解决方案3】:

      我已经创建了解决方案,对我来说效果很好,你可以测试一下

      android { 
          signingConfigs {
              release {
                  storeFile = file('android.keystore')
                  keyAlias = "my_key_alias"
              }
          }
      
          buildTypes {
              release {
                  signingConfig signingConfigs.release
              }
          }
      }
      
      task readPasswordFromInput << {
          if(!project.hasProperty('keyStore') || !project.hasProperty('keyPass') || !project.hasProperty('storePass')) {
              println "\n\$ Enter signing details manually or run with \"-PkeyStore={key.store.name} -PstorePass={StoreSecretPassword} -PkeyPass={KeySecretPassword}\""   
          }
      
          if(!project.hasProperty('keyStore')) {
              def newKeyStore = System.console().readLine("\n\$ Enter keystore location or enter (default: android.keystore): ")
              if(newKeyStore != '') android.signingConfigs.release.storeFile = file('${newKeyStore}')
          } else {
              android.signingConfigs.release.storeFile = file(project.keyStore)
          }
      
          android.signingConfigs.release.storePassword = project.hasProperty('storePass') ? project.storePass : new String(System.console().readPassword("\$ Store password: "))
              android.signingConfigs.release.keyPassword = project.hasProperty('keyPass') ? project.keyPass : new String(System.console().readPassword("\$ Key password: "))
      }
      
      tasks.whenTaskAdded { task ->
          if (task.name == 'validateReleaseSigning') {
              task.dependsOn readPasswordFromInput
          }
      }
      

      然后您可以在提示时从 CLI 传递所有参数(使用 readPassword,因此它不可见),或者您可以将它们作为 CLI 参数传递给脚本

      gradle assemble
      gradle assemble -PkeyStore="~/.android/my.keystore"
      gradle assemble -PkeyStore="~/.android/my.keystore" -PstorePass="MyStorePass"
      gradle assemble -PkeyStore="~/.android/my.keystore" -PstorePass="MyStorePass" -PkeyPass="MyKeyPass"
      

      【讨论】:

      • 脚本很好,但我认为最好避免在 shell 中使用密码作为命令参数 - 以后可以在 shell 历史记录中使用它们。
      • @snowdragon 我也这么认为,这就是为什么脚本允许您在提示符中输入它们,将它们放在 shell 或命令别名中只是奖励
      【解决方案4】:

      这就是我的工作。

      task('readPasswordFromInput') << {
          def console = System.console()
      
          ext.keystorePassword = console.readLine('\n\n\n> Enter keystore password: ')
      
          android.signingConfigs.release.storePassword = ext.keystorePassword
          android.signingConfigs.release.keyPassword = ext.keystorePassword
      }
      
      tasks.whenTaskAdded { task ->
          if (task.name.matches("validateReleaseSigning")) {
              task.dependsOn('readPasswordFromInput')
          }
      }
      
      
      signingConfigs {
          debug {
              storeFile file("my-debug-key.keystore")
          }
      
          release {
              storeFile file("my-release-key.keystore")
              storePassword ""
              keyAlias "release_key"
              keyPassword ""
          }
      }
      

      【讨论】:

        【解决方案5】:

        Google 最近添加了一种官方方式来执行此操作,请参阅 https://developer.android.com/studio/publish/app-signing.html#secure-shared-keystore

        它可能无法回答我最初的问题(询问密码),但我认为这是简化部署和保证凭据安全的更好方法。

        【讨论】:

          猜你喜欢
          • 2021-06-10
          • 2021-02-17
          • 1970-01-01
          • 2020-05-16
          • 1970-01-01
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多