NoSuchMethodError | Camera Package - flutter

So I am trying to get my camera preview working on iOS and Android, so that it can take a photo, however, I am receiving this error when trying to access my camera from the bottom navigation.
NoSuchMethodError: The Method '[]' was called on Null.
Receiver: null
Tried calling: [](0)
This is the camera I am using, and according to docs, this should be working correctly.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:stumble/main.dart';
import 'dart:async';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(MyApp());
}
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
I have tried various methods of troubleshooting and to no avail. Am I missing an asset entirely? How can I rectify? This is building on my initial question located here: Camera preview stretched in flutter
Edit:
New code re: answers
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:stumble/main.dart';
import 'dart:async';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(MyApp());
}
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
if (cameras.isNotEmpty) {
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
Edit:
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Camera(setData: (File file) {
_imageArray.add(file);
print("_imageArray-- " + _imageArray.length.toString());
setState(() {});
}),
));

It seems like the error indicates that you do not have any available cameras. You should check if you have available cameras like this:
class _CameraScreenState extends State<Camera> {
CameraController controller;
int selectedCameraIndex;
String imgPath;
var image;
#override
void initState() {
super.initState();
if(cameras.isNotEmpty) {
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if(cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}

The error indicates that there is no available cameras in your current environment. Are you trying this out on a simulator? If so, that might be the cause.
Try to set a breakpoint to check the value of the cameras variable or print the length of it afterwards like this:
cameras = await availableCameras();
print(cameras.length);
If you get 0 as the length, that means there is no available cameras.

Could you see if this minimal sample works?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
print(cameras.length); // Confirm here that more than 1 cameras do exist
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Camera(),
);
}
}
class Camera extends StatefulWidget {
Camera({Key key}) : super(key: key);
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController _controller;
#override
void initState() {
super.initState();
print(cameras.length); // Confirm here that cameras.length did not change from above
if (cameras.isNotEmpty) {
_controller = CameraController(cameras[0], ResolutionPreset.max);
_controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
#override
void dispose() {
_controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (cameras.isEmpty) {
return Center(child: Text('No cameras available'));
}
if (!_controller.value.isInitialized) {
return Container();
}
return CameraPreview(_controller);
}
}

Related

Splash Screen if there is no internet connection

Hello I am new in flutter. I created a webapp with webview. Now i want that if there is not internet connection the splash screen should display that there is no internet connection other wise it should load the web page.
in this code in initstate of stateful widget it will check if internet is available using isInternetAvailable then it will show webview else it will show text with Internet not available.
import 'package:flutter/material.dart';
import 'dart:io';
class SplashScreen extends StatefulWidget {
#override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
bool isInternetAvailable = false;
#override
void initState() {
isInternetConnected().then((value){
setState(() {
isInternetAvailable = value;
});
});
super.initState();
}
Future<bool> isInternetConnected() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
return true;
} else {
return false;
}
} on SocketException catch (_) {
print('not connected');
return false;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: isInternetAvailable ? Webview() : Center(
child: Text('Internet not available'),
)
);
}
}

flutte app run in background only if device is connected to usb charger

I try to validate simple task => persiste the vibration when device is horizontal (user sitdown)
Currently it's work when the screen is off only if device is connected to the laptop or usb charger. I try workmanager and android_alarm_manager but I have same issue. I'm doing something wrong ? or it's Impossible ?
Here is a simple reproduce code to test timer and vibration in background when device is connected and not connected.
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'dart:async';
main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Timer _timer;
test_vibration() {
_timer= Timer.periodic(const Duration(seconds: 1), (timer) {
Vibration.vibrate();
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
AndroidAlarmManager.periodic(Duration(seconds: 1), 0, test_vibration());
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center()
),
);
}
}
here is more complet example with accelerometer
import 'package:sensors/sensors.dart';
import 'package:android_alarm_manager/android_alarm_manager.dart';
import 'package:flutter/material.dart';
import 'package:vibration/vibration.dart';
import 'dart:async';
main() async {
WidgetsFlutterBinding.ensureInitialized();
await AndroidAlarmManager.initialize();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<double> _accelerometerValues;
List<StreamSubscription<dynamic>> _streamSubscriptions =
<StreamSubscription<dynamic>>[];
test_vibration() {
_streamSubscriptions.add(accelerometerEvents.listen((AccelerometerEvent event) { // Stream accelerometre
_accelerometerValues = <double>[event.y]; read accelerometer y
if (event.y>6.0||event.y<-6.0){ //device vertical
}else{ // device horizontal
Vibration.vibrate();
}
}));
}
#override
void initState() {
// TODO: implement initState
super.initState();
_streamSubscriptions.add(accelerometerEvents.listen((AccelerometerEvent event) {
setState(() {
_accelerometerValues = <double>[event.y];
});
AndroidAlarmManager.periodic(Duration(seconds: 1), 0, test_vibration());
}));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center()
),
);
}
}
solution I found :
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

