dt-obs-android
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAndroid Dynatrace Instrumentation
Android Dynatrace 集成
Scope: Basic setup only — from zero to first event. For anything beyond initial instrumentation (custom actions, crash grouping, data privacy policies, etc.) refer to the Dynatrace documentation directly.
适用范围: 仅基础设置——从无到首次事件。如需初始集成之外的配置(自定义操作、崩溃分组、数据隐私策略等),请直接参考Dynatrace官方文档。
Phase 1: Preflight
阶段1:前置检查
Before doing anything else, check that the current directory is an Android project root by looking for or . If neither exists, stop and tell the user this is not an Android project root, and ask them to navigate to the correct directory.
settings.gradle.ktssettings.gradleThen verify the following minimum requirements. If any are not met, stop and inform the user of what needs to be upgraded before proceeding:
| Requirement | Minimum |
|---|---|
| Gradle | 7.0.2 |
| Android Gradle Plugin (AGP) | 7.0 |
| JVM | Java 11 |
Run (or on Windows). The output covers both Gradle and the actual JVM Gradle is using (the line), which may differ from the system Java when the project is opened in Android Studio or IntelliJ. Do not use — it may report a different JDK than what the build actually runs on. The AGP version is declared in the root build file.
./gradlew --versiongradlew.bat --versionDaemon JVMjava -version在进行任何操作之前,通过查找或文件确认当前目录为Android项目根目录。如果两者都不存在,请立即停止操作并告知用户当前目录并非Android项目根目录,请用户导航至正确目录。
settings.gradle.ktssettings.gradle随后验证以下最低要求。如果任何一项未满足,请立即停止操作并告知用户需要升级的内容,之后再继续:
| 要求 | 最低版本 |
|---|---|
| Gradle | 7.0.2 |
| Android Gradle Plugin (AGP) | 7.0 |
| JVM | Java 11 |
运行(Windows系统运行)。输出内容包含Gradle版本以及Gradle实际使用的JVM版本(行),该版本可能与Android Studio或IntelliJ中项目使用的系统Java版本不同。请勿使用命令——它可能报告与实际构建使用的JDK不同的版本。AGP版本在根构建文件中声明。
./gradlew --versiongradlew.bat --versionDaemon JVMjava -versionPhase 2: Detect existing setup
阶段2:检测现有配置
If a block or a block (also written as when the class is imported) is found anywhere in the build files, read it and extract if present:
dynatrace { }configure<com.dynatrace.tools.android.dsl.DynatraceExtension> { }configure<DynatraceExtension> { }- (the value passed to
applicationIdorapplicationId(...))applicationId '...' - (the value passed to
beaconUrlorbeaconUrl(...))beaconUrl '...'
Save these as pre-filled values to carry into Phase 3. If either value is absent or uses a placeholder (e.g. ), treat it as not found. Proceed to Phase 3.
YOUR_APPLICATION_ID如果在构建文件中发现块或块(当类已导入时也可写为),读取并提取以下内容(如果存在):
dynatrace { }configure<com.dynatrace.tools.android.dsl.DynatraceExtension> { }configure<DynatraceExtension> { }- (传递给
applicationId或applicationId(...)的值)applicationId '...' - (传递给
beaconUrl或beaconUrl(...)的值)beaconUrl '...'
将这些值保存为预填充值,带入阶段3。如果任一值缺失或使用占位符(例如),则视为未找到。继续进入阶段3。
YOUR_APPLICATION_IDPhase 3: Collect inputs
阶段3:收集输入信息
First, ask only for:
- — Dynatrace application ID. Tell the user this can be found in their Dynatrace tenant, inside the mobile application they have already created. If a value was extracted in Phase 2, show it as the current value and ask the user to confirm or replace it.
applicationId - — Dynatrace beacon URL. Tell the user this can also be found in their Dynatrace tenant, inside the same mobile application configuration. Same: show the extracted value if available and ask to confirm or replace.
beaconUrl
Once the user confirms or provides both, then ask — unless the user already stated their session replay preference in their initial request, in which case skip this question and use what they said:
- Session replay — should session replay be enabled? (yes/no)
首先,仅询问以下两项:
- ——Dynatrace应用ID。告知用户该ID可在其Dynatrace租户中已创建的移动应用内找到。如果在阶段2中提取到值,将其显示为当前值并询问用户确认或替换。
applicationId - ——Dynatrace beacon URL。告知用户该URL同样可在其Dynatrace租户的同一移动应用配置中找到。同样:如果有提取到的值则显示并询问确认或替换。
beaconUrl
一旦用户确认或提供了这两项值,然后询问——除非用户在初始请求中已说明会话重放偏好,否则跳过此问题并使用用户提供的偏好:
- 会话重放——是否启用会话重放?(是/否)
Phase 4: Locate files
阶段4:定位文件
Finding the app module
查找应用模块
The application module is not always named . Read or to find all included modules, then check each module's build file for the plugin. Use the directory of the first module that applies it as for all paths below.
appsettings.gradle.ktssettings.gradlecom.android.applicationAPP_MODULEmacOS / Linux:
bash
grep -r -l --include="*.gradle" --include="*.gradle.kts" --exclude-dir=buildSrc "com.android.application" .Windows (cmd):
text
findstr /s /m "com.android.application" *.gradle *.gradle.ktsWindows (PowerShell):
text
Get-ChildItem -Recurse -Include "*.gradle","*.gradle.kts" | Select-String "com.android.application" | Select-Object -ExpandProperty PathDiscard any result where the matching line contains — those are version-catalog declarations in the root build file, not actual plugin applications. Also discard any result under .
apply falsebuildSrc/If no module applying is found after filtering, stop and report the failure — no files have been modified at this point.
com.android.application应用模块并不总是命名为。读取或以找到所有包含的模块,然后检查每个模块的构建文件是否应用了插件。将第一个应用该插件的模块目录作为后续所有路径的。
appsettings.gradle.ktssettings.gradlecom.android.applicationAPP_MODULEmacOS / Linux:
bash
grep -r -l --include="*.gradle" --include="*.gradle.kts" --exclude-dir=buildSrc "com.android.application" .Windows (cmd):
text
findstr /s /m "com.android.application" *.gradle *.gradle.ktsWindows (PowerShell):
text
Get-ChildItem -Recurse -Include "*.gradle","*.gradle.kts" | Select-String "com.android.application" | Select-Object -ExpandProperty Path丢弃任何匹配行包含的结果——这些是根构建文件中的版本目录声明,而非实际的插件应用。同时丢弃目录下的结果。
apply falsebuildSrc/如果过滤后未找到应用的模块,请立即停止操作并报告失败——此时尚未修改任何文件。
com.android.applicationFiles to read before editing
编辑前需读取的文件
- Root /
build.gradle.kts(sibling of the settings file)build.gradle - App /
APP_MODULE/build.gradle.ktsAPP_MODULE/build.gradle - Entry-point source file — see below
- 根目录/
build.gradle.kts(与settings文件同级)build.gradle - 应用模块/
APP_MODULE/build.gradle.ktsAPP_MODULE/build.gradle - 入口源文件——见下文
Finding the entry-point file
查找入口文件
Preferred: Application class. Search the source tree for a class that extends using the appropriate command for the OS:
ApplicationmacOS / Linux:
bash
grep -r -l --include="*.java" "extends Application" APP_MODULE/src
grep -r -l --include="*.kt" ": Application()" APP_MODULE/srcWindows (cmd):
text
findstr /s /m "extends Application" APP_MODULE\src\*.java
findstr /s /m ": Application()" APP_MODULE\src\*.ktWindows (PowerShell):
text
Get-ChildItem -Recurse -Path APP_MODULE/src -Include "*.java" | Select-String "extends Application" | Select-Object -ExpandProperty Path
Get-ChildItem -Recurse -Path APP_MODULE/src -Include "*.kt" | Select-String ": Application()" | Select-Object -ExpandProperty PathIf found, use that file. Add the privacy opt-in call inside its , after .
onCreate()super.onCreate()Fallback: Launcher activity. If no Application class exists, find the launcher activity in — it is the that contains:
AndroidManifest.xml<activity>text
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />Read the attribute of that activity, locate its source file, and add the privacy opt-in call inside , after .
android:nameonCreate()setContentView(...)Once the file is found, detect the language from its extension: = Kotlin, = Java.
.kt.javaDo not assume the file is named.MainActivity
首选:Application类。使用对应操作系统的命令在源码树中搜索继承自的类:
ApplicationmacOS / Linux:
bash
grep -r -l --include="*.java" "extends Application" APP_MODULE/src
grep -r -l --include="*.kt" ": Application()" APP_MODULE/srcWindows (cmd):
text
findstr /s /m "extends Application" APP_MODULE\src\*.java
findstr /s /m ": Application()" APP_MODULE\src\*.ktWindows (PowerShell):
text
Get-ChildItem -Recurse -Path APP_MODULE/src -Include "*.java" | Select-String "extends Application" | Select-Object -ExpandProperty Path
Get-ChildItem -Recurse -Path APP_MODULE/src -Include "*.kt" | Select-String ": Application()" | Select-Object -ExpandProperty Path如果找到,使用该文件。在其方法中,之后添加隐私授权调用。
onCreate()super.onCreate()备选:启动Activity。如果不存在Application类,在中查找启动Activity——即包含以下内容的:
AndroidManifest.xml<activity>text
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />读取该Activity的属性,定位其源文件,并在方法中之后添加隐私授权调用。
android:nameonCreate()setContentView(...)找到文件后,根据扩展名判断语言: = Kotlin, = Java。
.kt.java请勿假设文件名为。MainActivity
Phase 5: Instrument
阶段5:集成配置
For each step below, check whether the element is already present before writing. If it is present and correct, skip it. If it is present but incorrect or incomplete, update only the affected values. If it is absent, add it in full.
Before editing any file, record its original content. If any step fails for any reason (build error, missing file, unresolvable conflict, unexpected file structure, etc.):
- Stop immediately — do not attempt further changes.
- Report the failure — state clearly which step failed and why.
- Rollback all edits — restore every file modified in this phase to its original content. If a file was created from scratch, delete it.
- Confirm rollback — tell the user which files were restored and that the project is back to its original state.
Do not leave the project in a partially instrumented state.
对于以下每一步,在写入前检查元素是否已存在。如果已存在且正确,则跳过。如果已存在但不正确或不完整,则仅更新受影响的值。如果不存在,则完整添加。
在编辑任何文件之前,记录其原始内容。如果任何步骤因任何原因失败(构建错误、文件缺失、无法解决的冲突、意外的文件结构等):
- 立即停止——不要尝试进一步修改。
- 报告失败——明确说明哪一步失败以及原因。
- 回滚所有编辑——将此阶段修改的每个文件恢复为原始内容。如果是从零创建的文件,则删除它。
- 确认回滚——告知用户哪些文件已恢复,项目已回到原始状态。
请勿让项目处于部分集成的状态。
Root build file
根构建文件
First check whether the root build file is (Kotlin DSL) or (Groovy DSL) and apply the matching syntax.
build.gradle.ktsbuild.gradlemust be applied in the root build file, not the app module.com.dynatrace.instrumentation
首先检查根构建文件是(Kotlin DSL)还是(Groovy DSL),并应用匹配的语法。
build.gradle.ktsbuild.gradle必须在根构建文件中应用,而非应用模块。com.dynatrace.instrumentation
Kotlin DSL (build.gradle.kts
)
build.gradle.ktsKotlin DSL (build.gradle.kts
)
build.gradle.ktsClasspath dependency — check whether already appears in a block. If yes and the version spec is , skip. If yes with a different version, update the version to . If absent, add the classpath into an existing block if one exists; otherwise add the full block before the block:
com.dynatrace.tools.android:gradle-pluginbuildscript { dependencies { } }8.+8.+buildscript { dependencies { } }buildscriptplugins {}text
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.dynatrace.tools.android:gradle-plugin:8.+")
}
}Plugin apply — check whether is already present. If yes, skip. If absent, add it after the block.
apply(plugin = "com.dynatrace.instrumentation")plugins {}DynatraceExtension block — check whether a block already exists.
configure<com.dynatrace.tools.android.dsl.DynatraceExtension>- If it exists, check each field and update only those that differ from the target values: ,
applicationId,beaconUrl,userOptIn(true),agentBehavior.startupLoadBalancing(true), andagentBehavior.startupWithGrailEnabled(true)(if session replay was requested). Add any missing fields.sessionReplay.enabled(true) - If absent, add the full block after the plugin apply line. In both cases, substitute and
applicationIdwith the values confirmed in Phase 3 — do not leave the placeholders below in place:beaconUrl
text
configure<com.dynatrace.tools.android.dsl.DynatraceExtension> {
configurations {
create("sampleConfig") {
autoStart {
applicationId("YOUR_APPLICATION_ID")
beaconUrl("https://your-tenant.live.dynatrace.com/mbeacon")
}
userOptIn(true)
agentBehavior.startupLoadBalancing(true)
agentBehavior.startupWithGrailEnabled(true)
// only if session replay was requested:
sessionReplay.enabled(true)
}
}
}类路径依赖——检查是否已出现在块中。如果已存在且版本为,则跳过。如果已存在但版本不同,则将版本更新为。如果不存在,将类路径添加到现有的块中;如果不存在该块,则在块之前添加完整的块:
com.dynatrace.tools.android:gradle-pluginbuildscript { dependencies { } }8.+8.+buildscript { dependencies { } }plugins {}buildscripttext
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.dynatrace.tools.android:gradle-plugin:8.+")
}
}插件应用——检查是否已存在。如果已存在,则跳过。如果不存在,在块之后添加。
apply(plugin = "com.dynatrace.instrumentation")plugins {}DynatraceExtension块——检查块是否已存在。
configure<com.dynatrace.tools.android.dsl.DynatraceExtension>- 如果已存在,检查每个字段并仅更新与目标值不同的字段:、
applicationId、beaconUrl、userOptIn(true)、agentBehavior.startupLoadBalancing(true),以及(如果请求了会话重放)agentBehavior.startupWithGrailEnabled(true)。添加任何缺失的字段。sessionReplay.enabled(true) - 如果不存在,在插件应用行之后添加完整块。两种情况下,都用阶段3中确认的值替换和
applicationId——请勿保留下面的占位符:beaconUrl
text
configure<com.dynatrace.tools.android.dsl.DynatraceExtension> {
configurations {
create("sampleConfig") {
autoStart {
applicationId("YOUR_APPLICATION_ID")
beaconUrl("https://your-tenant.live.dynatrace.com/mbeacon")
}
userOptIn(true)
agentBehavior.startupLoadBalancing(true)
agentBehavior.startupWithGrailEnabled(true)
// only if session replay was requested:
sessionReplay.enabled(true)
}
}
}Groovy DSL (build.gradle
)
build.gradleGroovy DSL (build.gradle
)
build.gradleClasspath dependency — check whether already appears in a block. If yes and the version spec is , skip. If yes with a different version, update the version to . If absent, add the classpath inside the existing block, or create the full block before any lines if none exists:
com.dynatrace.tools.android:gradle-pluginbuildscript { dependencies { } }8.+8.+buildscript { dependencies { } }buildscriptapplytext
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.dynatrace.tools.android:gradle-plugin:8.+'
}
}Plugin apply — check whether is already present. If yes, skip. If absent, add it after the existing lines or at the end of the file.
apply plugin: 'com.dynatrace.instrumentation'applydynatrace block — check whether a block already exists.
dynatrace { }- If it exists, check each field and update only those that differ from the target values: ,
applicationId,beaconUrl,userOptIn true,agentBehavior.startupLoadBalancing true, andagentBehavior.startupWithGrailEnabled true(if session replay was requested). Add any missing fields.sessionReplay.enabled true - If absent, add the full block after the plugin apply line. In both cases, substitute and
applicationIdwith the values confirmed in Phase 3 — do not leave the placeholders below in place:beaconUrl
text
dynatrace {
configurations {
sampleConfig {
autoStart {
applicationId 'YOUR_APPLICATION_ID'
beaconUrl 'https://your-tenant.live.dynatrace.com/mbeacon'
}
userOptIn true
agentBehavior.startupLoadBalancing true
agentBehavior.startupWithGrailEnabled true
// only if session replay was requested:
sessionReplay.enabled true
}
}
}类路径依赖——检查是否已出现在块中。如果已存在且版本为,则跳过。如果已存在但版本不同,则将版本更新为。如果不存在,将类路径添加到现有的块中;如果不存在该块,则在所有行之前创建完整的块:
com.dynatrace.tools.android:gradle-pluginbuildscript { dependencies { } }8.+8.+buildscript { dependencies { } }applybuildscripttext
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.dynatrace.tools.android:gradle-plugin:8.+'
}
}插件应用——检查是否已存在。如果已存在,则跳过。如果不存在,在现有的行之后或文件末尾添加。
apply plugin: 'com.dynatrace.instrumentation'applydynatrace块——检查块是否已存在。
dynatrace { }- 如果已存在,检查每个字段并仅更新与目标值不同的字段:、
applicationId、beaconUrl、userOptIn true、agentBehavior.startupLoadBalancing true,以及(如果请求了会话重放)agentBehavior.startupWithGrailEnabled true。添加任何缺失的字段。sessionReplay.enabled true - 如果不存在,在插件应用行之后添加完整块。两种情况下,都用阶段3中确认的值替换和
applicationId——请勿保留下面的占位符:beaconUrl
text
dynatrace {
configurations {
sampleConfig {
autoStart {
applicationId 'YOUR_APPLICATION_ID'
beaconUrl 'https://your-tenant.live.dynatrace.com/mbeacon'
}
userOptIn true
agentBehavior.startupLoadBalancing true
agentBehavior.startupWithGrailEnabled true
// only if session replay was requested:
sessionReplay.enabled true
}
}
}Entry-point file (Application class or launcher activity)
入口文件(Application类或启动Activity)
Add only the imports not already present. For the privacy opt-in call, check whether already exists inside . If yes, verify each option (, , if session replay is enabled) and update any that differ. If absent, insert it at the position matching the entry-point type:
Dynatrace.applyUserPrivacyOptions(...)onCreateDataCollectionLevel.USER_BEHAVIORwithCrashReportingOptedIn(true)withScreenRecordOptedIn(true)- Application subclass — after
super.onCreate() - Launcher activity — after
setContentView(...)
仅添加尚未存在的导入。对于隐私授权调用,检查是否已存在于方法中。如果已存在,验证每个选项(、、如果启用会话重放则)并更新任何不同的选项。如果不存在,根据入口类型插入到对应位置:
Dynatrace.applyUserPrivacyOptions(...)onCreateDataCollectionLevel.USER_BEHAVIORwithCrashReportingOptedIn(true)withScreenRecordOptedIn(true)- Application子类——之后
super.onCreate() - 启动Activity——之后
setContentView(...)
Kotlin
Kotlin
Imports — add only those not already present:
text
import com.dynatrace.android.agent.Dynatrace
import com.dynatrace.android.agent.conf.DataCollectionLevel
import com.dynatrace.android.agent.conf.UserPrivacyOptionsPrivacy opt-in call — insert after (Application subclass) or after (launcher activity). Include only if session replay was enabled in Phase 3:
super.onCreate()setContentView(...).withScreenRecordOptedIn(true)text
Dynatrace.applyUserPrivacyOptions(
UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
// .withScreenRecordOptedIn(true) — add only if session replay is enabled
.build()
)导入——仅添加尚未存在的导入:
text
import com.dynatrace.android.agent.Dynatrace
import com.dynatrace.android.agent.conf.DataCollectionLevel
import com.dynatrace.android.agent.conf.UserPrivacyOptions隐私授权调用——插入到之后(Application子类)或之后(启动Activity)。仅当阶段3中启用了会话重放时才包含:
super.onCreate()setContentView(...).withScreenRecordOptedIn(true)text
Dynatrace.applyUserPrivacyOptions(
UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
// .withScreenRecordOptedIn(true) — add only if session replay is enabled
.build()
)Java
Java
Imports — add only those not already present:
text
import com.dynatrace.android.agent.Dynatrace;
import com.dynatrace.android.agent.conf.DataCollectionLevel;
import com.dynatrace.android.agent.conf.UserPrivacyOptions;Privacy opt-in call — insert after (Application subclass) or after (launcher activity). Include only if session replay was enabled in Phase 3:
super.onCreate()setContentView(...).withScreenRecordOptedIn(true)text
Dynatrace.applyUserPrivacyOptions(UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
// .withScreenRecordOptedIn(true) — add only if session replay is enabled
.build()
);导入——仅添加尚未存在的导入:
text
import com.dynatrace.android.agent.Dynatrace;
import com.dynatrace.android.agent.conf.DataCollectionLevel;
import com.dynatrace.android.agent.conf.UserPrivacyOptions;隐私授权调用——插入到之后(Application子类)或之后(启动Activity)。仅当阶段3中启用了会话重放时才包含:
super.onCreate()setContentView(...).withScreenRecordOptedIn(true)text
Dynatrace.applyUserPrivacyOptions(UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
// .withScreenRecordOptedIn(true) — add only if session replay is enabled
.build()
);Phase 6: Build and verify
阶段6:构建与验证
First, discover available assemble tasks to handle projects with custom build types or product flavors:
macOS / Linux:
bash
./gradlew tasks --group=build | grep -i "^assemble"Windows (cmd):
text
gradlew.bat tasks --group=build | findstr /i "assemble"Windows (PowerShell):
text
.\gradlew.bat tasks --group=build | Select-String -Pattern "^assemble" -CaseSensitive:$falseIf only one assemble task is listed, use it. If multiple tasks are listed, present them to the user and ask which one to run.
Then run it:
- macOS / Linux:
./gradlew CHOSEN_TASK - Windows (cmd):
gradlew.bat CHOSEN_TASK - Windows (PowerShell):
.\gradlew.bat CHOSEN_TASK
A successful build confirms the Dynatrace plugin is wired up correctly.
首先,发现可用的assemble任务,以处理带有自定义构建类型或产品风味的项目:
macOS / Linux:
bash
./gradlew tasks --group=build | grep -i "^assemble"Windows (cmd):
text
gradlew.bat tasks --group=build | findstr /i "assemble"Windows (PowerShell):
text
.\gradlew.bat tasks --group=build | Select-String -Pattern "^assemble" -CaseSensitive:$false如果仅列出一个assemble任务,则使用它。如果列出多个任务,将它们呈现给用户并询问要运行哪一个。
然后运行该任务:
- macOS / Linux:
./gradlew CHOSEN_TASK - Windows (cmd):
gradlew.bat CHOSEN_TASK - Windows (PowerShell):
.\gradlew.bat CHOSEN_TASK
构建成功则确认Dynatrace插件已正确配置。