Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
ddb8e6e3
Unverified
Commit
ddb8e6e3
authored
Jul 23, 2020
by
Emmanuel Garcia
Committed by
GitHub
Jul 23, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Test dynamic surface switch (#61918)
parent
b8df8a83
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
186 additions
and
43 deletions
+186
-43
MainActivity.java
...ava/io/flutter/integration/androidviews/MainActivity.java
+69
-3
android_platform_view.dart
...tests/hybrid_android_views/lib/android_platform_view.dart
+2
-0
future_data_handler.dart
...n_tests/hybrid_android_views/lib/future_data_handler.dart
+35
-0
main.dart
dev/integration_tests/hybrid_android_views/lib/main.dart
+1
-0
motion_events_page.dart
...on_tests/hybrid_android_views/lib/motion_events_page.dart
+2
-28
nested_view_event_page.dart
...ests/hybrid_android_views/lib/nested_view_event_page.dart
+21
-4
main_test.dart
...ion_tests/hybrid_android_views/test_driver/main_test.dart
+56
-8
No files found.
dev/integration_tests/hybrid_android_views/android/app/src/main/java/io/flutter/integration/androidviews/MainActivity.java
View file @
ddb8e6e3
...
...
@@ -12,9 +12,14 @@ import android.view.MotionEvent;
import
android.view.View
;
import
android.view.ViewGroup
;
import
java.lang.StringBuilder
;
import
java.util.HashMap
;
import
io.flutter.embedding.android.FlutterActivity
;
import
io.flutter.embedding.android.FlutterImageView
;
import
io.flutter.embedding.android.FlutterSurfaceView
;
import
io.flutter.embedding.android.FlutterTextureView
;
import
io.flutter.embedding.android.FlutterView
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.FlutterEngine
;
import
io.flutter.plugin.common.MethodCall
;
...
...
@@ -36,6 +41,63 @@ public class MainActivity extends FlutterActivity implements MethodChannel.Metho
return
((
ViewGroup
)
root
.
getChildAt
(
0
)).
getChildAt
(
0
);
}
private
String
getViewName
(
View
view
)
{
if
(
view
instanceof
FlutterImageView
)
{
return
"FlutterImageView"
;
}
if
(
view
instanceof
FlutterSurfaceView
)
{
return
"FlutterSurfaceView"
;
}
if
(
view
instanceof
FlutterTextureView
)
{
return
"FlutterTextureView"
;
}
if
(
view
instanceof
FlutterView
)
{
return
"FlutterView"
;
}
if
(
view
instanceof
ViewGroup
)
{
return
"ViewGroup"
;
}
return
"View"
;
}
private
void
recurseViewHierarchy
(
View
current
,
String
padding
,
StringBuilder
builder
)
{
if
(
current
.
getVisibility
()
!=
View
.
VISIBLE
||
current
.
getAlpha
()
==
0
)
{
return
;
}
String
name
=
getViewName
(
current
);
builder
.
append
(
padding
);
builder
.
append
(
"|-"
);
builder
.
append
(
name
);
builder
.
append
(
"\n"
);
if
(
current
instanceof
ViewGroup
)
{
ViewGroup
viewGroup
=
(
ViewGroup
)
current
;
for
(
int
index
=
0
;
index
<
viewGroup
.
getChildCount
();
index
++)
{
recurseViewHierarchy
(
viewGroup
.
getChildAt
(
index
),
padding
+
" "
,
builder
);
}
}
}
/**
* Serializes the view hierarchy, so it can be sent to Dart over the method channel.
*
* Notation:
* |- <view-name>
* |- ... child view ordered by z order.
*
* Example output:
* |- FlutterView
* |- FlutterImageView
* |- ViewGroup
* |- View
*/
private
String
getSerializedViewHierarchy
()
{
View
root
=
getFlutterView
();
StringBuilder
builder
=
new
StringBuilder
();
recurseViewHierarchy
(
root
,
""
,
builder
);
return
builder
.
toString
();
}
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
...
...
@@ -65,19 +127,23 @@ public class MainActivity extends FlutterActivity implements MethodChannel.Metho
getExternalStoragePermissions
();
return
;
case
"synthesizeEvent"
:
synthesizeEvent
(
methodCall
,
result
);
synthesizeEvent
(
methodCall
);
result
.
success
(
null
);
return
;
case
"getViewHierarchy"
:
String
viewHierarchy
=
getSerializedViewHierarchy
();
result
.
success
(
viewHierarchy
);
return
;
}
result
.
notImplemented
();
}
@SuppressWarnings
(
"unchecked"
)
public
void
synthesizeEvent
(
MethodCall
methodCall
,
MethodChannel
.
Result
result
)
{
public
void
synthesizeEvent
(
MethodCall
methodCall
)
{
MotionEvent
event
=
MotionEventCodec
.
decode
((
HashMap
<
String
,
Object
>)
methodCall
.
arguments
());
getFlutterView
().
dispatchTouchEvent
(
event
);
// TODO(egarciad): This can be cleaned up.
mMethodChannel
.
invokeMethod
(
"onTouch"
,
MotionEventCodec
.
encode
(
event
));
result
.
success
(
null
);
}
@Override
...
...
dev/integration_tests/hybrid_android_views/lib/android_platform_view.dart
View file @
ddb8e6e3
...
...
@@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
MethodChannel
channel
=
const
MethodChannel
(
'android_views_integration'
);
class
AndroidPlatformView
extends
StatelessWidget
{
/// Creates a platform view for Android, which is rendered as a
/// native view.
...
...
dev/integration_tests/hybrid_android_views/lib/future_data_handler.dart
0 → 100644
View file @
ddb8e6e3
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter_driver/driver_extension.dart'
;
typedef
DriverHandler
=
Future
<
String
>
Function
();
/// Wraps a flutter driver [DataHandler] with one that waits until a delegate is set.
///
/// This allows the driver test to call [FlutterDriver.requestData] before the handler was
/// set by the app in which case the requestData call will only complete once the app is ready
/// for it.
class
FutureDataHandler
{
final
Map
<
String
,
Completer
<
DriverHandler
>>
_handlers
=
<
String
,
Completer
<
DriverHandler
>>{};
/// Registers a lazy handler that will be invoked on the next message from the driver.
Completer
<
DriverHandler
>
registerHandler
(
String
key
)
{
_handlers
[
key
]
=
Completer
<
DriverHandler
>();
return
_handlers
[
key
];
}
Future
<
String
>
handleMessage
(
String
message
)
async
{
if
(
_handlers
[
message
]
==
null
)
{
return
'Unsupported driver message:
$message
.
\n
'
'Supported messages are:
${_handlers.keys}
.'
;
}
final
DriverHandler
handler
=
await
_handlers
[
message
].
future
;
return
handler
();
}
}
FutureDataHandler
driverDataHandler
=
FutureDataHandler
();
dev/integration_tests/hybrid_android_views/lib/main.dart
View file @
ddb8e6e3
...
...
@@ -5,6 +5,7 @@
import
'package:flutter/material.dart'
;
import
'package:flutter_driver/driver_extension.dart'
;
import
'future_data_handler.dart'
;
import
'motion_events_page.dart'
;
import
'nested_view_event_page.dart'
;
import
'page.dart'
;
...
...
dev/integration_tests/hybrid_android_views/lib/motion_events_page.dart
View file @
ddb8e6e3
...
...
@@ -8,15 +8,13 @@ import 'dart:typed_data';
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_driver/driver_extension.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'android_platform_view.dart'
;
import
'future_data_handler.dart'
;
import
'motion_event_diff.dart'
;
import
'page.dart'
;
MethodChannel
channel
=
const
MethodChannel
(
'android_views_integration'
);
const
String
kEventsFileName
=
'touchEvents'
;
class
MotionEventsPage
extends
PageWidget
{
...
...
@@ -29,22 +27,6 @@ class MotionEventsPage extends PageWidget {
}
}
/// Wraps a flutter driver [DataHandler] with one that waits until a delegate is set.
///
/// This allows the driver test to call [FlutterDriver.requestData] before the handler was
/// set by the app in which case the requestData call will only complete once the app is ready
/// for it.
class
FutureDataHandler
{
final
Completer
<
DataHandler
>
handlerCompleter
=
Completer
<
DataHandler
>();
Future
<
String
>
handleMessage
(
String
message
)
async
{
final
DataHandler
handler
=
await
handlerCompleter
.
future
;
return
handler
(
message
);
}
}
FutureDataHandler
driverDataHandler
=
FutureDataHandler
();
class
MotionEventsBody
extends
StatefulWidget
{
@override
State
createState
()
=>
MotionEventsBodyState
();
...
...
@@ -196,7 +178,7 @@ class MotionEventsBodyState extends State<MotionEventsBody> {
void
onPlatformViewCreated
(
int
id
)
{
viewChannel
=
MethodChannel
(
'simple_view/
$id
'
);
viewChannel
.
setMethodCallHandler
(
onViewMethodChannelCall
);
driverDataHandler
.
handlerCompleter
.
complete
(
handleDriverMessag
e
);
driverDataHandler
.
registerHandler
(
'run test'
).
complete
(
playEventsFil
e
);
}
void
listenToFlutterViewEvents
()
{
...
...
@@ -206,14 +188,6 @@ class MotionEventsBodyState extends State<MotionEventsBody> {
});
}
Future
<
String
>
handleDriverMessage
(
String
message
)
async
{
switch
(
message
)
{
case
'run test'
:
return
playEventsFile
();
}
return
'unknown message: "
$message
"'
;
}
Future
<
dynamic
>
onMethodChannelCall
(
MethodCall
call
)
{
switch
(
call
.
method
)
{
case
'onTouch'
:
...
...
dev/integration_tests/hybrid_android_views/lib/nested_view_event_page.dart
View file @
ddb8e6e3
...
...
@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import
'package:flutter/widgets.dart'
;
import
'android_platform_view.dart'
;
import
'future_data_handler.dart'
;
import
'page.dart'
;
class
NestedViewEventPage
extends
PageWidget
{
...
...
@@ -38,6 +39,7 @@ class NestedViewEventBodyState extends State<NestedViewEventBody> {
String
lastError
;
int
id
;
int
nestedViewClickCount
=
0
;
bool
showPlatformView
=
true
;
@override
Widget
build
(
BuildContext
context
)
{
...
...
@@ -49,10 +51,12 @@ class NestedViewEventBodyState extends State<NestedViewEventBody> {
children:
<
Widget
>[
SizedBox
(
height:
300
,
child:
AndroidPlatformView
(
viewType:
'simple_view'
,
onPlatformViewCreated:
onPlatformViewCreated
,
),
child:
showPlatformView
?
AndroidPlatformView
(
key:
const
ValueKey
<
String
>(
'PlatformView'
),
viewType:
'simple_view'
,
onPlatformViewCreated:
onPlatformViewCreated
,
)
:
null
,
),
if
(
lastTestStatus
!=
_LastTestStatus
.
pending
)
_statusWidget
(),
if
(
viewChannel
!=
null
)
...
<
Widget
>[
...
...
@@ -61,6 +65,11 @@ class NestedViewEventBodyState extends State<NestedViewEventBody> {
child:
const
Text
(
'SHOW ALERT DIALOG'
),
onPressed:
onShowAlertDialogPressed
,
),
RaisedButton
(
key:
const
ValueKey
<
String
>(
'TogglePlatformView'
),
child:
const
Text
(
'TOGGLE PLATFORM VIEW'
),
onPressed:
onTogglePlatformView
,
),
Row
(
children:
<
Widget
>[
RaisedButton
(
...
...
@@ -120,6 +129,12 @@ class NestedViewEventBodyState extends State<NestedViewEventBody> {
}
}
Future
<
void
>
onTogglePlatformView
()
async
{
setState
(()
{
showPlatformView
=
!
showPlatformView
;
});
}
Future
<
void
>
onChildViewPressed
()
async
{
try
{
await
viewChannel
.
invokeMethod
<
void
>(
'addChildViewAndWaitForClick'
);
...
...
@@ -152,5 +167,7 @@ class NestedViewEventBodyState extends State<NestedViewEventBody> {
setState
(()
{
viewChannel
=
MethodChannel
(
'simple_view/
$id
'
);
});
driverDataHandler
.
registerHandler
(
'hierarchy'
)
.
complete
(()
=>
channel
.
invokeMethod
<
String
>(
'getViewHierarchy'
));
}
}
dev/integration_tests/hybrid_android_views/test_driver/main_test.dart
View file @
ddb8e6e3
...
...
@@ -18,10 +18,8 @@ Future<void> main() async {
});
// Each test below must return back to the home page after finishing.
test
(
'MotionEvent recomposition'
,
()
async
{
final
SerializableFinder
motionEventsListTile
=
find
.
byValueKey
(
'MotionEventsListTile'
);
final
SerializableFinder
motionEventsListTile
=
find
.
byValueKey
(
'MotionEventsListTile'
);
await
driver
.
tap
(
motionEventsListTile
);
await
driver
.
waitFor
(
find
.
byValueKey
(
'PlatformView'
));
final
String
errorMessage
=
await
driver
.
requestData
(
'run test'
);
...
...
@@ -30,8 +28,7 @@ Future<void> main() async {
await
driver
.
tap
(
backButton
);
});
group
(
'Nested View Event'
,
()
{
group
(
'Nested View Event'
,
()
{
setUpAll
(()
async
{
final
SerializableFinder
wmListTile
=
find
.
byValueKey
(
'NestedViewEventTile'
);
...
...
@@ -44,8 +41,7 @@ Future<void> main() async {
});
test
(
'AlertDialog from platform view context'
,
()
async
{
final
SerializableFinder
showAlertDialog
=
find
.
byValueKey
(
'ShowAlertDialog'
);
final
SerializableFinder
showAlertDialog
=
find
.
byValueKey
(
'ShowAlertDialog'
);
await
driver
.
waitFor
(
showAlertDialog
);
await
driver
.
tap
(
showAlertDialog
);
final
String
status
=
await
driver
.
getText
(
find
.
byValueKey
(
'Status'
));
...
...
@@ -58,8 +54,60 @@ Future<void> main() async {
await
driver
.
tap
(
addChildView
);
final
SerializableFinder
tapChildView
=
find
.
byValueKey
(
'TapChildView'
);
await
driver
.
tap
(
tapChildView
);
final
String
nestedViewClickCount
=
await
driver
.
getText
(
find
.
byValueKey
(
'NestedViewClickCount'
));
final
String
nestedViewClickCount
=
await
driver
.
getText
(
find
.
byValueKey
(
'NestedViewClickCount'
));
expect
(
nestedViewClickCount
,
'Click count: 1'
);
});
});
group
(
'Flutter surface switch'
,
()
{
setUpAll
(()
async
{
final
SerializableFinder
wmListTile
=
find
.
byValueKey
(
'NestedViewEventTile'
);
await
driver
.
tap
(
wmListTile
);
});
tearDownAll
(()
async
{
await
driver
.
waitFor
(
find
.
pageBack
());
await
driver
.
tap
(
find
.
pageBack
());
});
test
(
'Uses FlutterImageView when Android view is on the screen'
,
()
async
{
await
driver
.
waitFor
(
find
.
byValueKey
(
'PlatformView'
));
expect
(
await
driver
.
requestData
(
'hierarchy'
),
'|-FlutterView
\n
'
' |-FlutterSurfaceView
\n
'
// Flutter UI (hidden)
' |-FlutterImageView
\n
'
// Flutter UI (background surface)
' |-ViewGroup
\n
'
// Platform View
' |-ViewGroup
\n
'
' |-FlutterImageView
\n
'
// Flutter UI (overlay surface)
);
// Hide platform view.
final
SerializableFinder
togglePlatformView
=
find
.
byValueKey
(
'TogglePlatformView'
);
await
driver
.
tap
(
togglePlatformView
);
await
driver
.
waitForAbsent
(
find
.
byValueKey
(
'PlatformView'
));
expect
(
await
driver
.
requestData
(
'hierarchy'
),
'|-FlutterView
\n
'
' |-FlutterSurfaceView
\n
'
// Just the Flutter UI
);
// Show platform view again.
await
driver
.
tap
(
togglePlatformView
);
await
driver
.
waitFor
(
find
.
byValueKey
(
'PlatformView'
));
expect
(
await
driver
.
requestData
(
'hierarchy'
),
'|-FlutterView
\n
'
' |-FlutterSurfaceView
\n
'
// Flutter UI (hidden)
' |-FlutterImageView
\n
'
// Flutter UI (background surface)
' |-ViewGroup
\n
'
// Platform View
' |-ViewGroup
\n
'
' |-FlutterImageView
\n
'
// Flutter UI (overlay surface)
);
});
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment