Skip to content

Commit 5fb8833

Browse files
authored
Merge branch 'main' into no/optimize
2 parents 6d9f3e6 + e9c5fc4 commit 5fb8833

File tree

50 files changed

+3012
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+3012
-44
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
3737

3838
- name: Initialize CodeQL
39-
uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # pin@v2
39+
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # pin@v2
4040
with:
4141
languages: 'java'
4242

@@ -45,4 +45,4 @@ jobs:
4545
./gradlew buildForCodeQL --no-build-cache
4646
4747
- name: Perform CodeQL Analysis
48-
uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # pin@v2
48+
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # pin@v2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.DS_Store
22
.idea/
33
.gradle/
4+
.run/
45
build/
56
artifacts/
67
out/

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,52 @@
44

55
### Fixes
66

7+
- No longer send out empty log envelopes ([#4497](https://github.com/getsentry/sentry-java/pull/4497))
8+
9+
## 8.14.0
10+
11+
### Fixes
12+
13+
- Fix Session Replay masking for newer versions of Jetpack Compose (1.8+) ([#4485](https://github.com/getsentry/sentry-java/pull/4485))
14+
15+
### Features
16+
17+
- Add New User Feedback Widget ([#4450](https://github.com/getsentry/sentry-java/pull/4450))
18+
- This widget is a custom button that can be used to show the user feedback form
19+
- Add New User Feedback form ([#4384](https://github.com/getsentry/sentry-java/pull/4384))
20+
- We now introduce SentryUserFeedbackDialog, which extends AlertDialog, inheriting the show() and cancel() methods, among others.
21+
To use it, just instantiate it and call show() on the instance (Sentry must be previously initialized).
22+
For customization options, please check the [User Feedback documentation](https://docs.sentry.io/platforms/android/user-feedback/configuration/).
23+
```java
24+
import io.sentry.android.core.SentryUserFeedbackDialog;
25+
26+
new SentryUserFeedbackDialog.Builder(context).create().show();
27+
```
28+
```kotlin
29+
import io.sentry.android.core.SentryUserFeedbackDialog
30+
31+
SentryUserFeedbackDialog.Builder(context).create().show()
32+
```
33+
- Add `user.id`, `user.name` and `user.email` to log attributes ([#4486](https://github.com/getsentry/sentry-java/pull/4486))
34+
- User `name` attribute has been deprecated, please use `username` instead ([#4486](https://github.com/getsentry/sentry-java/pull/4486))
35+
- Add device (`device.brand`, `device.model` and `device.family`) and OS (`os.name` and `os.version`) attributes to logs ([#4493](https://github.com/getsentry/sentry-java/pull/4493))
36+
- Serialize `preContext` and `postContext` in `SentryStackFrame` ([#4482](https://github.com/getsentry/sentry-java/pull/4482))
37+
38+
### Internal
39+
40+
- User Feedback now uses SentryUser.username instead of SentryUser.name ([#4494](https://github.com/getsentry/sentry-java/pull/4494))
41+
42+
## 8.13.3
43+
44+
### Fixes
45+
746
- Send UI Profiling app start chunk when it finishes ([#4423](https://github.com/getsentry/sentry-java/pull/4423))
847
- Republish Javadoc [#4457](https://github.com/getsentry/sentry-java/pull/4457)
948
- Finalize `OkHttpEvent` even if no active span in `SentryOkHttpInterceptor` [#4469](https://github.com/getsentry/sentry-java/pull/4469)
49+
- Session Replay: Do not capture current replay for cached events from the past ([#4474](https://github.com/getsentry/sentry-java/pull/4474))
1050
- Session Replay: Correctly capture Dialogs and non full-sized windows ([#4354](https://github.com/getsentry/sentry-java/pull/4354))
1151
- Session Replay: Fix inconsistent `segment_id` ([#4471](https://github.com/getsentry/sentry-java/pull/4471))
52+
- Session Replay: Fix crash on devices with the Unisoc/Spreadtrum T606 chipset ([#4477](https://github.com/getsentry/sentry-java/pull/4477))
1253

1354
## 8.13.2
1455

build-logic/src/main/kotlin/io.sentry.javadoc.aggregate.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ subprojects {
2020

2121
val javadocCollection = javadocPublisher.incoming.artifactView { lenient(true) }.files
2222

23-
tasks.register("aggregateJavadoc", AggregateJavadoc::class) {
23+
tasks.register("aggregateJavadocs", AggregateJavadoc::class) {
2424
group = "documentation"
2525
description = "Aggregates Javadocs from all subprojects into a single directory."
2626
javadocFiles.set(javadocCollection)

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ org.gradle.workers.max=2
1414
android.useAndroidX=true
1515

1616
# Release information
17-
versionName=8.13.2
17+
versionName=8.14.0
1818

1919
# Override the SDK name on native crashes on Android
2020
sentryAndroidSdkName=sentry.native.android

sentry-android-core/api/sentry-android-core.api

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,32 @@ public final class io/sentry/android/core/SentryPerformanceProvider {
385385
public fun shutdown ()V
386386
}
387387

388+
public class io/sentry/android/core/SentryUserFeedbackButton : android/widget/Button {
389+
public fun <init> (Landroid/content/Context;)V
390+
public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;)V
391+
public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;I)V
392+
public fun <init> (Landroid/content/Context;Landroid/util/AttributeSet;II)V
393+
public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
394+
}
395+
396+
public final class io/sentry/android/core/SentryUserFeedbackDialog : android/app/AlertDialog {
397+
public fun setCancelable (Z)V
398+
public fun setOnDismissListener (Landroid/content/DialogInterface$OnDismissListener;)V
399+
public fun show ()V
400+
}
401+
402+
public class io/sentry/android/core/SentryUserFeedbackDialog$Builder {
403+
public fun <init> (Landroid/content/Context;)V
404+
public fun <init> (Landroid/content/Context;I)V
405+
public fun <init> (Landroid/content/Context;ILio/sentry/android/core/SentryUserFeedbackDialog$OptionsConfiguration;)V
406+
public fun <init> (Landroid/content/Context;Lio/sentry/android/core/SentryUserFeedbackDialog$OptionsConfiguration;)V
407+
public fun create ()Lio/sentry/android/core/SentryUserFeedbackDialog;
408+
}
409+
410+
public abstract interface class io/sentry/android/core/SentryUserFeedbackDialog$OptionsConfiguration {
411+
public abstract fun configure (Landroid/content/Context;Lio/sentry/SentryFeedbackOptions;)V
412+
}
413+
388414
public class io/sentry/android/core/SpanFrameMetricsCollector : io/sentry/IPerformanceContinuousCollector, io/sentry/android/core/internal/util/SentryFrameMetricsCollector$FrameMetricsCollectorListener {
389415
protected final field lock Lio/sentry/util/AutoClosableReentrantLock;
390416
public fun <init> (Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/android/core/internal/util/SentryFrameMetricsCollector;)V

sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
import android.content.Context;
44
import android.content.pm.PackageInfo;
55
import android.content.pm.PackageManager;
6+
import android.os.Build;
67
import io.sentry.DateUtils;
78
import io.sentry.EventProcessor;
89
import io.sentry.Hint;
910
import io.sentry.IpAddressUtils;
11+
import io.sentry.NoOpLogger;
12+
import io.sentry.SentryAttributeType;
1013
import io.sentry.SentryBaseEvent;
1114
import io.sentry.SentryEvent;
1215
import io.sentry.SentryLevel;
16+
import io.sentry.SentryLogEvent;
17+
import io.sentry.SentryLogEventAttributeValue;
1318
import io.sentry.SentryReplayEvent;
1419
import io.sentry.android.core.internal.util.AndroidThreadChecker;
1520
import io.sentry.android.core.performance.AppStartMetrics;
@@ -23,6 +28,7 @@
2328
import io.sentry.protocol.SentryTransaction;
2429
import io.sentry.protocol.User;
2530
import io.sentry.util.HintUtils;
31+
import io.sentry.util.LazyEvaluator;
2632
import io.sentry.util.Objects;
2733
import java.util.Collections;
2834
import java.util.List;
@@ -42,6 +48,8 @@ final class DefaultAndroidEventProcessor implements EventProcessor {
4248
private final @NotNull BuildInfoProvider buildInfoProvider;
4349
private final @NotNull SentryAndroidOptions options;
4450
private final @NotNull Future<DeviceInfoUtil> deviceInfoUtil;
51+
private final @NotNull LazyEvaluator<String> deviceFamily =
52+
new LazyEvaluator<>(() -> ContextUtils.getFamily(NoOpLogger.getInstance()));
4553

4654
public DefaultAndroidEventProcessor(
4755
final @NotNull Context context,
@@ -81,6 +89,13 @@ public DefaultAndroidEventProcessor(
8189
return event;
8290
}
8391

92+
@Override
93+
public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) {
94+
setDevice(event);
95+
setOs(event);
96+
return event;
97+
}
98+
8499
/**
85100
* The last exception is usually used for picking the issue title, but the convention is to send
86101
* inner exceptions first, e.g. [inner, outer] This doesn't work very well on Android, as some
@@ -199,6 +214,34 @@ private void mergeOS(final @NotNull SentryBaseEvent event) {
199214
}
200215
}
201216

217+
private void setDevice(final @NotNull SentryLogEvent event) {
218+
try {
219+
event.setAttribute(
220+
"device.brand",
221+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.BRAND));
222+
event.setAttribute(
223+
"device.model",
224+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL));
225+
event.setAttribute(
226+
"device.family",
227+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue()));
228+
} catch (Throwable e) {
229+
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e);
230+
}
231+
}
232+
233+
private void setOs(final @NotNull SentryLogEvent event) {
234+
try {
235+
event.setAttribute(
236+
"os.name", new SentryLogEventAttributeValue(SentryAttributeType.STRING, "Android"));
237+
event.setAttribute(
238+
"os.version",
239+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.VERSION.RELEASE));
240+
} catch (Throwable e) {
241+
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve os system", e);
242+
}
243+
}
244+
202245
// Data to be applied to events that was created in the running process
203246
private void processNonCachedEvent(
204247
final @NotNull SentryBaseEvent event, final @NotNull Hint hint) {

sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.sentry.ILogger;
77
import io.sentry.InitPriority;
88
import io.sentry.ProfileLifecycle;
9+
import io.sentry.SentryFeedbackOptions;
910
import io.sentry.SentryIntegrationPackageStorage;
1011
import io.sentry.SentryLevel;
1112
import io.sentry.protocol.SdkVersion;
@@ -126,6 +127,18 @@ final class ManifestMetadataReader {
126127
static final String ENABLE_AUTO_TRACE_ID_GENERATION =
127128
"io.sentry.traces.enable-auto-id-generation";
128129

130+
static final String FEEDBACK_NAME_REQUIRED = "io.sentry.feedback.is-name-required";
131+
132+
static final String FEEDBACK_SHOW_NAME = "io.sentry.feedback.show-name";
133+
134+
static final String FEEDBACK_EMAIL_REQUIRED = "io.sentry.feedback.is-email-required";
135+
136+
static final String FEEDBACK_SHOW_EMAIL = "io.sentry.feedback.show-email";
137+
138+
static final String FEEDBACK_USE_SENTRY_USER = "io.sentry.feedback.use-sentry-user";
139+
140+
static final String FEEDBACK_SHOW_BRANDING = "io.sentry.feedback.show-branding";
141+
129142
/** ManifestMetadataReader ctor */
130143
private ManifestMetadataReader() {}
131144

@@ -477,6 +490,21 @@ static void applyMetadata(
477490
options
478491
.getLogs()
479492
.setEnabled(readBool(metadata, logger, ENABLE_LOGS, options.getLogs().isEnabled()));
493+
494+
final @NotNull SentryFeedbackOptions feedbackOptions = options.getFeedbackOptions();
495+
feedbackOptions.setNameRequired(
496+
readBool(metadata, logger, FEEDBACK_NAME_REQUIRED, feedbackOptions.isNameRequired()));
497+
feedbackOptions.setShowName(
498+
readBool(metadata, logger, FEEDBACK_SHOW_NAME, feedbackOptions.isShowName()));
499+
feedbackOptions.setEmailRequired(
500+
readBool(metadata, logger, FEEDBACK_EMAIL_REQUIRED, feedbackOptions.isEmailRequired()));
501+
feedbackOptions.setShowEmail(
502+
readBool(metadata, logger, FEEDBACK_SHOW_EMAIL, feedbackOptions.isShowEmail()));
503+
feedbackOptions.setUseSentryUser(
504+
readBool(
505+
metadata, logger, FEEDBACK_USE_SENTRY_USER, feedbackOptions.isUseSentryUser()));
506+
feedbackOptions.setShowBranding(
507+
readBool(metadata, logger, FEEDBACK_SHOW_BRANDING, feedbackOptions.isShowBranding()));
480508
}
481509
options
482510
.getLogger()
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package io.sentry.android.core;
2+
3+
import android.annotation.SuppressLint;
4+
import android.content.Context;
5+
import android.content.res.TypedArray;
6+
import android.os.Build;
7+
import android.util.AttributeSet;
8+
import android.util.TypedValue;
9+
import android.widget.Button;
10+
import org.jetbrains.annotations.NotNull;
11+
import org.jetbrains.annotations.Nullable;
12+
13+
public class SentryUserFeedbackButton extends Button {
14+
15+
private @Nullable OnClickListener delegate;
16+
17+
public SentryUserFeedbackButton(Context context) {
18+
super(context);
19+
init(context, null, 0, 0);
20+
}
21+
22+
public SentryUserFeedbackButton(Context context, AttributeSet attrs) {
23+
super(context, attrs);
24+
init(context, attrs, 0, 0);
25+
}
26+
27+
public SentryUserFeedbackButton(Context context, AttributeSet attrs, int defStyleAttr) {
28+
super(context, attrs, defStyleAttr);
29+
init(context, attrs, defStyleAttr, 0);
30+
}
31+
32+
public SentryUserFeedbackButton(
33+
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
34+
super(context, attrs, defStyleAttr, defStyleRes);
35+
init(context, attrs, defStyleAttr, defStyleRes);
36+
}
37+
38+
@SuppressLint("SetTextI18n")
39+
@SuppressWarnings("deprecation")
40+
private void init(
41+
final @NotNull Context context,
42+
final @Nullable AttributeSet attrs,
43+
final int defStyleAttr,
44+
final int defStyleRes) {
45+
try (final @NotNull TypedArray typedArray =
46+
context.obtainStyledAttributes(
47+
attrs, R.styleable.SentryUserFeedbackButton, defStyleAttr, defStyleRes)) {
48+
final float dimensionScale = context.getResources().getDisplayMetrics().density;
49+
final float drawablePadding =
50+
typedArray.getDimension(R.styleable.SentryUserFeedbackButton_android_drawablePadding, -1);
51+
final int drawableStart =
52+
typedArray.getResourceId(R.styleable.SentryUserFeedbackButton_android_drawableStart, -1);
53+
final boolean textAllCaps =
54+
typedArray.getBoolean(R.styleable.SentryUserFeedbackButton_android_textAllCaps, false);
55+
final int background =
56+
typedArray.getResourceId(R.styleable.SentryUserFeedbackButton_android_background, -1);
57+
final float padding =
58+
typedArray.getDimension(R.styleable.SentryUserFeedbackButton_android_padding, -1);
59+
final int textColor =
60+
typedArray.getColor(R.styleable.SentryUserFeedbackButton_android_textColor, -1);
61+
final @Nullable String text =
62+
typedArray.getString(R.styleable.SentryUserFeedbackButton_android_text);
63+
64+
// If the drawable padding is not set, set it to 4dp
65+
if (drawablePadding == -1) {
66+
setCompoundDrawablePadding((int) (4 * dimensionScale));
67+
}
68+
69+
// If the drawable start is not set, set it to the default drawable
70+
if (drawableStart == -1) {
71+
setCompoundDrawablesRelativeWithIntrinsicBounds(
72+
R.drawable.sentry_user_feedback_button_logo_24, 0, 0, 0);
73+
}
74+
75+
// Set the text all caps
76+
setAllCaps(textAllCaps);
77+
78+
// If the background is not set, set it to the default background
79+
if (background == -1) {
80+
setBackgroundResource(R.drawable.sentry_oval_button_ripple_background);
81+
}
82+
83+
// If the padding is not set, set it to 12dp
84+
if (padding == -1) {
85+
int defaultPadding = (int) (12 * dimensionScale);
86+
setPadding(defaultPadding, defaultPadding, defaultPadding, defaultPadding);
87+
}
88+
89+
// If the text color is not set, set it to the default text color
90+
if (textColor == -1) {
91+
// We need the TypedValue to resolve the color from the theme
92+
final @NotNull TypedValue typedValue = new TypedValue();
93+
context.getTheme().resolveAttribute(android.R.attr.colorForeground, typedValue, true);
94+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
95+
setTextColor(context.getResources().getColor(typedValue.resourceId, context.getTheme()));
96+
} else {
97+
setTextColor(context.getResources().getColor(typedValue.resourceId));
98+
}
99+
}
100+
101+
// If the text is not set, set it to "Report a Bug"
102+
if (text == null) {
103+
setText("Report a Bug");
104+
}
105+
}
106+
107+
// Set the default ClickListener to open the SentryUserFeedbackDialog
108+
setOnClickListener(delegate);
109+
}
110+
111+
@Override
112+
public void setOnClickListener(final @Nullable OnClickListener listener) {
113+
delegate = listener;
114+
super.setOnClickListener(
115+
v -> {
116+
new SentryUserFeedbackDialog.Builder(getContext()).create().show();
117+
if (delegate != null) {
118+
delegate.onClick(v);
119+
}
120+
});
121+
}
122+
}

0 commit comments

Comments
 (0)