New APIs for Android plugins that render to a Surface

Summary

#

The Android embedder for Flutter introduces a new API, SurfaceProducer, which allows plugins to render to a Surface without needing to manage what the backing implementation is. Plugins using the older createSurfaceTexture API will continue to work with Impeller after the next stable release, but are recommended to migrate to the new API.

Background

#

An Android SurfaceTexture is a backing implementation for a Surface that uses an OpenGLES texture as the backing store.

For example, a plugin might display frames from a camera plugin:

Flowchart

In newer versions of the Android API (>= 29), Android introduced a backend-agnostic HardwareBuffer, which coincides with the minimum version that Flutter will attempt to use the Vulkan renderer. The Android embedding API needed to be updated to support a more generic Surface creation API that doesn't rely on OpenGLES.

Migration guide

#

If you are using the older createSurfaceTexture API, you should migrate to the new createSurfaceProducer API. The new API is more flexible and allows the Flutter engine to opaquely pick the best implementation for the current platform and API level.

  1. Instead of creating a SurfaceTextureEntry, create a SurfaceProducer:

    - TextureRegistry.SurfaceTextureEntry entry = textureRegistry.createSurfaceTexture();
    + TextureRegistry.SurfaceProducer producer = textureRegistry.createSurfaceProducer();
  2. Instead of creating a new Surface(...), call getSurface() on the SurfaceProducer:

    - Surface surface = new Surface(entry.surfaceTexture());
    + Surface surface = producer.getSurface();

In order to conserve memory when the application is suspended in the background, Android and Flutter may destroy a surface when it is no longer visible. To ensure that the surface is recreated when the application is resumed, you should use the provided setCallback method to listen to surface lifecycle events:

java
surfaceProducer.setCallback(
   new TextureRegistry.SurfaceProducer.Callback() {
      @Override
      public void onSurfaceCreated() {
         // Do surface initialization here, and draw the current frame.
      }

      @Override
      public void onSurfaceDestroyed() {
         // Do surface cleanup here, and stop drawing frames.
      }
   }
);

A full example of using this new API can be found in PR 6989 for the video_player_android plugin.

Timeline

#

Landed in version: TBD

In stable release: 3.24

References

#

API documentation:

Relevant issues:

Relevant PRs:

  • PR 51061, where we test the new API in the engine tests.
  • PR 6456, where we migrate the video_player plugin to use the new API.
  • PR 6461, where we migrate the camera_android plugin to use the new API.
  • PR 6989, where we add a full example of using the new API in the video_player_android plugin.