Apparence-io / CamerAwesome

📸 Embedding a camera experience within your own app shouldn't be that hard. A flutter plugin to integrate awesome Android / iOS camera experience.
https://ApparenceKit.dev
MIT License
976 stars 256 forks source link

Exceptions when opening camera [Android 7 / Legacy mode] #47

Closed UlanNurmatov closed 2 years ago

UlanNurmatov commented 3 years ago

Steps to Reproduce

Trying the plugin on Redmi 4A. When opening the camera I'm getting this exception first PlatformException (PlatformException(MUST_CALL_INIT, , , null))

Then, after pressing Continue this exception shows PlatformException (PlatformException(TEXTURE_NOT_FOUND, cannot find texture, , null))

After pressing Continue one more time, camera finally opens.

> import 'package:flutter/material.dart';
> import 'package:camerawesome/camerawesome_plugin.dart';
> 
> // A screen that allows users to take a picture using a given camera.
> class TakePictureScreen extends StatefulWidget {
>   @override
>   TakePictureScreenState createState() => TakePictureScreenState();
> }
> 
> class TakePictureScreenState extends State<TakePictureScreen> {
>   ValueNotifier<CameraFlashes> _switchFlash = ValueNotifier(CameraFlashes.NONE);
>   ValueNotifier<Sensors> _sensor = ValueNotifier(Sensors.BACK);
>   ValueNotifier<Size> _photoSize = ValueNotifier(null);
>   ValueNotifier<double> _zoom = ValueNotifier(null);
>   double _previousScale;
>   List<Size> availableSizes;
> 
>   // Controller
>   PictureController _pictureController = new PictureController();
> 
>   // [...]
> 
>   @override
>   void initState() {
>     super.initState();
>   }
> 
>   @override
>   void dispose() {
>     super.dispose();
>   }
> 
>   @override
>   Widget build(BuildContext context) {
>     return CameraAwesome(
>       onPermissionsResult: _onPermissionsResult,
>       selectDefaultSize: (availableSizes) {
>         this.availableSizes = availableSizes;
>         return availableSizes[0];
>       },
>       photoSize: _photoSize,
>       sensor: _sensor,
>       switchFlashMode: _switchFlash,
>       zoom: _zoom,
>       //onOrientationChanged: _onOrientationChange,
>       // imagesStreamBuilder: (imageStream) {
>       //   /// listen for images preview stream
>       //   /// you can use it to process AI recognition or anything else...
>       //   print("-- init CamerAwesome images stream");
>       //   setState(() {
>       //     previewStream = imageStream;
>       //   });
>       // },
>       onCameraStarted: () {
>         // camera started here -- do your after start stuff
>       },
>     );
>   }
> 
>   _onPermissionsResult(bool granted) {
>     if (!granted) {
>       AlertDialog alert = AlertDialog(
>         title: Text('Error'),
>         content: Text(
>             'It seems you doesn\'t authorized some permissions. Please check on your settings and try again.'),
>         actions: [
>           FlatButton(
>             child: Text('OK'),
>             onPressed: () => Navigator.of(context).pop(),
>           ),
>         ],
>       );
> 
>       // show the dialog
>       showDialog(
>         context: context,
>         builder: (BuildContext context) {
>           return alert;
>         },
>       );
>     } else {
>       setState(() {});
>       print("granted");
>     }
>   }
> }

About your device

Brand Model OS
Android Redmi 4A 7.1.2

g-apparence commented 3 years ago

Hello, could you try without the setState in your _onPermissionsResult method ? By architecture, it's better to not redraw the CamerAwesome preview widget as we restart camera each time you refresh his view.

UlanNurmatov commented 3 years ago

Hello, thanks for response. I tried without setState, but result is the same. Also, the camera is stretched. I think it's the same problem described here https://github.com/flutter/flutter/issues/58163 As commented here https://github.com/flutter/flutter/issues/58163#issuecomment-702021144, the problem is related to Camera2 Api because my old devices run on LEGACY:

I/CameraManagerGlobal(30230): getCameraService: Reconnecting to camera service D/ViewRootImpl(30230): ViewPostImeInputStage ACTION_DOWN D/com.apparence.camerawesome.CamerawesomePlugin(30230): _handleCheckPermissions: D/SensorManager(30230): registerListener :: 0, BMA254 Acceleration Sensor, 200000, 0, E/SensorManager(30230): sensor or listener is null I/CameraManager(30230): Using legacy camera HAL. I/CameraDeviceState(30230): Legacy camera service transitioning to state CONFIGURING I/RequestThread-0(30230): Configure outputs: 2 surfaces configured. D/Camera (30230): app passed NULL surface I/RequestThread-0(30230): configureOutputs - set take picture size to 2576x1932 I/CameraDeviceState(30230): Legacy camera service transitioning to state IDLE I/RequestQueue(30230): Repeating capture request set. W/LegacyRequestMapper(30230): convertRequestMetadata - control.awbRegions setting is not supported, ignoring value W/LegacyRequestMapper(30230): Only received metering rectangles with weight 0. W/LegacyRequestMapper(30230): Only received metering rectangles with weight 0. W/LegacyMetadataMapper(30230): convertAfModeToLegacy - ignoring unsupported mode 4, defaulting to auto I/CameraDeviceState(30230): Legacy camera service transitioning to state CAPTURING D/ViewRootImpl(30230): ViewPostImeInputStage ACTION_DOWN

