38 View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
40 private final Activity activity;
41 private final PlatformChannel platformChannel;
43 private PlatformChannel.SystemChromeStyle currentTheme;
44 private int mEnabledOverlays;
45 private static final String TAG =
"PlatformPlugin";
77 new PlatformChannel.PlatformMessageHandler() {
79 public void playSystemSound(@NonNull PlatformChannel.SoundType soundType) {
85 @NonNull PlatformChannel.HapticFeedbackType feedbackType) {
90 public void setPreferredOrientations(
int androidOrientation) {
91 setSystemChromePreferredOrientations(androidOrientation);
95 public void setApplicationSwitcherDescription(
96 @NonNull PlatformChannel.AppSwitcherDescription description) {
97 setSystemChromeApplicationSwitcherDescription(description);
102 setSystemChromeEnabledSystemUIOverlays(overlays);
106 public void showSystemUiMode(@NonNull PlatformChannel.SystemUiMode mode) {
107 setSystemChromeEnabledSystemUIMode(mode);
111 public void setSystemUiChangeListener() {
112 setSystemChromeChangeListener();
116 public void restoreSystemUiOverlays() {
117 restoreSystemChromeSystemUIOverlays();
121 public void setSystemUiOverlayStyle(
122 @NonNull PlatformChannel.SystemChromeStyle systemUiOverlayStyle) {
123 setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle);
127 public void setFrameworkHandlesBack(
boolean frameworkHandlesBack) {
128 PlatformPlugin.this.setFrameworkHandlesBack(frameworkHandlesBack);
132 public void popSystemNavigator() {
137 public CharSequence getClipboardData(
138 @Nullable PlatformChannel.ClipboardContentFormat
format) {
143 public void setClipboardData(@NonNull String
text) {
148 public boolean clipboardHasStrings() {
153 public void share(@NonNull String
text) {
158 public PlatformPlugin(@NonNull Activity activity, @NonNull PlatformChannel platformChannel) {
159 this(activity, platformChannel,
null);
163 @NonNull Activity activity,
164 @NonNull PlatformChannel platformChannel,
166 this.activity = activity;
167 this.platformChannel = platformChannel;
169 this.platformPluginDelegate = delegate;
180 this.platformChannel.setPlatformMessageHandler(
null);
183 private void playSystemSound(@NonNull PlatformChannel.SoundType soundType) {
184 if (soundType == PlatformChannel.SoundType.CLICK) {
185 View view = activity.getWindow().getDecorView();
186 view.playSoundEffect(SoundEffectConstants.CLICK);
192 @NonNull PlatformChannel.HapticFeedbackType feedbackType) {
193 View view = activity.getWindow().getDecorView();
194 switch (feedbackType) {
196 view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
199 view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
202 view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
205 if (
Build.VERSION.SDK_INT >= API_LEVELS.API_23) {
206 view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
209 case SELECTION_CLICK:
210 view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
215 private void setSystemChromePreferredOrientations(
int androidOrientation) {
216 activity.setRequestedOrientation(androidOrientation);
219 @SuppressWarnings(
"deprecation")
220 private
void setSystemChromeApplicationSwitcherDescription(
221 PlatformChannel.AppSwitcherDescription description) {
222 if (
Build.VERSION.SDK_INT < API_LEVELS.API_28) {
223 activity.setTaskDescription(
224 new TaskDescription(description.label,
null, description.color));
226 TaskDescription taskDescription =
227 new TaskDescription(description.label, 0, description.color);
228 activity.setTaskDescription(taskDescription);
232 private void setSystemChromeChangeListener() {
234 View decorView = activity.getWindow().getDecorView();
235 decorView.setOnSystemUiVisibilityChangeListener(
236 new View.OnSystemUiVisibilityChangeListener() {
238 public void onSystemUiVisibilityChange(int visibility) {
248 if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
254 platformChannel.systemChromeChanged(true);
259 platformChannel.systemChromeChanged(false);
266 private void setSystemChromeEnabledSystemUIMode(PlatformChannel.SystemUiMode systemUiMode) {
269 if (systemUiMode == PlatformChannel.SystemUiMode.LEAN_BACK) {
278 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
279 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
280 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
281 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
282 | View.SYSTEM_UI_FLAG_FULLSCREEN;
283 }
else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE) {
292 View.SYSTEM_UI_FLAG_IMMERSIVE
293 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
294 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
295 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
296 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
297 | View.SYSTEM_UI_FLAG_FULLSCREEN;
298 }
else if (systemUiMode == PlatformChannel.SystemUiMode.IMMERSIVE_STICKY) {
306 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
307 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
308 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
309 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
310 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
311 | View.SYSTEM_UI_FLAG_FULLSCREEN;
312 }
else if (systemUiMode == PlatformChannel.SystemUiMode.EDGE_TO_EDGE
313 &&
Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
320 View.SYSTEM_UI_FLAG_LAYOUT_STABLE
321 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
322 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
328 mEnabledOverlays = enabledOverlays;
329 updateSystemUiOverlays();
332 private void setSystemChromeEnabledSystemUIOverlays(
336 int enabledOverlays =
338 | View.SYSTEM_UI_FLAG_FULLSCREEN
339 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
340 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
342 if (overlaysToShow.size() == 0) {
343 enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
347 for (
int i = 0; i < overlaysToShow.size(); ++i) {
348 PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i);
349 switch (overlayToShow) {
351 enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
353 case BOTTOM_OVERLAYS:
354 enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
355 enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
360 mEnabledOverlays = enabledOverlays;
361 updateSystemUiOverlays();
373 activity.getWindow().getDecorView().setSystemUiVisibility(mEnabledOverlays);
374 if (currentTheme !=
null) {
375 setSystemChromeSystemUIOverlayStyle(currentTheme);
379 private void restoreSystemChromeSystemUIOverlays() {
380 updateSystemUiOverlays();
383 @SuppressWarnings(
"deprecation")
384 private
void setSystemChromeSystemUIOverlayStyle(
385 PlatformChannel.SystemChromeStyle systemChromeStyle) {
387 View view =
window.getDecorView();
388 WindowInsetsControllerCompat windowInsetsControllerCompat =
389 new WindowInsetsControllerCompat(
window, view);
391 if (
Build.VERSION.SDK_INT < API_LEVELS.API_30) {
395 window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
401 WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
402 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
412 if (
Build.VERSION.SDK_INT >= API_LEVELS.API_23) {
413 if (systemChromeStyle.statusBarIconBrightness !=
null) {
414 switch (systemChromeStyle.statusBarIconBrightness) {
418 windowInsetsControllerCompat.setAppearanceLightStatusBars(
true);
423 windowInsetsControllerCompat.setAppearanceLightStatusBars(
false);
428 if (systemChromeStyle.statusBarColor !=
null) {
429 window.setStatusBarColor(systemChromeStyle.statusBarColor);
435 if (systemChromeStyle.systemStatusBarContrastEnforced !=
null
436 &&
Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
437 window.setStatusBarContrastEnforced(systemChromeStyle.systemStatusBarContrastEnforced);
447 if (
Build.VERSION.SDK_INT >= API_LEVELS.API_26) {
448 if (systemChromeStyle.systemNavigationBarIconBrightness !=
null) {
449 switch (systemChromeStyle.systemNavigationBarIconBrightness) {
453 windowInsetsControllerCompat.setAppearanceLightNavigationBars(
true);
458 windowInsetsControllerCompat.setAppearanceLightNavigationBars(
false);
463 if (systemChromeStyle.systemNavigationBarColor !=
null) {
464 window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor);
468 if (systemChromeStyle.systemNavigationBarDividerColor !=
null
469 &&
Build.VERSION.SDK_INT >= API_LEVELS.API_28) {
470 window.setNavigationBarDividerColor(systemChromeStyle.systemNavigationBarDividerColor);
477 if (systemChromeStyle.systemNavigationBarContrastEnforced !=
null
478 &&
Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
479 window.setNavigationBarContrastEnforced(
480 systemChromeStyle.systemNavigationBarContrastEnforced);
483 currentTheme = systemChromeStyle;
486 private void setFrameworkHandlesBack(
boolean frameworkHandlesBack) {
487 if (platformPluginDelegate !=
null) {
488 platformPluginDelegate.setFrameworkHandlesBack(frameworkHandlesBack);
492 private void popSystemNavigator() {
493 if (platformPluginDelegate !=
null && platformPluginDelegate.popSystemNavigator()) {
498 if (activity instanceof OnBackPressedDispatcherOwner) {
499 ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed();
505 private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat
format) {
506 ClipboardManager clipboard =
507 (ClipboardManager) activity.getSystemService(
Context.CLIPBOARD_SERVICE);
509 if (!clipboard.hasPrimaryClip())
return null;
511 CharSequence itemText =
null;
513 ClipData
clip = clipboard.getPrimaryClip();
514 if (
clip ==
null)
return null;
515 if (
format ==
null ||
format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
516 ClipData.Item item =
clip.getItemAt(0);
519 itemText = item.getText();
520 if (itemText ==
null) {
523 Uri itemUri = item.getUri();
525 if (itemUri ==
null) {
527 TAG,
"Clipboard item contained no textual content nor a URI to retrieve it from.");
532 String uriScheme = itemUri.getScheme();
534 if (!uriScheme.equals(
"content")) {
537 "Clipboard item contains a Uri with scheme '" + uriScheme +
"'that is unhandled.");
541 AssetFileDescriptor assetFileDescriptor =
542 activity.getContentResolver().openTypedAssetFileDescriptor(itemUri,
"text/*",
null);
546 itemText = item.coerceToText(activity);
547 if (assetFileDescriptor !=
null) assetFileDescriptor.close();
552 }
catch (SecurityException e) {
555 "Attempted to get clipboard data that requires additional permission(s).\n"
556 +
"See the exception details for which permission(s) are required, and consider adding them to your Android Manifest as described in:\n"
557 +
"https://developer.android.com/guide/topics/permissions/overview",
560 }
catch (FileNotFoundException e) {
561 Log.w(
TAG,
"Clipboard text was unable to be received from content URI.");
563 }
catch (IOException e) {
564 Log.w(
TAG,
"Failed to close AssetFileDescriptor while trying to read text from URI.", e);
571 private void setClipboardData(String text) {
572 ClipboardManager clipboard =
573 (ClipboardManager) activity.getSystemService(
Context.CLIPBOARD_SERVICE);
574 ClipData
clip = ClipData.newPlainText(
"text label?", text);
575 clipboard.setPrimaryClip(
clip);
578 private boolean clipboardHasStrings() {
579 ClipboardManager clipboard =
580 (ClipboardManager) activity.getSystemService(
Context.CLIPBOARD_SERVICE);
584 if (!clipboard.hasPrimaryClip()) {
587 ClipDescription description = clipboard.getPrimaryClipDescription();
588 if (description ==
null) {
591 return description.hasMimeType(
"text/*");
594 private void share(@NonNull String text) {
595 Intent intent =
new Intent();
596 intent.setAction(Intent.ACTION_SEND);
597 intent.setType(
"text/plain");
598 intent.putExtra(Intent.EXTRA_TEXT, text);
600 activity.startActivity(Intent.createChooser(intent,
null));