Android Studio:如何使用Gradle生成已签名的APK?

96

我在Google和SO上搜索了一下,但都没有找到答案。

这是我第一次使用Gradle系统,现在我正在生成一个签名APK以上传到Google Play(项目是从eclipse导入的)。

现在,我读到了这部分这里,说你应该向你的build.gradle添加signingConfigs

我添加了这些代码行,现在我发现你需要运行./gradlew assembleRelease,但在我的CMD中运行此命令会返回

'gradle'不是内部或外部命令,可执行的程序或批处理文件。

我还尝试右键单击build.gradle并运行它,它说成功了,但是一旦我查看build / apk文件夹,只有一个名为app-debug-unaligned.apk的文件。

那么,我如何使用Gradle系统生成签名APK?


1
请参见以下链接:https://dev59.com/DHrZa4cB1Zd3GeqP7NO8#20876737 - Scott Barta
@ScottBarta 部分地解决了问题,一旦我切换到发布模式并运行gradle,我仍然会遇到错误,但是通过菜单中的build > generate signed apk,最终问题得以解决!谢谢,我在提供的链接上为您点赞。 - Gooey
从gradle文件中使用v1(jar签名)或v2(完整apk签名)版本进行签名?解决方案在这里:https://dev59.com/t7bna4cB1Zd3GeqPZFM1#57946742 - user1506104
1
这个回答解决了你的问题吗?如何在Android Studio中构建“发布”APK? - Mahozad
7个回答

