Skip to content

Commit 1148499

Browse files
committed
Add notification default trigger to in-app feedback
1 parent 765f9c8 commit 1148499

File tree

17 files changed

+501
-71
lines changed

17 files changed

+501
-71
lines changed

firebase-appdistribution-api/api.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ package com.google.firebase.appdistribution {
1717
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.appdistribution.AppDistributionRelease> checkForNewRelease();
1818
method @NonNull public static com.google.firebase.appdistribution.FirebaseAppDistribution getInstance();
1919
method public boolean isTesterSignedIn();
20+
method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public <T extends android.app.Activity & androidx.activity.result.ActivityResultCaller> void requestNotificationPermissions(@NonNull T);
21+
method public void showFeedbackNotification(@NonNull int, int);
22+
method public void showFeedbackNotification(@NonNull CharSequence, int);
2023
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> signInTester();
2124
method public void signOutTester();
2225
method public void startFeedback(int);

firebase-appdistribution-api/firebase-appdistribution-api.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ plugins {
1717
}
1818

1919
android {
20-
compileSdkVersion project.targetSdkVersion
20+
compileSdkVersion 33
2121

2222
defaultConfig {
2323
minSdkVersion 16
24-
targetSdkVersion project.targetSdkVersion
24+
targetSdkVersion 33
2525
multiDexEnabled true
2626
versionName version
2727
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -41,6 +41,7 @@ dependencies {
4141
implementation 'org.jetbrains:annotations:15.0'
4242
implementation project(':firebase-components')
4343
implementation project(':firebase-common')
44+
implementation 'androidx.activity:activity:1.5.1'
4445
implementation 'com.google.android.gms:play-services-tasks:18.0.1'
4546
testImplementation 'junit:junit:4.13.2'
4647
testImplementation "org.robolectric:robolectric:$robolectricVersion"

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,15 @@
1414

1515
package com.google.firebase.appdistribution;
1616

17+
import android.app.Activity;
18+
import android.app.NotificationChannel;
1719
import android.net.Uri;
20+
import android.os.Build;
21+
import androidx.activity.result.ActivityResultCaller;
1822
import androidx.annotation.NonNull;
1923
import androidx.annotation.Nullable;
24+
import androidx.annotation.RequiresApi;
25+
import androidx.core.app.NotificationCompat;
2026
import com.google.android.gms.tasks.Task;
2127
import com.google.firebase.FirebaseApp;
2228
import com.google.firebase.appdistribution.internal.FirebaseAppDistributionProxy;
@@ -179,6 +185,94 @@ public interface FirebaseAppDistribution {
179185
*/
180186
void startFeedback(@NonNull CharSequence infoText, @Nullable Uri screenshot);
181187

188+
/**
189+
* Requests the {@code POST_NOTIFICATIONS} permission, if it is not already granted.
190+
*
191+
* <p>This <b>must</b> be called from {@link Activity#onCreate}.
192+
*
193+
* <p>Android 13 (API level 33) and above support a <a
194+
* href="https://developer.android.com/develop/ui/views/notifications/notification-permission">runtime
195+
* permission for sending notifications</a>: {@code POST_NOTIFICATIONS}. If you target Android 13
196+
* or higher and do not want to <a
197+
* href="https://developer.android.com/training/permissions/requesting">request the permission</a>
198+
* on your own, call this method to request the permission. This is helpful if you use the {@link
199+
* #updateIfNewReleaseAvailable} method, which shows notifications.
200+
*
201+
* @param activity the activity being initialized (this method <b>must</b> be called from this
202+
* activity's {@link Activity#onCreate})
203+
*/
204+
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
205+
<T extends Activity & ActivityResultCaller> void requestNotificationPermissions(
206+
@NonNull T activity);
207+
208+
/**
209+
* Displays a notification that, when tapped, will take a screenshot of the current activity, then
210+
* start a new activity to collect and submit feedback from the tester along with the screenshot.
211+
*
212+
* <p>On Android 13 and above, his method requires the <a
213+
* href="https://developer.android.com/develop/ui/views/notifications/notification-permission">runtime
214+
* permission for sending notifications</a>: {@code POST_NOTIFICATIONS}. Either <a
215+
* href="https://developer.android.com/training/permissions/requesting">request the permission</a>
216+
* on your own or call {@link #requestNotificationPermissions}.
217+
*
218+
* <p>When the notification is tapped:
219+
*
220+
* <ol>
221+
* <li>If the app is open, take a screenshot of the current activity
222+
* <li>If tester is not signed in, presents the tester with a Google Sign-in UI
223+
* <li>Starts a full screen activity for the tester to compose and submit the feedback
224+
* </ol>
225+
*
226+
* <p>On Android 8 and above, the notification will be created in its own notification channel.
227+
*
228+
* @param infoTextResourceId string resource ID of text to display to the tester before collecting
229+
* feedback data (e.g. Terms and Conditions)
230+
* @param importance the amount the user should be interrupted by notifications from the feedback
231+
* notification channel. Once the channel's importance is set it cannot be changed except by
232+
* the user. See {@link NotificationChannel#setImportance}. On platforms below Android 8, the
233+
* importance will be translated into a comparable notification priority (see {@link
234+
* NotificationCompat.Builder#setPriority}).
235+
*/
236+
void showFeedbackNotification(@NonNull int infoTextResourceId, int importance);
237+
238+
/**
239+
* Displays a notification that, when tapped, will take a screenshot of the current activity, then
240+
* start a new activity to collect and submit feedback from the tester along with the screenshot.
241+
*
242+
* <p>On Android 13 and above, his method requires the <a
243+
* href="https://developer.android.com/develop/ui/views/notifications/notification-permission">runtime
244+
* permission for sending notifications</a>: {@code POST_NOTIFICATIONS}. Either <a
245+
* href="https://developer.android.com/training/permissions/requesting">request the permission</a>
246+
* on your own or call {@link #requestNotificationPermissions}.
247+
*
248+
* <p>When the notification is tapped:
249+
*
250+
* <ol>
251+
* <li>If the app is open, take a screenshot of the current activity
252+
* <li>If tester is not signed in, presents the tester with a Google Sign-in UI
253+
* <li>Starts a full screen activity for the tester to compose and submit the feedback
254+
* </ol>
255+
*
256+
* <p>On Android 8 and above, the notification will be created in its own notification channel.
257+
*
258+
* @param infoText text to display to the tester before collecting feedback data (e.g. Terms and
259+
* Conditions)
260+
* @param importance the amount the user should be interrupted by notifications from the feedback
261+
* notification channel. Once the channel's importance is set it cannot be changed except by
262+
* the user. See {@link NotificationChannel#setImportance}. On platforms below Android 8, the
263+
* importance will be translated into a comparable notification priority (see {@link
264+
* NotificationCompat.Builder#setPriority}).
265+
*/
266+
void showFeedbackNotification(@NonNull CharSequence infoText, int importance);
267+
268+
/**
269+
* Hides the notification shown with {@link #showFeedbackNotification}.
270+
*
271+
* <p>This should be called in the {@link Activity#onDestroy} of the activity that showed the
272+
* notification.
273+
*/
274+
void hideFeedbackNotification();
275+
182276
/** Gets the singleton {@link FirebaseAppDistribution} instance. */
183277
@NonNull
184278
static FirebaseAppDistribution getInstance() {

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
package com.google.firebase.appdistribution.internal;
1616

17+
import android.app.Activity;
1718
import android.net.Uri;
19+
import androidx.activity.result.ActivityResultCaller;
1820
import androidx.annotation.NonNull;
1921
import androidx.annotation.Nullable;
2022
import com.google.android.gms.tasks.Task;
@@ -93,4 +95,25 @@ public void startFeedback(@NonNull int infoTextResourceId, @Nullable Uri screens
9395
public void startFeedback(@NonNull CharSequence infoText, @Nullable Uri screenshotUri) {
9496
delegate.startFeedback(infoText, screenshotUri);
9597
}
98+
99+
@Override
100+
public void showFeedbackNotification(@NonNull int infoTextResourceId, int importance) {
101+
delegate.showFeedbackNotification(infoTextResourceId, importance);
102+
}
103+
104+
@Override
105+
public void showFeedbackNotification(@NonNull CharSequence infoText, int importance) {
106+
delegate.showFeedbackNotification(infoText, importance);
107+
}
108+
109+
@Override
110+
public <T extends Activity & ActivityResultCaller> void requestNotificationPermissions(
111+
@NonNull T activity) {
112+
delegate.requestNotificationPermissions(activity);
113+
}
114+
115+
@Override
116+
public void hideFeedbackNotification() {
117+
delegate.hideFeedbackNotification();
118+
}
96119
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import android.app.Activity;
1818
import android.net.Uri;
19+
import androidx.activity.result.ActivityResultCaller;
1920
import androidx.annotation.NonNull;
2021
import androidx.annotation.Nullable;
2122
import com.google.android.gms.tasks.Continuation;
@@ -84,6 +85,19 @@ public void startFeedback(@NonNull int infoTextResourceId, @Nullable Uri screens
8485
@Override
8586
public void startFeedback(@NonNull CharSequence infoText, @Nullable Uri screenshotUri) {}
8687

88+
@Override
89+
public void showFeedbackNotification(@NonNull int infoTextResourceId, int importance) {}
90+
91+
@Override
92+
public void showFeedbackNotification(@NonNull CharSequence infoText, int importance) {}
93+
94+
@Override
95+
public <T extends Activity & ActivityResultCaller> void requestNotificationPermissions(
96+
@NonNull T activity) {}
97+
98+
@Override
99+
public void hideFeedbackNotification() {}
100+
87101
private static <TResult> Task<TResult> getNotImplementedTask() {
88102
return Tasks.forException(
89103
new FirebaseAppDistributionException(

firebase-appdistribution/firebase-appdistribution.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ firebaseLibrary {
2121
}
2222

2323
android {
24-
compileSdkVersion project.targetSdkVersion
24+
compileSdkVersion 33
2525

2626
defaultConfig {
2727
minSdkVersion 16
28-
targetSdkVersion project.targetSdkVersion
28+
targetSdkVersion 33
2929
multiDexEnabled true
3030
versionName version
3131
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

firebase-appdistribution/src/main/AndroidManifest.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
package="com.google.firebase.appdistribution.impl">
1818

1919
<uses-permission android:name="android.permission.INTERNET" />
20-
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
20+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
2121
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
22+
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
2223
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2324

2425
<application>
@@ -51,6 +52,10 @@
5152
android:exported="false"
5253
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
5354

55+
<activity
56+
android:name=".TakeScreenshotAndStartFeedbackActivity"
57+
android:exported="false" />
58+
5459
<provider
5560
android:name="com.google.firebase.appdistribution.impl.FirebaseAppDistributionFileProvider"
5661
android:authorities="${applicationId}.FirebaseAppDistributionFileProvider"

0 commit comments

Comments
 (0)