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

我不确定代码是否正确,或者我在做gradle构建时是否缺少一个参数?

这是build.gradle/build.gradle中的一些代码。节文件:

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

Gradle构建成功完成,在我的build/apk文件夹中,我只看到…-release-unsigned.apk和…-debug-unaligned.apk文件。

对如何解决这个问题有什么建议吗?


当前回答

@Destil的答案很好,如果你可以在所有项目中重用相同的配置。或者,Android Studio自带本地文件。可以使用的属性文件,但它应该是ide生成的,我找不到一种方法来扩展它从Android Studio。

这是@jonbo回答的一个变体。这个答案允许项目特定的设置,但它带来了一些开发人员的开销。具体来说,需要大量的样板文件来将signingConfigs定义移动到一个单独的文件中——特别是当您需要为多个项目这样做时,这是选择这个解决方案而不是Destil的主要原因。这可以通过包含线条在一定程度上得到缓解

apply plugin: 'com.android.application'

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

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

这个解决方案将允许调试构建而完全不用担心凭证,但是它将需要有效的凭证来生成发布构建,并且它只需要很少的样板文件。然而,作为一个缺点,它可能会鼓励其他人用真实的凭证替换虚拟值,并且没有办法防止这种情况。

// 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',
]

当然,签名。gradle应该被VCS忽略。

其他回答

如果您想避免在构建中硬编码您的密钥库和密码。gradle,你可以使用属性文件解释这里:处理签名配置与gradle

基本上:

1)创建一个myproject。属性文件在/home/[username]/。签名内容如下:

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

2)创建gradle。属性文件(可能在你的项目目录的根目录)的内容:

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

3)在你的构建中参考它。这样Gradle:

    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']
        }
    }
}

为了补充其他答案,你也可以放置gradle。属性文件与build一起放在您自己的模块文件夹中。Gradle,以防您的密钥库特定于一个项目。

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

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并不是强制性的,但建议这样做。

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

就像@Destil说的,但允许其他没有钥匙的人建造: 比之前的答案更简单的方法:

把它放到~/.gradle/gradle.properties中

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

修改构建。这样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 assemblerrelease 或 gradle构建

(回复user672009)

一个更简单的解决方案,如果你想让你的密码远离git存储库;但是,要包括您的构建。其中的Gradle,它甚至可以很好地处理产品口味,就是创建一个单独的Gradle文件。让我们称之为“签名”。Gradle '(包括它在你的。gitignore)。就像你的身材一样。Gradle文件减去所有与签名无关的东西。

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

然后在你的构建中。Gradle文件包括下面的这一行“应用插件:'android'”

 apply from: 'signing.gradle'

如果你没有或使用多种口味,将上面的“flavor1”重命名为“release”,你应该就完成了。如果你在使用香料,继续。

最后在构建中将您的flavor链接到正确的signingConfig。Gradle文件和你应该完成。

  ...

  productFlavors {

      flavor1 {
          ...
          signingConfig signingConfigs.flavor1
      }

      flavor2 {
          ...
          signingConfig signingConfigs.flavor2
      }
  }

  ...