11package io .flutter .plugin .platform ;
22
33import static io .flutter .embedding .engine .systemchannels .PlatformViewsChannel .PlatformViewTouch ;
4- import static org .junit .Assert .assertEquals ;
5- import static org .junit .Assert .assertNotEquals ;
6- import static org .junit .Assert .assertNotNull ;
7- import static org .junit .Assert .assertNull ;
8- import static org .mockito .Matchers .eq ;
9- import static org .mockito .Mockito .any ;
10- import static org .mockito .Mockito .mock ;
11- import static org .mockito .Mockito .never ;
12- import static org .mockito .Mockito .times ;
13- import static org .mockito .Mockito .verify ;
14- import static org .mockito .Mockito .when ;
4+ import static org .junit .Assert .*;
5+ import static org .mockito .Matchers .*;
6+ import static org .mockito .Mockito .*;
157
168import android .content .Context ;
179import android .content .res .AssetManager ;
1810import android .view .MotionEvent ;
1911import android .view .View ;
12+ import android .view .ViewParent ;
2013import io .flutter .embedding .android .FlutterView ;
2114import io .flutter .embedding .android .MotionEventTracker ;
2215import io .flutter .embedding .engine .FlutterJNI ;
2316import io .flutter .embedding .engine .dart .DartExecutor ;
17+ import io .flutter .embedding .engine .mutatorsstack .FlutterMutatorView ;
2418import io .flutter .plugin .common .MethodCall ;
2519import io .flutter .plugin .common .StandardMethodCodec ;
2620import java .nio .ByteBuffer ;
@@ -208,39 +202,126 @@ public void getPlatformViewById__hybridComposition() {
208202 int platformViewId = 0 ;
209203 assertNull (platformViewsController .getPlatformViewById (platformViewId ));
210204
205+ PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
206+ PlatformView platformView = mock (PlatformView .class );
207+ View androidView = mock (View .class );
208+ when (platformView .getView ()).thenReturn (androidView );
209+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
210+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
211+
211212 FlutterJNI jni = new FlutterJNI ();
212- AssetManager assetManager = mock (AssetManager .class );
213- Context context = RuntimeEnvironment .application .getApplicationContext ();
213+ attach (jni , platformViewsController );
214214
215- DartExecutor executor = new DartExecutor (jni , assetManager );
216- executor .onAttachedToJNI ();
217- platformViewsController .attach (context , null , executor );
218- platformViewsController .attachToView (mock (FlutterView .class ));
215+ // Simulate create call from the framework.
216+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
217+
218+ platformViewsController .initializePlatformViewIfNeeded (platformViewId );
219+
220+ View resultAndroidView = platformViewsController .getPlatformViewById (platformViewId );
221+ assertNotNull (resultAndroidView );
222+ assertEquals (resultAndroidView , androidView );
223+ }
224+
225+ @ Test
226+ public void initializePlatformViewIfNeeded__throwsIfViewIsNull () {
227+ PlatformViewsController platformViewsController = new PlatformViewsController ();
228+
229+ int platformViewId = 0 ;
230+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
231+
232+ PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
233+ PlatformView platformView = mock (PlatformView .class );
234+ when (platformView .getView ()).thenReturn (null );
235+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
236+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
237+
238+ FlutterJNI jni = new FlutterJNI ();
239+ attach (jni , platformViewsController );
240+
241+ // Simulate create call from the framework.
242+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
243+
244+ try {
245+ platformViewsController .initializePlatformViewIfNeeded (platformViewId );
246+ } catch (Exception exception ) {
247+ assertTrue (exception instanceof IllegalStateException );
248+ assertEquals (
249+ exception .getMessage (),
250+ "PlatformView#getView() returned null, but an Android view reference was expected." );
251+ return ;
252+ }
253+ assertTrue (false );
254+ }
255+
256+ @ Test
257+ public void initializePlatformViewIfNeeded__throwsIfViewHasParent () {
258+ PlatformViewsController platformViewsController = new PlatformViewsController ();
259+
260+ int platformViewId = 0 ;
261+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
219262
220263 PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
221264 PlatformView platformView = mock (PlatformView .class );
222265 View androidView = mock (View .class );
266+ when (androidView .getParent ()).thenReturn (mock (ViewParent .class ));
223267 when (platformView .getView ()).thenReturn (androidView );
224268 when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
269+ platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
270+
271+ FlutterJNI jni = new FlutterJNI ();
272+ attach (jni , platformViewsController );
273+
274+ // Simulate create call from the framework.
275+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
276+ try {
277+ platformViewsController .initializePlatformViewIfNeeded (platformViewId );
278+ } catch (Exception exception ) {
279+ assertTrue (exception instanceof IllegalStateException );
280+ assertEquals (
281+ exception .getMessage (),
282+ "The Android view returned from PlatformView#getView() was already added to a parent view." );
283+ return ;
284+ }
285+ assertTrue (false );
286+ }
225287
288+ @ Test
289+ public void disposeAndroidView__hybridComposition () {
290+ PlatformViewsController platformViewsController = new PlatformViewsController ();
291+
292+ int platformViewId = 0 ;
293+ assertNull (platformViewsController .getPlatformViewById (platformViewId ));
294+
295+ PlatformViewFactory viewFactory = mock (PlatformViewFactory .class );
296+ PlatformView platformView = mock (PlatformView .class );
297+
298+ Context context = RuntimeEnvironment .application .getApplicationContext ();
299+ View androidView = new View (context );
300+
301+ when (platformView .getView ()).thenReturn (androidView );
302+ when (viewFactory .create (any (), eq (platformViewId ), any ())).thenReturn (platformView );
226303 platformViewsController .getRegistry ().registerViewFactory ("testType" , viewFactory );
227304
305+ FlutterJNI jni = new FlutterJNI ();
306+ attach (jni , platformViewsController );
307+
228308 // Simulate create call from the framework.
229- Map <String , Object > platformViewCreateArguments = new HashMap <>();
230- platformViewCreateArguments .put ("hybrid" , true );
231- platformViewCreateArguments .put ("id" , platformViewId );
232- platformViewCreateArguments .put ("viewType" , "testType" );
233- platformViewCreateArguments .put ("direction" , 0 );
234- MethodCall platformCreateMethodCall = new MethodCall ("create" , platformViewCreateArguments );
309+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
310+ platformViewsController .initializePlatformViewIfNeeded (platformViewId );
235311
236- jni . handlePlatformMessage (
237- "flutter/platform_views" , encodeMethodCall ( platformCreateMethodCall ), /*replyId=*/ 0 );
312+ assertNotNull ( androidView . getParent ());
313+ assertTrue ( androidView . getParent () instanceof FlutterMutatorView );
238314
315+ // Simulate dispose call from the framework.
316+ disposePlatformView (jni , platformViewsController , platformViewId );
317+ assertNull (androidView .getParent ());
318+
319+ // Simulate create call from the framework.
320+ createPlatformView (jni , platformViewsController , platformViewId , "testType" );
239321 platformViewsController .initializePlatformViewIfNeeded (platformViewId );
240322
241- View resultAndroidView = platformViewsController .getPlatformViewById (platformViewId );
242- assertNotNull (resultAndroidView );
243- assertEquals (resultAndroidView , androidView );
323+ assertNotNull (androidView .getParent ());
324+ assertTrue (androidView .getParent () instanceof FlutterMutatorView );
244325 }
245326
246327 private static byte [] encodeMethodCall (MethodCall call ) {
@@ -250,4 +331,41 @@ private static byte[] encodeMethodCall(MethodCall call) {
250331 buffer .get (dest );
251332 return dest ;
252333 }
334+
335+ private static void createPlatformView (
336+ FlutterJNI jni ,
337+ PlatformViewsController platformViewsController ,
338+ int platformViewId ,
339+ String viewType ) {
340+ Map <String , Object > platformViewCreateArguments = new HashMap <>();
341+ platformViewCreateArguments .put ("hybrid" , true );
342+ platformViewCreateArguments .put ("id" , platformViewId );
343+ platformViewCreateArguments .put ("viewType" , viewType );
344+ platformViewCreateArguments .put ("direction" , 0 );
345+ MethodCall platformCreateMethodCall = new MethodCall ("create" , platformViewCreateArguments );
346+
347+ jni .handlePlatformMessage (
348+ "flutter/platform_views" , encodeMethodCall (platformCreateMethodCall ), /*replyId=*/ 0 );
349+ }
350+
351+ private static void disposePlatformView (
352+ FlutterJNI jni , PlatformViewsController platformViewsController , int platformViewId ) {
353+ Map <String , Object > platformViewDisposeArguments = new HashMap <>();
354+ platformViewDisposeArguments .put ("hybrid" , true );
355+ platformViewDisposeArguments .put ("id" , platformViewId );
356+ MethodCall platformDisposeMethodCall = new MethodCall ("dispose" , platformViewDisposeArguments );
357+
358+ jni .handlePlatformMessage (
359+ "flutter/platform_views" , encodeMethodCall (platformDisposeMethodCall ), /*replyId=*/ 0 );
360+ }
361+
362+ private void attach (FlutterJNI jni , PlatformViewsController platformViewsController ) {
363+ DartExecutor executor = new DartExecutor (jni , mock (AssetManager .class ));
364+ executor .onAttachedToJNI ();
365+
366+ Context context = RuntimeEnvironment .application .getApplicationContext ();
367+ platformViewsController .attach (context , null , executor );
368+
369+ platformViewsController .attachToView (mock (FlutterView .class ));
370+ }
253371}
0 commit comments