Android 要求所有 APK 必须先使用证书进行数字签署,然后才能安装。本文档介绍了如何使用 Android Studio 签署您的 APK,包括创建和存储证书、使用不同证书签署不同的构建配置,以及配置构建流程以自动签署您的 APK。
公钥证书(也称为数字证书或身份证书)包含公钥/私钥对的公钥,以及可以标识密钥所有者的一些其他元数据(例如名称和位置)。证书的所有者持有对应的私钥。
在您签署 APK 时,签署工具会将公钥证书附加到 APK。公钥证书充当“指纹”,用于将 APK 唯一关联到您及您的对应私钥。这有助于 Android 确保您 APK 的任何将来更新都是原版更新并来自原始作者。
密钥库是一种包含一个或多个私钥的二进制文件。在您使用 Android Studio 签署要发布的 APK 时,您可以选择生成新的密钥库和私钥,或者使用您已经拥有的密钥库和私钥。您应当为密钥库选择一个强密码,并为密钥库中存储的每个私钥选择一个单独的强密码。您必须将密钥库存放在安全可靠的地方。请参阅下面的保护您的私钥部分。
您必须在应用的整个生命周期内使用相同的证书,以便用户能够以应用更新的形式安装新版本。要详细了解为所有应用在其整个生命周期内使用相同证书的好处,请参阅下面的签署注意事项。
从 IDE 中运行或调试您的项目时,Android Studio 将自动使用通过 Android SDK 工具生成的调试证书签署您的 APK。当您在 Android Studio 中首次运行或调试项目时,IDE 将自动在 $HOME/.android/debug.keystore
中创建调试密钥库和证书,并设置密钥库和密钥密码。
由于调试证书通过构建工具创建并且在设计上不安全,大多数应用商店(包括 Google Play 商店)都不接受使用调试证书签署要发布的 APK。
Android Studio 会自动将您的调试签署信息存储在签署配置中,因此您不必在每次调试时都输入此信息。签署配置是一种包含签署 APK 所需全部必要信息的对象,这些信息包括密钥库位置、密钥库密码、密钥名称和密钥密码。您无法直接编辑调试签署配置,不过可以配置如何签署您的发布构建。
如需了解有关如何针对调试构建和运行应用的详细信息,请参阅构建和运行您的应用。
用于针对调试签署 APK 的自签署证书的有效期为 365 天,从其创建日期算起。当此证书到期时,您将收到一个构建错误。
要修复此问题,只需删除 debug.keystore
文件即可。文件存储在以下位置:
~/.android/
(OS X 和 Linux)C:\Documents and Settings\\.android\
(Windows XP)C:\Users\\.android\
(Windows Vista,Windows 7、8 和 10)当您下次构建和运行调试构建类型时,这些构建工具将重新生成新的密钥库和调试密钥。请注意,您必须运行应用,单纯的构建不会重新生成密钥库和调试密钥。
您可以使用 Android Studio 手动生成签署的 APK,既可以一次生成一个 APK,也可以一次为多个构建变体生成 APK。除了手动签署 APK 外,您还可以将 Gradle 构建设置配置为在构建流程期间自动处理签署。本部分将介绍手动签署流程。要详细了解如何在构建流程中签署应用,请参阅配置构建流程以自动签署您的 APK。
要在 Android Studio 中手动签署用于发布的 APK,请按以下步骤操作:
如果您已经拥有密钥库,请转到第 5 步。如果您希望创建一个新的密钥库,请点击 Create new。
在 New Key Store 窗口上,为您的密钥库和密钥提供以下信息,如图 1 所示。
密钥库
密钥
填写完表单后,请点击 OK。
在 Generate Signed APK Wizard 窗口上,选择一个密钥库和一个私钥,并为它们输入密码。(如果您已经在上一步中创建密钥库,这些字段将自动填充。)然后,点击 Next。
在下一个窗口上,为签署的 APK 选择一个目的地、选择构建类型、选择产品风味(如果适用),然后点击 Finish。
注:如果您的项目使用多个产品风味,那么在 Windows/Linux 上按住 Ctrl 键或者在 Mac OS X 上按住 Command 键可以选择多个产品风味。Android Studio 将为选择的每个产品风味生成单独的 APK。
在流程完成后,您会在上面选择的目标文件夹中找到签署的 APK。现在,您可以通过像 Google Play 商店一样的应用市场或者您选择的机制分发签署的 APK。要详细了解如何将签署的 APK 发布到 Google Play 商店,请参阅开始发布。要详细了解其他分发选项,请阅读替代分发选项。
为了确保用户将更新成功安装到您的应用中,您需要在应用的整个生命周期内使用相同的证书签署 APK。要详细了解使用相同密钥签署所有应用的各种好处,请参阅下面的签署注意事项。如需了解有关保护您的私钥和密钥库的详细信息,请参阅保护您的私钥。
在 Android Studio 中,您可以创建一个签署配置并将其分配至您的发布构建类型,将您的项目配置为在构建流程中自动签署发布 APK。一个签署配置包含一个密钥库位置、密钥库密码、密钥别名和密钥密码。要使用 Android Studio 创建一个签署配置并将其分配至您的发布构建类型,请按以下步骤操作:
选择您的密钥库文件,为此签署配置输入一个名称(因为您可能创建多个配置),然后输入所需的信息。
在 Signing Config 下,选择您刚创建的签署配置。
现在,在您每一次使用 Android Studio 构建发布构建时,IDE 都会使用您指定的签署配置自动签署 APK。您可以在所构建模块项目目录内部的 build/outputs/apk/
文件夹中找到签署的 APK。
在您创建签署配置时,您的签署信息将以纯文本形式包含到 Gradle 构建文件中。如果您是团队协作开发或者公开分享自己的代码,那么您应当从构建文件中移除签署信息并将其单独存储,从而确保此信息的安全。要详细了解如何从构建文件中移除您的签署信息,请参阅从您的构建文件中移除签署信息。要详细了解如何保证签署信息安全,请参阅保护您的私钥。
如果您的应用使用多个产品风味并且您想要以不同方式签署每个风味,则可以创建更多签署配置并将其按风味分配:
选择您的密钥库文件,为此签署配置输入一个名称(因为您可能创建多个配置),然后输入所需的信息。
重复操作以配置任何其他产品风味。
您还可以在 Gradle 配置文件中指定您的签署设置。如需了解详细信息,请参阅配置签署设置。
发布 Android Wear APK 时,请将可穿戴式设备 APK 打包到手持类 APK 中,因为用户无法直接在可穿戴式设备上浏览和安装应用。两种 APK 都必须签署。如需了解有关打包和签署 Android Wear APK 的详细信息,请参阅打包可穿戴式设备应用。
在应用的预期生命周期内,您应使用相同证书签署所有 APK。这么做的原因有多个:
如果您计划支持升级应用,请确保密钥的有效期超出该应用的预期生命周期。建议有效期为 25 年或以上。当密钥有效期过期后,用户将不能再无缝升级到应用的新版本。
如果您计划在 Google Play 上发布您的应用,您用于签署这些 APK 的密钥的有效期必须在 2033 年 10 月 22 日以后结束。Google Play 强制执行此要求,以确保在新版本可用时,用户可以无缝升级应用。
维护您私钥的安全性对于您和用户来说都至关重要。如果您允许某人使用您的密钥,或者将您的密钥库和密码放在了不安全的地方,以致于第三方可以找到和使用它们,则会损害您的作者身份和用户对您的信任。
如果某个第三方在您不知情或未经授权的情况下设法取得您的密钥,此人可能会签署和分发应用,从而恶意替换您的原版应用或损坏它们。另外,此人还可能利用您的身份签署和分发应用,从而攻击其他应用或系统本身,损坏或窃取用户数据。
您应用的所有将来版本签署时都需要使用您的私钥。如果您的密钥丢失或存放不当,您将无法发布您的现有应用的更新。您无法重新生成以前生成的密钥。
您作为开发者实体的声誉取决于您能否每时每刻正确保护私钥,直至密钥过期。以下是针对保护密钥安全的一些提示:
通常情况下,只要您在生成、使用和存储密钥时遵循通用的注意事项,就可以保障密钥的安全。
在您创建签署配置时,Android Studio 会以纯文本形式将您的签署信息添加到模块的 build.gradle
文件中。如果您是团队协作开发或者将您的代码开源,那么您应当将此敏感信息从构建文件中移出,以免被其他人轻易获取。为此,您应创建一个单独的属性文件来存储安全信息并按以下步骤操作,在您的构建文件中引用该文件:
keystore.properties
的文件。此文件应当包含您的签署信息,如下所示: storePassword=myStorePassword keyPassword=mykeyPassword keyAlias=myKeyAlias storeFile=myStoreFileLocation
build.gradle
文件中,于 android {}
块的前面添加用于加载 keystore.properties
文件的代码。 ... // Create a variable called keystorePropertiesFile, and initialize it to your // keystore.properties file, in the rootProject folder. def keystorePropertiesFile = rootProject.file("keystore.properties") // Initialize a new Properties() object called keystoreProperties. def keystoreProperties = new Properties() // Load your keystore.properties file into the keystoreProperties object. keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { ... }
注:您可以选择将 keystore.properties
文件存储在其他位置(例如,存储在模块文件夹中而不是项目的根文件夹中,或者如果您使用连续集成工具,也可以存储在构建服务器上)。在这种情况下,您应当修改上面的代码,以便使用实际 keystore.properties
文件的位置正确初始化 keystorePropertiesFile
。
keystoreProperties['属性名称']
引用存储在 keystoreProperties
中的属性。修改模块 build.gradle
文件的 signingConfigs
块,以便使用此语法引用存储在 keystoreProperties
中的签署信息。 android { signingConfigs { config { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] } } ... }
build/outputs/apk/
目录中创建一个签署的 APK。 由于您的构建文件不再包含敏感信息,您现在可以将其包含在源控制中或者上传到共享的代码库。务必保证 keystore.properties
文件的安全。您可能需要将其从您的源控制系统中移除。
不需要 Android Studio 也可以签署您的应用。您可以通过 Android SDK 和 JDK 使用标准工具从命令行签署您的应用。要通过命令行在发布模式下签署应用,请按顺序完成以下步骤:
使用 keytool
生成一个私钥。例如:
$ keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias app
本示例会提示您输入密钥库和密钥的密码,并为您的密钥提供“Distinguished Name”字段。随后,它将生成一个名为 my-release-key.jks
的密钥库文件。此密钥库包含一个有效期为 10,000 天的密钥。
在发布模式下编译您的应用,以获取一个未签署且未优化的 APK。
使用 zipalign
优化未签署的 APK:
$ zipalign -v -p 4 my-app-unaligned.apk my-app.apk
zipalign
可以确保所有未压缩的数据均是以相对于文件开始部分的特定字节对齐开始,这样可减少应用消耗的 RAM 量。
通过 apksigner
使用您的私钥签署 APK:
$ apksigner sign --ks my-release-key.jks my-app.apk
本示例使用单密钥密钥库文件 my-release-key.jks
中存储的私钥和证书签署应用 my-app.apk
。
apksigner
工具支持其他签署选项,包括使用单独的私钥和证书文件签署 APK 文件和使用多个签署人签署 APK。如需了解更多详情,请参阅 apksigner
参考。
验证您的 APK 是否已签署:
$ apksigner verify my-app.apk