104
根据buildType,生成构建版本有三种方式。(在您的情况下,它是“release”,但可以使用任何名称。)
  1. 打开Android Studio右侧面板中的Gradle Task,搜索Module Tasks下的assembleReleaseassemble(#your_defined_buildtype)

  2. 打开左侧面板中的Build Variant,并从下拉列表中选择相应的构建版本

  3. 在文件浏览器中转到项目根目录并打开cmd/terminal,然后运行以下命令:

    Linux: ./gradlew assembleRelease或assemble(#your_defined_buildtype)

    Windows: gradlew assembleRelease或assemble(#your_defined_buildtype)

如果你只想进行发布版本构建,你可以通过Build > Generate Signed apk来完成。对于其他构建类型,只有上述三个选项可用。
您可以在module/build目录中找到具有构建类型名称的生成APK。

4
只有在build.gradle文件中配置了构建配置才能生成已签名的apk。如果您将其存储在源代码管理工具中或与他人共享,应该考虑将签名密钥的凭据与源代码分开。 - Janusz
构建 > 生成已签名的apk ... 就是这么简单 - Atul

72

可以在不编辑任何文件的情况下,通过命令行构建/签名任何现有的Android Studio Gradle项目。这使得将项目存储在版本控制中并保持密钥和密码分离变得非常方便:

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

1
由于我们需要将源代码传递给伴侣,这是保持密钥库机密的最佳方法。谢谢。 - Yeung
3
无论如何,想了解这些“android.injected.signing.*”属性的存在吗? - Tixeon
我从 Android Studio 团队的 Xav 那里得到了这些信息,我不知道是否还有其他类似的变量。 - Wayne Piekarski
我遇到了java.lang.RuntimeException: com.android.ide.common.signing.KeytoolException异常:无法从存储“C:\Users\somedirectory\Desktop\someKey.jks”中读取密钥XXXXXX:在密钥库C:\Users\somedirectory\Desktop\someKey.jks中找不到别名为'XXXXXX'的密钥。这是为什么? - Archie G. Quiñones

49

您可以使用此代码

android {
   ...
    signingConfigs {
        release {
            storeFile file("../your_key_store_file.jks")
            storePassword "some_password"
            keyAlias "alias_name"
            keyPassword "key_password"
        }
    }

    buildTypes {

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

接着从您的终端运行以下命令

./gradlew assembleRelease

您可以在以下路径获取apk文件:

your-android-app/build/outputs/apk/your-android-app-release.apk


@ozcanovunc请再次检查您的密钥库路径,可能是您定义的路径有误。 - bhavesh kaila
在这种情况下,您的 build.gradle 可能已经被检入版本控制,而且您的密码也一样!如果项目安全性很重要,请考虑采用其他方法。 - Marco7757
1
gradle assembleRelease无法工作。请使用gradlew assembleRelease代替。 - Sathish Gadde
出于安全考虑,签名凭据可以从单独的文件中读取。 - dasar

2

0

这是针对 Kotlin DSL(build.gradle.kts)的。
您可以在项目根目录中的local.properties文件中定义属性,也可以将其定义为环境变量(这对于像GitHub Actions这样的CI特别有用)。

// See https://dev59.com/_FIH5IYBdhLWcg3wOrEY
fun getLocalProperty(key: String) = gradleLocalProperties(rootDir).getProperty(key)

fun String?.toFile() = file(this!!)

// Could also use System.getenv("VARIABLE_NAME") to get each variable individually
val environment: Map<String, String> = System.getenv()

android {
    signingConfigs {
        create("MyAppSigningConfig") {
            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 {
        getByName("release") { // OR simply release { in newer versions of Android Gradle Plugin (AGP)
            signingConfig = signingConfigs["MyAppSigningConfig"]
            // ...
        }
    }
}

myProject/local.properties文件:

signing.keyAlias=foo
signing.keyPassword=bar
# also called keystore
signing.storePassword=abcdefgh
signing.storeFile=C\:\\my-files\\my-keystore.jks

注意:不要将您的local.properties文件添加到版本控制系统(如Git)中,因为它会将您的密码等秘密信息公开给公众(如果它是公共存储库)。

使用this answer提到的3种方法之一生成您的APK。


0

如果您居住在某些国家,请务必使用 VPN。

步骤1:在命令行中运行以下命令:

keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

它会要求您提供一些信息,例如密码、姓名等,并输入它们。

步骤2:在您的Android文件夹中创建一个名为key.properties的文件。 在创建的文件中编写以下行

storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file, such as ~/key.jks>

保持 key.properties 文件私密,始终备份 key.properties 文件并永远不要公开发布。

步骤3:在应用级别的 Gradle 中替换以下行

def keystoreProperties = new Properties()
    def keystorePropertiesFile = rootProject.file('key.properties')
    if (keystorePropertiesFile.exists()) {
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    }
android {
signingConfigs {
  release {
    keyAlias keystoreProperties['keyAlias']
    keyPassword keystoreProperties['keyPassword']
    storeFile file(keystoreProperties['storeFile'])
    storePassword keystoreProperties['storePassword']
  }
}
buildTypes {
  release {
    signingConfig signingConfigs.release
  }
}
}

步骤4:

keytool -list -v -keystore ~/key.jks -alias key -storepass <password> -keypass <password>

步骤5: 我建议使用Android Studio构建APK。 Build > Generate Signed Bundle/APK...


-3

构建菜单 > 生成已签名 APK


如果你运行它,它会告诉你那不是正确的方法。此外,如果我上传那个.apk文件,它会出现一个错误,说检测到错误或其他什么东西。 - Gooey
11
在Android Studio中,有一个显示“调试模式”的提示。在左侧应该有一个名为“构建变体”的标签,点击它并将所有内容从“调试”切换到“发布”。然后再次生成已签名的APK文件。请注意不要改变原来的意思。 - trickedoutdavid
2
这个已经不再起作用了!例如,它构建的 APK 具有 BuildConfig.DEBUG 设置为 true。这给我带来了无尽的麻烦,现在你必须使用 gradlew assembleRelease 方法。 - Ben Clayton
@BenClayton 你说得完全正确!我因此浪费了好几个小时!另一个非常恼人的“bug”在Android Studio中 - 麻烦不断,无休止... - sjkm
我不知道为什么这个简单的步骤不能是生成签名APK的最佳方法,因为它明确地指出了。这个步骤生成的应用程序对我来说完美无缺,没有任何问题。但是,SO上的许多其他答案却让我感到困惑,让我认为我所做的可能不是正确的方式。 - Atul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接