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

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

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

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

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

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

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

346092 次浏览

我设法解决它添加这段代码,并与gradle build构建:

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

这将生成一个已签名的发布apk文件。

这是对user672009的回复和对sdqali的文章的补充(他的代码会在IDE的“运行”按钮构建调试版本时崩溃):

您可以使用以下代码:

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 {


}
}


}
注意@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
}
}

如果您想避免硬编码您的密钥库&密码在build.gradle,你可以使用一个属性文件解释在这里:使用gradle处理签名配置

基本上:

1)创建一个myproject。在/ .signing /home/[用户名)的属性文件中包含这样的内容:

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

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

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

3)像这样在build.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/gradle.properties

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

修改你的app/build.gradle,并将其添加到android {代码块中:

...
signingConfigs {


release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD


// Optional, specify signing versions used
v1SigningEnabled true
v2SigningEnabled true
}
}


buildTypes {
release {
signingConfig signingConfigs.release
}
}
....

然后您可以运行gradle assembleRelease


也参见signingConfigs Gradle DSL的参考

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

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 {
...
}
}

很容易犯这个错误。

(回复上面的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
}
}


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

现在几乎所有的平台都提供了某种密匙环,所以没有理由留下明文密码。

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

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

释放快乐!

你也可以使用gradle的- p命令行选项来帮助签名。在你的构建中。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用户指南

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

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=*****

像这样修改你的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 assembleRelease 或 # EYZ0 < / p >

我在计算这个过程中获得了很多乐趣。下面是我的演练。

如何在IntelliJ中创建gradle构建文件(v.13.1.4) 本演练假设您知道如何生成密钥存储库文件。 为了本教程的工作,你需要你的keystore文件位于你的应用文件夹,你需要有你的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 {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-v4:20.0.0'
implementation 'com.android.support:appcompat-v7:20.0.0'
}
你可以从菜单选项中构建这个构建文件的一部分(上面):文件/项目结构 从这里选择Facets,点击“Android-Gradle(App)”。 从这里,你会看到选项卡:“属性”,“签名”,“口味”,“构建类型”和“依赖关系”,在本教程中,我们将只使用“签名”和“构建类型”。 在“构建类型”(在名称部分)下输入任何您希望识别您的构建类型配置的名称,并在其他4个字段中输入您的密钥库信息(将密钥库路径设置为您的app文件夹下的路径)

在“构建类型”下,在名称字段中输入值“assemblerrelease”,“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 {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-v4:20.0.0'
implementation 'com.android.support:appcompat-v7:20.0.0'
}
注意上面的DSL容器('dependencies')应该在配置文件的底部,而不是在android DSL容器内。 为了从IntelliJ菜单中构建依赖项容器,选择:File/Project Structure。再次选择Facets,然后选择Android-Gradle(app)。您将看到与上述相同的5个选项卡。选择'Dependencies'选项卡并添加您需要的依赖项 所有这些都完成后,您应该看到一个与本演练顶部的文件类似的Gradle构建文件。 要构建你签名的zip对齐版本,你需要打开Gradle任务。你可以通过选择视图/工具窗口/Gradle来进入这个窗口。 在这里你可以双击' assembleassemblerrelease '。这将生成您的可部署APK

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

你也可能有棉绒问题。(注意: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'。在文件顶部的某个地方,你会看到一个节点'issue',在里面你会看到类似于'id="IDOfYourLintProblem"'

要纠正此问题,打开项目中'lint-results- assemblerrelease -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错误并不总是最好的想法,你可能会更好地改变导致lint错误的代码。

另一个可能发生的问题是,如果你没有为Gradle HOME环境变量设置环境变量。这个变量名为'GRADLE_HOME',应该设置为gradle主目录的路径,类似于'C:\gradle-1.12' 有时你可能还想设置'ANDROID_HOME'的环境变量,将其设置为'YOUR-SDK-Root\sdk'

完成后,返回Gradle任务窗口,双击assembleassemblerrelease。

如果一切都成功了,你应该能够进入app\build\apk文件夹并找到你的可部署apk文件。

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

@Destil的答案很好,如果你可以在所有项目中重用相同的配置。或者,Android Studio附带了一个local.properties文件,也许可以使用,但它应该是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',
]

当然,signing.gradle应该被vc忽略。

我在Ubuntu14.04工作。 vim ~ /。Bashrc和add 出口ANDROID_KEYSTORE = 出口ANDROID_KEYALIAS = < / p >

然后是构建。它集。

    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 {


}
}


}

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

  1. # EYZ0

  2. 选择主模块('app'或其他自定义名称)

  3. Signing标签->加图像添加新的配置

  4. 在右侧填写数据

  5. 然后自动创建Gradle文件

  6. 你必须手动在builtTypes{release{}}内添加一行signingConfig signingConfigs.NameOfYourConfig

