Sentry 的 Gradle 任务未编译

Posted

技术标签:

【中文标题】Sentry 的 Gradle 任务未编译【英文标题】:Gradle task for Sentry not compiling 【发布时间】:2020-06-02 14:07:41 【问题描述】:

我必须将分析工具 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 脚本时,我收到错误:

无法创建任务 ':app:processSentryProguardForPlayStoreStagingDebug'.

没有方法签名:java.util.ArrayList.multiply() 适用于参数类型:(ArrayList) 值:[[sentry-cli, upload-proguard, --write-properties,应用程序路径/app/build/intermediates/assets/playStoreStaging/debug/sentry-debug-meta.properties, ...]] 可能的解决方案:乘法(java.lang.Number), 乘法(java.lang.Number)

我认为 commandLine 数组之前的乘法符号 * 有问题。但是当我删除它时,我得到了错误

无法创建任务 ':app:processSentryProguardForPlayStoreStagingDebug'.

无法将具有类“java.lang.String”的对象“sentry-cli”转换为类“int”

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

commandLine "sentry-cli", ...

这又给了我一个错误

出了什么问题:无法在空对象上调用方法dependsOn()

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

谢谢!

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

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

transformClassesAndResourcesWithR8For...

transformClassesWithDexBuilderFor...

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

在我的任务列表中存在

transformClassesAndResourcesWithR8ForPlayStoreStagingDebug

但不是

transformClassesAndResourcesWithR8ForPlayStoreStagingRelease

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

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

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

变体:PlayStoreStagingRelease DexTask 为空

变体:PlayStorePreviewRelease DexTask 为空

变体:HockeyAppRelease DexTask 为空

变体:LocalServerRelease DexTask 为空

变体:PlayStoreProductionRelease DexTask 为空

那怎么可能呢?

【问题讨论】:

【参考方案1】:

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

Android Gradle 官方插件随版本更改了任务名称,Gradle 版本也会影响那些代码 sn-ps。

Google 还用 R8 替换了 Proguard,它也影响了那些代码 sn-ps。

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

谢谢。

【讨论】:

实际上,我这样做了,但它似乎不起作用。使用它时,我的混淆代码没有映射,我认为这是因为它没有正确“执行” 您介意提出问题github.com/getsentry/sentry-android-gradle-plugin 吗? Gradle + AGP 版本会有所帮助,几天前我使用 AGP 3.x 到 3.6.x 版本和 Gradle 到 5.6.x 版本对其进行了测试,它工作得很好,也许是配置错误?很高兴为您提供帮助,谢谢。【参考方案2】:

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 任务可能是基于没有代码(无事可做)。

【讨论】:

正如我的问题中所述,执行此操作时,我收到错误“无法在空对象上调用方法 dependsOn()”所以我猜 gradle 任务本身也以某种方式被破坏了。 def dexTask = project.tasks.findByName("transformClassesWithDexFor$variantName") is null ...这意味着任务名称不匹配。我只有一些名为transformClassesWithDexBuilderForDebug 的任务,它添加了Builder 是的,谢谢。如我的屏幕截图所示,我似乎没有 Release 任务。但这怎么可能呢?这些任务是在哪里生成的? Debug 存在,但 Release 不存在。 transformClassesAndResourcesWithR8ForPlayStoreStagingRelease 存在于屏幕截图中......显然需要混淆任务,以便映射文件甚至存在。还要确保映射文件甚至保存在预期位置。 好的,很抱歉再次打扰您。我在不存在的任务问题中添加了一个列表。不知何故,一些 Release 变体没有 Dex-Task。怎么会这样?【参考方案3】:

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

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

    在项目的根文件夹中提供一个 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/

    可选:如果您有构建风格)就我而言,我的应用程序有不同的风格。因此,我必须将 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 中添加根文件夹的 sentry.properties。因为,每次创建构建时都会复制它。

Sentry 现在应该能够上传任何发布版本的 proguard 文件(或者如果您为任何 buildType 设置了 minifyEnabled=true)。

【讨论】:

以上是关于Sentry 的 Gradle 任务未编译的主要内容,如果未能解决你的问题,请参考以下文章

Celery 任务未捕获的异常未发送到 Sentry

错误:Gradle:任务“:core:compileJava”执行失败。 > 编译失败

Android Gradle 插件ProductFlavor 配置 ( ProductFlavor#buildConfigField 方法 | 单独编译生成 BuildConfig 类的任务 )

没有可用的增量编译快照数据 gradle 错误

Gradle 依赖项未列出本地 maven jar 的依赖项

当我在我的项目中添加 uber sdk gradle 时,它​​返回 500+ 编译错误