Skip to main content

Submitting User Feedback

Beta release

Getting feedback from users and testers is crucial in the app development process. It provides valuable insights and helps improve the overall user experience. Sauce Labs Mobile App Distribution offers an effortless way to collect feedback through its In-App Feedback feature. By integrating the Sauce Mobile Beta SDK into your app, you can enable users to report bugs, suggest improvements, and share their thoughts directly in the app.

Using In-App Feedback​

Sauce Labs Mobile App Distribution provides an effortless way to collect this feedback. If you added the Sauce Mobile Beta SDK to your app, then all you need to do is enable the In-App Bug Reporting feature in your build settings in the Sauce Labs Mobile App Distribution dashboard, and you can start collecting feedback from your users with "shake to report":

Enable Shake to Feedback

Users or testers can initiate the feedback collection process by shaking their devices while using the app. When they shake the device, the feedback form will be triggered, allowing them to report bugs or share their suggestions.

This feedback will be added to the app session they are running.

All feedback includes a screenshot, device information, submitter email, and text comments added. The feedback is added to the event timeline so you can find it without difficulty.

Feedback Contents​

When users provide feedback using the In-App Bug Reporting feature, the following information will be included:

  • Screenshot - A screenshot of the app at the moment the feedback was triggered.
  • Device Information - Details about the device, such as model, OS version, and other relevant technical information.
  • Submitter Email - If available, the email address of the user or tester providing the feedback.
  • Text Comments - Users can include specific comments to describe the issue or suggestion they are reporting.
  • Event Timeline - The feedback will be added to the app's event timeline, so developers can track and analyze the feedback.

Customizing In-App Feedback​

Sauce Labs Mobile App Distribution allows you to customize the way In-App Feedback is collected. If you prefer not to use the shake gesture for feedback collection, you can programmatically invoke the feedback form using a button click or any other gesture in your app. This way, users can access the feedback form from a designated area in the app, like the help menu or after encountering unexpected errors.

If you choose to invoke the feedback form programmatically, it will be shown regardless if the in-app feedback is disabled in your build settings.

TestFairy.showFeedbackForm();
Example
// Be sure to import the SDK
import com.testfairy.TestFairy;

// Can be invoked on a button press
// or after your app passes a given page
TestFairy.showFeedbackForm();
note

showFeedbackForm() requires a running session. To collect feedback without a session, call TestFairy.showFeedbackForm(context, "<sauce-mobile-beta-token>", true). For custom fields, validation and callbacks, see Customizing the Feedback Form.

Customizing the Feedback Form​

The built-in form has an email field, a message field and, depending on the platform, buttons to attach a screenshot or a screen recording. You customize it by building a feedback options object and handing it to the SDK before the form is shown. Doing so before beginWithoutCrashHandler is fine. The feedback classes are in the TestFairy module on iOS and the com.testfairy package on Android.

The form can be shown in two ways. showFeedbackForm() with no arguments requires a running session and attaches the feedback to it. The overload that takes the app token (showFeedbackForm(context, appToken, takeScreenshot) on Android, showFeedbackForm(appToken, takeScreenshot:) on iOS and showFeedbackForm(appToken, takeScreenshot) on React Native) works without a session, optionally captures a screenshot first, and the feedback appears in the build's Feedbacks tab.

Rules that apply on Android and iOS:

  • Setting a list of form fields replaces the default fields. To keep the email and message fields, add them yourself with the reserved attribute names :userId (email or user identifier) and :text (message). Always include a :text field.
  • Every other field is sent with the feedback as a feedback attribute named after the field's attribute key, so pick short, stable names.
  • Three field types are built in: single-line text (String), multi-line text (TextArea) and a dropdown list (Select, a map of label to value). You can add up to 32 fields. Attribute names must be non-empty and unique (duplicates are dropped). For any other control, implement the FeedbackFormField interface (onCreateView, getAttribute, getValue) yourself.
  • The reserved fields are pre-filled by the SDK (last used email, unsent draft). The defaultText option only applies to the built-in form and is ignored after you set custom fields.
  • Email is mandatory by default. Hiding the email field lifts the requirement, and so does a custom field list without a :userId field.
  • A custom verifier replaces the SDK's default validation (email present and valid when mandatory, non-empty message), so re-implement the checks you still want.
import com.testfairy.FeedbackContent;
import com.testfairy.FeedbackFormField;
import com.testfairy.FeedbackOptions;
import com.testfairy.FeedbackVerifier;
import com.testfairy.SelectFeedbackFormField;
import com.testfairy.StringFeedbackFormField;
import com.testfairy.TestFairy;
import com.testfairy.TextAreaFeedbackFormField;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

Map<String, String> types = new LinkedHashMap<>(); // label -> value
types.put("Bug", "bug");
types.put("Feature request", "feature");

List<FeedbackFormField> fields = new ArrayList<>();
// Reserved names keep the built-in fields (attribute, placeholder, default value):
fields.add(new StringFeedbackFormField(":userId", "Your email", ""));
fields.add(new TextAreaFeedbackFormField(":text", "Describe the problem", ""));
// Your own fields (any attribute name):
fields.add(new StringFeedbackFormField("phone", "Phone number", ""));
fields.add(new SelectFeedbackFormField("type", "Is this a bug or a feature request?", types, "Bug")); // the default is a label

FeedbackOptions options = new FeedbackOptions.Builder()
.setFeedbackFormFields(fields)
.setEmailMandatory(false) // default true; only enforced when a :userId field exists
.setTakeScreenshotButtonVisible(true)
.setRecordVideoButtonVisible(false)
.setFeedbackInterceptor(content -> content) // optional: inspect or modify before sending; never return null
.setCallback(new FeedbackOptions.Callback() { // optional
@Override public void onFeedbackSent(FeedbackContent content) {}
@Override public void onFeedbackCancelled() {}
@Override public void onFeedbackFailed(int reason, FeedbackContent content) {}
})
.build();
TestFairy.setFeedbackOptions(options);

// Optional: custom validation (returning false blocks sending and shows your message)
TestFairy.setFeedbackVerifier(new FeedbackVerifier() {
@Override public boolean verifyFeedback(FeedbackContent content) {
return content.getEmail().endsWith("@yourcompany.com") && !content.getText().isEmpty();
}
@Override public String getVerificationFailedMessage() {
return "Please use your company email and describe the issue.";
}
});

// Show the form from a button after beginWithoutCrashHandler ...
TestFairy.showFeedbackForm();
// ... or without a running session, optionally taking a screenshot first:
TestFairy.showFeedbackForm(context, "<sauce-mobile-beta-token>", true);
Other FeedbackOptions.Builder options:
  • setEmailFieldVisible(boolean) hides the email field (and lifts the mandatory requirement).
  • setDefaultText(String) pre-fills the message of the built-in form.
  • setBrowserUrl(String) opens your own web form in the browser instead of the native form. The SDK appends sessionUrl, timestamp, user (your setUserId value), platform, packageName, versionName, versionCode and screenName as query parameters. The other options do not apply in this mode.
Shake trigger: call TestFairy.enableFeedbackForm("shake") (Android accepts only "shake") or TestFairy.disableFeedbackForm() before beginWithoutCrashHandler.