如何在 bazel 中构建带有签名的发布 apk

How to build a release apk with signature in bazel

我在 bazel 的文档中找不到关于 keystore 的任何规则,在 android_binary 的参数中找不到关于签名的任何参数。那么如何构建带有签名的发布apk?

这个问题是在 bazel-discuss mailing list 上提出的,它还包含一个解决方案和一些背景知识。

目前,Bazel 不支持对 apk 进行签名。 正如我们在文档中看到的那样:

android_binary creates a name_unsigned.apk: An unsigned version of the above file that could be signed with the release keys before release to the public.

这意味着您应该使用 Android 文档中的 apksigner using other tools. Take a look at Build an unsigned APK and sign it manually 对这个未签名的 apk 进行签名。

我没有足够的 Whosebug 信誉来评论 Steren 的答案,但答案的第一部分不正确。 Bazel 确实支持签署 APK。事实上,android_binary 的每个构建都会生成一个签名的 APK,但是它是使用硬编码调试密钥签名的。

Bazel 有意不提供用户指定密钥的机制,因为 Bazel 不应该用于使用发布密钥进行签名。这将需要您的发布密钥在您的工作区中,因此可能会被签入源代码管理。那将是非常糟糕的做法。

我穿了一件快速的绅士服,可以为你签名。但是,需要注意的一件事是,您将无法在输出签名的 APK 上使用 mobile-install,这非常不幸(仍在寻找解决方法)。

def signed_android_binray(
        name,
        android_binary,
        keystore,
        alias,
        password):
    """
    This macro signs given android_binary with the given keystore

    Example usage:
        load("//bzl:apksigner.bzl","signed_android_binray")

        signed_android_binray(
            name = "signed-foo-app",
            android_binary = ":foo-app",
            keystore = "//path/to/keystore:my-keystore",
            alias = mykeystore,
            pass = foo123,
        )
    """

    unsigned_android_binary = android_binary + "_unsigned.apk"
    output_name = "{}_signed.apk".format(name)

    native.genrule(
        name = name,
        srcs = [
            unsigned_android_binary,
            keystore,
        ],
        tools = [
            "@androidsdk//:apksigner",
        ],
        outs = [
            output_name,
        ],
        cmd = """
         $(location @androidsdk//:apksigner) sign \
            --ks $(location {}) \
            --ks-key-alias {} \
            --ks-pass pass:{} \
            --v1-signing-enabled true \
            --v1-signer-name CERT \
            --v2-signing-enabled true \
            --out $(location {}) \
            $(location {})
        """.format(keystore, alias, password output_name, unsigned_android_binary),
    )