g-apparence commented 3 years ago

Ok seems that legacy / Android 7 is a problem. Will try to get an emulator with it that can help reproducing it. I tag it as Bug. Thank you reporting it and correctly searching for the root cause, this is truly helping 👍

jarren-meep commented 3 years ago

Hello, I'm on Android 9, Blackview 450 (BV450) and the bug still persists, however only PlatformException (PlatformException(MUST_CALL_INIT, , , null)) will appear, the texture error doesn't appear.

Not sure if it's the same error as UlanNurmatov, but I'll post it here anyway because this seems similar enough

import 'dart:io';
import 'dart:typed_data';

import 'package:camerawesome/camerapreview.dart';
import 'package:camerawesome/camerawesome_plugin.dart';
import 'package:camerawesome/models/capture_modes.dart';
import 'package:camerawesome/models/flashmodes.dart';
import 'package:camerawesome/models/orientations.dart';
import 'package:camerawesome/models/sensors.dart';
import 'package:camerawesome/picture_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:image/image.dart' as image;

class FRCameraScreen extends StatefulWidget {
  @override
  _FRCameraScreenState createState() => _FRCameraScreenState();
}

class _FRCameraScreenState extends State<FRCameraScreen> {
  String _lastPhotoPath;
  ValueNotifier<CameraFlashes> _switchFlash = ValueNotifier(CameraFlashes.NONE);
  ValueNotifier<Sensors> _sensor = ValueNotifier(Sensors.BACK);
  ValueNotifier<CaptureModes> _captureMode = ValueNotifier(CaptureModes.PHOTO);
  ValueNotifier<Size> _photoSize = ValueNotifier(null);
  ValueNotifier<bool> _enableAudio = ValueNotifier(true);
  String imgName;
  int number = 0;

  Stream<Uint8List> previewStream;

  PictureController _pictureController = new PictureController();

  _takePhoto() async {
    final Directory extDir = await getExternalStorageDirectory();
    final testDir =
        await Directory('${extDir.path}/test').create(recursive: true);
    final String filePath = imgName != null
        ? '${testDir.path}/${DateTime.now().millisecondsSinceEpoch}.jpg'
        : '${testDir.path}/photo_test.jpg';
    await _pictureController.takePicture(filePath);
    // lets just make our phone vibrate
    HapticFeedback.mediumImpact();
    _lastPhotoPath = filePath;
    setState(() {});

    print("----------------------------------");
    print("TAKE PHOTO CALLED");
    final file = File(filePath);
    print("==> hastakePhoto : ${file.exists()} | path : $filePath");
    final img = image.decodeImage(file.readAsBytesSync());
    print("==> img.width : ${img.width} | img.height : ${img.height}");
    print("----------------------------------");

    setState(() {});
  }

  _onPermissionsResult(bool granted) {
    if (!granted) {
      print("Not Granted");
    } else {
      print("Granted");
    }
  }

  Widget _buildPreviewStream() {
    if (previewStream == null) return Container();
    return Positioned(
      left: 32,
      bottom: 120,
      child: StreamBuilder(
        stream: previewStream,
        builder: (context, snapshot) {
          if (!snapshot.hasData && snapshot.data.isNotEmpty) return Container();
          List<Uint8List> data = snapshot.data;
          print(
              "...${DateTime.now()} new image received... ${data.last.lengthInBytes} bytes");
          return Image.memory(
            data.last,
            width: 120,
          );
        },
      ),
    );
  }

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

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

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    return CameraAwesome(
      testMode: true,
      onPermissionsResult: _onPermissionsResult,
      selectDefaultSize: (List<Size> availableSizes) => Size(640, 480),
      onCameraStarted: () {},
      onOrientationChanged: (CameraOrientations newOrientation) {},
      sensor: _sensor,
      switchFlashMode: _switchFlash,
      captureMode: _captureMode,
      orientation: DeviceOrientation.portraitUp,
      fitted: true,
      enableAudio: _enableAudio,
      photoSize: _photoSize,
    );
  }
}

No error seems to show in my console, the error only appears and once I press Continue, the camera is working and I can move on. Also, this error only happens when I fully stop the app, the error doesn't appear anymore when I hot restart, if that's any useful information.

Hope this helps! (somehow)

edited: to format use this syntax ```dart

g-apparence commented 3 years ago

Hello @jarren-meep , this isn't the same problem. So if this persist after this, please open another issue.

Hope this helps

jarren-meep commented 3 years ago

Hello @jarren-meep , this isn't the same problem. So if this persist after this, please open another issue.

  • remove testMode: true (this is just for unit test, it create a blank container instead of the camera to let you test your page in units tests)
  • selectDefaultSize: (List availableSizes) => Size(640, 480), => change this by selecting in the list, if your device doesn't have this size this will throw

Hope this helps

My bad then, I'll open a new issue and bring it up there.

pkofcgit commented 3 years ago

Exception has occurred. PlatformException (PlatformException(CAMERA_MUST_BE_INIT, init must be call before start, , null)) Device :Samsung GalaxyA32, Mi Note 7 Android Version 11

the Exception is occure only first time, White Preview screen and with null text no camera is shown, its working fine after close and and restart

if i uninstall application and launch again same thing, its only happened first time

g-apparence commented 2 years ago

Fixed with version 0.3.3 Thank you for reporting it and sorry for the time