flutter-unity-view-widget icon indicating copy to clipboard operation
flutter-unity-view-widget copied to clipboard

[ANDROID] Screenshots no longer work on 4.0.0+ (Blank screen)

Open TudorAxinte opened this issue 4 years ago • 9 comments

Screenshots no longer work on Android since the latest release. I've tried plenty of workarounds, yet ever since I updated to the latest release I always get a blank (white) screen. IOS still works fine.

String path = await NativeScreenshot.takeScreenshot();

if (path != null ) {
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => ScreenshotScreen(path: path,)));
}

Code gets executed properly. Yet, as the latest release changed the way platform views are handled the console throws:

[ERROR:flutter/flow/layers/platform_view_layer.cc(40)] Trying to embed a platform view but the PaintContext does not support embedding

Instead of saving a capture of the unity view as it used to for a very long time, it saves a capture of flutter's UI only (blank page). Reimplementing the project using flutter_unity_widget: ^2.0.0 solves the issue, but it's still a workaround.

[√] Flutter (Channel dev, 2.1.0-12.1.pre, on Microsoft Windows [Version 10.0.19042.867], locale en-US) [√] Android toolchain - develop for Android devices (Android SDK version 29.0.3)

Unity 2019.4.9f1

TudorAxinte avatar Apr 10 '21 18:04 TudorAxinte

@TudorAxinte you mean screenshooting the app screen?

juicycleff avatar Apr 11 '21 10:04 juicycleff

Or using flutter to capture the screen?

juicycleff avatar Apr 11 '21 10:04 juicycleff

Flutter. In the latest version, it appears the order of the native layers changed, and any attempt to capture from flutter does not capture the Unity view as it's on top. Native screenshot works fine.

TudorAxinte avatar Apr 11 '21 11:04 TudorAxinte

I have the same problem with IOS。 version: flutter_unity_widget: ^4.2.0

I use the screenshot to take a screenshot on the widget. oh my god,my picture is blank.

Eashiong avatar Jun 27 '21 03:06 Eashiong

Hello, I face the same issue with flutter_unity_widget: ^4.2.4 on iOS The UnityWidget is ignored appears white on the screenshot - I'd like to share the scene as image. Is there any progress or workaround on this?

tomLeclercqDD avatar Feb 07 '22 09:02 tomLeclercqDD

Hello, I face the same issue with flutter_unity_widget: ^4.2.4 on iOS The UnityWidget is ignored appears white on the screenshot - I'd like to share the scene as image. Is there any progress or workaround on this?

Hello Tom. Use the native screenshot package and the 4.0.0 plugin and you'll be fine.

TudorAxinte avatar Feb 07 '22 12:02 TudorAxinte

Hello, I face the same issue with flutter_unity_widget: ^4.2.4 on iOS The UnityWidget is ignored appears white on the screenshot - I'd like to share the scene as image. Is there any progress or workaround on this?

Hello Tom. Use the native screenshot package and the 4.0.0 plugin and you'll be fine.

Many thanks for you reply, I was selecting few other widgets as overlay but not the entire application. I will go with the native solution for now but I hope we'll be able to use the RepaintBoundary in the future. Cheers,

tomLeclercqDD avatar Feb 07 '22 12:02 tomLeclercqDD

Here's how I do it

import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:native_screenshot/native_screenshot.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';

class AR extends StatefulWidget {
  @override
  _ARState createState() => _ARState();
}

class _ARState extends State<AR> {
  late UnityWidgetController _unityWidgetController;
  final ValueNotifier<bool> _takingScreenshot = ValueNotifier(false);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: Image.asset(
          'assets/logo_white.png',
          height: 24,
        ),
        iconTheme: IconThemeData(
          color: Colors.white, //change your color here
        ),
        leading: ValueListenableBuilder<bool>(
          valueListenable: _takingScreenshot,
          builder: (_, takingScreenshot, __) => Visibility(
            visible: !takingScreenshot,
            child: IconButton(
              onPressed: () {
                dispose();
                Navigator.of(context).pop();
              },
              icon: Icon(Icons.arrow_back),
            ),
          ),
        ),
        automaticallyImplyLeading: false,
      ),
      body: UnityWidget(
        onUnityCreated: onUnityCreated,
        borderRadius: BorderRadius.all(
          Radius.circular(0),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: ValueListenableBuilder<bool>(
        valueListenable: _takingScreenshot,
        builder: (_, takingScreenshot, __) => Visibility(
          visible: !takingScreenshot,
          child: FloatingActionButton(
            onPressed: () async {
              try {
                _takingScreenshot.value = true;
                await Future.delayed(Duration(seconds: 1));
                var path = await NativeScreenshot.takeScreenshot();
                _takingScreenshot.value = false;
                if (path != null) {
                  await _unityWidgetController.unload();
                  Navigator.of(context).pushReplacement(
                    MaterialPageRoute(
                      builder: (_) => ScreenshotScreen(
                        path,
                      ),
                    ),
                  );
                }
              } catch (e) {
                BotToast.showText(text: e.toString(), duration: Duration(seconds: 5));
              }
            },
            child: Icon(Icons.camera_alt),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        ),
      ),
    );
  }

  void onUnityCreated(controller) {
    this._unityWidgetController = controller;
  }
}

TudorAxinte avatar Feb 07 '22 12:02 TudorAxinte

Here's how I do it

import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:native_screenshot/native_screenshot.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';

class AR extends StatefulWidget {
  @override
  _ARState createState() => _ARState();
}

class _ARState extends State<AR> {
  late UnityWidgetController _unityWidgetController;
  final ValueNotifier<bool> _takingScreenshot = ValueNotifier(false);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: Image.asset(
          'assets/logo_white.png',
          height: 24,
        ),
        iconTheme: IconThemeData(
          color: Colors.white, //change your color here
        ),
        leading: ValueListenableBuilder<bool>(
          valueListenable: _takingScreenshot,
          builder: (_, takingScreenshot, __) => Visibility(
            visible: !takingScreenshot,
            child: IconButton(
              onPressed: () {
                dispose();
                Navigator.of(context).pop();
              },
              icon: Icon(Icons.arrow_back),
            ),
          ),
        ),
        automaticallyImplyLeading: false,
      ),
      body: UnityWidget(
        onUnityCreated: onUnityCreated,
        borderRadius: BorderRadius.all(
          Radius.circular(0),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: ValueListenableBuilder<bool>(
        valueListenable: _takingScreenshot,
        builder: (_, takingScreenshot, __) => Visibility(
          visible: !takingScreenshot,
          child: FloatingActionButton(
            onPressed: () async {
              try {
                _takingScreenshot.value = true;
                await Future.delayed(Duration(seconds: 1));
                var path = await NativeScreenshot.takeScreenshot();
                _takingScreenshot.value = false;
                if (path != null) {
                  await _unityWidgetController.unload();
                  Navigator.of(context).pushReplacement(
                    MaterialPageRoute(
                      builder: (_) => ScreenshotScreen(
                        path,
                      ),
                    ),
                  );
                }
              } catch (e) {
                BotToast.showText(text: e.toString(), duration: Duration(seconds: 5));
              }
            },
            child: Icon(Icons.camera_alt),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        ),
      ),
    );
  }

  void onUnityCreated(controller) {
    this._unityWidgetController = controller;
  }
}

Yes Indeed, I figured out rather the same kind of solution, with maintainSize option so that the UI stays put while the screenshot is being captured. Pretty neat 👌

Thanks a lot for this amazing package!

tomLeclercqDD avatar Feb 07 '22 12:02 tomLeclercqDD