Flutter | how can i record the time user spend in my app in flutter?

I have developed and app and the client want me to store the total time spend by the user inside the app
how can I achieve that
I have tried using this App_usage package in flutter but its showing me Star Activity error
if you guys have any solution please let me know
thanks in advance :)
Have some variable that tracks the start time and end/ pause time of the app and persist the difference. You will have to hook that up to the app lifecycle to listen to events such as pausing/ resuming the app. (e.g. How to handle onPause/onResume in Flutter App?)
Something like this:
class AppLifecycleReactor extends StatefulWidget {
const AppLifecycleReactor({Key key}) : super(key: key);
#override
_AppLifecycleReactorState createState() => _AppLifecycleReactorState();
}
class _AppLifecycleReactorState extends State<AppLifecycleReactor>
with WidgetsBindingObserver {
DateTime startTime;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
startTime = DateTime.now();
}
if (state == AppLifecycleState.detached ||
state == AppLifecycleState.paused) {
var usageTime = DateTime.now().difference(startTime);
// do whatever with the usageTime
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: MyContent(),
);
}
}
like Chris Marx said, you can use the counter to store usage time. and to handle the sync operation to server, you can use shared preferenceq to store data and when the app launched again you do sync(update) with the server.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(new HomePage());
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String? docId;
addTime() async {
docId = await TimeHomePageUsage.addUserStartTime();
}
#override
void initState() {
// TODO: implement initState
super.initState();
addTime();
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
TimeHomePageUsage.addUserEndTime(docId);
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Home Page'),
),
);
}
}
class TimeHomePageUsage {
static Future<String?> addUserStartTime() async {
String? docId;
await FirebaseFirestore.instance
.collection('timeUsage')
.add({'startTime': DateTime.now().toString()})
.then((doc) => print("Start Time added ${docId = doc.id} "))
.catchError((error) => print("Failed to add Start Time: $error"));
return docId;
}
static Future<void> addUserEndTime(String? docId) async {
await FirebaseFirestore.instance
.collection('timeUsage')
.doc(docId)
.update({"endTime": DateTime.now().toString()})
.then((value) => print("End Time added "))
.catchError((error) => print("Failed to add End Time: $error"));
}
}

in_app_purchase purchaseUpdatedStream listen event not firing

