我想让我的Gradle构建使用Gradle创建一个发布签名的apk文件。
我不确定代码是否正确或者我在做gradle build
时是否缺少参数?
这是我的gradle文件中的一些代码:
android {
...
signingConfigs {
release {
storeFile file("release.keystore")
storePassword "******"
keyAlias "******"
keyPassword "******"
}
}
}
gradle构建完成SUCCESSFUL,在我的build/apk
文件夹中,我只看到...-release-unsigned.apk
和...-debug-unaligned.apk
文件。
关于如何解决这个问题的任何建议?
比以前的答案更容易:
把它放入~/.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
在较新的Android Studio中,有一种非常简单的GUI方式,它也可以填充Gradle文件。
File -> Project Structure
Module ->
选择主模块('app'或其他自定义名称)Signing
选项卡 - >加上图像添加新配置signingConfig signingConfigs.NameOfYourConfig
中添加一行builtTypes{release{}}
图片:
两个重要的(!)笔记:
(编辑12/15)
./gradlew assembleRelease
keyAlias
(我经常会发生什么),你将不得不启动Build -> Generate Signed APK
来启动进程并查看别名键的名称。如果您已经拥有密钥库文件,则可以像在构建命令中添加一些参数一样简单:
./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 {
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
}
}
}
您还可以使用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。
如果您可以在所有项目中重用相同的配置,那么@ Destil的答案很好。或者,Android Studio附带了一个可以替代使用的local.properties
文件,但它应该是IDE生成的,我找不到从Android Studio中扩展它的方法。
这是@jonbo's answer的变种。该答案允许项目特定的设置,但它带来一些开发人员的开销。具体而言,需要使用重要的样板来将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',
]
当然,VCS应该忽略signing.gradle
。
几乎所有平台现在都提供某种密钥环,因此没有理由留下明文密码。
我提出了一个简单的解决方案,使用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
快乐发布!
扩展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
}
}
}
我非常有趣地想出这个。这是我的演练。
关于如何在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 {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-v4:20.0.0'
implementation '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 {
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任务。您可以通过选择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文件。
另一种解决同一问题的方法。由于不建议在源代码中存储任何类型的凭据,因此我们决定在单独的属性文件中设置密钥库和密钥别名的密码,如下所示:
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完成,而不必使用命令行。
我设法解决它添加此代码,并使用gradle build
构建:
android {
...
signingConfigs {
release {
storeFile file("release.keystore")
storePassword "******"
keyAlias "******"
keyPassword "******"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
这会生成一个签名版本的apk文件。
我有几个问题,我把以下行放在错误的地方:
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 {
...
}
}
很容易犯这个错误。
为了补充其他答案,您还可以将gradle.properties文件与build.gradle一起放在您自己的模块文件夹中,以防您的密钥库特定于一个项目。
我在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 {
}
}
}
另一种方法是定义仅在发布版本上运行的任务。
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
任务。
背景故事。正如https://stackoverflow.com/a/19130098/3664487所述,“Gradle脚本可以使用System.console()。readLine方法提示用户输入。”不幸的是,Gradle将始终请求密码,即使您正在构建调试版本(参见How to create a release signed apk file using Gradle?)。幸运的是,正如我上面所示,这可以克服。
如果你不想看到无法在null对象上调用方法readLine()。你需要先在gradle.properties中写一下。
KEYSTORE_PASS=*****
ALIAS_NAME=*****
ALIAS_PASS=*****
如果您和我一样希望能够在设备上运行该版本以进行测试,请考虑创建第二个用于签名的密钥库,这样您只需将密码放入build.gradle,而无需担心市场密钥。商店安全。
您可以通过单击构建/生成已签名的APK /创建新的来创建新的密钥库...
请注意,@ 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中对密钥库和密码进行硬编码,可以使用如下所述的属性文件: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)在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']
}
}
}
就像@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
或gradle build
令人惊讶的是,有多少令人费解的方式可以做到这一点。这是我自己的方式,我试图坚持谷歌自己的recommendation。但是,他们的解释并不完全清楚,因此我将详细介绍Linux的过程。
默认的Google instructions用于在构建期间自动签署应用程序,而不会将密码和签名文件保留在应用程序开发(GIT)路径中,这是相当模糊的。以下是有关如何执行此操作的明确说明。
您在由以下路径指定的目录中有一个名为“MyApp”的应用程序:$HOME/projects/mydev/MyApp
。但是,MyApp目录由GIT使用和控制。
我们显然不希望在GIT控制目录中的任何地方都有我们的签名或密码文件,即使我们非常能够使用.gitignore
等,它仍然过于冒险而且容易出错。所以我们想要外面的密钥库和签名文件。
我们需要做三(3)件事:
build.gradle
文件以使用(1)和(2)。在本例中,我们将这两个文件命名为:
keystore.properties
MyApp-release-key.jks
我们可以在这里放置这两个文件:
cd $HOME/projects/mydev/
第一个文件包含用于的明文密码;和(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
创建签名密钥时会自动生成第二个文件。如果您没有其他应用程序且这是您唯一的密钥库,则使用以下命令创建文件:
cd $HOME/projects/mydev/
keytool -genkeypair -v -keystore MyApp-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myapp
这将要求您提供两个密码和一堆信息。 (与Android Studio中的内容相同。)现在复制/粘贴以前选择的密码。
gradle.build
file to use the above您的app / module的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:获取密钥失败:给定最终块未正确填充。如果在解密期间使用坏密钥,则可能出现此类问题。
所以不要使用转换后的密钥!
(回复上面的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
}
}
...
这是对user672009的回复以及对sdqali's post的补充(他的代码将在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 {
}
}
}
如果你像我这样通过命令行构建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"