未验证 提交 898480fe 编写于 作者: S Shi-Hao Hong 提交者: GitHub

Android 10+ View.getSystemGestureExclusionRects (#11451)

* SystemGesture.getSystemGestureExclusionRects

* Add getSystemExclusionRects unit tests
上级 27955f24
......@@ -15,6 +15,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import io.flutter.Log;
......@@ -145,7 +146,7 @@ public class PlatformChannel {
* @throws JSONException if {@code inputRects} does not contain expected keys and value types.
*/
@NonNull
private ArrayList<Rect> decodeRects(@NonNull JSONArray inputRects) throws JSONException {
private ArrayList<Rect> decodeExclusionRects(@NonNull JSONArray inputRects) throws JSONException {
ArrayList<Rect> exclusionRects = new ArrayList<Rect>();
for (int i = 0; i < inputRects.length(); i++) {
JSONObject rect = inputRects.getJSONObject(i);
......@@ -173,6 +174,31 @@ public class PlatformChannel {
return exclusionRects;
}
/**
* Encodes a List<Rect> provided by the Android host into an
* ArrayList<HashMap<String, Integer>>.
*
* Since View.getSystemGestureExclusionRects returns a list of Rects, these
* Rects need to be transformed into UTF-8 encoded JSON messages to be
* properly decoded by the Flutter framework.
*
* This method is used by the SystemGestures.getSystemGestureExclusionRects
* platform channel.
*/
private ArrayList<HashMap<String, Integer>> encodeExclusionRects(List<Rect> exclusionRects) {
ArrayList<HashMap<String, Integer>> encodedExclusionRects = new ArrayList<HashMap<String, Integer>>();
for (Rect rect : exclusionRects) {
HashMap<String, Integer> rectMap = new HashMap<String, Integer>();
rectMap.put("top", rect.top);
rectMap.put("right", rect.right);
rectMap.put("bottom", rect.bottom);
rectMap.put("left", rect.left);
encodedExclusionRects.add(rectMap);
}
return encodedExclusionRects;
}
@NonNull
private AppSwitcherDescription decodeAppSwitcherDescription(@NonNull JSONObject encodedDescription) throws JSONException {
int color = encodedDescription.getInt("primaryColor");
......@@ -337,6 +363,12 @@ public class PlatformChannel {
*/
void setClipboardData(@NonNull String text);
/**
* The Flutter application would like to get the system gesture exclusion
* rects.
*/
List<Rect> getSystemGestureExclusionRects();
/**
* The Flutter application would like to set the system gesture exclusion
* rects through the given {@code rects}.
......@@ -594,18 +626,6 @@ public class PlatformChannel {
platformMessageHandler.popSystemNavigator();
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 = decodeRects(inputRects);
platformMessageHandler.setSystemGestureExclusionRects(decodedRects);
result.success(null);
break;
case "Clipboard.getData": {
String contentFormatName = (String) arguments;
ClipboardContentFormat clipboardFormat = null;
......@@ -634,6 +654,30 @@ public class PlatformChannel {
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;
......
......@@ -88,6 +88,11 @@ public class PlatformPlugin {
PlatformPlugin.this.setClipboardData(text);
}
@Override
public List<Rect> getSystemGestureExclusionRects() {
return PlatformPlugin.this.getSystemGestureExclusionRects();
}
@Override
public void setSystemGestureExclusionRects(@NonNull ArrayList rects) {
PlatformPlugin.this.setSystemGestureExclusionRects(rects);
......@@ -281,6 +286,16 @@ public class PlatformPlugin {
clipboard.setPrimaryClip(clip);
}
private List<Rect> getSystemGestureExclusionRects() {
if (Build.VERSION.SDK_INT >= 29) {
Window window = activity.getWindow();
View view = window.getDecorView();
return view.getSystemGestureExclusionRects();
}
return null;
}
private void setSystemGestureExclusionRects(ArrayList<Rect> rects) {
if (Build.VERSION.SDK_INT < 29) {
return;
......
......@@ -3,6 +3,7 @@ package io.flutter.embedding.engine.systemchannels;
import android.graphics.Rect;
import java.util.ArrayList;
import java.util.HashMap;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
......@@ -21,6 +22,7 @@ import org.robolectric.annotation.Config;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@Config(manifest=Config.NONE)
@RunWith(RobolectricTestRunner.class)
......@@ -50,12 +52,12 @@ public class PlatformChannelTest {
Rect gestureRect = new Rect(left, top, right, bottom);
expectedDecodedRects.add(gestureRect);
MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
inputRects
);
platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);
verify(platformMessageHandler, times(1)).setSystemGestureExclusionRects(expectedDecodedRects);
verify(resultsMock, times(1)).success(null);
}
......@@ -69,11 +71,11 @@ public class PlatformChannelTest {
ResultsMock resultsMock = mock(ResultsMock.class);
String nonJsonInput = "Non-JSON";
MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
nonJsonInput
);
platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);
String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
verify(resultsMock, times(1)).error(
......@@ -100,11 +102,11 @@ public class PlatformChannelTest {
JSONArray inputArray = new JSONArray();
inputArray.put(jsonObject);
MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
inputArray
);
platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);
verify(resultsMock, times(1)).error(
"error",
"JSON error: Incorrect JSON data shape. To set system gesture exclusion rects, \n" +
......@@ -113,6 +115,67 @@ public class PlatformChannelTest {
);
}
@Test
public void itSendsSuccessMessageToFrameworkWhenGettingSystemGestureExclusionRects() throws JSONException {
// --- Test Setup ---
DartExecutor dartExecutor = mock(DartExecutor.class);
PlatformChannel platformChannel = new PlatformChannel(dartExecutor);
PlatformMessageHandler platformMessageHandler = mock(PlatformMessageHandler.class);
platformChannel.setPlatformMessageHandler(platformMessageHandler);
Result result = mock(Result.class);
// Fake API output setup
ArrayList<Rect> fakeExclusionRects = new ArrayList<Rect>();
Rect gestureRect = new Rect(0, 0, 500, 250);
fakeExclusionRects.add(gestureRect);
when(platformMessageHandler.getSystemGestureExclusionRects()).thenReturn(fakeExclusionRects);
// Parsed API output that should be passed to result.success()
ArrayList<HashMap<String, Integer>> expectedEncodedOutputRects = new ArrayList<HashMap<String, Integer>>();
HashMap<String, Integer> rectMap = new HashMap<String, Integer>();
rectMap.put("top", 0);
rectMap.put("right", 500);
rectMap.put("bottom", 250);
rectMap.put("left", 0);
expectedEncodedOutputRects.add(rectMap);
MethodCall callGetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.getSystemGestureExclusionRects",
null
);
// --- Execute Test ---
platformChannel.parsingMethodCallHandler.onMethodCall(callGetSystemGestureExclusionRects, result);
// --- Verify Results ---
verify(result, times(1)).success(expectedEncodedOutputRects);
}
@Test
public void itSendsAPILevelErrorWhenAndroidVersionIsTooLowWhenGettingSystemGestureExclusionRects() {
// --- Test Setup ---
DartExecutor dartExecutor = mock(DartExecutor.class);
PlatformChannel platformChannel = new PlatformChannel(dartExecutor);
PlatformMessageHandler platformMessageHandler = mock(PlatformMessageHandler.class);
platformChannel.setPlatformMessageHandler(platformMessageHandler);
when(platformMessageHandler.getSystemGestureExclusionRects()).thenReturn(null);
Result result = mock(Result.class);
MethodCall callGetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.getSystemGestureExclusionRects",
null
);
// --- Execute Test ---
platformChannel.parsingMethodCallHandler.onMethodCall(callGetSystemGestureExclusionRects, result);
// --- Verify Results ---
verify(result, times(1)).error(
"error",
"Exclusion rects only exist for Android API 29+.",
null
);
}
private class ResultsMock implements Result {
@Override
public void success(Object result) {}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册