hello i`m trying to open camera on flutter app but i'm getting I/flutter (12909): NoSuchMethodError: The getter 'name' was called on null.
I/flutter (12909): Receiver: null
I/flutter (12909): Tried calling: name
here is my code
`import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
// Ensure that plugin services are initialized so that `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
final CameraDescription camera;
const TakePictureScreen({
Key key,
#required this.camera,
}) : super(key: key);
#override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
CameraController _controller;
Future<void> _initializeControllerFuture;
#override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Take a picture')),
// Wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner
// until the controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.camera_alt),
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Attempt to take a picture and get the file `image`
// where it was saved.
final image = await _controller.takePicture();
// If the picture was taken, display it on a new screen.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(
// Pass the automatically generated path to
// the DisplayPictureScreen widget.
imagePath: image?.path,
),
),
);
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({Key key, this.imagePath}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
From https://flutter.dev/docs/cookbook/plugins/picture-using-camera#3-create-and-initialize-the-cameracontroller`
Related
I was trying to make a videoplayer that can be paused by tapping the screen (like YouTube Short)
but I was having a tough time working with Provider as I'm still new to it I was unable to access methods in VideoPlayerScreen so I decided to make a VideoPlayerProvider class so I can update the URL attribute inside it through other classes but I'm getting the ProviderNotFound Exception
Can someone guide me what am I doing wrong here? Any Resources for learning provider in depth would be helpful too, Thanks in Advance.
Apologies if I was unable to frame my question properly
`
import 'dart:async';
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() => runApp(ChangeNotifierProvider(
create: (context) => VideoPlayerProvider(), child: const VideoPlayerApp()));
class VideoPlayerProvider extends ChangeNotifier {
String url =
'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4';
late VideoPlayerController _controller = VideoPlayerController.network(url);
String get getUrl => url;
VideoPlayerController get getController => _controller;
void newVid(String newUrl) {
url = newUrl;
notifyListeners();
}
void pp() {
if (_controller.value.isPlaying) {
_controller.pause();
} else {
_controller.play();
}
notifyListeners();
}
}
class VideoPlayerApp extends StatelessWidget {
const VideoPlayerApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Player Demo',
home: Stack(children: [ VideoPlayerScreen()]),
);
}
}
class VideoPlayerScreen extends StatefulWidget{
const VideoPlayerScreen({super.key});
#override
State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen>{
late VideoPlayerController _controller =
context.watch<VideoPlayerProvider>().getController;
late Future<void> _initializeVideoPlayerFuture;
late String _url = context.watch<VideoPlayerProvider>().getUrl;
#override
void initState() {
super.initState();
_controller = VideoPlayerController.network(_url);
_initializeVideoPlayerFuture = _controller.initialize();
_controller.setLooping(true);
_controller.play();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: 9 / 18.45,
child: VideoPlayer(_controller),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
`
I was trying to update the URL of VideoPlayerScreen So I can update it from external methods
Your code contained redundant initialization of variables and improper usage of the Provider. For a better understanding, you are suggested to go back to the documentation and examples of the Provider package.
However, I've removed all the redundancy from the code and tried to present a better usage of the Provider to you.
Revised code has been pasted below. I've tested it with the latest versions of the VideoPlayer and Provider packages and it is working perfectly fine.
I've mentioned step wise detailed comments inside the code for you to understand what changes have been made and why. Some bonus steps have also been added and explained therein.
You would notice that the provider is being fully used to initialize the controller and play, pause and change the video.
Remember, there can be better ways of achieving this; however, for simplicity and relevance, your code has been modified wherever necessary, in order to achieve the required objective.
void main() => runApp(ChangeNotifierProvider(
create: (context) => VideoPlayerProvider(), child: const VideoPlayerApp()));
class VideoPlayerProvider extends ChangeNotifier {
String url =
'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4';
late VideoPlayerController _controller;
/// STEP 1
/// Defined this async method for use in the FutureBuilder. It contains the
/// code required to initialize the controller and play the video.
Future<void> initializeController() async {
_controller = VideoPlayerController.network(url);
await _controller.initialize();
await _controller.setLooping(true);
return _controller.play();
}
String get getUrl => url;
VideoPlayerController get controller => _controller;
/// BONUS STEP 3
/// Removed the unnecessary notifyListeners() method and instead called
/// initializeController() in order to load and play the new video.
void newVid(String newUrl) {
url = newUrl;
initializeController();
// notifyListeners();
}
/// BONUS STEP 2
/// Removed the unnecessary notifyListeners() method.
/// Since we are using the same instance of controller inside the widget, we
/// don't need to define and notify the listeners
void pp() {
if (_controller.value.isPlaying) {
_controller.pause();
} else {
_controller.play();
}
// notifyListeners();
}
}
class VideoPlayerApp extends StatelessWidget {
const VideoPlayerApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Player Demo',
home: Stack(children: const [VideoPlayerScreen()]),
);
}
}
class VideoPlayerScreen extends StatefulWidget {
const VideoPlayerScreen({super.key});
#override
State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
late VideoPlayerProvider provider;
/// STEP 4
/// Used the same instance of controller as initialized in the provider
VideoPlayerController get controller => provider.controller;
#override
void initState() {
super.initState();
/// STEP 2
/// Lazy initialized the provider variable, for later use in the app
provider = Provider.of<VideoPlayerProvider>(context, listen: false);
/// STEP 3
/// Removed all redundant code for initializing the controller
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
/// STEP 5
/// Used the provider's async method here instead of creating a new
/// redundant one here
future: provider.initializeController(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: 9 / 18.45,
/// BONUS STEP 1
/// Used a GestureDetector widget to listen to screen taps and
/// called the pp() toggle method of the provider.
child: GestureDetector(
onTap: () => provider.pp(),
child: VideoPlayer(controller),
),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
Hope it helps!
Is there a way in Flutter to scan QR codes that enables you to take the picture of what is being scanned? How can this be implemented? The problem I am running into is whenever I successfully scan a QR Code and then try to take a picture with the camera of the phone, it is in use (by the QR Code library). If I then shut down the library and turn on the camera, there is a black screen, delay, and a refocusing of the camera. Terrible user experience.
One workaround would be to take a picture and then read the QR code from the saved image by using the qr_code_tools (https://pub.dev/packages/qr_code_tools) plugin:
String data = await QrCodeToolsPlugin.decodeFrom(imagePath);
A full example can be found below:
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_tools/qr_code_tools.dart';
Future<void> main() async {
// Ensure that plugin services are initialized so that `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
const TakePictureScreen({
Key? key,
required this.camera,
}) : super(key: key);
final CameraDescription camera;
#override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
late CameraController _controller;
late Future<void> _initializeControllerFuture;
#override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Take a picture')),
// You must wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner until the
// controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Attempt to take a picture and get the file `image`
// where it was saved.
final image = await _controller.takePicture();
// If the picture was taken, display it on a new screen.
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(
// Pass the automatically generated path to
// the DisplayPictureScreen widget.
imagePath: image.path,
),
),
);
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
child: const Icon(Icons.camera_alt),
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({Key? key, required this.imagePath})
: super(key: key);
#override
void initState() {
super.initState();
String data = await QrCodeToolsPlugin.decodeFrom(imagePath);
print(data);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
(Source: https://flutter.dev/docs/cookbook/plugins/picture-using-camera)
can anyone help me to open camera on flutter app but i'm getting I/flutter (12909): NoSuchMethodError: The getter 'name' was called on null. I/flutter (12909): Receiver: null I/flutter (12909): Tried calling: name
i dont know why
here is my code
`import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
// Ensure that plugin services are initialized so that `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
final CameraDescription camera;
const TakePictureScreen({
Key key,
#required this.camera,
}) : super(key: key);
#override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
CameraController _controller;
Future<void> _initializeControllerFuture;
#override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Take a picture')),
// Wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner
// until the controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.camera_alt),
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Attempt to take a picture and get the file `image`
// where it was saved.
final image = await _controller.takePicture();
// If the picture was taken, display it on a new screen.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(
// Pass the automatically generated path to
// the DisplayPictureScreen widget.
imagePath: image?.path,
),
),
);
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({Key key, this.imagePath}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
From https://flutter.dev/docs/cookbook/plugins/picture-using-camera#3-create-and-initialize-the-cameracontroller
I assume you have already added the camera package from pub site in your pubspec.yaml file and sync / get the dependencies.
In my case, I tested on my Android Emulator as well as Android Physical device too. The problem which I faced was from the app/build.gradle file where the camera plugin required the minSdkVersion 21 but By default it was minSdkVersion 16
Upgrading to the SdkVersion solves the first issue. Make sure to upgrade the minSdkVersion from 16 to 21 and should look like minSdkVersion 21
NOTE: Allow the required Runtime Permission required by the camera plugin.
I hope this solution will help you to solve your issue.
I am getting an exception thrown while using a back button after disposing of my VideoPlayerController.
I have my VideoPlayer and VideoPlayerController set up like this:
String url;
var plan;
_VideoPlayerScreenState(this.url,{this.plan});
Future<Null> OnWillPop(){
_controller.dispose();
if(plan!=null)
Navigator.push(context, MaterialPageRoute(builder: (context)=>
ListSession(plan :plan)));
else
Navigator.push(context, MaterialPageRoute(builder: (context)=>
ListMoves()));
}
VideoPlayerController _controller;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
_controller = VideoPlayerController.network(
url,
);
// Initialize the controller and store the Future for later use.
_initializeVideoPlayerFuture = _controller.initialize();
// Use the controller to loop the video.
_controller.setLooping(true);
_controller.play();
super.initState();
}
#override
void dispose() {
print("+++++++++++++++++++++++++++++++++++++++++++");
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return WillPopScope(onWillPop: OnWillPop,child:Scaffold(
// Use a FutureBuilder to display a loading spinner while waiting for the
// VideoPlayerController to finish initializing.
body: FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the video.
return Center(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: VideoPlayer(_controller),
),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
));
}
but when I press the back button, I get this error:
Another exception was thrown: A VideoPlayerController was used after being disposed.
How do I properly dispose of my VideoPlayerController and be able to incorporate the back button?
You can copy paste run full code below
and mark unmark Navigator.push / Navigator.pushReplacement to check effect
In your case, you do not need to dispose of controller, because controller is local to this page, you can just do _controller.pause()
You use Navigator.push go to next page means you will pop from next page
If you dispose controller and set controller to null successfully, when pop from next page, you will get an error because initState will not be called again, controller will not init again
If you use Navigator.pushReplacement, dispose will be called automatically,
You can see console show _controller.dispose in demo code.
working demo
you can see when back from ListMove page, video still can play
full code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() => runApp(VideoPlayerApp());
class VideoPlayerApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Player Demo',
home: VideoPlayerScreen(),
);
}
}
class VideoPlayerScreen extends StatefulWidget {
VideoPlayerScreen({Key key}) : super(key: key);
#override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
VideoPlayerController _controller;
VideoPlayerController _oldController;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
print("initState");
// Create and store the VideoPlayerController. The VideoPlayerController
// offers several different constructors to play videos from assets, files,
// or the internet.
_controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
);
// Initialize the controller and store the Future for later use.
_initializeVideoPlayerFuture = _controller.initialize();
// Use the controller to loop the video.
_controller.setLooping(true);
super.initState();
}
#override
void dispose() {
print("_controller.dispose");
// Ensure disposing of the VideoPlayerController to free up resources.
//_initializeVideoPlayerFuture = null;
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
await _controller.pause();
Navigator.push(
context, MaterialPageRoute(builder: (context) => ListMoves()));
/*Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => ListMoves()));*/
},
child: Scaffold(
appBar: AppBar(
title: Text('Butterfly Video'),
),
// Use a FutureBuilder to display a loading spinner while waiting for the
// VideoPlayerController to finish initializing.
body: FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the video.
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: VideoPlayer(_controller),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Wrap the play or pause in a call to `setState`. This ensures the
// correct icon is shown.
setState(() {
// If the video is playing, pause it.
if (_controller.value.isPlaying) {
_controller.pause();
} else {
// If the video is paused, play it.
_controller.play();
}
});
},
// Display the correct icon depending on the state of the player.
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
), // This trailing comma makes auto-formatting nicer for build methods.
),
);
}
}
class ListMoves extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List Movies'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {},
),
),
);
}
}
How to set Flutter CameraPreview Size "Fullscreen"
Problem is same with this link however the solution isn't working on my phone (LG G5). Leaving a black margin around the camera preview for back camera however works fine for front camera but this time recorded video will cover a larger area than the preview video. I tried on other phones front and back camera preview works just fine but the actual recorded video covering more area problem still persists.
Edit: Problem originates from the Camera package itself not the framework for anyone out there who has a similar problem.
Further investigation and playing around with the package revealed that aspect ratio value that is returned from the package is not guaranteed to match the device's aspect ratio however works fine most of the cases.
final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
return Scaffold(
key: _scaffoldKey,
body: Stack(
children: <Widget>[
controller != null
? Center(
child: Transform.scale(
scale: controller.value.aspectRatio / deviceRatio,
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
),
),
)
: Container(),
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(
cameraDescription,
ResolutionPreset.high,
enableAudio: enableAudio,
);
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
showInSnackBar('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {
print("controller inited");
});
}
}
this is the same exact code from the docs and no use of ratio or scale found, and it works fine on every device I have including the emulator
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' show join;
import 'package:path_provider/path_provider.dart';
Future<void> main() async {
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
final CameraDescription camera;
const TakePictureScreen({
Key key,
#required this.camera,
}) : super(key: key);
#override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
CameraController _controller;
Future<void> _initializeControllerFuture;
#override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Take a picture')),
// Wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner
// until the controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.camera_alt),
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Construct the path where the image should be saved using the
// pattern package.
final path = join(
// Store the picture in the temp directory.
// Find the temp directory using the `path_provider` plugin.
(await getTemporaryDirectory()).path,
'${DateTime.now()}.png',
);
// Attempt to take a picture and log where it's been saved.
await _controller.takePicture(path);
// If the picture was taken, display it on a new screen.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(imagePath: path),
),
);
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({Key key, this.imagePath}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}