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 任务未编译的主要内容,如果未能解决你的问题,请参考以下文章
错误:Gradle:任务“:core:compileJava”执行失败。 > 编译失败
Android Gradle 插件ProductFlavor 配置 ( ProductFlavor#buildConfigField 方法 | 单独编译生成 BuildConfig 类的任务 )