图片:

enter image description here

enter image description here

两个重要的(!)注意事项:

(12/15)编辑

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

  2. 如果您忘记了keyAlias(这经常发生在我身上),您将不得不启动Build -> Generate Signed APK来启动进程,并看到别名键的名称。

另一种方法是定义一个只在发行版上运行的任务。

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

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

...


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任务。

# EYZ0。正如https://stackoverflow.com/a/19130098/3664487所指出的,“Gradle脚本可以使用System.console()提示用户输入。readLine方法.”不幸的是,Gradle总是会要求密码,即使你正在构建一个调试版本(参考如何使用Gradle创建一个发布签名apk文件?)。幸运的是,这是可以克服的,如上所述。

如果你像我一样通过命令行构建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"

如果你不想看到不能在空对象上调用readLine()方法。,你需要先写gradle.properties

KEYSTORE_PASS=*****
ALIAS_NAME=*****
ALIAS_PASS=*****

如果您像我一样,只是希望能够在您的设备上运行该版本用于测试目的,那么可以考虑使用创建第二个密钥库作为签名,这样您就可以使用简单地把密码放在build.gradle中,而不必担心市场密钥存储的安全性。

您可以通过单击Build/Generate Signed APK/ create new…来创建一个新的密钥库。

扩展David Vavra的回答,创建一个文件~/.gradle/gradle。属性和添加

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

使用git时使用Gradle自动应用程序签名

令人惊讶的是,有这么多复杂的方法可以做到这一点。这是我自己的方式,我试图坚持谷歌自己的建议。但是,他们的解释并不完全清楚,所以我将详细描述Linux的过程。


描述:

自动签名应用程序的默认谷歌的指令 在构建过程中,不保留密码和签名文件 在你的应用程序开发(GIT)路径中,是相当模糊的。这里是 详细说明了如何做到这一点。< / p >

最初的假设:

你有一个名为“MyApp”的应用程序,在以下路径给出的目录中: # EYZ0。但是,使用MyApp目录和 由GIT控制。< / p >

enter image description here

问题

我们显然不希望我们的签名或密码文件在任何地方 GIT控制的目录,即使我们很会使用.gitignore等,仍然太冒险,容易出错。因此,我们希望我们的密钥存储库和签名文件在外部

解决方案

我们需要做三件事:

  1. 创建一个Android Studio使用的密码文件
  2. 创建签名密钥文件
  3. 编辑模块build.gradle文件以使用(1)和(2)。

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

  1. # EYZ0
  2. # EYZ0

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

cd $HOME/projects/mydev/

(1)创建keystore密码文件

第一个文件包含明文密码;和(2)中释放密钥文件的路径。从填写这个开始,因为它将使下一步的复制粘贴操作更容易。

cd $HOME/projects/mydev/

编辑keystore.properties,使它的内容是:

storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
这里唯一棘手的部分是myStoreFileLocation。这是路径,在构建过程中模块build.gradle文件。这通常意味着一个类似于:$HOME/projects/mydev/MyApp/app/build.gradle的路径。为了指向MyApp-release-key.jks 文件,我们需要在这里放的是:

# EYZ0

这里,我们还为键选择了“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文件来使用上面的内容

以下部分需要出现在你的应用/模块的Gradle构建文件中。首先,在android {}块中添加以下行之前

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

然后,内部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

这应该生成一个正确签名的应用程序,可以在谷歌播放中使用。


# EYZ0 2019-04-02

keytool某物的最新版本告诉你,你应该使用一个基于PKCS12的键文件,而不是我上面使用的原始/默认键文件。他们然后继续告诉你你应该转换到新的开放PKCS12格式。然而,似乎Android开发工具还没有完全准备好,因为如果你这样做了,你会得到以下奇怪的错误:

com.android.ide.common.signing.KeytoolException:读取密钥失败 “F:\XXX\XXX.”获取键失败:给定的最终块没有 适当的衬垫。如果在过程中使用了错误的密钥,就会出现这种问题 解密。< / p >

所以不要使用转换后的密钥!

如果您已经拥有密钥存储库文件,那么只需向构建命令中添加一些参数即可:

./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项目进行永久性更改。

来源:# EYZ0

< p > Android工作室 转到File ->项目结构或按Ctrl+Alt+Shift+S

查看图片

enter image description here

单击Ok

然后在构建中生成signingconfig。gradle文件。

enter image description here

现在是2019年,我需要用V1 (jar签名)或V2(完整APK签名)签署APK。我谷歌了“生成签名apk gradle”,它把我带到了这里。我把原来的解加到这里。

