Skip to content

Add Android new User Feedback instructions #13758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 281 additions & 0 deletions docs/platforms/android/user-feedback/configuration/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
---
title: Configure User Feedback
sidebar_order: 6900
description: "Learn about general User Feedback configuration fields."
---

## User Feedback Widget

The User Feedback Widget offers many customization options, and if the available options are insufficient, you can [use your own UI](#bring-your-own-widget).
The widget is a custom button that opens the form, a custom AlertDialog that allows users to submit feedback.

### Hooks

There are hooks available so you can react when the user opens or closes the form, successfully submits it, or an error is triggered:

| Hook | Type | Description |
| ----------------- | ------------------------- | ------------------------------------------------------------------------ |
| `onFormOpen` | `() -> Void` | Called when the feedback form is opened. |
| `onFormClose` | `() -> Void` | Called when the feedback form is closed. |
| `onSubmitSuccess` | `(Feedback) -> Void` | Called when feedback is successfully submitted via the prepared form. |
| `onSubmitError` | `(Feedback) -> Void` | Called when there is an error submitting feedback via the prepared form. |
Comment on lines +16 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the tables 👍

we should use those more often in docs where it makes sense 🤔


`onSubmitSuccess` and `onSubmitError` forward the feedback object that was submitted, which contains the following properties:

- `message`: The message the user entered in the feedback form.
- `name`: The name the user entered in the feedback form.
- `contactEmail`: The email the user entered in the feedback form.

Example:

```java
SentryAndroid.init(context, options -> {
options.getFeedbackOptions().setOnFormOpen(() -> System.out.println("Form opened"));
options.getFeedbackOptions().setOnFormClose(() -> System.out.println("Form closed"));
options.getFeedbackOptions().setOnSubmitSuccess((feedback) -> System.out.println("Feedback submitted successfully: " + feedback.toString()));
options.getFeedbackOptions().setOnSubmitError((feedback) -> System.out.println("Failed to submit feedback: " + feedback.toString()));
});
```
```kotlin
SentryAndroid.init(this) { options ->
options.feedbackOptions.onFormOpen = Runnable { println("Form opened") }
options.feedbackOptions.onFormClose = Runnable { println("Form closed") }
options.feedbackOptions.onSubmitSuccess = SentryFeedbackOptions.SentryFeedbackCallback {
println("Feedback submitted successfully: $it")
}
options.feedbackOptions.onSubmitError = SentryFeedbackOptions.SentryFeedbackCallback {
println("Failed to submit feedback: $it")
}
}
```

### Widget

The widget is a custom button that opens the feedback form. As such, you can treat it like any View, customizing it through its XML attributes or programmatically.
The default attributes of the widget are:

| Attribute | Default Value |
| -------------------------- | ------------------------------------------- |
| `android:drawablePadding` | `4dp` |
| `android:drawableStart` | `@drawable/baseline_campaign_24` |
| `android:textAllCaps` | `false` |
| `android:background` | `@drawable/oval_button_ripple_background` |
| `android:padding` | `12dp` |
| `android:textColor` | `?android:attr/colorForeground` |
| `android:text` | `"Report a Bug"` |

Example:
```xml {filename:myLayout.xml}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<io.sentry.android.core.SentryUserFeedbackButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
```
```java
import io.sentry.android.core.SentryUserFeedbackButton;

SentryUserFeedbackButton widget = new SentryUserFeedbackButton(context);
```
```kotlin
import io.sentry.android.core.SentryUserFeedbackButton

val widget = SentryUserFeedbackButton(context)
```

### Form Configuration

You can customize which form elements are shown, whether they are required, and even prefill some info, in `SentryOptions.SentryFeedbackOptions`:

| Option | Type | Default | Description |
| ----------------------------- | -------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `showBranding` | `Bool` | `true` | Displays the Sentry logo inside the form |
| `isNameRequired` | `Bool` | `false` | Requires the name field on the feedback form to be filled in. |
| `showName` | `Bool` | `true` | Displays the name field on the feedback form. Ignored if `isNameRequired` is `true`. |
| `isEmailRequired` | `Bool` | `false` | Requires the email field on the feedback form to be filled in. |
| `showEmail` | `Bool` | `true` | Displays the email field on the feedback form. Ignored if `isEmailRequired` is `true`. |
| `useSentryUser` | `Bool` | `true` | Sets the `email` and `name` fields to the corresponding Sentry SDK user fields that were called with `SentrySDK.setUser`. |

Example:

```xml {filename:AndroidManifest.xml}
<application>
<meta-data android:name="io.sentry.feedback.is-name-required" android:value="true" />
<meta-data android:name="io.sentry.feedback.show-name" android:value="false" />
<meta-data android:name="io.sentry.feedback.is-email-required" android:value="false" />
<meta-data android:name="io.sentry.feedback.show-email" android:value="false" />
<meta-data android:name="io.sentry.feedback.use-sentry-user" android:value="false" />
<meta-data android:name="io.sentry.feedback.show-branding" android:value="false" />
</application>
```
```java
SentryAndroid.init(context, options -> {
options.getFeedbackOptions().setNameRequired(true);
options.getFeedbackOptions().setShowName(false);
options.getFeedbackOptions().setEmailRequired(true);
options.getFeedbackOptions().setShowEmail(false);
options.getFeedbackOptions().setUseSentryUser(false);
options.getFeedbackOptions().setShowBranding(false);
});
```
```kotlin
SentryAndroid.init(this) { options ->
options.feedbackOptions.isNameRequired = true
options.feedbackOptions.isShowName = false
options.feedbackOptions.isEmailRequired = true
options.feedbackOptions.isShowEmail = false
options.feedbackOptions.isUseSentryUser = false
options.feedbackOptions.isShowBranding = false
}
```

### Form Label Customization

You can customize the labels and placeholders used in the form.
Note: manifest options are not supported here, due to internationalization:
Copy link
Contributor

@buenaflor buenaflor May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe the note should be an <Alert>, up to you


| Option | Type | Default | Description |
| ----------------------------- | -------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `formTitle` | `String` | `"Report a Bug"` | The title of the feedback form. |
| `messageLabel` | `String` | `"Description"` | The label of the feedback description input field. |
| `messagePlaceholder` | `String` | `"What's the bug? What did you expect?"` | The placeholder in the feedback description input field. |
| `isRequiredLabel` | `String` | `" (Required)"` | The text to attach to the title label for a required field. |
| `successMessageText` | `String` | `"Thank you for your report!"` | The message displayed after a successful feedback submission. |
| `nameLabel` | `String` | `"Name"` | The label next to the name input field. |
| `namePlaceholder` | `String` | `"Your Name"` | The placeholder in the name input field. |
| `emailLabel` | `String` | `"Email"` | The label next to the email input field. |
| `emailPlaceholder` | `String` | `"[email protected]"` | The placeholder in the email input field. |
| `submitButtonLabel` | `String` | `"Send Bug Report"` | The label of the submit button. |
| `cancelButtonLabel` | `String` | `"Cancel"` | The label of the cancel button. |

Example:

```java
SentryAndroid.init(context, options -> {
options.getFeedbackOptions().setFormTitle("We want to hear from you!");
options.getFeedbackOptions().setMessageLabel("Feedback");
options.getFeedbackOptions().setMessagePlaceholder("Type your feedback");
options.getFeedbackOptions().setIsRequiredLabel(" *");
options.getFeedbackOptions().setSuccessMessageText("Thanks for the feedback!");
options.getFeedbackOptions().setNameLabel("Full Name");
options.getFeedbackOptions().setNamePlaceholder("Type your full name");
options.getFeedbackOptions().setEmailLabel("Email Address");
options.getFeedbackOptions().setEmailPlaceholder("Type your email");
options.getFeedbackOptions().setSubmitButtonLabel("Submit");
options.getFeedbackOptions().setCancelButtonLabel("Back");
});
```
```kotlin
SentryAndroid.init(this) { options ->
options.feedbackOptions.formTitle = "We want to hear from you!"
options.feedbackOptions.messageLabel = "Feedback"
options.feedbackOptions.messagePlaceholder = "Type your feedback"
options.feedbackOptions.isRequiredLabel = " *"
options.feedbackOptions.successMessageText = "Thanks for the feedback!"
options.feedbackOptions.nameLabel = "Full Name"
options.feedbackOptions.namePlaceholder = "Type your full name"
options.feedbackOptions.emailLabel = "Email Address"
options.feedbackOptions.emailPlaceholder = "Type your email"
options.feedbackOptions.submitButtonLabel = "Submit"
options.feedbackOptions.cancelButtonLabel = "Back"
}
```

### Theme Customization

The User Feedback form integrates with the app theme by default, and can be customized with a custom xml style.
Here are the attributes used by the form:

| Android style attribute | Description |
| --------------------------------- | ----------------------------------------------------------- |
| `android:windowTitleStyle` | Style of the feedback dialog title |
| `android:textColor` | Color of title, cancel button text, and non-editable texts. |
| `android:editTextColor` | Color of editable texts. |
| `android:textColorHint` | Color of the hint of editable texts. |
| `android:textColorPrimaryInverse` | Color of the send button text. |
| `android:colorPrimary` | Background color of the send button. |
| `android:colorBackground` | Background color of the cancel button. |
| `android:colorForeground` | Color tint of the image logo. |

The theme used by the form is the one set in the application theme as the `android:dialogTheme`.
A custom theme can be also set when instantiating it:

```java
SentryUserFeedbackDialog dialog = new SentryUserFeedbackDialog.Builder(context, R.style.MyAppDialogTheme).create();
```
```kotlin
val dialog = SentryUserFeedbackDialog.Builder(context, R.style.MyAppDialogTheme).create()
```

Here is an example of how the feedback form can be customized:

```xml {filename:styles.xml}
<!-- Application theme. -->
<style name="MyAppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- ... Current theme customizations ... -->

<!-- Set a dialog theme if not already done. -->
<item name="android:dialogTheme">@style/MyAppDialogTheme</item>
</style>

<!-- Edit application dialog theme. -->
<style name="MyAppDialogTheme" parent="Theme.MaterialComponents.DayNight.Dialog">
<!-- Set the style of the feedback dialog title. -->
<item name="android:windowTitleStyle">@style/FeedbackFormTitleStyle</item>

<!-- Set the color of title, cancel button text, and non editable texts. -->
<item name="android:textColor">@color/colorPrimary</item>
<!-- Set the color of editable texts. -->
<item name="android:editTextColor">@color/colorPrimaryDark</item>
<!-- Set the color of the hint of editable texts. -->
<item name="android:textColorHint">@color/colorPrimaryDark</item>
<!-- Set the color of the send button text. -->
<item name="android:textColorPrimaryInverse">@android:color/white</item>

<!-- Set the background color of the send button. -->
<item name="android:colorPrimary">@color/colorPrimary</item>
<!-- Set the background color of the cancel button. -->
<item name="android:colorBackground">@android:color/black</item>
<!-- Set the color tint of the image logo. -->
<item name="android:colorForeground">@color/colorPrimary</item>
</style>

<style name="FeedbackFormTitleStyle">
<!-- Customize your theme here. -->
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Title</item>
</style>
```

### Bring Your Own Widget

You can also use your own UI components to gather feedback and pass the feedback data object to the `Sentry.captureFeedback(Feedback)` function:

```java
import io.sentry.Sentry;
import io.sentry.protocol.Feedback;

Feedback feedback = new Feedback("I encountered a bug while using the app.");
feedback.setName("John Doe");
feedback.setContactEmail("[email protected]");
// Optionally associate the feedback with an event
SentryId sentryId = Sentry.captureMessage("My message");
feedback.setAssociatedEventId(sentryId);
Sentry.captureFeedback(feedback);
```
```kotlin
import io.sentry.Sentry
import io.sentry.protocol.Feedback

val feedback = Feedback("I encountered a bug while using the app.")
feedback.name = "John Doe"
feedback.contactEmail = "[email protected]"
// Optionally associate the feedback with an event
val sentryId = Sentry.captureMessage("My message")
feedback.associatedEventId = sentryId
Sentry.captureFeedback(feedback)
```
Loading