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


514

我想使用Gradle构建Gradle版本以创建发布签名的apk文件。

我不确定代码是否正确或执行时是否缺少参数gradle build

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

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

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

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



从gradle文件中使用v1(jar签名)或v2(完整的apk签名)版本签名?解决方案在这里:stackoverflow.com/questions/57943259/…–
user1506104

Answers:


429

比以前的答案更简单的方法:

放进去 ~/.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


另请参阅signingConfigsGradle DSL 参考


12
最好的方法,如果你问我。将任何内容保存在我的项目文件夹/ SVN中,并且我可以签出项目的10个版本,而不必担心密钥。
2014年

8
如果您在Windows上使用gradlew,则需要确保将GRADLE_USER_HOME定义为环境变量才能使此工作有效。我将其设置为项目目录上方的一个目录,并将密钥库放置在该目录中。gradle.properties中密钥库的路径应使用正斜杠(/)或双反斜杠(\\),而不是Windows单反斜杠。要从Windows命令提示符创建密钥库,请参阅stackoverflow.com/questions/3997748/how-can-i-create-a-keystore
Anachronist 2014年

3
是相对于build.gradle文件所在位置的路径,还是相对于机器根目录的路径?
2014年

1
@Prem,file()始终假定相对路径。使用new File(path),如果你希望它被视为绝对的。
ars-longa-vita-brevis 2014年

4
这对我和最简单的工作。在gradle.properties中,指定相对于模块build.gradle的storeFile,就像RELEASE_STORE_FILE = .. / mykeystore一样。不要添加引号,否则gradle会破坏路径
Lakshman Chilukuri 2015年

263

我设法通过添加以下代码来解决它,并使用gradle build

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

这将生成一个签名的发行版apk文件。


33
有没有办法让我提示输入密码?或其他建议,以防止密码进入我的git仓库?
user672009 2013-09-18

3
我编辑了build.gradle使其看起来像您一样,但是运行“内置>生成已签名的APK ...”仍会显示该对话框(“请参阅Gradle用户指南以获取更多信息。”等),并且没有APK。
语义者

3
@Semanticer执行gradle buildgradlew build在终端/提示命令中执行
Phillip Kamikaze,

12
@ user672009,您可以将密码放在属性文件中,并使用.gitignore将其从存储库中排除。您可以看到此链接。gist.github.com/gabrielemariotti/6856974
Gabriele Mariotti

1
@GabrieleMariotti仍然留下一个不完整的存储库。更好的方法是在发出“ git update-index --assume-unchanged signing.properties”后创建一个框架signing.properties。但是,这样会阻止提交futura编辑。sdqali建议的第一种选择似乎更好。
user672009 2013年

67

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

执行此操作后,installRelease从任务列表中消失了...为什么?
卡雷尔

1
@caspase希望我已更认真地对待您关于假冒的“ storePassword”和“ keyPassword”的评论。如果不初始化这些属性(例如““”),则不会创建已签名的* -release.apk,不会显示错误,并且您对PROJECT_NAME / build / apk /目录中的* -release-unsigned.apk完全感到困惑。 。Man ...:/
vizZ

感谢您在buildTypes-> Release下添加signingConfig的说明。为我解决了自动签名!
mm2001

1
我制作了一个简单的gradle插件,在构建发行版apk时要求输入密码(使用本文中介绍的mathod,但您无需定义伪造的storePassword和keyPassword)。它也可以在Maven Central中使用。github.com/alexvasilkov/AndroidGradleSignPlugin
Alex Vasilkov

这很棒。请注意,KEYSTORE即使对于调试版本和Android Studio中的“渐变同步”,也需要定义环境变量,否则会给出关于路径为null的错误。
Jerry101

63

如果要避免在build.gradle中对您的密钥库和密码进行硬编码,则可以按照以下说明使用属性文件:使用GRANDLE处理签名配置

基本上:

1)在/ home / [用户名] /。signing中创建myproject.properties文件,其内容如下:

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

