提问人:Jan-Terje Sørensen 提问时间:8/20/2013 最后编辑:Amanda MartinJan-Terje Sørensen 更新时间:6/5/2023 访问量:375549
如何使用 Gradle 创建发布签名的 apk 文件?
How to create a release signed apk file using Gradle?
问:
我想让我的 Gradle 构建使用 Gradle 创建一个发布签名的 apk 文件。
我不确定代码是否正确,或者我在执行时是否缺少参数?gradle build
这是我的 / 文件中的一些代码:build.gradle
build.gradle.kts
android {
...
signingConfigs {
release {
storeFile(file("release.keystore"))
storePassword("******")
keyAlias("******")
keyPassword("******")
}
}
}
Gradle 构建成功完成,在我的文件夹中我只看到 和 文件。build/apk
...-release-unsigned.apk
...-debug-unaligned.apk
关于如何解决这个问题的任何建议?
答:
我设法解决了它,添加了此代码,并使用以下命令进行构建:gradle build
android {
...
signingConfigs {
release {
storeFile file("release.keystore")
storePassword "******"
keyAlias "******"
keyPassword "******"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
这将生成一个已签名的发布 apk 文件。
评论
gradle build
gradlew build
这是对 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 {
}
}
}
评论
keyPassword new String(console.readPassword("Enter key password: "))
请注意,@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
KEYSTORE
如果你想避免在build.gradle中对你的密钥库和密码进行硬编码,你可以使用一个属性文件,如下所述: 使用 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) 在 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 的参考
评论
.gradle
我有几个问题,我把以下行放在错误的地方:
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 存储库之外,这是一个更简单的解决方案;然而,想要将你的 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
}
}
...
评论
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 模块(主要是配套的控制台脚本)和围绕 Groovy 功能的最小包装器:keyring
['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 命令行选项来帮助签名。在 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 用户指南。
解决同一问题的另一种方法。由于不建议在源代码中存储任何类型的凭据,因此我们决定在单独的属性文件中设置密钥存储和密钥别名的密码,如下所示:
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 构建类型并运行应用程序,而不必使用命令行。
评论
就像@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
}
}
}
....
然后你可以运行 ORgradle assembleRelease
gradle build
评论
我在弄清楚这个问题时玩得很开心。这是我的演练。
关于如何在 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 个字段中输入您的密钥库信息(设置密钥库路径,即应用程序文件夹下的路径)。
在“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 {
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 任务。您可以通过选择“视图”/“工具窗口”/“Gradle”来访问此窗口。 从这里您可以双击“assembleAssembleRelease”。这应该会生成可部署的 APK。
编译版本时可能出现的潜在问题包括(但不限于): 您的 Gradle 构建文件位于错误的位置。有两个 Gradle 构建文件;一个位于应用程序根文件夹中,另一个位于应用程序根目录下的 App 文件夹中。您必须使用后者。
您也可能有棉绒问题。(注意:Android Developer Studio 在发现 Lint 问题方面比 IntelliJ 要好得多,当您尝试从菜单选项生成已签名的 APK 时,您会注意到这一点)
为了解决 lint 问题,您需要将以下 DSL 容器放在 android 容器中(在顶部):
android {
....
lintOptions {
abortOnError false
}
....
}
将其放在您的 Android DSL 容器中将导致在 build 文件夹(直接在您的应用程序文件夹下)中生成一个错误文件,文件名应类似于“lint-results-release-fatal.html”,此文件将告诉您发生错误的类。将生成的另一个文件是一个 XML 文件,其中包含与 lint 错误关联的“问题 ID”。文件名应类似于“lint-results-release-fatal.xml”。在文件顶部附近的某个地方,你会看到一个节点“issue”,其中你会看到类似于“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 错误并不总是最好的想法,您最好更改导致 lint 错误的代码。
另一个可能出现的问题是,如果您尚未为 Gradle HOME 环境变量设置环境变量。此变量名为“GRADLE_HOME”,应设置为 gradle 主目录的路径,类似于“C:\gradle-1.12” 有时您可能还想将环境变量设置为“ANDROID_HOME”,将其设置为“YOUR-SDK-Root\sdk”
完成此操作后,返回 Gradle tasks 窗口,然后双击 assembleAssembleRelease。
如果一切顺利,您应该能够转到文件夹 app\build\apk 并找到可部署的 APK 文件。
评论
为了补充其他答案,您还可以将 gradle.properties 文件与 build.gradle 一起放在您自己的模块文件夹中,以防万一您的密钥库特定于一个项目。
如果您可以在所有项目中重用相同的配置,@Destil的答案很好。或者,Android Studio 附带了一个文件,也许可以使用它,但它应该是 IDE 生成的,我找不到从 Android Studio 中扩展它的方法。local.properties
这是@jonbo答案的变体。该答案允许特定于项目的设置,但它会带来一些开发人员开销。具体来说,将定义移动到一个单独的文件中需要大量的样板 - 特别是当你需要为多个项目这样做时,这是选择这个解决方案而不是 Destil 解决方案的主要原因。这可以通过包括线来在一定程度上缓解signingConfigs
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',
]
当然,VCS应该忽略。signing.gradle
我在 Ubuntu14.04 工作。 vim ~/.bashrc 并添加 导出 ANDROID_KEYSTORE= 导出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 {
}
}
}
评论
在较新的 Android Studio 中,有一种非常简单的 GUI 方式,它也填充了 Gradle 文件。
File -> Project Structure
Module ->
选择主模块(“应用”或其他自定义名称)Signing
tab -> 加图片添加新配置在右侧填充数据
确定并自动创建 Gradle 文件
您必须手动在里面添加一行
signingConfig signingConfigs.NameOfYourConfig
builtTypes{release{}}
图像:
两个重要的(!)注意事项:
(编辑 12/15)
要创建已签名的APK,您必须打开Android Studio(主界面底部)的终端选项卡并发出命令
./gradlew assembleRelease
如果您忘记了(我经常发生的情况),则必须启动该过程并查看别名密钥的名称。
keyAlias
Build -> Generate Signed APK
评论
build.gradle
File
> Project Structure
> Modules(located in right pane)
> app(located in center pane under Modules)
> Signing Configs
另一种方法是定义仅在发布版本上运行的任务。
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
}
...
}
...
该块可防止在构建版本时请求密码。尽管无法访问该分支,但它会诱使 Gradle 创建任务。if-then-else
else
install...Release
背景故事。正如 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"
评论
build.gradle
app/build.gradle
扩展 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
}
}
}
使用 git 时使用 Gradle 自动对应用进行签名
令人惊讶的是,有多少复杂的方法可以做到这一点。这是我自己的方式,我试图遵守谷歌自己的建议。但是,他们的解释并不完全清楚,因此我将详细描述Linux的过程。
描述:
用于自动为应用签名的默认 Google 说明 在构建过程中,不保留密码和签名文件 在您的应用程序开发 (GIT) 路径中,是相当晦涩难懂的。以下是 阐明了如何执行此操作的分步说明。
初始假设:
在以下路径给出的目录中,您有一个名为“MyApp”的应用:。但是,使用 MyApp 目录和
用 GIT 控制。$HOME/projects/mydev/MyApp
问题
我们显然不希望将我们的签名或密码文件放在任何地方
GIT控制的目录,即使我们非常能够使用等,它仍然太冒险,容易出错。因此,我们希望我们的密钥库和签名文件在外面。.gitignore
溶液
我们需要做三 (3) 件事:
- 创建供 Android Studio 使用的密码文件
- 创建签名密钥文件
- 编辑模块文件以使用 (1) 和 (2)。
build.gradle
在此示例中,我们将这两个文件命名为:
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
$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
的最新版本告诉您,您应该使用基于 PKCS12 的密钥文件,而不是我上面使用的原始/默认密钥文件。然后他们继续告诉您应该转换为新的开放 PKCS12 格式。但是,Android开发工具似乎还没有为此做好准备,因为如果您这样做,您将收到以下奇怪的错误:keytool
com.android.ide.common.signing.KeytoolException:
无法读取密钥 来自存储“F:\XXX\XXX.jks”的 XXX:获取密钥失败:给定最终块未 适当填充。如果在期间使用坏密钥,则可能会出现此类问题 解密。
所以不要使用转换后的密钥!
评论
keytool
-storetype JKS
keytool
如果您已经有密钥库文件,那么只需向构建命令添加几个参数即可:
./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
评论
Android 工作室 转到“文件”-“项目结构”>或按 Ctrl+Alt+Shift+S
查看图片
单击“确定”
然后,signingConfigs 将在您的 build.gradle 文件上生成。
评论
现在是 2019 年,我需要使用 V1(jar 签名)或 V2(完整 APK 签名)对 APK 进行签名。我在谷歌上搜索了“生成签名的 apk gradle”,它把我带到了这里。因此,我在这里添加我的原始解决方案。
signingConfigs {
release {
...
v1SigningEnabled true
v2SigningEnabled true
}
}
我原来的问题:如何从build.gradle文件中使用V1(Jar签名)或V2(完整APK签名)
使用 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')
}
}
就我而言,我上传了错误的apk,到另一个应用程序的版本。
对于 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
// ...
}
}
}
对于 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
构建.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 插件 (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
...或者您可以在操作系统上设置/创建环境变量;例如,要创建名为 run 的环境变量:SIGNING_KEY_ALIAS
- Windows 命令提示符:
setx SIGNING_KEY_ALIAS "My key"
- Linux 终端:
export SIGNING_KEY_ALIAS="My key"
注意:正如其他答案所提到的,不要将 local.properties 文件添加到您的版本控制系统(如 Git)中,因为它会将您的秘密信息(如密码等)暴露给公众(如果它是公共存储库)。
评论
build.gradle.kts
解决方案:stackoverflow.com/a/61188101/1562087