Last active
January 27, 2025 16:28
-
-
Save Bringoff/97dee6e8e711223b0b74b389df8bc390 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Override | |
| public void onAccessibilityEvent(final AccessibilityEvent event) { | |
| ... | |
| UsageAccessHelper.ActivityData realActivity = appStatsHelper.getCurrentActivity(); | |
| realActivityName = realActivity.getActivityFullName(); | |
| checkIfPictureInPicture(realActivityName); | |
| } | |
| private void checkIfPictureInPicture(String activityName) { | |
| if ("com.android.systemui/.pip.phone.PipMenuActivity".equals(activityName)) { | |
| notificationService.fireNotificationAsync(Notifications.PICTURE_IN_PICTURE_MODE_ACTIVATED); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ... | |
| @Nullable | |
| @Override | |
| public ActivityData getCurrentActivity() { | |
| try { | |
| long ts = System.currentTimeMillis(); | |
| UsageEvents queryEvents = usageStatsManager.queryEvents(ts - STATS_INTERVAL, ts); | |
| String activityName = null; | |
| String packageName = null; | |
| int eventCount = 0; | |
| while (queryEvents.hasNextEvent()) { | |
| queryEvents.getNextEvent(eventOut); | |
| if (!TextUtils.isEmpty(eventOut.getPackageName()) && eventOut.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) { | |
| packageName = eventOut.getPackageName(); | |
| activityName = eventOut.getClassName(); | |
| } | |
| eventCount++; | |
| } | |
| if (TextUtils.isEmpty(packageName)) { | |
| return null; | |
| } | |
| if (eventCount == 0) { | |
| logger.debug(LOG_TAG + "usage stats contains no events for last %d ms", STATS_INTERVAL); | |
| } | |
| return new ActivityData(packageName, activityName); | |
| } catch (Exception e) { | |
| logger.error("[UsageAccessHelper50] cannot query usage events: %s", e); | |
| return null; | |
| } | |
| } | |
| ... | |
| @ToString | |
| @AllArgsConstructor | |
| class ActivityData { | |
| public String packageName; | |
| public String activityName; | |
| public ActivityData(String fullActivityName) { | |
| try { | |
| String[] data = fullActivityName.split("/"); | |
| packageName = data[0]; | |
| activityName = data[1]; | |
| } catch (Exception e) { | |
| packageName = ""; | |
| activityName = null; | |
| } | |
| } | |
| public String getActivityFullName() { | |
| return TextUtils.isEmpty(packageName) || TextUtils.isEmpty(activityName) ? "" : | |
| packageName + "/" + activityName; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * This Activity does nothing except closing itself. Used to close Picture-in-Picture window opened | |
| * by another app. | |
| */ | |
| public class FakePictureInPictureActivity extends AppCompatActivity { | |
| public static Intent getStartIntent(@NonNull Context context) { | |
| return new Intent(context, FakePictureInPictureActivity.class) | |
| .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
| } | |
| public static boolean isRunning() { | |
| return isAlreadyRunning; | |
| } | |
| private static boolean isAlreadyRunning = false; | |
| @Override | |
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| FrameLayout root = new FrameLayout(this); | |
| root.setId(R.id.nationaledtech_fake_picture_in_picture_container); | |
| setContentView(root); | |
| } | |
| @Override | |
| protected void onStart() { | |
| super.onStart(); | |
| isAlreadyRunning = true; | |
| } | |
| @Override | |
| protected void onStop() { | |
| super.onStop(); | |
| isAlreadyRunning = false; | |
| } | |
| @Override | |
| protected void onResume() { | |
| super.onResume(); | |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O | |
| && getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) | |
| && !isInPictureInPictureMode()) { | |
| try { | |
| enterPictureInPictureMode(new PictureInPictureParams.Builder().build()); | |
| } catch (Exception e) { | |
| MobivementApplication.getMobivementContext() | |
| .getLogger().error("[FakePictureInPictureActivity] Cannot enter PiP mode: %s", e); | |
| } | |
| } | |
| } | |
| @Override | |
| public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) { | |
| super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); | |
| if (isInPictureInPictureMode) { | |
| try { | |
| moveTaskToBack(false); | |
| finishAndRemoveTask(); | |
| } catch (Exception e) { | |
| MobivementApplication.getMobivementContext() | |
| .getLogger().error("[FakePictureInPictureActivity]Cannot exit PiP mode: %s", e); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @RequiredArgsConstructor | |
| public class PictureInPictureActivationListener implements NotificationListener { | |
| private final Context context; | |
| private final Logger logger; | |
| @Override | |
| public void onNotification(String category, Bundle extras) { | |
| if (!Notifications.PICTURE_IN_PICTURE_MODE_ACTIVATED.equals(category)) { | |
| return; | |
| } | |
| logger.info("[PictureInPictureActivationListener] picture-in-picture detected"); | |
| if (isDefinitelyHasPictureInPictureApi() && !isOurPictureInPictureActivityRunning()) { | |
| logger.info("[PictureInPictureActivationListener]" + | |
| "picture-in-picture is not allowed at the moment"); | |
| ContextCompat.startActivitн(context, FakePictureInPictureActivity.getStartIntent(context), null); | |
| } | |
| } | |
| private boolean isDefinitelyHasPictureInPictureApi() { | |
| PackageManager packageManager = context.getPackageManager(); | |
| return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O | |
| && packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); | |
| } | |
| private boolean isOurPictureInPictureActivityRunning() { | |
| return FakePictureInPictureActivity.isRunning(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment