Gradle Sentry 任务未编译

Gradle task for Sentry not compiling

我必须将分析工具 Sentry 添加到我们的 Android 项目中。为了使其工作,需要为混淆代码(来自 Proguard/R8)创建映射,然后将其上传到 Sentry。

在网站 https://docs.sentry.io/platforms/android/ 上甚至描述了如何做到这一点。 那里写道,需要创建一个 gradle 任务,如下所示:

gradle.projectsEvaluated {
    android.applicationVariants.each { variant ->
        def variantName = variant.name.capitalize();
        def proguardTask = project.tasks.findByName(
            "transformClassesAndResourcesWithProguardFor${variantName}")
        def dexTask = project.tasks.findByName(
            "transformClassesWithDexFor${variantName}")
        def task = project.tasks.create(
                name: "processSentryProguardFor${variantName}",
                type: Exec) {
            workingDir project.rootDir
            commandLine *[
                "sentry-cli",
                "upload-proguard",
                "--write-properties",
                "${project.rootDir.toPath()}/app/build/intermediates/assets" +
                    "/${variant.dirName}/sentry-debug-meta.properties",
                variant.getMappingFile(),
                "--no-upload"
            ]
        }
        dexTask.dependsOn task
        task.dependsOn proguardTask
    }
}

这应该等到 Proguard 完成,然后将此属性文件复制到资产中。但是,当我将其添加到我的 Android gradle 脚本时,我收到错误消息:

Could not create task ':app:processSentryProguardForPlayStoreStagingDebug'.

No signature of method: java.util.ArrayList.multiply() is applicable for argument types: (ArrayList) values: [[sentry-cli, upload-proguard, --write-properties, {Application-Path}/app/build/intermediates/assets/playStoreStaging/debug/sentry-debug-meta.properties, ...]] Possible solutions: multiply(java.lang.Number), multiply(java.lang.Number)

我假设命令行数组前的乘号 * 有问题。但是当我删除它时,我得到了错误

Could not create task ':app:processSentryProguardForPlayStoreStagingDebug'.

Cannot cast object 'sentry-cli' with class 'java.lang.String' to class 'int'

所以我试着只用那一行来测试这个

commandLine "sentry-cli", ...

这给了我另一个错误

What went wrong: Cannot invoke method dependsOn() on null object

因此我认为 gradle 脚本确实出了点问题,因为它似乎无法找到依赖任务。有谁知道如何解决这个问题(或者有其他想法如何在 Proguard/R8 完成后以另一种方式将 sentry-debug-meta.properties 文件复制到我的资产中)?

谢谢!

--------编辑--------

我注意到一些重要的事情。 gradle 任务的定义名称与手册中定义的名称不同。查看我的任务,我将它们命名为

transformClassesAndResourcesWithR8For...

transformClassesWithDexBuilderFor...

但是,我打印了 variantName 然后进行检查,但似乎我的任务未完成。

在我的任务列表中有

transformClassesAndResourcesWithR8ForPlayStoreStagingDebug

但不是

transformClassesAndResourcesWithR8ForPlayStoreStagingRelease

因此找不到任务。我认为这才是真正的问题所在。那么这些 gradle 任务在哪里定义的?

-------- 编辑 2 --------

好的,我注意到这里有些奇怪。有些变体没有任务。 DEBUG 任务没有 R8 任务是有道理的,但我在这里找到了这个:

Variant: PlayStoreStagingRelease DexTask is null

Variant: PlayStorePreviewRelease DexTask is null

Variant: HockeyAppRelease DexTask is null

Variant: LocalServerRelease DexTask is null

Variant: PlayStoreProductionRelease DexTask is null

这怎么可能?

java.util.ArrayList.multiply()[ ] 列表前面提示 *,这对我来说很奇怪。尝试删除 *[ ],只保留 List<String>(开始时没有 ArrayList):

commandLine "sentry-cli", "upload-proguard", "--write-properties", "${project.rootDir.toPath()}/app/build/intermediates/assets/${variant.dirName}/sentry-debug-meta.properties", variant.getMappingFile(), "--no-upload"

您必须查看您的任务实际上是如何被调用的,但它应该是类似的:

def r8Task = project.tasks.findByName("transformClassesAndResourcesWithR8For${variantName}")
def d8Task = project.tasks.findByName("transformClassesWithDexBuilderFor${variantName}")

使用 null 检查,因为并非每个变体都可能设置 minifyEnabled true

if(r8Task != null) {
    d8Task.dependsOn task
    task.dependsOn r8Task
}

也许甚至需要之前的 null 检查,因为 variant.getMappingFile() 需要 R8。

并且某些版本没有 D8 任务可能是基于缺少代码(无事可做)。

我建议使用此处描述的 Sentry Gradle 集成(Gradle 插件)https://docs.sentry.io/platforms/android/#gradle-integration

官方 Android Gradle 插件在不同版本中更改了任务名称,Gradle 版本也会影响这些代码片段。

Google 还用 R8 替换了 Proguard,它也影响了那些代码片段。

是否有不使用 Sentry Gradle 集成的原因?如果是这样,我们将考虑更新它们。

谢谢。

以下是我将 Sentry 与我的 Android 应用程序集成所遵循的步骤的摘要。这些步骤是为了确保 sentry gradle 插件按预期工作并自动上传 proguard 映射文件,而无需担心使用 cli 上传。我假设您已经按照此处所述设置了 Sentry SDK: https://docs.sentry.io/platforms/android/#integrating-the-sdk

  1. 确保您有 Android Studio gradle 插件 3.5.0(不是 3.6.x,这似乎破坏了哨兵插件。我观察到哨兵混淆器或本机符号上传任务根本没有配置或执行)。这个值应该在你根项目的 build.gradledependencies

  2. 在项目的根文件夹中提供一个 sentry.properties 文件。 sentry.properties 文件至少应具有以下值:

    defaults.project=your_sentry_project_name
    defaults.org=your_sentry_org_name
    auth.token=sentry_project_auth_token

您可以在此处获取有关生成身份验证令牌的信息:https://sentry.io/settings/account/api/auth-tokens/

  1. 可选:如果您有构建风格)就我而言,我的应用程序有不同的风格。因此,我不得不将 sentry.properties 放入 /app/src/ 文件夹中的特定风味文件夹中。然后,我编写了一个 gradle 任务,以在 gradle 的配置阶段将风味特定的 sentry.properties 文件复制到项目的根文件夹中。示例:
    task copySentryPropertiesTask {
        if (getBuildFlavor() != null && !getBuildFlavor().isEmpty()) {
            println("Copying Sentry properties file: ${getBuildFlavor()}")
            copy {
                from "src/${getBuildFlavor()}/"
                include "sentry.properties"
                into "../"
            }
        }
    }

    def getBuildFlavor() {
        Gradle gradle = getGradle()
        String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
        Pattern pattern;
        if (tskReqStr.contains("assemble"))
            pattern = Pattern.compile("assemble(\w+)(Release|Debug)")
        else
            pattern = Pattern.compile("generate(\w+)(Release|Debug)")
        Matcher matcher = pattern.matcher(tskReqStr)
        if (matcher.find())
            return matcher.group(1)
        else {
            println "NO MATCH FOUND"
            return ""
        }
    }

注意 1:您可以将此任务放在您的 app/build.gradle 中的任何位置(我已将其放在末尾)。

注2:如果你按照第3步构建风格,你也可以在.gitignore[=45中添加根文件夹的sentry.properties =].因为,每次创建构建时都会复制它。

Sentry 现在应该能够为任何发布版本上传混淆文件(或者如果您为任何构建类型设置 minifyEnabled=true)。