2)使用内容创建gradle.properties文件(也许在项目目录的根目录):

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

1
很棒!谢谢。必须在buildTypes {}部分之前添加此代码,并且该部分必须正常声明signingConfig signingConfigs.release。
theczechsensation 2014年

最后,我找到了解决该问题的方法。唯一真正帮助过我的东西!这是被接受的答案……
devnull69年

39

使用git时使用Gradle自动进行应用签名

令人惊讶的是,有许多复杂的方法可以做到这一点。这是我自己的方式,我尝试遵循Google的推荐。但是,它们的解释还不够清楚,因此我将详细描述Linux的过程。


描述:

Google的默认说明在构建过程中自动对应用程序进行自动签名而不将密码和签名文件保留在应用程序开发(GIT)路径中非常晦涩。以下是明确的分步说明。

初步假设:

在以下路径指定的目录中,您有一个名为“ MyApp”的应用 $HOME/projects/mydev/MyApp。但是,MyApp目录是通过GIT使用和控制的。

在此处输入图片说明

问题

我们显然不希望在GIT控制的目录中的任何位置拥有我们的签名或密码文件,即使我们能够使用 .gitignore易于等,它仍然过于冒险并且容易出错。因此,我们需要外部的密钥库和签名文件。

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

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

在此示例中,我们将两个文件命名为:

  1. keystore.properties
  2. MyApp-release-key.jks

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

cd $HOME/projects/mydev/

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

第一个文件包含用于的明文密码;和(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 文件,我们需要在此处放置以下内容:

../../../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文件以使用以上内容

应用/模块的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

这会生成一个经过正确签名的应用,可以在Google Play中使用。


更新: 2019-04-02

最近的版本keytool东西告诉你,你应该使用PKCS12基于密钥文件的代替了原来的/默认就像我上面使用。然后,他们继续告诉您您应该转换为新的打开PKCS12格式。但是,似乎Android开发工具尚未为此做好准备,因为如果您这样做,则会出现以下奇怪的错误:

com.android.ide.common.signing.KeytoolException:无法从存储“ F:\ XXX \ XXX.jks”中读取密钥XXX:获取密钥失败:由于未正确填充最终块。如果在解密过程中使用了错误的密钥,则会出现此类问题。

因此,请勿使用转换后的密钥!


是将signingConfigs保存在apk内,然后任何用户都可以对其进行反编译以获取密码,或者它不会出现在apk中?
哈维尔·塞哥维亚·科尔多瓦

2
像魅力一样工作。谢谢你,这应该是被接受的答案
pratham kesarkar

如果您只想在构建服务器上使用密钥库和密码怎么办?通过上述解决方案,团队中的每个开发人员都需要在其本地计算机上拥有密钥库。否则,Gradle项目同步将失败:keystore.properties(无此文件或目录)。
戴安娜·法林

1
您可以将虚拟keystore.properties文件提交到源代码管理,因此可以在开发机器上进行构建。我在这里描述了构建服务器的设置。
dskrvk

1
您对上次更新的说明keytool生成PKCS12密钥库:你可以通过-storetype JKSkeytool命令密钥库类型设置为这是由Android的工具需要JKS。
Trevor Halvorson

35

就像@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 OR gradle build


如何在Windows中设置路径:密钥库的路径
reza_khalafi

storeFile文件(“ C:\\ Users \\ xxxx \\ Documents \\ yyyy \\ mykey.jks”)对吗?
reza_khalafi

28

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

  ...

您能具体一点吗?我无法使其运行:“无法解析符号signingConfig”。
Amio.io 2014年

如果我在build.gradle中包含'signing.gradle'-我被迫在git存储库中添加一个(否则我收到错误消息'signing.gradle不存在')。而且,如果我在git中放入“ signing.gradle”,它就无法达到目的。我如何才能使signing.gradle包含为可选?
捷豹

21

如果您已经有了密钥库文件,那么可以简单地向构建命令中添加一些参数:

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


18

这是对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 {

        }
    }

}

