首页 文章

如何使用Gradle创建一个发布签名的apk文件?

提问于
浏览
458

我想让我的Gradle构建使用Gradle创建一个发布签名的apk文件 .

我'm not sure if the code is correct or if I'在做 gradle build 时缺少一个参数?

这是我的gradle文件中的一些代码:

android {
    ...
    signingConfigs {
          release {
              storeFile file("release.keystore")
              storePassword "******"
              keyAlias "******"
              keyPassword "******"
         }
     }
}

gradle构建完成SUCCESSFUL,在我的 build/apk 文件夹中,我只看到 ...-release-unsigned.apk...-debug-unaligned.apk 文件 .

有关如何解决这个问题的任何建议?

26 回答

  • 21

    这是对user672009的回复以及sdqali's post的补充(他的代码将因IDE的"Run"按钮构建调试版本而崩溃):

    您可以使用以下代码:

    final Console console = System.console();
    if (console != null) {
    
        // Building from console 
        signingConfigs {
            release {
                storeFile file(console.readLine("Enter keystore path: "))
                storePassword console.readLine("Enter keystore password: ")
                keyAlias console.readLine("Enter alias key: ")
                keyPassword console.readLine("Enter key password: ")
            }
        }
    
    } else {
    
        // Building from IDE's "Run" button
        signingConfigs {
            release {
    
            }
        }
    
    }
    
  • 14

    如果你不想看到 Cannot invoke method readLine() on null object. ,你需要先写入 gradle.properties .

    KEYSTORE_PASS=*****
    ALIAS_NAME=*****
    ALIAS_PASS=*****
    
  • 9

    我有几个问题,我把以下行放在错误的地方:

    signingConfigs {
        release {
            // We can leave these in environment variables
            storeFile file("d:\\Fejlesztés\\******.keystore")
            keyAlias "mykey"
    
            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "*****"
            keyPassword "******"
        }
    }
    

    确保将signingConfigs部分放在android部分中:

    android
    {
        ....
        signingConfigs {
            release {
              ...
            }
        }
    }
    

    代替

    android
    {
        ....
    }
    
    signingConfigs {
       release {
            ...
       }
    }
    

    很容易犯这个错误 .

  • 27

    在较新的Android Studio中,有一种非常简单的GUI方式,它也可以填充Gradle文件 .

    • File -> Project Structure

    • Module -> 选择主模块('app'或其他自定义名称)

    • Signing tab - > Plus image添加新配置

    • 在右侧填写数据

    • 确定并自动创建Gradle文件

    • 您将手动在 builtTypes{release{}} 内添加一行 signingConfig signingConfigs.NameOfYourConfig

    图片:

    enter image description here

    enter image description here

    两个重要的(!)笔记:

    (编辑12/15)

    • 要创建已签名的APK,您必须打开Android Studio的终端选项卡(主界面的底部)并发出命令 ./gradlew assembleRelease

    • 如果您忘记 keyAlias (我经常会发生什么),您必须启动 Build -> Generate Signed APK 以启动该过程并查看别名键的名称 .

  • 17

    就像@Destil所说,但允许其他没有密钥构建的人:比以前的答案更容易:

    把它放入 ~/.gradle/gradle.properties

    RELEASE_STORE_FILE={path to your keystore}
    RELEASE_STORE_PASSWORD=*****
    RELEASE_KEY_ALIAS=*****
    RELEASE_KEY_PASSWORD=*****
    

    像这样修改你的 build.gradle

    ...    
    if(project.hasProperty("RELEASE_STORE_FILE")) {
        signingConfigs {    
           release {
               storeFile file(RELEASE_STORE_FILE)
               storePassword RELEASE_STORE_PASSWORD
               keyAlias RELEASE_KEY_ALIAS
               keyPassword RELEASE_KEY_PASSWORD
           }
        }
    }
    
    buildTypes {
        if(project.hasProperty("RELEASE_STORE_FILE")) {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
    ....
    

    然后你可以运行 gradle assembleReleasegradle build

  • 14

    如果你像我一样通过命令行构建apk,那么你可以提供签名配置作为参数 .

    将此添加到您的 build.gradle

    def getStore = { ->
        def result = project.hasProperty('storeFile') ? storeFile : "null"
        return result
    }
    
    def getStorePassword = { ->
        def result = project.hasProperty('storePassword') ? storePassword : ""
        return result
    }
    
    def getKeyAlias = { ->
        def result = project.hasProperty('keyAlias') ? keyAlias : ""
        return result
    }
    
    def getKeyPassword = { ->
        def result = project.hasProperty('keyPassword') ? keyPassword : ""
        return result
    }
    

    像你这样做 signingConfigs

    signingConfigs {
        release {
            storeFile file(getStore())
            storePassword getStorePassword()
            keyAlias getKeyAlias()
            keyPassword getKeyPassword()
        }
    }
    

    然后你像这样执行 gradlew

    ./gradlew assembleRelease -PstoreFile="keystore.jks" -PstorePassword="password" -PkeyAlias="alias" -PkeyPassword="password"
    
  • 6
    android {
        compileSdkVersion 17
        buildToolsVersion "19.0.3"
    
        defaultConfig {
            minSdkVersion 9
            targetSdkVersion 18
        }
    
        File signFile = rootProject.file('sign/keystore.properties')
        if (signFile.exists()) {
            Properties properties = new Properties()
            properties.load(new FileInputStream(signFile))
            signingConfigs {
                release {
                    storeFile rootProject.file(properties['keystore'])
                    storePassword properties['storePassword']
                    keyAlias properties['keyAlias']
                    keyPassword properties['keyPassword']
                }
            }
        }
    
        buildTypes {
            release {
                runProguard true
                zipAlign true
                proguardFile rootProject.file('proguard-rules.cfg')
                signingConfig signingConfigs.release
            }
            debug {
                runProguard false
                zipAlign true
            }
        }
    }
    
  • 1

    Android Studio转到 File -> Project Structure 或按Ctrl Alt Shift S.

    见图像

    单击确定

    然后,signedConfigs将在build.gradle文件上生成 .

  • -1

    (回复上面的user672009 . )

    如果您想将密码保存在git存储库之外,那么这是一个更简单的解决方案;但是,想要在其中包含build.gradle,即使对于产品风格也很好,就是创建一个单独的gradle文件 . 我们称之为'signing.gradle'(将其包含在您的.gitignore中) . 就像它是你的build.gradle文件减去与登录无关的一切 .

    android {
        signingConfigs { 
            flavor1 {
                storeFile file("..")
                storePassword ".."
                keyAlias ".."
                keyPassword ".."
            }
            flavor2 {
                storeFile file("..")
                storePassword ".."
                keyAlias ".."
                keyPassword ".."
            }
        }
    }
    

    然后在你的build.gradle文件中包含这行“apply plugin:'android'”

    apply from: 'signing.gradle'
    

    如果您没有或使用多种口味,请将“flavor1”重命名为“release”,然后您应该完成 . 如果你正在使用口味继续 .

    最后将你的风格链接到build.gradle文件中正确的signingConfig,你应该完成了 .

    ...
    
      productFlavors {
    
          flavor1 {
              ...
              signingConfig signingConfigs.flavor1
          }
    
          flavor2 {
              ...
              signingConfig signingConfigs.flavor2
          }
      }
    
      ...
    
  • 4

    如果您已经拥有密钥库文件,则可以像在构建命令中添加一些参数一样简单:

    ./gradlew assembleRelease \
     -Pandroid.injected.signing.store.file=$KEYFILE \
     -Pandroid.injected.signing.store.password=$STORE_PASSWORD \
     -Pandroid.injected.signing.key.alias=$KEY_ALIAS \
     -Pandroid.injected.signing.key.password=$KEY_PASSWORD
    

    无需对您的Android项目进行永久性更改 .

    资料来源:http://www.tinmith.net/wayne/blog/2014/08/gradle-sign-command-line.htm

  • 55

    扩展David Vavra的答案,创建一个文件〜/ .gradle / gradle.properties并添加

    RELEASE_STORE_FILE=/path/to/.keystore
    RELEASE_KEY_ALIAS=XXXXX
    RELEASE_STORE_PASSWORD=XXXXXXXXX
    RELEASE_KEY_PASSWORD=XXXXXXXXX
    

    然后在build.gradle中

    signingConfigs {
        release {
        }
      }
    
      buildTypes {
        release {
          minifyEnabled true
          shrinkResources true
    
        }
      }
    
      // make this optional
      if ( project.hasProperty("RELEASE_KEY_ALIAS") ) {
        signingConfigs {
          release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
          }
        }
        buildTypes {
          release {
            signingConfig signingConfigs.release
          }
        }
      }
    
  • 8

    另一种方法是定义仅在发布版本上运行的任务 .

    android {
      ...
      signingConfigs {
         release {
            // We can leave these in environment variables
            storeFile file('nameOfKeystore.keystore')
            keyAlias 'nameOfKeyAlias'
    
            // These two lines make gradle believe that the signingConfigs
            // section is complete. Without them, tasks like installRelease
            // will not be available!
            storePassword "notYourRealPassword"
            keyPassword "notYourRealPassword"
    
         }
      }
      buildTypes {
         ...
         release {
            signingConfig signingConfigs.release
            ...
         }
      }
      ...
    }
    
    task setupKeystore << {
    final Console console = System.console();
    if (console != null) {
        //def keyFile = console.readLine(“\nProject: “ + project.name + “Enter keystore path: "))
        //def keyAlias = console.readLine(“Project: “ + project.name + “Enter key alias: ")
            def storePw = new String(console.readPassword(“Project: “ + project.name + “. Enter keystore password: "))
            def keyPw  = new String(console.readPassword(“Project: “ + project.name + “.Enter keystore password: "))
    
        //android.signingConfigs.release.storeFile = file(keyFile);
        //android.signingConfigs.release.keyAlias = keyAlias
            android.signingConfigs.release.storePassword = storePw
            android.signingConfigs.release.keyPassword = keyPw
    }
    }
    
    //Validate t
    def isReleaseConfig = gradle.startParameter.taskNames.any {it.contains('Release') }
    if (isReleaseConfig) {
        setupKeystore.execute();
    }
    
  • 10

    如果您想避免在 build.gradle 中对密钥库和密码进行硬编码,可以使用如下所述的属性文件:HANDLING SIGNING CONFIGS WITH GRADLE

    基本上:

    1)在 /home/[username]/.signing 创建一个myproject.properties文件,其中包含以下内容:

    keystore=[path to]\release.keystore
    keystore.password=*********
    keyAlias=***********
    keyPassword=********
    

    2)使用以下内容创建一个gradle.properties文件(可能位于项目目录的根目录下):

    MyProject.properties=/home/[username]/.signing/myproject.properties
    

    3)在你的_216666中引用它,如下所示:

    if(project.hasProperty("MyProject.properties")
            && new File(project.property("MyProject.properties")).exists()) {
    
        Properties props = new Properties()
        props.load(new FileInputStream(file(project.property("MyProject.properties"))))
    
        signingConfigs {
            release {
                storeFile file(props['keystore'])
                storePassword props['keystore.password']
                keyAlias props['keyAlias']
                keyPassword props['keyPassword']
            }
        }
    }
    
  • 3

    我在Ubuntu14.04工作 . vim~ / .bashrc并添加导出ANDROID_KEYSTORE = export ANDROID_KEYALIAS =

    然后在build.gradle中 .

    final Console console = System.console();
    if (console != null) {
    
        // Building from console
        signingConfigs {
            release {
                storeFile file(System.getenv("KEYSTORE"))
                storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
                keyAlias System.getenv("KEY_ALIAS")
                keyPassword new String(System.console().readPassword("\n\$ Enter key password: "))
            }
        }
    
    } else {
    
        // Building from IDE's "Run" button
        signingConfigs {
            release {
    
            }
        }
    
    }
    
  • 5

    另一种解决同一问题的方法 . 由于不建议在源代码中存储任何类型的凭据,因此我们决定在单独的属性文件中设置密钥库和密钥别名的密码,如下所示:

    key.store.password=[STORE PASSWORD]
    key.alias.password=[KEY PASSWORD]
    

    如果使用git,则可以创建一个名为secure.properties的文本文件 . 您应确保将其从存储库中排除(如果使用git,则将其添加到.gitignore文件中) . 然后,您需要创建一个签名配置,就像其他一些答案所示 . 唯一的区别在于您将如何加载凭据:

    android {
        ...
        signingConfigs {
            ...
            release {
                storeFile file('[PATH TO]/your_keystore_file.jks')
                keyAlias "your_key_alias"
    
                File propsFile = file("[PATH TO]/secure.properties");
                if (propsFile.exists()) {
                    Properties props = new Properties();
                    props.load(new FileInputStream(propsFile))
                    storePassword props.getProperty('key.store.password')
                    keyPassword props.getProperty('key.alias.password')
                }
            }
            ...
        }
    
        buildTypes {
            ...
            release {
                signingConfig signingConfigs.release
                runProguard true
                proguardFile file('proguard-rules.txt')
            }
            ...
        }
    }
    

    永远不要忘记手动将signingConfig分配给发布版本类型(出于某种原因,我有时会假设它会自动使用) . 此外,启用proguard并非强制要求,但确实如此值得推荐的 .

    我们比使用环境变量或请求用户输入更喜欢这种方法,因为它可以通过切换到realease构建类型并运行应用程序从IDE完成,而不必使用命令行 .

  • 1

    几乎所有平台现在都提供某种密钥环,因此没有理由留下明文密码 .

    我提出了一个简单的解决方案,它使用Python Keyring module(主要是配套控制台脚本 keyring )和Groovy的最小包装 ['do', 'something'].execute() feature

    def execOutput= { args ->
        def proc = args.execute()
        proc.waitFor()
        def stdout = proc.in.text
        return stdout.trim()
    }
    

    使用此功能, signingConfigs 部分变为:

    signingConfigs {
        release {
            storeFile file("android.keystore")
            storePassword execOutput(["keyring", "get", "google-play", storeFile.name])
            keyAlias "com.example.app"
            keyPassword execOutput(["keyring", "get", "google-play", keyAlias])
        }
    }
    

    在运行 gradle assembleRelease 之前,您必须在密钥环中设置密码,只需一次:

    $ keyring set google-play android.keystore # will be prompted for the passwords
    $ keyring set google-play com.example.app
    

    快乐发布!

  • -1

    我非常有趣地想出这个 . 这是我的演练 .

    关于如何在IntelliJ中创建gradle构建文件的A到Z演练(v.13.1.4)本演练假定您知道如何制作密钥库文件 . 要使本教程起作用,您需要将密钥库文件放在app文件夹中,并且需要将zipalign.exe文件放在“SDK-ROOT \ tools”中 . 这个文件通常位于'SDK-ROOT \ build-tools'中,在这个文件夹下,它将位于最高的api文件夹中(alpha或beta我推荐使用alpha版本) .

    对于那些希望直接进入这里的人来说,是gradle构建文件 .

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:0.9.+'
        }
    }
    apply plugin: 'android'
    
    repositories {
        mavenCentral()
    }
    android {
        compileSdkVersion 19
        buildToolsVersion '20.0.0'
        defaultConfig {
            minSdkVersion 8
            targetSdkVersion 19
            versionCode 1
            versionName "1.0"
        }
        signingConfigs {
            playstore {
                keyAlias 'developers4u'
                keyPassword 'thisIsNotMyRealPassword'
                storeFile file('developers4u.keystore')
                storePassword 'realyItIsNot'
            }
        }
        buildTypes {
            assembleRelease {
                debuggable false
                jniDebugBuild false
                runProguard true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
                zipAlign true
                signingConfig signingConfigs.playstore
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:support-v4:20.0.0'
        compile 'com.android.support:appcompat-v7:20.0.0'
    }
    

    您可以从菜单选项构建此构建文件的一部分(上图):文件/项目结构从此处选择构面并单击“Android-Gradle(App)” . 从这里你会看到标签:'属性','签名','风味','构建类型'和'依赖关系'这个演练我们将使用'签名'和'构建类型' . 在“构建类型”(在名称部分)下,输入您希望识别构建类型配置的任何名称,并在其他4个字段中输入您的密钥库信息(将密钥库路径设置为您的app文件夹下的密钥库路径) .

    在'Build Types'下,在name字段中输入值'assembleRelease','Debuggable'应设置为false,'Jni Debug Build'应为false,将'Run Proguard'设置为true,将'Zip Align'设置为true . 这将生成构建文件,但不是如上所述,之后您将不得不向构建文件添加一些内容 . 此处的ProGuard文件位置将在gradle构建文件中手动设置 . (如上所述)

    之后您必须添加的DSL容器如下:

    android {
        ....
        compileSdkVersion 19
        buildToolsVersion '20.0.0'
        defaultConfig {
            minSdkVersion 8
            targetSdkVersion 19
            versionCode 1
            versionName "1.0"
        }
        ....
    }
    

    您还必须添加:

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:support-v4:20.0.0'
        compile 'com.android.support:appcompat-v7:20.0.0'
    }
    

    注意上面的这个DSL容器('dependencies')应该在配置文件的底部,但不在android DSL容器内 . 要从IntelliJ菜单构建依赖项容器,请选择:文件/项目结构 . 从那里再次选择Facets然后选择Android-Gradle(app) . 您将看到与上面提到的相同的5个选项卡 . 选择“依赖关系”选项卡并添加所需的依赖关系 .

    完成所有这些操作后,您应该看到一个Gradle构建文件,类似于此演练顶部的文件 . 要构建已签名的zip对齐版本,您需要打开Gradle任务 . 您可以通过选择View / Tool Windows / Gradle来访问此窗口 . 从这里你可以双击'assembleAssembleRelease . 这应该生成可部署的APK .

    编译发行版时可能出现的潜在问题是(但不限于):您的Gradle构建文件位于错误的位置 . 有两个Gradle构建文件;一个在应用程序根文件夹中,另一个在应用程序根目录下的app文件夹中 . 你必须使用后者 .

    您可能还有皮棉问题 . (注意:Android Developer Studio在发现Lint问题方面要比IntelliJ好得多,你会在尝试从菜单选项生成签名的APK时注意到这一点)

    要解决lint问题,你需要将以下DSL容器放在android容器中(在顶部):

    android {
            ....
        lintOptions {
            abortOnError false
        }
        ....
    }
    

    把它放在你的android DSL容器里会导致在build文件夹中生成一个错误文件(直接在你的app文件夹下),文件名应该是'lint-results-release-fatal.html',这个文件会告诉你发生错误的类 . 将生成的另一个文件是XML文件,其中包含与lint错误关联的“问题ID” . 文件名应该类似于'lint-results-release-fatal.xml' . 在文件顶部附近的某处,您将看到一个节点“问题”,在其中您将看到类似于'id =“IDOfYourLintProblem”'的内容

    要解决此问题,请在项目中打开“lint-results-assembleRelease-fatal.html”文件中列出的文件,并在类名称上方的Java类文件中输入以下代码行:@SuppressLint(“IDOfYourLintProblem” “) . 您可能必须导入'android.annotation.SuppressLint;'

    所以你的java类文件应该如下所示:

    package com.WarwickWestonWright.developers4u.app.CandidateArea;
    
    import android.annotation.SuppressLint;
    ... other imports
    
    @SuppressLint("IDOfYourLintProblem")
    public class SearchForJobsFragment extends Fragment {... rest of your class definition}
    

    请注意,抑制lint错误并不总是最好的IDEA,您可能最好更改导致lint错误的代码 .

    可能的另一个问题如果您尚未为Gradle HOME环境变量设置环境变量,则可能发生 . 这个变量名为'GRADLE_HOME',应该设置gradle主目录的路径,比如'C:\ gradle-1.12'有时您可能还想为'ANDROID_HOME'设置环境变量,将其设置为'YOUR- SDK-ROOT \ SDK”

    完成此操作后,返回Gradle任务窗口并双击assembleAssembleRelease .

    如果一切顺利,您应该能够访问app \ build \ apk文件夹并找到可部署的APK文件 .

  • 1

    我设法解决它添加此代码,并使用 gradle build 构建:

    android {
        ...
        signingConfigs {
            release {
                storeFile file("release.keystore")
                storePassword "******"
                keyAlias "******"
                keyPassword "******"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
    }
    

    这会生成一个签名版本的apk文件 .

  • 32

    比以前的答案更容易:

    把它放入 ~/.gradle/gradle.properties

    RELEASE_STORE_FILE={path to your keystore}
    RELEASE_STORE_PASSWORD=*****
    RELEASE_KEY_ALIAS=*****
    RELEASE_KEY_PASSWORD=*****
    

    像这样修改 build.gradle

    ...    
    signingConfigs {
    
       release {
           storeFile file(RELEASE_STORE_FILE)
           storePassword RELEASE_STORE_PASSWORD
           keyAlias RELEASE_KEY_ALIAS
           keyPassword RELEASE_KEY_PASSWORD
       }
    }
    
    buildTypes {
            release {
                signingConfig signingConfigs.release
            }
    }
    ....
    

    然后你可以运行 gradle assembleRelease

  • 2

    您可以从命令行请求密码:

    ...
    
    signingConfigs {
      if (gradle.startParameter.taskNames.any {it.contains('Release') }) {
        release {
          storeFile file("your.keystore")
          storePassword new String(System.console().readPassword("\n\$ Enter keystore password: "))
          keyAlias "key-alias"
          keyPassword new String(System.console().readPassword("\n\$ Enter keys password: "))
        } 
      } else {
        //Here be dragons: unreachable else-branch forces Gradle to create
        //install...Release tasks.
        release {
          keyAlias 'dummy'
          keyPassword 'dummy'
          storeFile file('dummy')
          storePassword 'dummy'
        } 
      }
    }
    
    ...
    
    buildTypes {
      release {
    
        ...
    
        signingConfig signingConfigs.release
      }
    
      ...
    }
    
    ...
    

    if-then-else 阻止在您构建版本时阻止对密码的请求 . 虽然 else 分支无法访问,但它会欺骗Gradle创建 install...Release 任务 .

    Backstory . 如https://stackoverflow.com/a/19130098/3664487所述,“Gradle脚本可以使用System.console() . readLine方法提示用户输入 . ”不幸的是,Gradle将始终请求密码,即使您正在构建调试版本(参见How to create a release signed apk file using Gradle?) . 幸运的是,正如我上面所示,这可以克服 .

  • 2

    如果您和我一样希望能够在您的设备上运行发布以进行测试,请考虑 creating a second keystore 进行签名,这样您就可以 simply put the passwords for it into your build.gradle 而无需担心您的市场密钥存储安全性 .

    您可以通过单击构建/生成签名APK /创建新的来创建新的密钥库...

  • 348

    如果您可以在所有项目中重用相同的配置,那么@ Destil的答案很好 . 或者,Android Studio附带了一个可以替代使用的 local.properties 文件,但它找到了一种从Android Studio中扩展它的方法 .

    这是@jonbo's answer的变体 . 该答案允许项目特定的设置,但它带来一些开发人员的开销 . 具体而言,需要使用重要的样板来将 signingConfigs 定义移动到单独的文件中 - 特别是如果您需要为多个项目执行此操作,这是在Destil上选择此解决方案的主要原因 . 这也可以通过包括线来稍微减轻

    apply plugin: 'com.android.application'
    

    在凭证文件中,因为这将允许IDE完成 .

    最后,这里的大多数解决方案都不允许在调试模式下构建项目 - 它自动处理调试签名 - 而不提供语法上(如果不是语义上有效的) signingConfigs 定义 . 如果您不需要从给定的机器生成版本构建,则可以将此额外步骤视为不必要的障碍 . 另一方面,它可以帮助对付在 生产环境 中运行调试版本的无知或懒惰的同事 .

    这个解决方案将允许调试构建而不必担心凭据,但它需要有效的凭据来生成发布版本,并且它只需要很少的样板 . 然而,作为一个缺点 it might encourage others to replace dummy values with real credentials 并且没有办法防止这种情况发生 .

    // app/build.gradle
    // Define this structure in signing.gradle to enable release builds.
    ext.signing = [
            storeFilePath : 'path/to/keystore',
            storePassword : 'keystore password',
            keyAlias      : 'key alias',
            keyPassword   : 'key password',
    ]
    
    if (file('signing.gradle').exists()) {
        apply from: 'signing.gradle'
    }
    
    android {
        ...
        signingConfigs {
            release {
                storeFile file(project.signing.storeFilePath)
                storePassword project.signing.storePassword
                keyAlias project.signing.keyAlias
                keyPassword project.signing.keyPassword
            }
        }
        buildTypes {
            debug { ... }
            release {
                signingConfig signingConfigs.release
                ...
            }
        }
    }
    

    这将创建一个虚拟属性,纯粹用于生成语法上有效的构建文件 . 在调试版本中,分配给 ext.signing 属性的值无关紧要 . 要启用发布版本,请将 ext.signing 复制到 signing.gradle 并使用有效凭据替换虚拟值 .

    // signing.gradle
    ext.signing = [
            storeFilePath : 'real/keystore',
            storePassword : 'real keystore password',
            keyAlias : 'real key alias',
            keyPassword : 'real key password',
    ]
    

    当然,VCS应该忽略 signing.gradle .

  • 5

    请注意,@ sdqali的脚本(至少在使用Gradle 1.6时)会在您调用任何gradle任务时随时询问密码 . 因为你在做 gradle assembleRelease (或类似)时只需要它,你可以使用以下技巧:

    android {
        ...
        signingConfigs {
            release {
                // We can leave these in environment variables
                storeFile file(System.getenv("KEYSTORE"))
                keyAlias System.getenv("KEY_ALIAS")
    
                // These two lines make gradle believe that the signingConfigs
                // section is complete. Without them, tasks like installRelease
                // will not be available!
                storePassword "notYourRealPassword"
                keyPassword "notYourRealPassword"
            }
        }
        ...
    }
    
    task askForPasswords << {
        // Must create String because System.readPassword() returns char[]
        // (and assigning that below fails silently)
        def storePw = new String(System.console().readPassword("Keystore password: "))
        def keyPw  = new String(System.console().readPassword("Key password: "))
    
        android.signingConfigs.release.storePassword = storePw
        android.signingConfigs.release.keyPassword = keyPw
    }
    
    tasks.whenTaskAdded { theTask -> 
        if (theTask.name.equals("packageRelease")) {
            theTask.dependsOn "askForPasswords"
        }
    }
    

    请注意,我还必须添加以下(在android下)以使其工作:

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
    
  • 63

    为了补充其他答案,您还可以将gradle.properties文件与build.gradle一起放在您自己的模块文件夹中,以防您的密钥库特定于一个项目 .

  • 1

    使用git时使用Gradle自动签名

    令人惊讶的是,有多少令人费解的方式可以做到这一点 . 这是我自己的方式,我试图坚持谷歌自己的recommendation . 但是,他们的解释并不完全清楚,因此我将详细介绍Linux的过程 .


    描述:

    用于在构建期间自动签署应用程序的默认Google instructions,而不会将密码和签名文件保留在应用程序开发(GIT)路径中,这是相当模糊的 . 以下是如何执行此操作的明确说明 .

    初步假设:

    您在以下路径指定的目录中有一个名为"MyApp"的应用程序: $HOME/projects/mydev/MyApp . 但是,MyApp目录由GIT使用和控制 .

    问题

    我们显然不希望在GIT控制目录中的任何地方都有我们的签名或密码文件,即使我们非常能够使用 .gitignore 等,它仍然过于冒险和容易弄错了 . 所以我们想要外面的密钥库和签名文件 .

    解决方案

    我们需要做三(3)件事:

    • 创建供Android Studio使用的密码文件

    • 创建签名密钥文件

    • 编辑模块 build.gradle 文件以使用(1)和(2) .

    在本例中,我们将这两个文件命名为:

    • keystore.properties

    • MyApp-release-key.jks

    我们可以在这里放置这两个文件:

    cd $HOME/projects/mydev/
    

    (1)创建密钥库密码文件

    第一个文件包含使用的明文密码;和(2)中的release-key文件的路径 . 首先填写此内容,因为它将使下一步的复制粘贴操作更容易 .

    cd $HOME/projects/mydev/
    

    编辑 keystore.properties ,使其内容为:

    storePassword=myStorePassword
    keyPassword=mykeyPassword
    keyAlias=myKeyAlias
    storeFile=myStoreFileLocation
    

    这里唯一棘手的部分是 myStoreFileLocation . 这是构建期间模块 build.gradle 文件的路径 as seen from . 这通常意味着类似于以下的路径: $HOME/projects/mydev/MyApp/app/build.gradle . 所以为了指向 MyApp-release-key.jks 文件,我们需要放在这里:

    ../../../MyApp-release-key.jks

    在这里,我们还为密钥选择了“myapp”别名 . 然后最终文件应该看起来:

    storePassword=myStorePassword
    keyPassword=mykeyPassword
    keyAlias=myapp
    storeFile=../../../MyApp-release-key.jks
    

    (2)创建签名文件

    创建签名密钥时会自动生成第二个文件 . 如果您没有其他应用程序且这是您唯一的密钥库,则使用以下命令创建文件:

    cd $HOME/projects/mydev/
    keytool -genkeypair -v -keystore MyApp-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myapp
    

    这将要求您提供两个密码和一堆信息 . (与Android Studio中的内容相同 . )现在复制/粘贴您之前选择的密码 .

    (3)编辑模块gradle.build文件以使用上述内容

    您的app / module的Gradle构建文件中需要包含以下部分 . 首先,添加以下行 outsidebefore 您的 android {} 块 .

    //def keystorePropertiesFile = rootProject.file("$HOME/.android/keystore.properties")
    def keystorePropertiesFile = rootProject.file("../../keystore.properties")
    def keystoreProperties = new Properties()
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    

    然后, inside android {} 块,添加:

    android {
        ...
        defaultConfig { ... }
        signingConfigs {
                release {
                    keyAlias keystoreProperties['keyAlias']
                    keyPassword keystoreProperties['keyPassword']
                    storeFile file(keystoreProperties['storeFile'])
                    storePassword keystoreProperties['storePassword']
                }
            }
        // Tell Gradle to sign your APK
        buildTypes {
            release {
                signingConfig signingConfigs.release
                ...
            }
        }
    }
    

    现在从shell,您可以使用以下命令重新构建您的应用:

    cd $HOME/projects/mydev/MyApp/app/
    ./gradlew clean build
    

    这应该会生成一个可以在Google Play中使用的正确签名的应用 .

  • 240

    您还可以使用gradle的 -P 命令行选项来帮助签名 . 在你的build.gradle中,添加如下的singingConfigs:

    signingConfigs {
       release {
           storeFile file("path/to/your/keystore")
           storePassword RELEASE_STORE_PASSWORD
           keyAlias "your.key.alias"
           keyPassword RELEASE_KEY_PASSWORD
       }
    }
    

    然后像这样调用gradle build:

    gradle -PRELEASE_KEYSTORE_PASSWORD=******* -PRELEASE_KEY_PASSWORD=****** build
    

    如果您愿意,可以使用-P设置storeFile和keyAlias .

    这基本上是Destil的解决方案,但使用命令行选项 .

    有关gradle属性的更多详细信息,请查看gradle user guide .

相关问题