I want to subscribe to the purchaseUpdatedStream event after my app has initialised as I want to access localization text to display messages to the user if a purchase has failed. However I can't get the listen event to fire unless it's subscribed BEFORE the MaterialApp widget is built.
Working example:
class AppConfig extends InheritedWidget {
AppConfig({
#required this.appName,
#required Widget child,
#required this.prefs,
#required this.devMode
}) : super(child: child);
final String appName;
final SharedPreferences prefs;
final bool devMode;
static AppConfig of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType();
}
#override
bool updateShouldNotify(InheritedWidget oldWidget) => false;
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
var configuredApp = new AppConfig(
appName: 'app',
child: new MyApp(),
prefs: await SharedPreferences.getInstance(),
devMode: true,
);
InAppPurchaseConnection.enablePendingPurchases();
runApp(configuredApp);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
StreamSubscription<List<PurchaseDetails>> _subscription;
#override
void initState() {
Stream purchaseUpdated =
InAppPurchaseConnection.instance.purchaseUpdatedStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
_listenToPurchaseUpdated(purchaseDetailsList, context);
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// handle error here.
});
super.initState();
}
#override
void dispose() {
_subscription.cancel();
super.dispose();
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList, BuildContext context) {
var config = AppConfig.of(context);
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
if (purchaseDetails.status == PurchaseStatus.pending) {
print('pending');
} else {
if (purchaseDetails.status == PurchaseStatus.error) {
print('error');
} else if (purchaseDetails.status == PurchaseStatus.purchased) {
print('purchased');
}
if (purchaseDetails.pendingCompletePurchase) {
print('complete');
await InAppPurchaseConnection.instance
.completePurchase(purchaseDetails);
}
}
});
}
#override
Widget build(BuildContext context) {
var config = AppConfig.of(context);
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return MultiProvider(
providers: [
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: config.appName,
home: Scaffold(
body: SomeWidget(); // whack a button in this widget that triggers a product purchase
),
)
);
}
}
Non-working example:
class AppConfig extends InheritedWidget {
AppConfig({
#required this.appName,
#required Widget child,
#required this.prefs,
#required this.devMode
}) : super(child: child);
final String appName;
final SharedPreferences prefs;
final bool devMode;
static AppConfig of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType();
}
#override
bool updateShouldNotify(InheritedWidget oldWidget) => false;
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
var configuredApp = new AppConfig(
appName: 'app',
child: new AppScaffold(),
prefs: await SharedPreferences.getInstance(),
devMode: true,
);
InAppPurchaseConnection.enablePendingPurchases();
runApp(configuredApp);
}
class AppScaffold extends StatelessWidget {
#override
Widget build(BuildContext context) {
var config = AppConfig.of(context);
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return MultiProvider(
providers: [
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: config.appName,
home: Scaffold(
body: MyApp()
),
)
);
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
StreamSubscription<List<PurchaseDetails>> _subscription;
#override
void initState() {
Stream purchaseUpdated =
InAppPurchaseConnection.instance.purchaseUpdatedStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
_listenToPurchaseUpdated(purchaseDetailsList, context);
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// handle error here.
});
super.initState();
}
#override
void dispose() {
_subscription.cancel();
super.dispose();
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList, BuildContext context) {
var config = AppConfig.of(context);
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
if (purchaseDetails.status == PurchaseStatus.pending) {
print('pending');
} else {
if (purchaseDetails.status == PurchaseStatus.error) {
print('error');
} else if (purchaseDetails.status == PurchaseStatus.purchased) {
print('purchased');
}
if (purchaseDetails.pendingCompletePurchase) {
print('complete');
await InAppPurchaseConnection.instance
.completePurchase(purchaseDetails);
}
}
});
}
#override
Widget build(BuildContext context) {
return SomeWidget(); // whack a button in this widget that triggers a product purchase
}
}
Can anyone see if I'm going about this the wrong way and/or explain why this doesn't work?
My own fault - I was using Navigator.pushReplacement(...); elsewhere in the app which was triggering the dispose method on the child widget. Obvious now I think about it.

Flutter CamerPlugin "camera preview" freezed when app goes to background

Hi iam using flutter cameraPreview to capture photo, the camera preview works fine but when the camera screen goes to background, while on resumed on that screen the camera screen is frezzed, cant able to view cameraPrview onResume.
mycode:
Future<void> _initializeCamera() async {
final cameras = await availableCameras();
final firstCamera = cameras.first;
_controller = CameraController(firstCamera, ResolutionPreset.high);
_initializeControllerFuture = _controller.initialize();
if (!mounted) {
return;
}
setState(() {
isCameraReady = true;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: Stack(children: <Widget>[
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
return Center(
child:
CircularProgressIndicator()); // Otherwise, display a loading indicator.
}
},
),],),);
controller is disposed prpoperly.
I want to know why camera preview is disposed while pause.
Issue is solved by initialised cameraPreview onResume
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_controller != null
? _initializeControllerFuture = _controller.initialize()
: null; //on pause camera disposed so we need call again "issue is only for android"
}
}
On resuming to the page, _controller.initialize will call, so that cameraPreview will works fine.
This is due to cameraPreview runs for long on onPause, it will be disposed..onAndroid i think so..
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
late List<CameraDescription> _cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
_cameras = await availableCameras();
runApp(const CameraApp());
}
/// CameraApp is the Main Application.
class CameraApp extends StatefulWidget {
/// Default Constructor
const CameraApp({Key? key}) : super(key: key);
#override
State<CameraApp> createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> with WidgetsBindingObserver {
late CameraController controller;
// late AppLifecycleState _appLifecycleState;
#override
void initState() {
super.initState();
// _appLifecycleState = AppLifecycleState.resumed;
WidgetsBinding.instance.addObserver(this);
controller = CameraController(_cameras[0], ResolutionPreset.max);
cameraInit();
}
void cameraInit() {
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
}).catchError((Object e) {
if (e is CameraException) {
switch (e.code) {
case 'CameraAccessDenied':
// Handle access errors here.
break;
default:
// Handle other errors here.
break;
}
}
});
}
#override
void dispose() {
controller.dispose();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
// _appLifecycleState = state;
});
if (state == AppLifecycleState.resumed) {
// App is in the foreground
print('App is in the foreground');
cameraInit();
} else if (state == AppLifecycleState.paused) {
// App is in the background
print('App is in the background');
}
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}