有没有办法提供一些默认值?我的密钥库通常是相同的。storePassword通常与keyPassword相同,而keyAlias通常是小写的项目名称。
2013年

@ user672009,您始终可以在脚本内部使用Java代码。
AChep

1
您可能想要使用以下方式:keyPassword new String(console.readPassword("Enter key password: "))确保输入期间未显示您的密码
Alex Semeniuk 2014年

这不再起作用了,请参见github.com/gradle/gradle/issues/1251
SqAR.org

16

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

  1. File -> Project Structure

  2. Module -> 选择主模块(“应用”或其他自定义名称)

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

  4. 在右侧填写数据

  5. 单击确定,并自动创建Gradle文件

  6. 您将必须手动添加一行signingConfig signingConfigs.NameOfYourConfigbuiltTypes{release{}}

图片:

在此处输入图片说明

在此处输入图片说明

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

(编辑12/15)

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

  2. 如果您忘记了keyAlias(我经常发生的事情),则必须启动Build -> Generate Signed APK以启动该过程并查看Alias密钥的名称。


2
但这会将您的密码硬编码到build.gradle文件中,不是吗?
Joshua Pinter

16

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

这是build.gradle?顶层?请添加更多代码
-Vlad

为了澄清,这是app/build.gradle我正在谈论的文件。
伊吉斯(Egis)'18年

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

使用Android Studio 0.5.1,Gradle 1.11和Gradle插件0.9。
JP文图拉

1
按需创建属性(又称动态属性)已被弃用,并计划在Gradle 2.0中删除
-JP Ventura

10

您还可以使用gradle的-P命令行选项来帮助签名。在您的build.gradle中,像这样添加唱歌配置:

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用户指南


7

如果您可以在所有项目中重复使用相同的配置,则@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.signingsigning.gradle与有效凭证代替虚拟值。

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

当然,signing.gradleVCS应该忽略它。


6

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

我提出了一个简单的解决方案,该解决方案使用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

发布愉快!


5

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

5

弄清楚这一点,我有很多乐趣。这是我的演练。

关于如何在IntelliJ中创建gradle构建文件的A至Z演练(v.13.1.4)此演练假定您知道如何制作密钥库文件。为了使本教程正常工作,您需要将密钥库文件放在应用程序文件夹中,并且需要将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文件夹下的密钥库路径)。

在“构建类型”下的名称字段中输入值“ 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 {
    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菜单构建依赖关系容器,请选择:文件/项目结构。从那里再次选择Facets,然后选择Android-Gradle(app)。您将看到与上述相同的5个标签。选择“依赖项”标签,然后添加所需的依赖项。

完成所有这些操作后,您应该在该演练顶部看到一个类似于Gradle的构建文件。要构建签名的zip对齐版本,您需要打开Gradle任务。您可以通过选择视图/工具窗口/渐变进入此窗口。在这里,您可以双击'assembleAssembleRelease。这应该会生成可部署的APK。

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

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

为了解决棉绒问题,您需要将以下DSL容器放入android容器中(顶部):

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

将其放入您的android DSL容器中将导致在build文件夹(直接在您的应用文件夹下)中生成错误文件,该文件名应类似于'lint-results-release-fatal.html',该文件将告诉您发生错误的类。将生成的另一个文件是一个XML文件,其中包含与棉绒错误相关的“问题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}

请注意,抑制棉绒错误并不总是最好的IDEA,您最好更改导致棉绒错误的代码。

可能发生的另一个问题是,如果尚未为Gradle HOME环境变量设置环境变量。此变量名为“ GRADLE_HOME”,应将其设置为gradle主目录的路径,例如“ C:\ gradle-1.12”。有时,您可能还希望将“ ANDROID_HOME”的环境变量设置为“ YOUR- SDK-Root \ sdk'

完成此操作后,请返回Gradle任务窗口,然后双击assembleAssembleRelease。

