-
Notifications
You must be signed in to change notification settings - Fork 55
Add support for capturing screenshots for modals #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for capturing screenshots for modals #82
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds MediaProjection-based screenshot capture to include overlays in modal dialogs.
- Enables toggling between default and MediaProjection screenshot methods in Shaky.
- Introduces ScreenCaptureService and ScreenCaptureManager to handle permission, foreground service, and capture flow.
- Updates the sample app with a bottom sheet demo, styles, permissions, and Gradle dependencies.
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| shaky/src/main/java/com/linkedin/android/shaky/Shaky.java | Added fields, methods, and flow logic to support MediaProjection. |
| shaky/src/main/java/com/linkedin/android/shaky/ScreenCaptureService.java | New foreground service for MediaProjection on Android 10+. |
| shaky/src/main/java/com/linkedin/android/shaky/ScreenCaptureManager.java | New manager to request permission and perform screen capture. |
| shaky/src/main/AndroidManifest.xml | Added permissions and service declaration for MediaProjection. |
| shaky-sample/src/main/res/values/styles.xml | Defined custom bottom sheet dialog styles. |
| shaky-sample/src/main/res/values/strings.xml | Added string resource for opening the bottom sheet. |
| shaky-sample/src/main/res/layout/activity_demo.xml | Added a button to launch the bottom sheet. |
| shaky-sample/src/main/java/com/linkedin/android/shaky/app/ShakyDemo.java | Switched to FragmentActivity, wired up bottom sheet and result handling. |
| shaky-sample/src/main/java/com/linkedin/android/shaky/app/SampleBottomSheetDialog.java | New bottom sheet dialog fragment with styling and layout. |
| shaky-sample/src/main/AndroidManifest.xml | Declared needed permissions for MediaProjection in the sample. |
| shaky-sample/build.gradle | Added Material Components dependency. |
Comments suppressed due to low confidence (1)
shaky/src/main/java/com/linkedin/android/shaky/ScreenCaptureManager.java:1
- New screen capture functionality (permission flow, virtual display, image processing) lacks unit or instrumentation tests. Consider adding tests to cover success and failure paths.
package com.linkedin.android.shaky;
| private CollectDataTask.Callback pendingDataCollectionCallback = null; | ||
|
|
Copilot
AI
Jun 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The field 'pendingDataCollectionCallback' is declared but never used. Consider removing it or implementing its intended usage to avoid dead code.
| private CollectDataTask.Callback pendingDataCollectionCallback = null; |
| <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item> | ||
| </style> | ||
|
|
||
| <style name="CustomShapeAppearanceBottomSheetDialog" parent=""> |
Copilot
AI
Jun 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'parent' attribute is empty, which will break style inheritance at runtime. Specify a valid parent style (e.g., a ShapeAppearance material component).
| <style name="CustomShapeAppearanceBottomSheetDialog" parent=""> | |
| <style name="CustomShapeAppearanceBottomSheetDialog" parent="ShapeAppearance.MaterialComponents"> |
| view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { | ||
| // Get the parent view of the bottom sheet | ||
| View bottomSheet = (View) view.getParent(); | ||
| // Set up the bottom sheet behavior | ||
| BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheet); | ||
| // Set the height to 50% of screen | ||
| behavior.setPeekHeight(getResources().getDisplayMetrics().heightPixels / 2); | ||
| behavior.setState(BottomSheetBehavior.STATE_EXPANDED); |
Copilot
AI
Jun 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] You register an OnGlobalLayoutListener without removing it after the first callback, which can lead to repeated invocations or memory leaks. Remove the listener once layout is complete.
| view.getViewTreeObserver().addOnGlobalLayoutListener(() -> { | |
| // Get the parent view of the bottom sheet | |
| View bottomSheet = (View) view.getParent(); | |
| // Set up the bottom sheet behavior | |
| BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheet); | |
| // Set the height to 50% of screen | |
| behavior.setPeekHeight(getResources().getDisplayMetrics().heightPixels / 2); | |
| behavior.setState(BottomSheetBehavior.STATE_EXPANDED); | |
| view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { | |
| @Override | |
| public void onGlobalLayout() { | |
| // Get the parent view of the bottom sheet | |
| View bottomSheet = (View) view.getParent(); | |
| // Set up the bottom sheet behavior | |
| BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheet); | |
| // Set the height to 50% of screen | |
| behavior.setPeekHeight(getResources().getDisplayMetrics().heightPixels / 2); | |
| behavior.setState(BottomSheetBehavior.STATE_EXPANDED); | |
| // Remove the listener to prevent repeated invocations | |
| view.getViewTreeObserver().removeOnGlobalLayoutListener(this); | |
| } |
| private Notification createNotification() { | ||
| NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) | ||
| .setContentTitle("Capturing Screenshot") | ||
| .setContentText("Processing your feedback...") |
Copilot
AI
Jun 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Hardcoded notification text should be moved to string resources for localization support.
Add support to capture screenshots for modals which are linked to window root view rather than activity root view.
Requires adding more permissions for capturing screenshots using MediaProjectionManager API:
MEDIA_PROJECTION_SERVICE
Before adding support for this API:

After adding support for this API:
