Skip to content

Commit 3ae5c08

Browse files
committed
Request different permission on 33+ and some more feedback
1 parent 77ce58d commit 3ae5c08

File tree

4 files changed

+41
-30
lines changed

4 files changed

+41
-30
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ public void makePostRequest_whenConnectionFails_throwsError() throws Exception {
252252
public void makeUploadRequest_writesRequestBodyAndSetsCorrectHeaders() throws Exception {
253253
String responseJson = readTestFile("testSimpleResponse.json");
254254

255-
// Setup test streams. They should be closed but close them anyway just to be safe.
256255
try (InputStream postBodyInputStream =
257256
new ByteArrayInputStream("Test post body".getBytes(UTF_8));
258257
ByteArrayOutputStream requestBodyOutputStream = new ByteArrayOutputStream();

firebase-appdistribution/test-app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="com.googletest.firebase.appdistribution.testapp">
4+
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
45

56
<application
67
android:allowBackup="true"

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
@@ -70,7 +70,7 @@ class MainActivity : AppCompatActivity() {
7070
screenshotTrigger =
7171
ScreenshotDetectionFeedbackTrigger(
7272
this,
73-
"Here's some terms and conditions",
73+
R.string.terms_and_conditions,
7474
Handler(screenshotTriggerThread.looper)
7575
)
7676
}

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

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
package com.googletest.firebase.appdistribution.testapp;
1616

17-
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
17+
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
18+
import static android.Manifest.permission.READ_MEDIA_IMAGES;
1819
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
1920

2021
import android.app.AlertDialog;
21-
import android.content.Context;
2222
import android.database.ContentObserver;
2323
import android.database.Cursor;
2424
import android.net.Uri;
@@ -27,17 +27,22 @@
2727
import android.provider.MediaStore;
2828
import android.provider.MediaStore.Images.Media;
2929
import android.util.Log;
30-
import androidx.activity.ComponentActivity;
3130
import androidx.activity.result.ActivityResultLauncher;
3231
import androidx.activity.result.contract.ActivityResultContracts;
32+
import androidx.appcompat.app.AppCompatActivity;
3333
import androidx.core.content.ContextCompat;
3434
import com.google.firebase.appdistribution.FirebaseAppDistribution;
3535
import java.util.HashSet;
3636
import java.util.Set;
3737

3838
class ScreenshotDetectionFeedbackTrigger extends ContentObserver {
39-
private static final String TAG = "FeedbackTriggers";
40-
private static final boolean SHOULD_CHECK_IF_PENDING = Build.VERSION.SDK_INT == 29;
39+
private static final String TAG = "ScreenshotDetectionFeedbackTrigger";
40+
41+
private static final String PERMISSION_TO_REQUEST =
42+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
43+
? READ_MEDIA_IMAGES
44+
: READ_EXTERNAL_STORAGE;
45+
private static final boolean SHOULD_CHECK_IF_PENDING = Build.VERSION.SDK_INT >= 29;
4146
private static final String[] PROJECTION =
4247
SHOULD_CHECK_IF_PENDING
4348
? new String[] {MediaStore.Images.Media.DATA}
@@ -46,8 +51,8 @@ class ScreenshotDetectionFeedbackTrigger extends ContentObserver {
4651
};
4752
private final Set<Uri> seenImages = new HashSet<>();
4853

49-
private final Context context;
50-
private final CharSequence infoText;
54+
private final AppCompatActivity activity;
55+
private final int infoTextResourceId;
5156

5257
private final ActivityResultLauncher<String> requestPermissionLauncher;
5358

@@ -62,10 +67,10 @@ class ScreenshotDetectionFeedbackTrigger extends ContentObserver {
6267
* @param handler The handler to run {@link #onChange} on, or null if none.
6368
*/
6469
public ScreenshotDetectionFeedbackTrigger(
65-
ComponentActivity activity, CharSequence infoText, Handler handler) {
70+
AppCompatActivity activity, int infoTextResourceId, Handler handler) {
6671
super(handler);
67-
this.context = activity;
68-
this.infoText = infoText;
72+
this.activity = activity;
73+
this.infoTextResourceId = infoTextResourceId;
6974

7075
// Register the permissions launcher
7176
requestPermissionLauncher =
@@ -75,28 +80,23 @@ public ScreenshotDetectionFeedbackTrigger(
7580
if (isGranted) {
7681
maybeStartFeedbackForScreenshot(currentUri);
7782
} else {
78-
new AlertDialog.Builder(context)
79-
.setMessage(
80-
"Without storage access, screenshots taken while in the app will not be able to automatically start the feedback flow. To enable this feature, grant the app storage access in Settings.")
81-
.setPositiveButton(
82-
"OK",
83-
(a, b) -> {
84-
/* do nothing */
85-
})
86-
.show();
83+
Log.i(TAG, "Permission not granted");
84+
// TODO: Ideally we would show a message indicating the impact of not enabling the
85+
// permission, but there's no way to know if they've permanently denied the
86+
// permission, and we don't want to show them a message on every screenshot.
8787
}
8888
});
8989
}
9090

9191
void registerScreenshotObserver() {
92-
context
92+
activity
9393
.getContentResolver()
9494
.registerContentObserver(
9595
Media.EXTERNAL_CONTENT_URI, /* notifyForDescendants= */ true, this);
9696
}
9797

9898
void unRegisterScreenshotObserver() {
99-
context.getContentResolver().unregisterContentObserver(this);
99+
activity.getContentResolver().unregisterContentObserver(this);
100100
}
101101

102102
@Override
@@ -106,28 +106,39 @@ public void onChange(boolean selfChange, Uri uri) {
106106
return;
107107
}
108108

109-
if (ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
109+
if (ContextCompat.checkSelfPermission(activity, PERMISSION_TO_REQUEST) == PERMISSION_GRANTED) {
110110
maybeStartFeedbackForScreenshot(uri);
111+
} else if (activity.shouldShowRequestPermissionRationale(PERMISSION_TO_REQUEST)) {
112+
Log.i(TAG, "Showing customer rationale for requesting permission.");
113+
new AlertDialog.Builder(activity)
114+
.setMessage(
115+
"Taking a screenshot of the app can initiate feedback to the developer. To enable this feature, allow the app access to device storage.")
116+
.setPositiveButton(
117+
"OK",
118+
(a, b) -> {
119+
Log.i(TAG, "Launching request for permission.");
120+
currentUri = uri;
121+
requestPermissionLauncher.launch(PERMISSION_TO_REQUEST);
122+
})
123+
.show();
111124
} else {
112-
// Ideally we'd give the user some context here, but we have no way of knowing if they
113-
// have previously "Deny & don't ask again" in which case we wouldn't want to show them
114-
// anything here.
125+
Log.i(TAG, "Does not have permission. Launching request.");
115126
currentUri = uri;
116-
requestPermissionLauncher.launch(WRITE_EXTERNAL_STORAGE);
127+
requestPermissionLauncher.launch(PERMISSION_TO_REQUEST);
117128
}
118129
}
119130

120131
private void maybeStartFeedbackForScreenshot(Uri uri) {
121132
Cursor cursor = null;
122133
try {
123-
cursor = context.getContentResolver().query(uri, PROJECTION, null, null, null);
134+
cursor = activity.getContentResolver().query(uri, PROJECTION, null, null, null);
124135
if (cursor != null && cursor.moveToFirst()) {
125136
// TODO: check if it's pending
126137
// (http://google3/lens/screenshots/demo/java/com/google/android/lensonscreenshots/ScreenshotDetector.java?l=184)
127138
String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
128139
Log.i(TAG, "Path: " + path);
129140
if (path.toLowerCase().contains("screenshot")) {
130-
FirebaseAppDistribution.getInstance().startFeedback(infoText, uri);
141+
FirebaseAppDistribution.getInstance().startFeedback(infoTextResourceId, uri);
131142
}
132143
}
133144
} catch (Exception e) {

0 commit comments

Comments
 (0)