如果一切成功,则应该能够转到文件夹app \ build \ apk并找到可部署的APK文件。


+1表示努力,并且:'lintOptions {abortOnError false}'
Raz Tourgman

4

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

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中完成,方法是切换到realease构建类型并运行应用程序,而不必使用命令行。


1
Gradle不会使用以下代码进行编译:props = new Properties(); 无法设置只读属性的值“道具”
cesards

您说对了@ m3n0R。我编辑了一行答复,以反映我们必须在应用程序中引入的修复程序,以便它仍可以使用最新版本的Gradle进行编译。基本上,必须将props声明为局部变量。
argenkiwi 2014年

如何使用云CI / CD工具将其采用。.../ path / to / keystore和/path/to/secure.props让我感到....尽管如此。
sirvon

4

Android Studio转到文件->项目结构或按Ctrl + Alt + Shift + S

看到图像

在此处输入图片说明

点击确定

然后signingConfigs将在您的build.gradle文件上生成。

在此处输入图片说明


而这正是您不想做的。这样,您所有的密码都是明文形式的,并且是项目的一部分,即使在您的分布式构建中,也很容易意外地包含在内。
not2qubit

2

我遇到了几个问题,将以下行放在错误的位置:

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

很容易犯这个错误。


2

现在是2019年,我需要使用V1(罐子签名)或V2(完整的APK签名)签署APK。我用谷歌搜索“生成签名的apk gradle”,它把我带到了这里。所以我在这里添加我的原始解决方案。

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

我的原始问题:如何从build.gradle文件使用V1(Jar签名)或V2(完整APK签名)


不需要分号;它会给你一个错误。
加贺

没错 谢谢。我编辑了答案。
user1506104 '19

1

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


1

我在Ubuntu14.04中工作。vim〜/ .bashrc并添加export 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 {

        }
    }

}

恕我直言,这似乎是最好的解决办法,但不幸的是它停在摇篮的较新版本的工作System.console()回报null
Antonio Vinicius Menezes Medei,

1

一种替代方法是定义仅在发行版本上运行的任务。

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

以下似乎对我而言更可取:stackoverflow.com/a/19130098/3664487两种方法如何比较?
user2768

1

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

...

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

背景故事。如https://stackoverflow.com/a/19130098/3664487所述,“ Gradle脚本可以使用System.console()。readLine方法提示用户输入。” 不幸的是,即使您正在构建调试版本,Gradle也会始终要求输入密码(请参阅如何使用Gradle创建带有签名的APK文件?)。幸运的是,如上所述,这是可以克服的。


由于stackoverflow.com/questions/33897802/…,我之前的回答遇到了问题。我修改了答案以消除此问题。
user2768 2015年

@Haroon,截至2015年11月24日。社区也许可以帮助您解决问题,但是您需要提供更多详细信息。
user2768 '16

我喜欢此解决方案,因为它避免将密码以明文形式输入文本文件中,但是由于烦人的问题,System.console()。readLine无法在gradle中工作。
morpheus

@morpheus,我从来没有遇到过问题。以上为我工作。
user2768 '17

我认为您是在IDE中运行脚本的。如果脚本是从终端运行的,您将看到错误。但感谢您的回答。这就是我想要的。
morpheus

0

使用react-native-config包在React-Native中添加我的方法。
创建一个.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')
        }
    }

0

就我而言,我将错误的APK上传到另一个应用的发行版中。


0

对于Groovy(build.gradle)

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

将一个文件signing.properties其中模块特定的build.gradle中找到。不要忘记将其添加到您的.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
            // ...
        }
    }
}

0

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

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

将一个文件signing.properties其中模块特定build.gradle.kts被发现。不要忘记将其添加到您的.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")
            // ...
        }
    }
}

-1

如果您不想看到无法在空对象上调用方法readLine()。您需要先在gradle.properties中编写。

KEYSTORE_PASS=*****
ALIAS_NAME=*****
ALIAS_PASS=*****
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.