Skip to content

应用签名配置

源:Android 官方文档 - 为应用签名

Android 要求所有 APK 必须经过数字签名后才能安装。应用签名用于验证应用的作者身份,并确保应用未被篡改。

签名密钥类型

调试密钥

调试构建自动使用调试密钥库签名,位于:

~/.android/debug.keystore  (macOS/Linux)
C:\Users\<username>\.android\debug.keystore  (Windows)

特点

  • 由 Android Studio 自动创建
  • 不安全,仅用于开发和测试
  • 有效期 365 天
  • 密码和别名已知:android / androiddebugkey

上传密钥

用于向 Google Play 上传应用的密钥。Google Play 使用 Play 应用签名功能,会用自己的发布密钥重新签名。

应用签名密钥

最终安装到用户设备的 APK 所使用的密钥。如果使用 Play 应用签名,这个密钥由 Google 管理;否则需要自己管理。

生成上传密钥

使用 Android Studio 生成

  1. 选择 BuildGenerate Signed Bundle/APK
  2. 选择 Android App BundleAPK,点击 Next
  3. Key store path 下点击 Create new
  4. 填写信息:

密钥库

  • Key store path:选择保存位置,文件扩展名为 .jks
  • Password:创建安全密码

密钥

  • Alias:密钥标识名
  • Password:密钥密码(建议与密钥库密码相同)
  • Validity:有效期(建议至少 25 年)
  • Certificate:证书信息(组织、城市等)

使用命令行生成

bash
keytool -genkey -v -keystore my-release-key.jks \
  -alias my-key-alias \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000

配置签名

在 build.gradle 中配置

kotlin
android {
    signingConfigs {
        create("release") {
            storeFile = file("../keystore/release.jks")
            storePassword = "your-keystore-password"
            keyAlias = "your-key-alias"
            keyPassword = "your-key-password"
        }
    }
    
    buildTypes {
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file('../keystore/release.jks')
            storePassword 'your-keystore-password'
            keyAlias 'your-key-alias'
            keyPassword 'your-key-password'
        }
    }
    
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

⚠️ 安全警告:不要将密码硬编码在构建文件中!

从环境变量读取密码

kotlin
android {
    signingConfigs {
        create("release") {
            storeFile = file("../keystore/release.jks")
            storePassword = System.getenv("KEYSTORE_PASSWORD")
            keyAlias = System.getenv("KEY_ALIAS")
            keyPassword = System.getenv("KEY_PASSWORD")
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file('../keystore/release.jks')
            storePassword System.getenv('KEYSTORE_PASSWORD')
            keyAlias System.getenv('KEY_ALIAS')
            keyPassword System.getenv('KEY_PASSWORD')
        }
    }
}

从 gradle.properties 读取

在项目根目录或用户目录的 gradle.properties 中配置:

properties
KEYSTORE_FILE=../keystore/release.jks
KEYSTORE_PASSWORD=your-keystore-password
KEY_ALIAS=your-key-alias
KEY_PASSWORD=your-key-password

build.gradle(.kts) 中读取:

kotlin
android {
    signingConfigs {
        create("release") {
            storeFile = file(project.property("KEYSTORE_FILE") as String)
            storePassword = project.property("KEYSTORE_PASSWORD") as String
            keyAlias = project.property("KEY_ALIAS") as String
            keyPassword = project.property("KEY_PASSWORD") as String
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file(project.property('KEYSTORE_FILE'))
            storePassword project.property('KEYSTORE_PASSWORD')
            keyAlias project.property('KEY_ALIAS')
            keyPassword project.property('KEY_PASSWORD')
        }
    }
}

⚠️ 注意:将本地 gradle.properties 添加到 .gitignore

为不同变体配置签名

kotlin
android {
    signingConfigs {
        create("debug") {
            // 使用默认调试密钥
        }
        
        create("release") {
            storeFile = file("release.jks")
            storePassword = System.getenv("RELEASE_KEYSTORE_PASSWORD")
            keyAlias = "release"
            keyPassword = System.getenv("RELEASE_KEY_PASSWORD")
        }
        
        create("staging") {
            storeFile = file("staging.jks")
            storePassword = System.getenv("STAGING_KEYSTORE_PASSWORD")
            keyAlias = "staging"
            keyPassword = System.getenv("STAGING_KEY_PASSWORD")
        }
    }
    
    buildTypes {
        getByName("debug") {
            signingConfig = signingConfigs.getByName("debug")
        }
        
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
        }
        
        create("staging") {
            signingConfig = signingConfigs.getByName("staging")
        }
    }
    
    productFlavors {
        create("demo") {
            // Demo 使用 debug 签名
            signingConfig = signingConfigs.getByName("debug")
        }
        
        create("full") {
            // Full 使用 release 签名
            signingConfig = signingConfigs.getByName("release")
        }
    }
}
groovy
android {
    signingConfigs {
        debug {
            // 使用默认调试密钥
        }
        
        release {
            storeFile file('release.jks')
            storePassword System.getenv('RELEASE_KEYSTORE_PASSWORD')
            keyAlias 'release'
            keyPassword System.getenv('RELEASE_KEY_PASSWORD')
        }
        
        staging {
            storeFile file('staging.jks')
            storePassword System.getenv('STAGING_KEYSTORE_PASSWORD')
            keyAlias 'staging'
            keyPassword System.getenv('STAGING_KEY_PASSWORD')
        }
    }
    
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        
        release {
            signingConfig signingConfigs.release
        }
        
        staging {
            signingConfig signingConfigs.staging
        }
    }
    
    productFlavors {
        demo {
            signingConfig signingConfigs.debug
        }
        
        full {
            signingConfig signingConfigs.release
        }
    }
}

查看签名信息

查看 APK 签名

bash
# 查看签名证书信息
keytool -printcert -jarfile app-release.apk

# 查看密钥库信息
keytool -list -v -keystore release.jks

生成签名报告

在Android Studio 中:BuildGenerate Signed Bundle/APKView signing report

或使用 Gradle 任务:

bash
./gradlew signingReport

输出示例:

Variant: release
Config: release
Store: /path/to/release.jks
Alias: release-key
MD5: A1:B2:C3:...
SHA1: D4:E5:F6:...
SHA-256: G7:H8:I9:...
Valid until: ...

Play 应用签名

使用 Play 应用签名后,签名流程如下:

  1. 开发者使用上传密钥签名 AAB/APK
  2. 上传到 Google Play
  3. Google Play 验证上传密钥
  4. Google Play 使用应用签名密钥重新签名
  5. 用户下载使用应用签名密钥签名的 APK

优势

  • 上传密钥丢失可以重置
  • 应用签名密钥由 Google 安全保管
  • 支持 App Bundle 优化分发

密钥安全最佳实践

保护密钥库文件

  • 不要提交到版本控制系统
  • 添加到 .gitignore
  • 安全备份(多个位置)

密码安全

  • 使用强密码
  • 不要硬编码在代码中
  • 使用环境变量或安全的密钥管理工具

CI/CD 环境

  • 使用加密的环境变量
  • 限制访问权限
  • 使用专用的构建密钥(非开发者个人密钥)

备份策略

  • 备份密钥库文件到安全位置
  • 记录密码(保存在密码管理器中)
  • 记录密钥别名和有效期

密钥丢失补救

  • 使用 Play 应用签名可以重置上传密钥
  • 如果应用签名密钥丢失,无法更新应用(只能发布新应用)