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
确保您有 Android Studio gradle 插件 3.5.0(不是 3.6.x,这似乎破坏了哨兵插件。我观察到哨兵混淆器或本机符号上传任务根本没有配置或执行)。这个值应该在你根项目的 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[=45中添加根文件夹的sentry.properties =].因为,每次创建构建时都会复制它。
Sentry 现在应该能够为任何发布版本上传混淆文件(或者如果您为任何构建类型设置 minifyEnabled=true)。
我必须将分析工具 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
确保您有 Android Studio gradle 插件 3.5.0(不是 3.6.x,这似乎破坏了哨兵插件。我观察到哨兵混淆器或本机符号上传任务根本没有配置或执行)。这个值应该在你根项目的 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[=45中添加根文件夹的sentry.properties =].因为,每次创建构建时都会复制它。
Sentry 现在应该能够为任何发布版本上传混淆文件(或者如果您为任何构建类型设置 minifyEnabled=true)。