Skip to content

[PlatformView][Android] Unexpected behavior when embedding an Android SurfaceView #128920

@designDo

Description

@designDo

Is there an existing issue for this?

Steps to reproduce

I embed a SurfaceView in a Flutter page, and I get some unexpected results. When using AndroidView, SurfaceView is added to VirtualDisplay, and when performing hot reload or rotate the screen , SurfaceView will not display any frame. When using AndroidSurfaceView, hot reload is normal, But when the page exits, there will be one frame left.
Steps to reproduce:
1.Run the example, click the play_video button, it will jump to the playback page, and then execute hot reload or rotate the screen.
2.Change the child to AndroidSurfaceView , re-run the example, when you exit the page, you will see a frame remains.

Expected results

It is expected that when embedding SurfaceView, it can behave normally regardless of whetherVDmode orHC mode is used.

Actual results

When using VD mode
Do a hot reload or rotate the screen

AndroidView.mp4

When using HD mode

AndroidSurfaceViews.mp4

image

Code sample

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

class VideoPlayPage extends StatefulWidget {
  const VideoPlayPage({Key? key}) : super(key: key);

  @override
  State<VideoPlayPage> createState() => _VideoPlayPageState();
}

class _VideoPlayPageState extends State<VideoPlayPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('play'),
      ),
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints boxConstraints) {
          return Container(
            color: Colors.black,
            width: boxConstraints.maxWidth,
            height: boxConstraints.maxWidth * 9 / 16,
            child: _surface(),
          );
        },
      ),
    );
  }

  Widget _surface() {
    return PlatformViewLink(
        surfaceFactory: (context, controller) {
          return AndroidViewSurface(
            controller: controller as AndroidViewController,
            gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
            hitTestBehavior: PlatformViewHitTestBehavior.opaque,
          );
        },
        onCreatePlatformView: (params) {
          return PlatformViewsService.initSurfaceAndroidView(
            id: params.id,
            viewType: 'video_player',
            layoutDirection: TextDirection.ltr,
            creationParams: {},
            creationParamsCodec: const StandardMessageCodec(),
            onFocus: () {
              params.onFocusChanged(true);
            },
          )
            ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
            ..create();
        },
        viewType: 'video_player');
  }

  Widget _vd() {
    return const AndroidView(viewType: 'video_player');
  }
}

PlatformView is defined in java, providing a MediaPlayer for playing MP4 files in the asset.

// create SurfaceViewPlatformView
class SurfaceViewPlatformView implements PlatformView {
    private final SurfaceView surfaceView;
    private MediaPlayer mediaPlayer;

    SurfaceViewPlatformView(SurfaceView surfaceView) {
        this.surfaceView = surfaceView;
        //simple delay play the video
        surfaceView.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 创建MediaPlayer并设置数据源
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setDisplay(surfaceView.getHolder());

                AssetFileDescriptor assetFileDescriptor = null;
                try {
                    // 获取MP4文件的AssetFileDescriptor
                    assetFileDescriptor = surfaceView.getContext().getAssets().openFd("big_buck_bunny.mp4");
                    // 设置MediaPlayer的数据源为AssetFileDescriptor
                    mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),
                            assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
                    // 准备MediaPlayer
                    mediaPlayer.prepare();
                    // 开始播放
                    mediaPlayer.start();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // 释放AssetFileDescriptor资源
                    if (assetFileDescriptor != null) {
                        try {
                            assetFileDescriptor.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }, 1000);
    }

    @Override
    public View getView() {
        return surfaceView;
    }

    @Override
    public void dispose() {
        // 清理资源
        mediaPlayer.release();
    }
}

The demo example is a plugin,
The complete code can be found in project video_player_surface

Screenshots or Video

No response

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[√]  Flutter (Channel stable, 3.10.4, on Microsoft Windows [版本 10.0.19044.2965], locale zh-CN)
[X] Windows Version (Installed version of Windows is version 10 or higher)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    X cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[√] Chrome - develop for the web
[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components
[√] Android Studio (version 2021.3)
[!] Android Studio (version 2022.1)
    X Unable to find bundled Java version.
[√] VS Code (version 1.77.1)
[√] Connected device (4 available)

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: platform-viewsEmbedding Android/iOS views in Flutter appsa: videoVideo playbackengineflutter/engine related. See also e: labels.found in release: 3.10Found to occur in 3.10found in release: 3.12Found to occur in 3.12has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyplatform-views: vdIssues specific to the Android VirtualDisplay platform views backendr: fixedIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform teamtriaged-androidTriaged by Android platform team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions