Skip to content

Commit 81991a4

Browse files
TheBuggedYRNHeshamMegid
authored andcommitted
[MOB-10001] Remove Media Projection from Android (#281)
When invoking Instabug on Android, a "scary" dialog appears, asking for permission to record screen. This was due to the way we captured screenshots on Android, using Media Projection, since other alternatives didn't work with Flutter. This PR aims at providing an alternative approach for Media Projection, using FlutterRenderer to capture screenshots. This implicitly fixes Repro Steps on Android as well.
1 parent 9382329 commit 81991a4

File tree

8 files changed

+86
-36
lines changed

8 files changed

+86
-36
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
* Bumps Instabug Android SDK to v11.6.0
44
* Bumps Instabug iOS SDK to v11.5.0
5+
* Enables Repro Steps screenshots on Android
6+
* Removes "Media Projection" dialog while taking screenshots on Android
57
* Adds BugReporting.setDisclaimerText API
68
* Adds BugReporting.setCommentMinimumCharacterCount API
79
* Adds Romanian locale support

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ Repro Steps list all of the actions an app user took before reporting a bug or c
8484
));
8585
```
8686

87-
⚠️ Screenshots in repro steps on android is not currently supported.
8887

8988
## Network Logging
9089
You can choose to attach all your network requests to the reports being sent to the dashboard. To enable the feature when using the `dart:io` package `HttpClient`, please refer to the [Instabug Dart IO Http Client](https://github.com/Instabug/instabug-dart-io-http-client) repository.
Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package com.instabug.flutter;
22

3+
import android.annotation.SuppressLint;
4+
import android.app.Activity;
35
import android.content.Context;
6+
import android.graphics.Bitmap;
7+
import android.util.Log;
8+
import android.view.View;
49

510
import androidx.annotation.NonNull;
11+
import androidx.annotation.Nullable;
612

713
import com.instabug.flutter.modules.ApmApi;
814
import com.instabug.flutter.modules.BugReportingApi;
@@ -13,36 +19,92 @@
1319
import com.instabug.flutter.modules.RepliesApi;
1420
import com.instabug.flutter.modules.SurveysApi;
1521

22+
import java.util.concurrent.Callable;
23+
1624
import io.flutter.embedding.engine.plugins.FlutterPlugin;
25+
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
26+
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
27+
import io.flutter.embedding.engine.renderer.FlutterRenderer;
1728
import io.flutter.plugin.common.BinaryMessenger;
1829
import io.flutter.plugin.common.PluginRegistry.Registrar;
1930

20-
public class InstabugFlutterPlugin implements FlutterPlugin {
31+
public class InstabugFlutterPlugin implements FlutterPlugin, ActivityAware {
32+
private static final String TAG = InstabugFlutterPlugin.class.getName();
33+
34+
@SuppressLint("StaticFieldLeak")
35+
private static Activity activity;
36+
2137
/**
2238
* Embedding v1
2339
*/
2440
@SuppressWarnings("deprecation")
2541
public static void registerWith(Registrar registrar) {
26-
register(registrar.context().getApplicationContext(), registrar.messenger());
42+
activity = registrar.activity();
43+
register(registrar.context().getApplicationContext(), registrar.messenger(), (FlutterRenderer) registrar.textures());
44+
}
45+
46+
@Override
47+
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
48+
register(binding.getApplicationContext(), binding.getBinaryMessenger(), (FlutterRenderer) binding.getTextureRegistry());
49+
}
50+
51+
@Override
52+
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
53+
activity = null;
54+
}
55+
56+
@Override
57+
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
58+
activity = binding.getActivity();
59+
}
60+
61+
@Override
62+
public void onDetachedFromActivityForConfigChanges() {
63+
activity = null;
64+
}
65+
66+
@Override
67+
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
68+
activity = binding.getActivity();
69+
}
70+
71+
@Override
72+
public void onDetachedFromActivity() {
73+
activity = null;
2774
}
2875

29-
private static void register(Context context, BinaryMessenger messenger) {
76+
private static void register(Context context, BinaryMessenger messenger, FlutterRenderer renderer) {
77+
final Callable<Bitmap> screenshotProvider = new Callable<Bitmap>() {
78+
@Override
79+
public Bitmap call() {
80+
return takeScreenshot(renderer);
81+
}
82+
};
83+
3084
ApmApi.init(messenger);
3185
BugReportingApi.init(messenger);
3286
CrashReportingApi.init(messenger);
3387
FeatureRequestsApi.init(messenger);
34-
InstabugApi.init(messenger, context);
88+
InstabugApi.init(messenger, context, screenshotProvider);
3589
InstabugLogApi.init(messenger);
3690
RepliesApi.init(messenger);
3791
SurveysApi.init(messenger);
3892
}
3993

40-
@Override
41-
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
42-
register(binding.getApplicationContext(), binding.getBinaryMessenger());
43-
}
94+
@Nullable
95+
private static Bitmap takeScreenshot(FlutterRenderer renderer) {
96+
try {
97+
final View view = activity.getWindow().getDecorView().getRootView();
4498

45-
@Override
46-
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
99+
view.setDrawingCacheEnabled(true);
100+
final Bitmap bitmap = renderer.getBitmap();
101+
Log.v(TAG, bitmap.toString());
102+
view.setDrawingCacheEnabled(false);
103+
104+
return bitmap;
105+
} catch (Exception e) {
106+
Log.e(TAG, "Failed to take screenshot using " + renderer.toString() + ". Cause: " + e);
107+
return null;
108+
}
47109
}
48110
}

android/src/main/java/com/instabug/flutter/modules/InstabugApi.java

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.instabug.flutter.modules;
22

3-
import android.annotation.SuppressLint;
43
import android.app.Application;
54
import android.content.Context;
65
import android.graphics.Bitmap;
@@ -9,9 +8,8 @@
98

109
import androidx.annotation.NonNull;
1110
import androidx.annotation.Nullable;
12-
import androidx.annotation.VisibleForTesting;
1311

14-
import com.instabug.bug.BugReporting;
12+
import com.instabug.flutter.util.ArgsRegistry;
1513
import com.instabug.flutter.generated.InstabugPigeon;
1614
import com.instabug.flutter.util.ArgsRegistry;
1715
import com.instabug.flutter.util.Reflection;
@@ -33,30 +31,24 @@
3331
import java.util.List;
3432
import java.util.Locale;
3533
import java.util.Map;
34+
import java.util.concurrent.Callable;
3635

3736
import io.flutter.plugin.common.BinaryMessenger;
3837

3938
public class InstabugApi implements InstabugPigeon.InstabugHostApi {
4039
private final String TAG = InstabugApi.class.getName();
4140
private final Context context;
41+
private final Callable<Bitmap> screenshotProvider;
4242
private final InstabugCustomTextPlaceHolder placeHolder = new InstabugCustomTextPlaceHolder();
4343

44-
public static void init(BinaryMessenger messenger, Context context) {
45-
final InstabugApi api = new InstabugApi(context);
44+
public static void init(BinaryMessenger messenger, Context context, Callable<Bitmap> screenshotProvider) {
45+
final InstabugApi api = new InstabugApi(context, screenshotProvider);
4646
InstabugPigeon.InstabugHostApi.setup(messenger, api);
4747
}
4848

49-
public InstabugApi(Context context) {
49+
public InstabugApi(Context context, Callable<Bitmap> screenshotProvider) {
5050
this.context = context;
51-
}
52-
53-
/**
54-
* Enables taking screenshots by media projection.
55-
*/
56-
@SuppressLint("NewApi")
57-
@VisibleForTesting
58-
public static void enableScreenShotByMediaProjection(boolean isEnabled) {
59-
BugReporting.setScreenshotByMediaProjectionEnabled(isEnabled);
51+
this.screenshotProvider = screenshotProvider;
6052
}
6153

6254
private void setCurrentPlatform() {
@@ -98,8 +90,7 @@ public void start(@NonNull String token, @NonNull List<String> invocationEvents)
9890
new Instabug.Builder(application, token)
9991
.setInvocationEvents(invocationEventsArray)
10092
.build();
101-
102-
enableScreenShotByMediaProjection(true);
93+
Instabug.setScreenshotProvider(screenshotProvider);
10394
}
10495

10596
@Override

android/src/test/java/com/instabug/flutter/InstabugApiTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
public class InstabugApiTest extends TestCase {
14-
private final InstabugApi mApi = new InstabugApi(null);
14+
private final InstabugApi mApi = new InstabugApi(null, null);
1515
private final MockedStatic<Instabug> mInstabug = mockStatic(Instabug.class);
1616

1717
public void testLogOut() {

e2e/BugReporting.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ public void ReportABug()
2020
ios: "IBGFloatingButtonAccessibilityIdentifier"
2121
).Tap();
2222

23-
if (captain.IsAndroid) captain.GoBack();
24-
2523
captain.FindByText("Report a bug").Tap();
2624

2725
captain.FindInput(

example/android/app/src/androidTest/java/com/example/InstabugSample/InvokeInstabugUITest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,6 @@ public void ensureInstabugInvocation() throws InterruptedException {
3333
onView(withResourceName("instabug_floating_button")).perform(click());
3434
Thread.sleep(1000);
3535

36-
// Dismiss media projection prompt.
37-
// This is a temporary solution as we are dropping media projection in a future release.
38-
device.pressBack();
39-
Thread.sleep(1000);
40-
4136
onView(withText("Report a bug")).perform(click());
4237
Thread.sleep(1000);
4338

example/lib/main.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class MyApp extends StatelessWidget {
2020
Widget build(BuildContext context) {
2121
return MaterialApp(
2222
title: 'Flutter Demo',
23+
navigatorObservers: [
24+
InstabugNavigatorObserver(),
25+
],
2326
theme: ThemeData(
2427
// This is the theme of your application.
2528
//

0 commit comments

Comments
 (0)