Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,151 @@ public class PlatformChannel {
private PlatformMessageHandler platformMessageHandler;
@NonNull
@VisibleForTesting
protected final PlatformMethodCallHandler parsingMethodCallHandler = new PlatformMethodCallHandler();
protected final MethodChannel.MethodCallHandler parsingMethodCallHandler = new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (platformMessageHandler == null) {
// If no explicit PlatformMessageHandler has been registered then we don't
// need to forward this call to an API. Return.
return;
}

String method = call.method;
Object arguments = call.arguments;
Log.v(TAG, "Received '" + method + "' message.");
try {
switch (method) {
case "SystemSound.play":
try {
SoundType soundType = SoundType.fromValue((String) arguments);
platformMessageHandler.playSystemSound(soundType);
result.success(null);
} catch (NoSuchFieldException exception) {
// The desired sound type does not exist.
result.error("error", exception.getMessage(), null);
}
break;
case "HapticFeedback.vibrate":
try {
HapticFeedbackType feedbackType = HapticFeedbackType.fromValue((String) arguments);
platformMessageHandler.vibrateHapticFeedback(feedbackType);
result.success(null);
} catch (NoSuchFieldException exception) {
// The desired feedback type does not exist.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setPreferredOrientations":
try {
int androidOrientation = decodeOrientations((JSONArray) arguments);
platformMessageHandler.setPreferredOrientations(androidOrientation);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more expected fields were either omitted or referenced an invalid type.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setApplicationSwitcherDescription":
try {
AppSwitcherDescription description = decodeAppSwitcherDescription((JSONObject) arguments);
platformMessageHandler.setApplicationSwitcherDescription(description);
result.success(null);
} catch (JSONException exception) {
// One or more expected fields were either omitted or referenced an invalid type.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setEnabledSystemUIOverlays":
try {
List<SystemUiOverlay> overlays = decodeSystemUiOverlays((JSONArray) arguments);
platformMessageHandler.showSystemOverlays(overlays);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more of the overlay names are invalid.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.restoreSystemUIOverlays":
platformMessageHandler.restoreSystemUiOverlays();
result.success(null);
break;
case "SystemChrome.setSystemUIOverlayStyle":
try {
SystemChromeStyle systemChromeStyle = decodeSystemChromeStyle((JSONObject) arguments);
platformMessageHandler.setSystemUiOverlayStyle(systemChromeStyle);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more of the brightness names are invalid.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemNavigator.pop":
platformMessageHandler.popSystemNavigator();
result.success(null);
break;
case "SystemGestures.getSystemGestureExclusionRects":
List<Rect> exclusionRects = platformMessageHandler.getSystemGestureExclusionRects();
if (exclusionRects == null) {
String incorrectApiLevel = "Exclusion rects only exist for Android API 29+.";
result.error("error", incorrectApiLevel, null);
break;
}

ArrayList<HashMap<String, Integer>> encodedExclusionRects = encodeExclusionRects(exclusionRects);
result.success(encodedExclusionRects);
break;
case "SystemGestures.setSystemGestureExclusionRects":
if (!(arguments instanceof JSONArray)) {
String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
result.error("inputTypeError", inputTypeError, null);
break;
}

JSONArray inputRects = (JSONArray) arguments;
ArrayList<Rect> decodedRects = decodeExclusionRects(inputRects);
platformMessageHandler.setSystemGestureExclusionRects(decodedRects);
result.success(null);
break;
case "Clipboard.getData": {
String contentFormatName = (String) arguments;
ClipboardContentFormat clipboardFormat = null;
if (contentFormatName != null) {
try {
clipboardFormat = ClipboardContentFormat.fromValue(contentFormatName);
} catch (NoSuchFieldException exception) {
// An unsupported content format was requested. Return failure.
result.error("error", "No such clipboard content format: " + contentFormatName, null);
}
}

CharSequence clipboardContent = platformMessageHandler.getClipboardData(clipboardFormat);
if (clipboardContent != null) {
JSONObject response = new JSONObject();
response.put("text", clipboardContent);
result.success(response);
} else {
result.success(null);
}
break;
}
case "Clipboard.setData": {
String clipboardContent = ((JSONObject) arguments).getString("text");
platformMessageHandler.setClipboardData(clipboardContent);
result.success(null);
break;
}
default:
result.notImplemented();
break;
}
} catch (JSONException e) {
result.error("error", "JSON error: " + e.getMessage(), null);
}
}
};

/**
* Constructs a {@code PlatformChannel} that connects Android to the Dart code
Expand Down Expand Up @@ -143,6 +287,13 @@ private int decodeOrientations(@NonNull JSONArray encodedOrientations) throws JS
/**
* Decodes a JSONArray of rectangle data into an ArrayList<Rect>.
*
* Since View.setSystemGestureExclusionRects receives a JSONArray containing
* JSONObjects, these values need to be transformed into the expected input
* of View.setSystemGestureExclusionRects, which is ArrayList<Rect>.
*
* This method is used by the SystemGestures.setSystemGestureExclusionRects
* platform channel.
*
* @throws JSONException if {@code inputRects} does not contain expected keys and value types.
*/
@NonNull
Expand Down Expand Up @@ -535,159 +686,6 @@ public SystemChromeStyle(
}
}

/**
* A handler of incoming platform channel method calls received from Flutter.
* It first determines the platform's API to be called. If it exists, it then
* decodes incoming arguments, if needed, into a format that is necessary for the API.
*/
@VisibleForTesting
protected class PlatformMethodCallHandler implements MethodChannel.MethodCallHandler {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (platformMessageHandler == null) {
// If no explicit PlatformMessageHandler has been registered then we don't
// need to forward this call to an API. Return.
return;
}

String method = call.method;
Object arguments = call.arguments;
Log.v(TAG, "Received '" + method + "' message.");
try {
switch (method) {
case "SystemSound.play":
try {
SoundType soundType = SoundType.fromValue((String) arguments);
platformMessageHandler.playSystemSound(soundType);
result.success(null);
} catch (NoSuchFieldException exception) {
// The desired sound type does not exist.
result.error("error", exception.getMessage(), null);
}
break;
case "HapticFeedback.vibrate":
try {
HapticFeedbackType feedbackType = HapticFeedbackType.fromValue((String) arguments);
platformMessageHandler.vibrateHapticFeedback(feedbackType);
result.success(null);
} catch (NoSuchFieldException exception) {
// The desired feedback type does not exist.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setPreferredOrientations":
try {
int androidOrientation = decodeOrientations((JSONArray) arguments);
platformMessageHandler.setPreferredOrientations(androidOrientation);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more expected fields were either omitted or referenced an invalid type.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setApplicationSwitcherDescription":
try {
AppSwitcherDescription description = decodeAppSwitcherDescription((JSONObject) arguments);
platformMessageHandler.setApplicationSwitcherDescription(description);
result.success(null);
} catch (JSONException exception) {
// One or more expected fields were either omitted or referenced an invalid type.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.setEnabledSystemUIOverlays":
try {
List<SystemUiOverlay> overlays = decodeSystemUiOverlays((JSONArray) arguments);
platformMessageHandler.showSystemOverlays(overlays);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more of the overlay names are invalid.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemChrome.restoreSystemUIOverlays":
platformMessageHandler.restoreSystemUiOverlays();
result.success(null);
break;
case "SystemChrome.setSystemUIOverlayStyle":
try {
SystemChromeStyle systemChromeStyle = decodeSystemChromeStyle((JSONObject) arguments);
platformMessageHandler.setSystemUiOverlayStyle(systemChromeStyle);
result.success(null);
} catch (JSONException | NoSuchFieldException exception) {
// JSONException: One or more expected fields were either omitted or referenced an invalid type.
// NoSuchFieldException: One or more of the brightness names are invalid.
result.error("error", exception.getMessage(), null);
}
break;
case "SystemNavigator.pop":
platformMessageHandler.popSystemNavigator();
result.success(null);
break;
case "Clipboard.getData": {
String contentFormatName = (String) arguments;
ClipboardContentFormat clipboardFormat = null;
if (contentFormatName != null) {
try {
clipboardFormat = ClipboardContentFormat.fromValue(contentFormatName);
} catch (NoSuchFieldException exception) {
// An unsupported content format was requested. Return failure.
result.error("error", "No such clipboard content format: " + contentFormatName, null);
}
}

CharSequence clipboardContent = platformMessageHandler.getClipboardData(clipboardFormat);
if (clipboardContent != null) {
JSONObject response = new JSONObject();
response.put("text", clipboardContent);
result.success(response);
} else {
result.success(null);
}
break;
}
case "Clipboard.setData": {
String clipboardContent = ((JSONObject) arguments).getString("text");
platformMessageHandler.setClipboardData(clipboardContent);
result.success(null);
break;
}
case "SystemGestures.setSystemGestureExclusionRects":
if (!(arguments instanceof JSONArray)) {
String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
result.error("inputTypeError", inputTypeError, null);
break;
}

JSONArray inputRects = (JSONArray) arguments;
ArrayList<Rect> decodedRects = decodeExclusionRects(inputRects);
platformMessageHandler.setSystemGestureExclusionRects(decodedRects);
result.success(null);
break;
case "SystemGestures.getSystemGestureExclusionRects": {
List<Rect> exclusionRects = platformMessageHandler.getSystemGestureExclusionRects();
if (exclusionRects == null) {
String incorrectApiLevel = "Exclusion rects only exist for Android API 29+.";
result.error("error", incorrectApiLevel, null);
break;
}

ArrayList<HashMap<String, Integer>> encodedExclusionRects = encodeExclusionRects(exclusionRects);
result.success(encodedExclusionRects);
break;
}
default:
result.notImplemented();
break;
}
} catch (JSONException e) {
result.error("error", "JSON error: " + e.getMessage(), null);
}
}
}

public enum Brightness {
LIGHT("Brightness.light"),
DARK("Brightness.dark");
Expand Down
Loading