signingConfigs {
release {
...
v1SigningEnabled true
v2SigningEnabled true
}
}

我最初的问题:如何使用V1 (Jar签名)或V2(完整的APK签名)从构建。gradle文件

在React-Native中使用react-native-config包添加我的方法 创建一个。env文件:

RELEASE_STORE_PASSWORD=[YOUR_PASSWORD]
RELEASE_KEY_PASSWORD=[YOUR_PASSWORD]

注意,这不应该是版本控制的一部分。

在你的build.gradle:

signingConfigs {
debug {
...
}
release {
storeFile file(RELEASE_STORE_FILE)
storePassword project.env.get('RELEASE_STORE_PASSWORD')
keyAlias RELEASE_KEY_ALIAS
keyPassword project.env.get('RELEASE_KEY_PASSWORD')
}
}

就我而言,我上传了错误的apk到另一个应用程序的发布中。

对于Groovy (build.gradle)

您不应该将签名凭据直接放在build.gradle文件中。相反,凭证应该来自不受版本控制的文件。

在找到特定模块build.gradle的地方放置一个文件signing.properties。不要忘记将它添加到您的.gitignore文件!

signing.properties

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle

android {
// ...
signingConfigs{
release {
def props = new Properties()


def fileInputStream = new FileInputStream(file('../signing.properties'))
props.load(fileInputStream)
fileInputStream.close()


storeFile = file(props['storeFilePath'])
storePassword = props['storePassword']
keyAlias = props['keyAlias']
keyPassword = props['keyPassword']
}
}


buildTypes {
release {
signingConfig signingConfigs.release
// ...
}
}
}

对于Kotlin脚本(build.gradle.kts)

您不应该将签名凭据直接放在build.gradle.kts文件中。相反,凭证应该来自不受版本控制的文件。

在找到特定模块build.gradle.kts的地方放置一个文件signing.properties。不要忘记将它添加到您的.gitignore文件!

signing.properties

storeFilePath=/home/willi/example.keystore
storePassword=secret
keyPassword=secret
keyAlias=myReleaseSigningKey

build.gradle.kts

android {
// ...
signingConfigs {
create("release") {
val properties = Properties().apply {
load(File("signing.properties").reader())
}
storeFile = File(properties.getProperty("storeFilePath"))
storePassword = properties.getProperty("storePassword")
keyPassword = properties.getProperty("keyPassword")
keyAlias = "release"
}
}


buildTypes {
getByName("release") {
signingConfig = signingConfigs.getByName("release")
// ...
}
}
}

这是Kotlin构建脚本 (build.gradle.kts)与威利·门泽尔的回答不同的另一个答案。

它尝试从local.properties文件读取,返回到OS环境变量。它在像GitHub Actions这样的ci中特别有用(你可以在存储库设置中创建环境秘密)。

注意,我使用的是Kotlin 1.6.10和Gradle 7.4.2和Android Gradle Plugin (AGP) 7.0.4。

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
// ...


val environment = System.getenv()
fun getLocalProperty(key: String) = gradleLocalProperties(rootDir).getProperty(key)
fun String.toFile() = File(this)


android {
signingConfigs {
create("MySigningConfig") {
keyAlias = getLocalProperty("signing.keyAlias") ?: environment["SIGNING_KEY_ALIAS"] ?: error("Error!")
storeFile = (getLocalProperty("signing.storeFile") ?: environment["SIGNING_STORE_FILE"] ?: error("Error!")).toFile()
keyPassword = getLocalProperty("signing.keyPassword") ?: environment["SIGNING_KEY_PASSWORD"] ?: error("Error!")
storePassword = getLocalProperty("signing.storePassword") ?: environment["SIGNING_STORE_PASSWORD"] ?: error("Error!")
enableV1Signing = true
enableV2Signing = true
}
}


buildTypes {
release {
signingConfig = signingConfigs["MySigningConfig"]
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}

如前所述,你可以有一个local.properties文件在你的项目的根属性值:

signing.keyAlias=My key
signing.keyPassword=zyxwvuts
signing.storePassword=abcdefgh
signing.storeFile=C\:\\Users\\Mahozad\\keystore.jks

... 或者你可以在你的操作系统上设置/创建环境变量;例如,创建一个名为SIGNING_KEY_ALIAS的环境变量:

  • Windows命令提示符:setx SIGNING_KEY_ALIAS "My key"
  • Linux终端:export SIGNING_KEY_ALIAS="My key"

请注意:正如其他答案所提到的,不要将你的local.properties文件添加到你的版本控制系统(如Git),因为它将你的秘密信息,如密码等暴露给公众(如果它是一个公共存储库)。

使用这个答案提到的3种方法中的任意一种生成APK。