Skip to content

Commit a65a25b

Browse files
lfkelloggkaibolay
authored andcommitted
Add info text argument to startFeedback (#3971)
* Add info text argument to startFeedback * Formatting * Update api.txt * Make infoText CharSequence non null
1 parent a60492d commit a65a25b

File tree

11 files changed

+91
-27
lines changed

11 files changed

+91
-27
lines changed

firebase-appdistribution-api/api.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ package com.google.firebase.appdistribution {
1919
method public boolean isTesterSignedIn();
2020
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> signInTester();
2121
method public void signOutTester();
22-
method public void startFeedback();
22+
method public void startFeedback(int);
23+
method public void startFeedback(@NonNull CharSequence);
2324
method @NonNull public com.google.firebase.appdistribution.UpdateTask updateApp();
2425
method @NonNull public com.google.firebase.appdistribution.UpdateTask updateIfNewReleaseAvailable();
2526
}

firebase-appdistribution-api/src/main/java/com/google/firebase/appdistribution/FirebaseAppDistribution.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,27 @@ public interface FirebaseAppDistribution {
119119
* <li>If tester is not signed in, presents the tester with a Google Sign-in UI
120120
* <li>Starts a full screen activity for the tester to compose and submit the feedback
121121
* </ol>
122+
*
123+
* @param infoTextResourceId string resource ID of text to display to the tester before collecting
124+
* feedback data (e.g. Terms and Conditions)
125+
*/
126+
void startFeedback(int infoTextResourceId);
127+
128+
/**
129+
* Takes a screenshot, and starts an activity to collect and submit feedback from the tester.
130+
*
131+
* <p>Performs the following actions:
132+
*
133+
* <ol>
134+
* <li>Takes a screenshot of the current activity
135+
* <li>If tester is not signed in, presents the tester with a Google Sign-in UI
136+
* <li>Starts a full screen activity for the tester to compose and submit the feedback
137+
* </ol>
138+
*
139+
* @param infoText text to display to the tester before collecting feedback data (e.g. Terms and
140+
* Conditions)
122141
*/
123-
void startFeedback();
142+
void startFeedback(@NonNull CharSequence infoText);
124143

125144
/** Gets the singleton {@link FirebaseAppDistribution} instance. */
126145
@NonNull

firebase-appdistribution-api/src/main/java/com/google/firebase/appdistribution/internal/FirebaseAppDistributionProxy.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ public UpdateTask updateApp() {
7373
}
7474

7575
@Override
76-
public void startFeedback() {
77-
delegate.startFeedback();
76+
public void startFeedback(int infoTextResourceId) {
77+
delegate.startFeedback(infoTextResourceId);
78+
}
79+
80+
@Override
81+
public void startFeedback(@NonNull CharSequence infoText) {
82+
delegate.startFeedback(infoText);
7883
}
7984
}

firebase-appdistribution-api/src/main/java/com/google/firebase/appdistribution/internal/FirebaseAppDistributionStub.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ public UpdateTask updateApp() {
7474
}
7575

7676
@Override
77-
public void startFeedback() {
77+
public void startFeedback(int infoTextResourceId) {
78+
return;
79+
}
80+
81+
@Override
82+
public void startFeedback(@NonNull CharSequence infoText) {
7883
return;
7984
}
8085

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FeedbackActivity.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
import android.graphics.Bitmap;
1818
import android.os.Bundle;
19+
import android.text.method.LinkMovementMethod;
1920
import android.view.View;
2021
import android.widget.EditText;
2122
import android.widget.ImageView;
23+
import android.widget.TextView;
2224
import android.widget.Toast;
2325
import androidx.annotation.Nullable;
2426
import androidx.appcompat.app.AppCompatActivity;
@@ -33,17 +35,21 @@ public class FeedbackActivity extends AppCompatActivity {
3335

3436
public static final String RELEASE_NAME_EXTRA_KEY =
3537
"com.google.firebase.appdistribution.FeedbackActivity.RELEASE_NAME";
38+
public static final String INFO_TEXT_EXTRA_KEY =
39+
"com.google.firebase.appdistribution.FeedbackActivity.INFO_TEXT";
3640
public static final String SCREENSHOT_FILENAME_EXTRA_KEY =
3741
"com.google.firebase.appdistribution.FeedbackActivity.SCREENSHOT_FILE_NAME";
3842

3943
private FeedbackSender feedbackSender;
4044
private String releaseName;
45+
private CharSequence infoText;
4146
@Nullable private File screenshotFile;
4247

4348
@Override
4449
protected void onCreate(Bundle savedInstanceState) {
4550
super.onCreate(savedInstanceState);
4651
releaseName = getIntent().getStringExtra(RELEASE_NAME_EXTRA_KEY);
52+
infoText = getIntent().getCharSequenceExtra(INFO_TEXT_EXTRA_KEY);
4753
if (getIntent().hasExtra(SCREENSHOT_FILENAME_EXTRA_KEY)) {
4854
screenshotFile = getFileStreamPath(getIntent().getStringExtra(SCREENSHOT_FILENAME_EXTRA_KEY));
4955
}
@@ -53,9 +59,14 @@ protected void onCreate(Bundle savedInstanceState) {
5359

5460
private void setupView() {
5561
setContentView(R.layout.activity_feedback);
62+
63+
TextView infoTextView = this.findViewById(R.id.infoText);
64+
infoTextView.setText(infoText);
65+
infoTextView.setMovementMethod(LinkMovementMethod.getInstance());
66+
5667
Bitmap thumbnail = readThumbnail();
5768
if (thumbnail != null) {
58-
ImageView screenshotImageView = (ImageView) this.findViewById(R.id.thumbnail);
69+
ImageView screenshotImageView = this.findViewById(R.id.thumbnail);
5970
screenshotImageView.setImageBitmap(thumbnail);
6071
} else {
6172
View screenshotErrorLabel = this.findViewById(R.id.screenshotErrorLabel);
@@ -73,7 +84,7 @@ private Bitmap readThumbnail() {
7384

7485
public void submitFeedback(View view) {
7586
setSubmittingStateEnabled(true);
76-
EditText feedbackText = (EditText) findViewById(R.id.feedbackText);
87+
EditText feedbackText = findViewById(R.id.feedbackText);
7788
feedbackSender
7889
.sendFeedback(releaseName, feedbackText.getText().toString(), screenshotFile)
7990
.addOnSuccessListener(

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionImpl.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static com.google.firebase.appdistribution.FirebaseAppDistributionException.Status.AUTHENTICATION_FAILURE;
1919
import static com.google.firebase.appdistribution.FirebaseAppDistributionException.Status.HOST_ACTIVITY_INTERRUPTED;
2020
import static com.google.firebase.appdistribution.FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE;
21+
import static com.google.firebase.appdistribution.impl.FeedbackActivity.INFO_TEXT_EXTRA_KEY;
2122
import static com.google.firebase.appdistribution.impl.FeedbackActivity.RELEASE_NAME_EXTRA_KEY;
2223
import static com.google.firebase.appdistribution.impl.FeedbackActivity.SCREENSHOT_FILENAME_EXTRA_KEY;
2324
import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskException;
@@ -44,7 +45,6 @@
4445
import com.google.firebase.appdistribution.UpdateStatus;
4546
import com.google.firebase.appdistribution.UpdateTask;
4647
import java.util.concurrent.Executor;
47-
import java.util.concurrent.Executors;
4848

4949
/**
5050
* This class is the "real" implementation of the Firebase App Distribution API which should only be
@@ -63,6 +63,7 @@ class FirebaseAppDistributionImpl implements FirebaseAppDistribution {
6363
private final SignInStorage signInStorage;
6464
private final ReleaseIdentifier releaseIdentifier;
6565
private final ScreenshotTaker screenshotTaker;
66+
private final Executor taskExecutor;
6667

6768
private final Object updateIfNewReleaseTaskLock = new Object();
6869

@@ -95,7 +96,8 @@ class FirebaseAppDistributionImpl implements FirebaseAppDistribution {
9596
@NonNull SignInStorage signInStorage,
9697
@NonNull FirebaseAppDistributionLifecycleNotifier lifecycleNotifier,
9798
@NonNull ReleaseIdentifier releaseIdentifier,
98-
@NonNull ScreenshotTaker screenshotTaker) {
99+
@NonNull ScreenshotTaker screenshotTaker,
100+
@NonNull Executor taskExecutor) {
99101
this.firebaseApp = firebaseApp;
100102
this.testerSignInManager = testerSignInManager;
101103
this.newReleaseFetcher = newReleaseFetcher;
@@ -105,6 +107,7 @@ class FirebaseAppDistributionImpl implements FirebaseAppDistribution {
105107
this.releaseIdentifier = releaseIdentifier;
106108
this.lifecycleNotifier = lifecycleNotifier;
107109
this.screenshotTaker = screenshotTaker;
110+
this.taskExecutor = taskExecutor;
108111
lifecycleNotifier.addOnActivityDestroyedListener(this::onActivityDestroyed);
109112
lifecycleNotifier.addOnActivityPausedListener(this::onActivityPaused);
110113
lifecycleNotifier.addOnActivityResumedListener(this::onActivityResumed);
@@ -306,12 +309,12 @@ private UpdateTask updateApp(boolean showDownloadInNotificationManager) {
306309
}
307310

308311
@Override
309-
public void startFeedback() {
310-
startFeedback(Executors.newSingleThreadExecutor());
312+
public void startFeedback(int infoTextResourceId) {
313+
startFeedback(firebaseApp.getApplicationContext().getString(infoTextResourceId));
311314
}
312315

313316
@VisibleForTesting
314-
public void startFeedback(Executor taskExecutor) {
317+
public void startFeedback(@NonNull CharSequence infoText) {
315318
screenshotTaker
316319
.takeScreenshot()
317320
.onSuccessTask(
@@ -327,16 +330,19 @@ public void startFeedback(Executor taskExecutor) {
327330
.onSuccessTask(taskExecutor, unused -> releaseIdentifier.identifyRelease())
328331
.onSuccessTask(
329332
taskExecutor,
330-
releaseName -> launchFeedbackActivity(releaseName, screenshotFilename)))
333+
releaseName ->
334+
launchFeedbackActivity(releaseName, infoText, screenshotFilename)))
331335
.addOnFailureListener(
332336
taskExecutor, e -> LogWrapper.getInstance().e("Failed to launch feedback flow", e));
333337
}
334338

335-
private Task<Void> launchFeedbackActivity(String releaseName, String screenshotFilename) {
339+
private Task<Void> launchFeedbackActivity(
340+
String releaseName, CharSequence infoText, String screenshotFilename) {
336341
return lifecycleNotifier.consumeForegroundActivity(
337342
activity -> {
338343
Intent intent = new Intent(activity, FeedbackActivity.class);
339344
intent.putExtra(RELEASE_NAME_EXTRA_KEY, releaseName);
345+
intent.putExtra(INFO_TEXT_EXTRA_KEY, infoText);
340346
intent.putExtra(SCREENSHOT_FILENAME_EXTRA_KEY, screenshotFilename);
341347
activity.startActivity(intent);
342348
});

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionRegistrar.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.firebase.platforminfo.LibraryVersionComponent;
3030
import java.util.Arrays;
3131
import java.util.List;
32+
import java.util.concurrent.Executors;
3233

3334
/**
3435
* Registers FirebaseAppDistribution.
@@ -92,7 +93,8 @@ private FirebaseAppDistribution buildFirebaseAppDistribution(ComponentContainer
9293
signInStorage,
9394
lifecycleNotifier,
9495
releaseIdentifier,
95-
new ScreenshotTaker(firebaseApp, lifecycleNotifier));
96+
new ScreenshotTaker(firebaseApp, lifecycleNotifier),
97+
Executors.newSingleThreadExecutor());
9698

9799
if (context instanceof Application) {
98100
Application firebaseApplication = (Application) context;

firebase-appdistribution/src/main/res/layout/activity_feedback.xml

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
xmlns:tools="http://schemas.android.com/tools"
55
android:layout_width="match_parent"
66
android:layout_height="match_parent"
7+
android:padding="24dp"
78
tools:context=".FeedbackActivity">
89

910
<TextView
@@ -34,28 +35,29 @@
3435
android:id="@+id/submitButton"
3536
android:layout_width="wrap_content"
3637
android:layout_height="wrap_content"
37-
android:layout_marginTop="32dp"
38-
android:text="Submit"
38+
android:layout_marginTop="24dp"
3939
android:onClick="submitFeedback"
40+
android:text="Submit"
4041
app:layout_constraintEnd_toEndOf="parent"
42+
app:layout_constraintHorizontal_bias="0.5"
4143
app:layout_constraintStart_toStartOf="parent"
42-
app:layout_constraintTop_toBottomOf="@+id/feedbackText" />
44+
app:layout_constraintTop_toBottomOf="@+id/infoText" />
4345
<TextView
4446
android:id="@+id/loadingLabel"
4547
android:layout_width="wrap_content"
4648
android:layout_height="wrap_content"
47-
android:layout_marginTop="44dp"
49+
android:layout_marginTop="24dp"
4850
android:text="Submitting feedback..."
4951
android:visibility="invisible"
5052
app:layout_constraintEnd_toEndOf="parent"
5153
app:layout_constraintStart_toStartOf="parent"
52-
app:layout_constraintTop_toBottomOf="@+id/feedbackText" />
53-
<!-- Width and height should match bitmap created in setupView() -->
54+
app:layout_constraintTop_toBottomOf="@+id/infoText" />
5455
<ImageView
5556
android:id="@+id/thumbnail"
5657
android:layout_width="wrap_content"
5758
android:layout_height="wrap_content"
5859
android:scaleType="centerInside"
60+
android:layout_marginTop="24dp"
5961
app:layout_constraintBottom_toBottomOf="parent"
6062
app:layout_constraintEnd_toEndOf="parent"
6163
app:layout_constraintStart_toStartOf="parent"
@@ -72,5 +74,14 @@
7274
app:layout_constraintStart_toStartOf="parent"
7375
app:layout_constraintTop_toBottomOf="@+id/submitButton"
7476
app:layout_constraintVertical_bias="0.403" />
77+
<TextView
78+
android:id="@+id/infoText"
79+
android:layout_width="match_parent"
80+
android:layout_height="wrap_content"
81+
android:ems="5"
82+
android:layout_marginTop="24dp"
83+
app:layout_constraintEnd_toEndOf="parent"
84+
app:layout_constraintStart_toStartOf="parent"
85+
app:layout_constraintTop_toBottomOf="@+id/feedbackText" />
7586

7687
</androidx.constraintlayout.widget.ConstraintLayout>

firebase-appdistribution/src/test/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionServiceImplTest.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static com.google.firebase.appdistribution.impl.ErrorMessages.NETWORK_ERROR;
2828
import static com.google.firebase.appdistribution.impl.ErrorMessages.RELEASE_NOT_FOUND_ERROR;
2929
import static com.google.firebase.appdistribution.impl.ErrorMessages.UPDATE_CANCELED;
30+
import static com.google.firebase.appdistribution.impl.FeedbackActivity.INFO_TEXT_EXTRA_KEY;
3031
import static com.google.firebase.appdistribution.impl.FeedbackActivity.RELEASE_NAME_EXTRA_KEY;
3132
import static com.google.firebase.appdistribution.impl.FeedbackActivity.SCREENSHOT_FILENAME_EXTRA_KEY;
3233
import static com.google.firebase.appdistribution.impl.TestUtils.assertTaskFailure;
@@ -122,6 +123,7 @@ public class FirebaseAppDistributionServiceImplTest {
122123
private FirebaseAppDistributionImpl firebaseAppDistribution;
123124
private TestActivity activity;
124125
private FirebaseApp firebaseApp;
126+
private ExecutorService taskExecutor = Executors.newSingleThreadExecutor();
125127

126128
@Mock private InstallationTokenResult mockInstallationTokenResult;
127129
@Mock private TesterSignInManager mockTesterSignInManager;
@@ -162,7 +164,8 @@ public void setup() throws FirebaseAppDistributionException {
162164
mockSignInStorage,
163165
mockLifecycleNotifier,
164166
mockReleaseIdentifier,
165-
mockScreenshotTaker));
167+
mockScreenshotTaker,
168+
taskExecutor));
166169

167170
when(mockTesterSignInManager.signInTester()).thenReturn(Tasks.forResult(null));
168171
when(mockSignInStorage.getSignInStatus()).thenReturn(true);
@@ -632,11 +635,9 @@ public void updateApp_withApkReleaseAvailable_returnsSameApkTask() {
632635

633636
@Test
634637
public void startFeedback_signsInTesterAndStartsActivity() throws InterruptedException {
635-
ExecutorService testExecutor = Executors.newSingleThreadExecutor();
636638
when(mockReleaseIdentifier.identifyRelease()).thenReturn(Tasks.forResult("release-name"));
637-
638-
firebaseAppDistribution.startFeedback(testExecutor);
639-
TestUtils.awaitAsyncOperations(testExecutor);
639+
firebaseAppDistribution.startFeedback("Some terms and conditions");
640+
TestUtils.awaitAsyncOperations(taskExecutor);
640641

641642
ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
642643
verify(activity).startActivity(argument.capture());
@@ -645,5 +646,7 @@ public void startFeedback_signsInTesterAndStartsActivity() throws InterruptedExc
645646
.isEqualTo("release-name");
646647
assertThat(argument.getValue().getStringExtra(SCREENSHOT_FILENAME_EXTRA_KEY))
647648
.isEqualTo(TEST_SCREENSHOT_FILE_NAME);
649+
assertThat(argument.getValue().getStringExtra(INFO_TEXT_EXTRA_KEY))
650+
.isEqualTo("Some terms and conditions");
648651
}
649652
}

firebase-appdistribution/test-app/src/main/java/com/googletest/firebase/appdistribution/testapp/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class MainActivity : AppCompatActivity() {
169169
}
170170

171171
feedbackButton.setOnClickListener {
172-
firebaseAppDistribution.startFeedback()
172+
firebaseAppDistribution.startFeedback(R.string.terms_and_conditions)
173173
}
174174
}
175175

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<resources>
22
<string name="app_name">App Distro Sample</string>
3+
<string name="terms_and_conditions"><b>Before giving feedback</b> you might want to check out the <a href="http://google.com">Terms and Conditions</a></string>
34
</resources>

0 commit comments

Comments
 (0)